Title: [281788] trunk
Revision
281788
Author
[email protected]
Date
2021-08-30 18:56:19 -0700 (Mon, 30 Aug 2021)

Log Message

[JSC] Implement Temporal.Calendar
https://bugs.webkit.org/show_bug.cgi?id=229651

Reviewed by Ross Kirsling.

JSTests:

* stress/temporal-calendar.js: Added.
(shouldBe):
(shouldThrow):
(new.Temporal.Calendar):

Source/_javascript_Core:

This patch implements Temporal.Calendar's simple part. Currently, we do not implement many part of Temporal.Calendar since
we do not have Temporal Date-like structures yet, but this patch implemented core part of Temporal.Calendar: keeping calendar
identifier.

We also defer implementing Temporal.Calendar.from's calendar ID parsing part since it requires full-fledged ISO 8601 parser,
which will be implemented in a separate patch.

We use `unsigned` for CalendarID, and this id corresponds to the array index of intlAvailableCalendars, which returns array
of String from ICU.

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* runtime/CommonIdentifiers.h:
* runtime/IntlObject.cpp:
(JSC::intlAvailableCalendars):
(JSC::iso8601CalendarIDSlow):
(JSC::availableCalendars):
(JSC::createArrayFromStringVector): Deleted.
* runtime/IntlObject.h:
(JSC::iso8601CalendarID):
* runtime/IntlObjectInlines.h:
(JSC::createArrayFromStringVector):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildrenImpl):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::calendarStructure):
* runtime/TemporalCalendar.cpp: Added.
(JSC::TemporalCalendar::create):
(JSC::TemporalCalendar::createStructure):
(JSC::TemporalCalendar::TemporalCalendar):
(JSC::TemporalCalendar::isBuiltinCalendar):
(JSC::parseTemporalCalendarString):
(JSC::TemporalCalendar::from):
* runtime/TemporalCalendar.h: Added.
* runtime/TemporalCalendarConstructor.cpp: Added.
(JSC::TemporalCalendarConstructor::create):
(JSC::TemporalCalendarConstructor::createStructure):
(JSC::TemporalCalendarConstructor::TemporalCalendarConstructor):
(JSC::TemporalCalendarConstructor::finishCreation):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* runtime/TemporalCalendarConstructor.h: Added.
* runtime/TemporalCalendarPrototype.cpp: Added.
(JSC::TemporalCalendarPrototype::create):
(JSC::TemporalCalendarPrototype::createStructure):
(JSC::TemporalCalendarPrototype::TemporalCalendarPrototype):
(JSC::TemporalCalendarPrototype::finishCreation):
(JSC::JSC_DEFINE_CUSTOM_GETTER):
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::defaultMergeFields):
* runtime/TemporalCalendarPrototype.h: Added.
* runtime/TemporalObject.cpp:
(JSC::createCalendarConstructor):
* runtime/VM.cpp:
* runtime/VM.h:

Source/WTF:

Add UChar version of createStaticStringImpl to make immortal thread-safe StringImpl with UChar.

* wtf/text/StringImpl.cpp:
(WTF::StringImpl::createStaticStringImpl):
* wtf/text/StringImpl.h:
(WTF::StringImpl::createStaticStringImpl):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (281787 => 281788)


--- trunk/JSTests/ChangeLog	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/JSTests/ChangeLog	2021-08-31 01:56:19 UTC (rev 281788)
@@ -1,3 +1,15 @@
+2021-08-30  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Implement Temporal.Calendar
+        https://bugs.webkit.org/show_bug.cgi?id=229651
+
+        Reviewed by Ross Kirsling.
+
+        * stress/temporal-calendar.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (new.Temporal.Calendar):
+
 2021-08-29  Yusuke Suzuki  <[email protected]>
 
         [JSC] Upgrade test262

Added: trunk/JSTests/stress/temporal-calendar.js (0 => 281788)


--- trunk/JSTests/stress/temporal-calendar.js	                        (rev 0)
+++ trunk/JSTests/stress/temporal-calendar.js	2021-08-31 01:56:19 UTC (rev 281788)
@@ -0,0 +1,92 @@
+//@ requireOptions("--useTemporal=1")
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`expected ${expected} but got ${actual}`);
+}
+
+function shouldThrow(func, errorType, message) {
+    let error;
+    try {
+        func();
+    } catch (e) {
+        error = e;
+    }
+
+    if (!(error instanceof errorType))
+        throw new Error(`Expected ${errorType.name}!`);
+    if (message !== undefined)
+        shouldBe(String(error), message);
+}
+
+{
+    let calendar = new Temporal.Calendar("iso8601");
+    shouldBe(calendar.id, `iso8601`);
+    shouldBe(String(calendar), `iso8601`);
+}
+{
+    let calendar = new Temporal.Calendar("gregory");
+    shouldBe(calendar.id, `gregory`);
+    shouldBe(String(calendar), `gregory`);
+}
+
+shouldThrow(() => {
+    new Temporal.Calendar("discordian");
+}, RangeError, `RangeError: invalid calendar ID`);
+
+{
+    let input = ["monthCode", "day"];
+    let fields = Temporal.Calendar.from("iso8601").fields(input);
+    shouldBe(input !== fields, true);
+    shouldBe(JSON.stringify(fields), `["monthCode","day"]`);
+}
+{
+    let input = ["monthCode", "day"];
+    let fields = Temporal.Calendar.from("gregory").fields(input);
+    shouldBe(input !== fields, true);
+    shouldBe(JSON.stringify(fields), `["monthCode","day"]`);
+}
+{
+    let input = ["monthCode", "day", "year"];
+    let fields = Temporal.Calendar.from("iso8601").fields(input);
+    shouldBe(input !== fields, true);
+    shouldBe(JSON.stringify(fields), `["monthCode","day","year"]`);
+}
+
+{
+    let input = ["monthCode", "day", "year"];
+    let fields = Temporal.Calendar.from("gregory").fields(input);
+    shouldBe(input !== fields, true);
+    shouldBe(JSON.stringify(fields), `["monthCode","day","year","era","eraYear"]`);
+}
+{
+    let merged = Temporal.Calendar.from('iso8601').mergeFields(
+      { year: 2006, month: 7, day: 31 },
+      { monthCode: 'M08' }
+    );
+    shouldBe(JSON.stringify(merged), `{"year":2006,"day":31,"monthCode":"M08"}`);
+}
+{
+    let merged = Temporal.Calendar.from('gregory').mergeFields(
+      { year: 2006, month: 7, day: 31 },
+      { monthCode: 'M08' }
+    );
+    shouldBe(JSON.stringify(merged), `{"year":2006,"day":31,"monthCode":"M08"}`);
+}
+
+{
+    const user = {
+        id: 775,
+        username: 'robotcat',
+        password: 'hunter2', // Note: Don't really store passwords like that
+        userCalendar: Temporal.Calendar.from('gregory')
+    };
+    let string = JSON.stringify(user);
+    shouldBe(string, `{"id":775,"username":"robotcat","password":"hunter2","userCalendar":"gregory"}`);
+    // To rebuild from the string:
+    function reviver(key, value) {
+        if (key.endsWith('Calendar'))
+            return Temporal.Calendar.from(value);
+        return value;
+    }
+    shouldBe(JSON.parse(string, reviver).userCalendar instanceof Temporal.Calendar, true);
+}

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (281787 => 281788)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2021-08-31 01:56:19 UTC (rev 281788)
@@ -107,6 +107,8 @@
     runtime/StringPrototype.cpp
     runtime/SymbolConstructor.cpp
     runtime/SymbolPrototype.cpp
+    runtime/TemporalCalendarConstructor.cpp
+    runtime/TemporalCalendarPrototype.cpp
     runtime/TemporalObject.cpp
 
     wasm/js/JSWebAssembly.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (281787 => 281788)


--- trunk/Source/_javascript_Core/ChangeLog	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-08-31 01:56:19 UTC (rev 281788)
@@ -1,3 +1,70 @@
+2021-08-30  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Implement Temporal.Calendar
+        https://bugs.webkit.org/show_bug.cgi?id=229651
+
+        Reviewed by Ross Kirsling.
+
+        This patch implements Temporal.Calendar's simple part. Currently, we do not implement many part of Temporal.Calendar since
+        we do not have Temporal Date-like structures yet, but this patch implemented core part of Temporal.Calendar: keeping calendar
+        identifier.
+
+        We also defer implementing Temporal.Calendar.from's calendar ID parsing part since it requires full-fledged ISO 8601 parser,
+        which will be implemented in a separate patch.
+
+        We use `unsigned` for CalendarID, and this id corresponds to the array index of intlAvailableCalendars, which returns array
+        of String from ICU.
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * runtime/CommonIdentifiers.h:
+        * runtime/IntlObject.cpp:
+        (JSC::intlAvailableCalendars):
+        (JSC::iso8601CalendarIDSlow):
+        (JSC::availableCalendars):
+        (JSC::createArrayFromStringVector): Deleted.
+        * runtime/IntlObject.h:
+        (JSC::iso8601CalendarID):
+        * runtime/IntlObjectInlines.h:
+        (JSC::createArrayFromStringVector):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildrenImpl):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::calendarStructure):
+        * runtime/TemporalCalendar.cpp: Added.
+        (JSC::TemporalCalendar::create):
+        (JSC::TemporalCalendar::createStructure):
+        (JSC::TemporalCalendar::TemporalCalendar):
+        (JSC::TemporalCalendar::isBuiltinCalendar):
+        (JSC::parseTemporalCalendarString):
+        (JSC::TemporalCalendar::from):
+        * runtime/TemporalCalendar.h: Added.
+        * runtime/TemporalCalendarConstructor.cpp: Added.
+        (JSC::TemporalCalendarConstructor::create):
+        (JSC::TemporalCalendarConstructor::createStructure):
+        (JSC::TemporalCalendarConstructor::TemporalCalendarConstructor):
+        (JSC::TemporalCalendarConstructor::finishCreation):
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        * runtime/TemporalCalendarConstructor.h: Added.
+        * runtime/TemporalCalendarPrototype.cpp: Added.
+        (JSC::TemporalCalendarPrototype::create):
+        (JSC::TemporalCalendarPrototype::createStructure):
+        (JSC::TemporalCalendarPrototype::TemporalCalendarPrototype):
+        (JSC::TemporalCalendarPrototype::finishCreation):
+        (JSC::JSC_DEFINE_CUSTOM_GETTER):
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        (JSC::defaultMergeFields):
+        * runtime/TemporalCalendarPrototype.h: Added.
+        * runtime/TemporalObject.cpp:
+        (JSC::createCalendarConstructor):
+        * runtime/VM.cpp:
+        * runtime/VM.h:
+
 2021-08-30  Ross Kirsling  <[email protected]>
 
         Unreviewed, add missing include to pre-empt unified source shift.

Modified: trunk/Source/_javascript_Core/DerivedSources-input.xcfilelist (281787 => 281788)


--- trunk/Source/_javascript_Core/DerivedSources-input.xcfilelist	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/DerivedSources-input.xcfilelist	2021-08-31 01:56:19 UTC (rev 281788)
@@ -169,6 +169,8 @@
 $(PROJECT_DIR)/runtime/StringPrototype.cpp
 $(PROJECT_DIR)/runtime/SymbolConstructor.cpp
 $(PROJECT_DIR)/runtime/SymbolPrototype.cpp
+$(PROJECT_DIR)/runtime/TemporalCalendarConstructor.cpp
+$(PROJECT_DIR)/runtime/TemporalCalendarPrototype.cpp
 $(PROJECT_DIR)/runtime/TemporalObject.cpp
 $(PROJECT_DIR)/ucd/CaseFolding.txt
 $(PROJECT_DIR)/ucd/DerivedBinaryProperties.txt

Modified: trunk/Source/_javascript_Core/DerivedSources-output.xcfilelist (281787 => 281788)


--- trunk/Source/_javascript_Core/DerivedSources-output.xcfilelist	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/DerivedSources-output.xcfilelist	2021-08-31 01:56:19 UTC (rev 281788)
@@ -66,6 +66,8 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/StringPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/SymbolConstructor.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/SymbolPrototype.lut.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/TemporalCalendarConstructor.lut.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/TemporalCalendarPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/TemporalObject.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/UnicodePatternTables.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/WasmB3IRGeneratorInlines.h

Modified: trunk/Source/_javascript_Core/DerivedSources.make (281787 => 281788)


--- trunk/Source/_javascript_Core/DerivedSources.make	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/DerivedSources.make	2021-08-31 01:56:19 UTC (rev 281788)
@@ -191,6 +191,8 @@
     StringPrototype.lut.h \
     SymbolConstructor.lut.h \
     SymbolPrototype.lut.h \
+    TemporalCalendarConstructor.lut.h \
+    TemporalCalendarPrototype.lut.h \
     TemporalObject.lut.h \
     WebAssemblyCompileErrorConstructor.lut.h \
     WebAssemblyCompileErrorPrototype.lut.h \

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (281787 => 281788)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2021-08-31 01:56:19 UTC (rev 281788)
@@ -1847,6 +1847,9 @@
 		E328DAEB1D38D005001A2529 /* BytecodeRewriter.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D2642A1D38C042000BE174 /* BytecodeRewriter.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E32AB2441DCD75F400D7533A /* MacroAssemblerHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = E380A76B1DCD7195000F89E6 /* MacroAssemblerHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E32C3C6923E94C1E00BC97C0 /* UnlinkedCodeBlockGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = E32C3C6823E94C1E00BC97C0 /* UnlinkedCodeBlockGenerator.h */; };
+		E32D4DE726DAFD4300D4533A /* TemporalCalendarPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D4DE126DAFD4200D4533A /* TemporalCalendarPrototype.h */; };
+		E32D4DE926DAFD4300D4533A /* TemporalCalendar.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D4DE326DAFD4300D4533A /* TemporalCalendar.h */; };
+		E32D4DEA26DAFD4300D4533A /* TemporalCalendarConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = E32D4DE426DAFD4300D4533A /* TemporalCalendarConstructor.h */; };
 		E33095DD23210A1B00EB7856 /* JSInternalFieldObjectImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = E33095DC23210A1400EB7856 /* JSInternalFieldObjectImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E334CBB521FD96A9000EB178 /* RegExpGlobalData.h in Headers */ = {isa = PBXBuildFile; fileRef = E334CBB321FD96A9000EB178 /* RegExpGlobalData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E33637A61B63220200EE0840 /* ReflectObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E33637A41B63220200EE0840 /* ReflectObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1902,6 +1905,8 @@
 		E39BF39922A2288B00BD183E /* SymbolTableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39BF39822A2288B00BD183E /* SymbolTableInlines.h */; };
 		E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E39D8B2E23021E2600265852 /* WasmOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D8B2D23021E1E00265852 /* WasmOperations.h */; };
+		E39DA1DA26DB5E4C00100437 /* TemporalCalendarPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C4630626DB5DE900896336 /* TemporalCalendarPrototype.lut.h */; };
+		E39DA1DB26DB5E5100100437 /* TemporalCalendarConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C4630526DB5DE900896336 /* TemporalCalendarConstructor.lut.h */; };
 		E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E39EEAF322812450008474F4 /* CachedSpecialPropertyAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E39EEAF22281244C008474F4 /* CachedSpecialPropertyAdaptiveStructureWatchpoint.h */; };
 		E39FEBE32339C5D900B40AB0 /* JSAsyncGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = E39FEBE22339C5D400B40AB0 /* JSAsyncGenerator.h */; };
@@ -5087,6 +5092,12 @@
 		E3282BB91FE930A300EDAF71 /* YarrErrorCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrErrorCode.cpp; path = yarr/YarrErrorCode.cpp; sourceTree = "<group>"; };
 		E3282BBA1FE930A400EDAF71 /* YarrErrorCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrErrorCode.h; path = yarr/YarrErrorCode.h; sourceTree = "<group>"; };
 		E32C3C6823E94C1E00BC97C0 /* UnlinkedCodeBlockGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedCodeBlockGenerator.h; sourceTree = "<group>"; };
+		E32D4DE026DAFD4200D4533A /* TemporalCalendar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalCalendar.cpp; sourceTree = "<group>"; };
+		E32D4DE126DAFD4200D4533A /* TemporalCalendarPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalCalendarPrototype.h; sourceTree = "<group>"; };
+		E32D4DE226DAFD4200D4533A /* TemporalCalendarPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalCalendarPrototype.cpp; sourceTree = "<group>"; };
+		E32D4DE326DAFD4300D4533A /* TemporalCalendar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalCalendar.h; sourceTree = "<group>"; };
+		E32D4DE426DAFD4300D4533A /* TemporalCalendarConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalCalendarConstructor.h; sourceTree = "<group>"; };
+		E32D4DE526DAFD4300D4533A /* TemporalCalendarConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalCalendarConstructor.cpp; sourceTree = "<group>"; };
 		E3305FB020B0F78700CEB82B /* InByVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InByVariant.cpp; sourceTree = "<group>"; };
 		E3305FB120B0F78800CEB82B /* InByVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InByVariant.h; sourceTree = "<group>"; };
 		E33095DC23210A1400EB7856 /* JSInternalFieldObjectImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSInternalFieldObjectImpl.h; sourceTree = "<group>"; };
@@ -5202,6 +5213,8 @@
 		E3BFD0B91DAF807C0065DEA2 /* AccessCaseSnippetParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessCaseSnippetParams.cpp; sourceTree = "<group>"; };
 		E3BFD0BA1DAF807C0065DEA2 /* AccessCaseSnippetParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessCaseSnippetParams.h; sourceTree = "<group>"; };
 		E3C295DC1ED2CBAA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectPropertyChangeAdaptiveWatchpoint.h; sourceTree = "<group>"; };
+		E3C4630526DB5DE900896336 /* TemporalCalendarConstructor.lut.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TemporalCalendarConstructor.lut.h; sourceTree = "<group>"; };
+		E3C4630626DB5DE900896336 /* TemporalCalendarPrototype.lut.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TemporalCalendarPrototype.lut.h; sourceTree = "<group>"; };
 		E3C694B123026873006FBE42 /* WasmOSREntryData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmOSREntryData.h; sourceTree = "<group>"; };
 		E3C694B223026874006FBE42 /* WasmTierUpCount.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmTierUpCount.cpp; sourceTree = "<group>"; };
 		E3C73A8F25BFA73400EFE303 /* WasmStreamingPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmStreamingPlan.cpp; sourceTree = "<group>"; };
@@ -7009,6 +7022,8 @@
 				996B73111BD9FA2C00331B84 /* StringConstructor.lut.h */,
 				996B73131BD9FA2C00331B84 /* SymbolConstructor.lut.h */,
 				996B73141BD9FA2C00331B84 /* SymbolPrototype.lut.h */,
+				E3C4630526DB5DE900896336 /* TemporalCalendarConstructor.lut.h */,
+				E3C4630626DB5DE900896336 /* TemporalCalendarPrototype.lut.h */,
 				F6F150202693D450004B98EF /* TemporalObject.lut.h */,
 				533B15DE1DC7F463004D500A /* WasmOps.h */,
 				AD2FCC0A1DB59C5900B3E736 /* WebAssemblyCompileErrorConstructor.lut.h */,
@@ -7953,6 +7968,12 @@
 				E31179A92288385D00514B2C /* SymbolTableOrScopeDepth.h */,
 				BDB4B5E099CD4C1BB3C1CF05 /* TemplateObjectDescriptor.cpp */,
 				70ECA6041AFDBEA200449739 /* TemplateObjectDescriptor.h */,
+				E32D4DE026DAFD4200D4533A /* TemporalCalendar.cpp */,
+				E32D4DE326DAFD4300D4533A /* TemporalCalendar.h */,
+				E32D4DE526DAFD4300D4533A /* TemporalCalendarConstructor.cpp */,
+				E32D4DE426DAFD4300D4533A /* TemporalCalendarConstructor.h */,
+				E32D4DE226DAFD4200D4533A /* TemporalCalendarPrototype.cpp */,
+				E32D4DE126DAFD4200D4533A /* TemporalCalendarPrototype.h */,
 				F6F1501B2693D33E004B98EF /* TemporalNow.cpp */,
 				F6F150182693D33D004B98EF /* TemporalNow.h */,
 				F6F150192693D33E004B98EF /* TemporalObject.cpp */,
@@ -10649,6 +10670,11 @@
 				A784A26411D16622005776AC /* SyntaxChecker.h in Headers */,
 				DC7997831CDE9FA0004D4A09 /* TagRegistersMode.h in Headers */,
 				70ECA6091AFDBEA200449739 /* TemplateObjectDescriptor.h in Headers */,
+				E32D4DE926DAFD4300D4533A /* TemporalCalendar.h in Headers */,
+				E32D4DEA26DAFD4300D4533A /* TemporalCalendarConstructor.h in Headers */,
+				E39DA1DB26DB5E5100100437 /* TemporalCalendarConstructor.lut.h in Headers */,
+				E32D4DE726DAFD4300D4533A /* TemporalCalendarPrototype.h in Headers */,
+				E39DA1DA26DB5E4C00100437 /* TemporalCalendarPrototype.lut.h in Headers */,
 				F6F150212693D450004B98EF /* TemporalObject.lut.h in Headers */,
 				0F24E54F17EE274900ABB217 /* TempRegisterSet.h in Headers */,
 				0F44A7B420BF68D90022B171 /* TerminatedCodeOrigin.h in Headers */,

Modified: trunk/Source/_javascript_Core/Sources.txt (281787 => 281788)


--- trunk/Source/_javascript_Core/Sources.txt	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/Sources.txt	2021-08-31 01:56:19 UTC (rev 281788)
@@ -1010,6 +1010,9 @@
 runtime/SymbolPrototype.cpp
 runtime/SymbolTable.cpp
 runtime/TemplateObjectDescriptor.cpp
+runtime/TemporalCalendar.cpp
+runtime/TemporalCalendarConstructor.cpp
+runtime/TemporalCalendarPrototype.cpp
 runtime/TemporalNow.cpp
 runtime/TemporalObject.cpp
 runtime/TestRunnerUtils.cpp

Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -110,6 +110,7 @@
     macro(dotAll) \
     macro(enumerable) \
     macro(era) \
+    macro(eraYear) \
     macro(errors) \
     macro(eval) \
     macro(events) \
@@ -169,6 +170,7 @@
     macro(minimumSignificantDigits) \
     macro(minute) \
     macro(month) \
+    macro(monthCode) \
     macro(multiline) \
     macro(name) \
     macro(next) \

Modified: trunk/Source/_javascript_Core/runtime/IntlObject.cpp (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/IntlObject.cpp	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/IntlObject.cpp	2021-08-31 01:56:19 UTC (rev 281788)
@@ -1575,51 +1575,72 @@
     return JSValue::encode(localeArray);
 }
 
-// https://tc39.es/proposal-intl-enumeration/#sec-availablecalendars
-static JSArray* availableCalendars(JSGlobalObject* globalObject)
+const Vector<String>& intlAvailableCalendars()
 {
-    VM& vm = globalObject->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
+    static LazyNeverDestroyed<Vector<String>> availableCalendars;
+    static std::once_flag initializeOnce;
+    std::call_once(initializeOnce, [&] {
+        availableCalendars.construct();
+        ASSERT(availableCalendars->isEmpty());
 
-    UErrorCode status = U_ZERO_ERROR;
-    auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucal_getKeywordValuesForLocale("calendars", "und", false, &status));
-    if (U_FAILURE(status)) {
-        throwTypeError(globalObject, scope, "failed to enumerate available calendars"_s);
-        return { };
-    }
+        UErrorCode status = U_ZERO_ERROR;
+        auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucal_getKeywordValuesForLocale("calendars", "und", false, &status));
+        ASSERT(U_SUCCESS(status));
 
-    int32_t count = uenum_count(enumeration.get(), &status);
-    if (U_FAILURE(status)) {
-        throwTypeError(globalObject, scope, "failed to enumerate available calendars"_s);
-        return { };
-    }
+        int32_t count = uenum_count(enumeration.get(), &status);
+        ASSERT(U_SUCCESS(status));
+        availableCalendars->reserveInitialCapacity(count);
 
-    Vector<String, 1> elements;
-    elements.reserveInitialCapacity(count);
-    for (int32_t index = 0; index < count; ++index) {
-        int32_t length = 0;
-        const char* pointer = uenum_next(enumeration.get(), &length, &status);
-        if (U_FAILURE(status)) {
-            throwTypeError(globalObject, scope, "failed to enumerate available calendars"_s);
-            return { };
+        auto createImmortalThreadSafeString = [&](String&& string) {
+            if (string.is8Bit())
+                return StringImpl::createStaticStringImpl(string.characters8(), string.length());
+            return StringImpl::createStaticStringImpl(string.characters16(), string.length());
+        };
+
+        for (int32_t index = 0; index < count; ++index) {
+            int32_t length = 0;
+            const char* pointer = uenum_next(enumeration.get(), &length, &status);
+            ASSERT(U_SUCCESS(status));
+            String calendar(pointer, length);
+            if (auto mapped = mapICUCalendarKeywordToBCP47(calendar))
+                availableCalendars->append(createImmortalThreadSafeString(WTFMove(mapped.value())));
+            else
+                availableCalendars->append(createImmortalThreadSafeString(WTFMove(calendar)));
         }
-        String calendar(pointer, length);
-        if (auto mapped = mapICUCalendarKeywordToBCP47(calendar))
-            elements.append(WTFMove(mapped.value()));
-        else
-            elements.append(WTFMove(calendar));
-    }
 
-    // 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
-    std::sort(elements.begin(), elements.end(),
-        [](const String& a, const String& b) {
-            return WTF::codePointCompare(a, b) < 0;
-        });
+        // 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
+        std::sort(availableCalendars->begin(), availableCalendars->end(),
+            [](const String& a, const String& b) {
+                return WTF::codePointCompare(a, b) < 0;
+            });
+    });
+    return availableCalendars;
+}
 
-    RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
+CalendarID iso8601CalendarIDStorage { std::numeric_limits<CalendarID>::max() };
+CalendarID iso8601CalendarIDSlow()
+{
+    static std::once_flag initializeOnce;
+    std::call_once(initializeOnce, [&] {
+        const auto& calendars = intlAvailableCalendars();
+        for (unsigned index = 0; index < calendars.size(); ++index) {
+            if (calendars[index] == "iso8601"_s) {
+                iso8601CalendarIDStorage = index;
+                return;
+            }
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+    });
+    return iso8601CalendarIDStorage;
 }
 
+// https://tc39.es/proposal-intl-enumeration/#sec-availablecalendars
+static JSArray* availableCalendars(JSGlobalObject* globalObject)
+{
+    return createArrayFromStringVector(globalObject, intlAvailableCalendars());
+}
+
 // https://tc39.es/proposal-intl-enumeration/#sec-availablecollations
 static JSArray* availableCollations(JSGlobalObject* globalObject)
 {
@@ -1865,21 +1886,4 @@
     return { };
 }
 
-JSArray* createArrayFromStringVector(JSGlobalObject* globalObject, Vector<String, 1>&& elements)
-{
-    VM& vm = globalObject->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    JSArray* result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), elements.size());
-    if (!result) {
-        throwOutOfMemoryError(globalObject, scope);
-        return nullptr;
-    }
-    for (unsigned index = 0; index < elements.size(); ++index) {
-        result->putDirectIndex(globalObject, index, jsString(vm, WTFMove(elements[index])));
-        RETURN_IF_EXCEPTION(scope, { });
-    }
-    return result;
-}
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/IntlObject.h (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/IntlObject.h	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/IntlObject.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -101,6 +101,19 @@
 inline const LocaleSet& intlRelativeTimeFormatAvailableLocales() { return intlAvailableLocales(); }
 inline const LocaleSet& intlListFormatAvailableLocales() { return intlAvailableLocales(); }
 
+using CalendarID = unsigned;
+const Vector<String>& intlAvailableCalendars();
+
+extern CalendarID iso8601CalendarIDStorage;
+CalendarID iso8601CalendarIDSlow();
+inline CalendarID iso8601CalendarID()
+{
+    unsigned value = iso8601CalendarIDStorage;
+    if (value == std::numeric_limits<CalendarID>::max())
+        return iso8601CalendarIDSlow();
+    return value;
+}
+
 TriState intlBooleanOption(JSGlobalObject*, JSObject* options, PropertyName);
 String intlStringOption(JSGlobalObject*, JSObject* options, PropertyName, std::initializer_list<const char*> values, const char* notFound, const char* fallback);
 unsigned intlNumberOption(JSGlobalObject*, JSObject* options, PropertyName, unsigned minimum, unsigned maximum, unsigned fallback);
@@ -148,6 +161,4 @@
 std::optional<String> mapICUCalendarKeywordToBCP47(const String&);
 std::optional<String> mapBCP47ToICUCalendarKeyword(const String&);
 
-JSArray* createArrayFromStringVector(JSGlobalObject*, Vector<String, 1>&&);
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/IntlObjectInlines.h (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/IntlObjectInlines.h	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/IntlObjectInlines.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -225,4 +225,22 @@
     return options;
 }
 
+template<typename Container>
+JSArray* createArrayFromStringVector(JSGlobalObject* globalObject, const Container& elements)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSArray* result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), elements.size());
+    if (!result) {
+        throwOutOfMemoryError(globalObject, scope);
+        return nullptr;
+    }
+    for (unsigned index = 0; index < elements.size(); ++index) {
+        result->putDirectIndex(globalObject, index, jsString(vm, elements[index]));
+        RETURN_IF_EXCEPTION(scope, { });
+    }
+    return result;
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-08-31 01:56:19 UTC (rev 281788)
@@ -201,6 +201,9 @@
 #include "SymbolConstructor.h"
 #include "SymbolObject.h"
 #include "SymbolPrototype.h"
+#include "TemporalCalendar.h"
+#include "TemporalCalendarConstructor.h"
+#include "TemporalCalendarPrototype.h"
 #include "TemporalObject.h"
 #include "VMTrapsInlines.h"
 #include "WasmCapabilities.h"
@@ -1212,6 +1215,13 @@
     putDirectWithoutTransition(vm, vm.propertyNames->Intl, intl, static_cast<unsigned>(PropertyAttribute::DontEnum));
 
     if (Options::useTemporal()) {
+        m_calendarStructure.initLater(
+            [] (const Initializer<Structure>& init) {
+                JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner);
+                TemporalCalendarPrototype* calendarPrototype = TemporalCalendarPrototype::create(init.vm, globalObject, TemporalCalendarPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
+                init.set(TemporalCalendar::createStructure(init.vm, globalObject, calendarPrototype));
+            });
+
         TemporalObject* temporal = TemporalObject::create(vm, TemporalObject::createStructure(vm, this));
         putDirectWithoutTransition(vm, vm.propertyNames->Temporal, temporal, static_cast<unsigned>(PropertyAttribute::DontEnum));
     }
@@ -2090,6 +2100,8 @@
     thisObject->m_dateTimeFormatStructure.visit(visitor);
     thisObject->m_numberFormatStructure.visit(visitor);
 
+    thisObject->m_calendarStructure.visit(visitor);
+
     visitor.append(thisObject->m_nullGetterFunction);
     visitor.append(thisObject->m_nullSetterFunction);
     visitor.append(thisObject->m_nullSetterStrictFunction);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -324,6 +324,8 @@
     LazyClassStructure m_dateTimeFormatStructure;
     LazyClassStructure m_numberFormatStructure;
 
+    LazyProperty<JSGlobalObject, Structure> m_calendarStructure;
+
     WriteBarrier<NullGetterFunction> m_nullGetterFunction;
     WriteBarrier<NullSetterFunction> m_nullSetterFunction;
     WriteBarrier<NullSetterFunction> m_nullSetterStrictFunction;
@@ -870,6 +872,8 @@
     JSObject* numberFormatConstructor() { return m_numberFormatStructure.constructor(this); }
     JSObject* numberFormatPrototype() { return m_numberFormatStructure.prototype(this); }
 
+    Structure* calendarStructure() { return m_calendarStructure.get(this); }
+
     JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool);
     JS_EXPORT_PRIVATE bool remoteDebuggingEnabled() const;
 

Added: trunk/Source/_javascript_Core/runtime/TemporalCalendar.cpp (0 => 281788)


--- trunk/Source/_javascript_Core/runtime/TemporalCalendar.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemporalCalendar.cpp	2021-08-31 01:56:19 UTC (rev 281788)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TemporalCalendar.h"
+
+namespace JSC {
+
+const ClassInfo TemporalCalendar::s_info = { "Object", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(TemporalCalendar) };
+
+namespace TemporalCalendarInternal {
+static constexpr bool verbose = false;
+}
+
+TemporalCalendar* TemporalCalendar::create(VM& vm, Structure* structure, CalendarID identifier)
+{
+    TemporalCalendar* format = new (NotNull, allocateCell<TemporalCalendar>(vm.heap)) TemporalCalendar(vm, structure, identifier);
+    format->finishCreation(vm);
+    return format;
+}
+
+Structure* TemporalCalendar::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+}
+
+TemporalCalendar::TemporalCalendar(VM& vm, Structure* structure, CalendarID identifier)
+    : Base(vm, structure)
+    , m_identifier(identifier)
+{
+}
+
+std::optional<CalendarID> TemporalCalendar::isBuiltinCalendar(StringView string)
+{
+    const auto& calendars = intlAvailableCalendars();
+    for (unsigned index = 0; index < calendars.size(); ++index) {
+        if (calendars[index] == string)
+            return index;
+    }
+    return std::nullopt;
+}
+
+// https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalcalendarstring
+static std::optional<CalendarID> parseTemporalCalendarString(JSGlobalObject* globalObject, StringView)
+{
+    // FIXME: Implement parsing temporal calendar string, which requires full ISO 8601 parser.
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    throwRangeError(globalObject, scope, "invalid calendar ID"_s);
+    return std::nullopt;
+}
+
+// https://tc39.es/proposal-temporal/#sec-temporal-totemporalcalendar
+JSObject* TemporalCalendar::from(JSGlobalObject* globalObject, JSValue calendarLike)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (calendarLike.isObject()) {
+        JSObject* calendarLikeObject = jsCast<JSObject*>(calendarLike);
+
+        // FIXME: We need to implement code retrieving Calendar from Temporal Date Like objects. But
+        // currently they are not implemented yet.
+
+        bool hasProperty = calendarLikeObject->hasProperty(globalObject, vm.propertyNames->calendar);
+        RETURN_IF_EXCEPTION(scope, { });
+        if (!hasProperty)
+            return jsCast<JSObject*>(calendarLike);
+
+        calendarLike = calendarLikeObject->get(globalObject, vm.propertyNames->calendar);
+        if (calendarLike.isObject()) {
+            bool hasProperty = jsCast<JSObject*>(calendarLike)->hasProperty(globalObject, vm.propertyNames->calendar);
+            RETURN_IF_EXCEPTION(scope, { });
+            if (!hasProperty)
+                return jsCast<JSObject*>(calendarLike);
+        }
+    }
+
+    auto identifier = calendarLike.toWTFString(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    std::optional<CalendarID> calendarId = isBuiltinCalendar(identifier);
+    if (!calendarId) {
+        calendarId = parseTemporalCalendarString(globalObject, identifier);
+        RETURN_IF_EXCEPTION(scope, { });
+    }
+
+    ASSERT(calendarId);
+    return TemporalCalendar::create(vm, globalObject->calendarStructure(), calendarId.value());
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/TemporalCalendar.h (0 => 281788)


--- trunk/Source/_javascript_Core/runtime/TemporalCalendar.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemporalCalendar.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IntlObject.h"
+#include "JSObject.h"
+
+namespace JSC {
+
+class TemporalCalendar final : public JSNonFinalObject {
+public:
+    using Base = JSNonFinalObject;
+
+    template<typename CellType, SubspaceAccess mode>
+    static IsoSubspace* subspaceFor(VM& vm)
+    {
+        return vm.temporalCalendarSpace<mode>();
+    }
+
+    static TemporalCalendar* create(VM&, Structure*, CalendarID);
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+    DECLARE_INFO;
+
+    CalendarID identifier() const { return m_identifier; }
+    bool isISO8601() const { return m_identifier == iso8601CalendarID(); }
+
+    static std::optional<CalendarID> isBuiltinCalendar(StringView);
+
+    static JSObject* from(JSGlobalObject*, JSValue);
+
+private:
+    TemporalCalendar(VM&, Structure*, CalendarID);
+
+    CalendarID m_identifier { 0 };
+};
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/TemporalCalendarConstructor.cpp (0 => 281788)


--- trunk/Source/_javascript_Core/runtime/TemporalCalendarConstructor.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemporalCalendarConstructor.cpp	2021-08-31 01:56:19 UTC (rev 281788)
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TemporalCalendarConstructor.h"
+
+#include "JSCInlines.h"
+#include "TemporalCalendar.h"
+#include "TemporalCalendarPrototype.h"
+
+namespace JSC {
+
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(TemporalCalendarConstructor);
+static JSC_DECLARE_HOST_FUNCTION(temporalCalendarConstructorFuncFrom);
+
+}
+
+#include "TemporalCalendarConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo TemporalCalendarConstructor::s_info = { "Function", &InternalFunction::s_info, &temporalCalendarConstructorTable, nullptr, CREATE_METHOD_TABLE(TemporalCalendarConstructor) };
+
+/* Source for TemporalCalendarConstructor.lut.h
+@begin temporalCalendarConstructorTable
+    from             temporalCalendarConstructorFuncFrom             DontEnum|Function 1
+@end
+*/
+
+TemporalCalendarConstructor* TemporalCalendarConstructor::create(VM& vm, Structure* structure, TemporalCalendarPrototype* temporalCalendarPrototype)
+{
+    TemporalCalendarConstructor* constructor = new (NotNull, allocateCell<TemporalCalendarConstructor>(vm.heap)) TemporalCalendarConstructor(vm, structure);
+    constructor->finishCreation(vm, temporalCalendarPrototype);
+    return constructor;
+}
+
+Structure* TemporalCalendarConstructor::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(InternalFunctionType, StructureFlags), info());
+}
+
+static JSC_DECLARE_HOST_FUNCTION(callTemporalCalendar);
+static JSC_DECLARE_HOST_FUNCTION(constructTemporalCalendar);
+
+TemporalCalendarConstructor::TemporalCalendarConstructor(VM& vm, Structure* structure)
+    : InternalFunction(vm, structure, callTemporalCalendar, constructTemporalCalendar)
+{
+}
+
+void TemporalCalendarConstructor::finishCreation(VM& vm, TemporalCalendarPrototype* temporalCalendarPrototype)
+{
+    Base::finishCreation(vm, 0, "Calendar"_s, PropertyAdditionMode::WithoutStructureTransition);
+    putDirectWithoutTransition(vm, vm.propertyNames->prototype, temporalCalendarPrototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
+}
+
+JSC_DEFINE_HOST_FUNCTION(constructTemporalCalendar, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSObject* newTarget = asObject(callFrame->newTarget());
+    Structure* structure = JSC_GET_DERIVED_STRUCTURE(vm, calendarStructure, newTarget, callFrame->jsCallee());
+    RETURN_IF_EXCEPTION(scope, { });
+
+    auto calendarString = callFrame->argument(0).toWTFString(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    std::optional<CalendarID> identifier = TemporalCalendar::isBuiltinCalendar(calendarString);
+    if (!identifier) {
+        throwRangeError(globalObject, scope, "invalid calendar ID"_s);
+        return { };
+    }
+
+    return JSValue::encode(TemporalCalendar::create(vm, structure, identifier.value()));
+}
+
+JSC_DEFINE_HOST_FUNCTION(callTemporalCalendar, (JSGlobalObject* globalObject, CallFrame*))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(globalObject, scope, "Calendar"));
+}
+
+JSC_DEFINE_HOST_FUNCTION(temporalCalendarConstructorFuncFrom, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    return JSValue::encode(TemporalCalendar::from(globalObject, callFrame->argument(0)));
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/TemporalCalendarConstructor.h (0 => 281788)


--- trunk/Source/_javascript_Core/runtime/TemporalCalendarConstructor.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemporalCalendarConstructor.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+class TemporalCalendarPrototype;
+
+class TemporalCalendarConstructor final : public InternalFunction {
+public:
+    using Base = InternalFunction;
+    static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
+
+    static TemporalCalendarConstructor* create(VM&, Structure*, TemporalCalendarPrototype*);
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+    DECLARE_INFO;
+
+private:
+    TemporalCalendarConstructor(VM&, Structure*);
+    void finishCreation(VM&, TemporalCalendarPrototype*);
+};
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(TemporalCalendarConstructor, InternalFunction);
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/TemporalCalendarPrototype.cpp (0 => 281788)


--- trunk/Source/_javascript_Core/runtime/TemporalCalendarPrototype.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemporalCalendarPrototype.cpp	2021-08-31 01:56:19 UTC (rev 281788)
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TemporalCalendarPrototype.h"
+
+#include "BuiltinNames.h"
+#include "IteratorOperations.h"
+#include "JSCInlines.h"
+#include "ObjectConstructor.h"
+
+namespace JSC {
+
+static JSC_DECLARE_HOST_FUNCTION(temporalCalendarPrototypeFuncFields);
+static JSC_DECLARE_HOST_FUNCTION(temporalCalendarPrototypeFuncMergeFields);
+static JSC_DECLARE_HOST_FUNCTION(temporalCalendarPrototypeFuncToString);
+static JSC_DECLARE_HOST_FUNCTION(temporalCalendarPrototypeFuncToJSON);
+static JSC_DECLARE_CUSTOM_GETTER(temporalCalendarPrototypeGetterId);
+
+}
+
+#include "TemporalCalendarPrototype.lut.h"
+
+namespace JSC {
+
+const ClassInfo TemporalCalendarPrototype::s_info = { "Temporal.Calendar", &Base::s_info, &temporalCalendarPrototypeTable, nullptr, CREATE_METHOD_TABLE(TemporalCalendarPrototype) };
+
+/* Source for TemporalCalendarPrototype.lut.h
+@begin temporalCalendarPrototypeTable
+    fields          temporalCalendarPrototypeFuncFields       DontEnum|Function 1
+    mergeFields     temporalCalendarPrototypeFuncMergeFields  DontEnum|Function 2
+    toString        temporalCalendarPrototypeFuncToString     DontEnum|Function 0
+    toJSON          temporalCalendarPrototypeFuncToJSON       DontEnum|Function 0
+    id              temporalCalendarPrototypeGetterId         ReadOnly|DontEnum|CustomAccessor
+@end
+*/
+
+TemporalCalendarPrototype* TemporalCalendarPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
+{
+    TemporalCalendarPrototype* object = new (NotNull, allocateCell<TemporalCalendarPrototype>(vm.heap)) TemporalCalendarPrototype(vm, structure);
+    object->finishCreation(vm, globalObject);
+    return object;
+}
+
+Structure* TemporalCalendarPrototype::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+}
+
+TemporalCalendarPrototype::TemporalCalendarPrototype(VM& vm, Structure* structure)
+    : Base(vm, structure)
+{
+}
+
+void TemporalCalendarPrototype::finishCreation(VM& vm, JSGlobalObject*)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+    JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+// https://tc39.es/proposal-temporal/#sec-get-temporal.calendar.prototype.id
+JSC_DEFINE_CUSTOM_GETTER(temporalCalendarPrototypeGetterId, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
+{
+    return JSValue::encode(JSValue::decode(thisValue).toString(globalObject));
+}
+
+// https://tc39.es/proposal-temporal/#sup-temporal.calendar.prototype.fields
+JSC_DEFINE_HOST_FUNCTION(temporalCalendarPrototypeFuncFields, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* calendar = jsDynamicCast<TemporalCalendar*>(vm, callFrame->thisValue());
+    if (!calendar)
+        return throwVMTypeError(globalObject, scope, "Temporal.Calendar.prototype.fields called on value that's not a Calendar"_s);
+
+    bool isISO8601 = calendar->isISO8601();
+    bool shouldAddEraAndEraYear = false;
+    MarkedArgumentBuffer fieldNames;
+    forEachInIterable(globalObject, callFrame->argument(0), [isISO8601, &shouldAddEraAndEraYear, &fieldNames](VM& vm, JSGlobalObject* globalObject, JSValue value) {
+        auto scope = DECLARE_THROW_SCOPE(vm);
+        if (!value.isString()) {
+            throwTypeError(globalObject, scope, "fields include non string value"_s);
+            return;
+        }
+        if (!isISO8601 && !shouldAddEraAndEraYear) {
+            auto string = jsCast<JSString*>(value)->value(globalObject);
+            RETURN_IF_EXCEPTION(scope, void());
+            if (string == "year"_s)
+                shouldAddEraAndEraYear = true;
+        }
+        fieldNames.append(value);
+    });
+    RETURN_IF_EXCEPTION(scope, { });
+
+    if (shouldAddEraAndEraYear) {
+        fieldNames.append(jsNontrivialString(vm, vm.propertyNames->era.impl()));
+        fieldNames.append(jsNontrivialString(vm, vm.propertyNames->eraYear.impl()));
+    }
+
+    return JSValue::encode(constructArray(globalObject, static_cast<ArrayAllocationProfile*>(nullptr), fieldNames));
+}
+
+// https://tc39.es/proposal-temporal/#sec-temporal-defaultmergefields
+static JSObject* defaultMergeFields(JSGlobalObject* globalObject, JSObject* fields, JSObject* additionalFields)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* merged = constructEmptyObject(globalObject);
+
+    {
+        PropertyNameArray originalKeys(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
+        fields->methodTable(vm)->getOwnPropertyNames(fields, globalObject, originalKeys, DontEnumPropertiesMode::Include);
+        RETURN_IF_EXCEPTION(scope, { });
+
+        for (const auto& nextKey : originalKeys) {
+            if (nextKey != vm.propertyNames->month && nextKey != vm.propertyNames->monthCode) {
+                JSValue propValue = fields->get(globalObject, nextKey);
+                RETURN_IF_EXCEPTION(scope, { });
+                if (!propValue.isUndefined()) {
+                    PutPropertySlot slot(merged, true);
+                    merged->putOwnDataProperty(vm, nextKey, propValue, slot);
+                    RETURN_IF_EXCEPTION(scope, { });
+                }
+            }
+        }
+    }
+
+    bool includesMonthOrMonthCode = false;
+    {
+        PropertyNameArray newKeys(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
+        additionalFields->methodTable(vm)->getOwnPropertyNames(additionalFields, globalObject, newKeys, DontEnumPropertiesMode::Include);
+        RETURN_IF_EXCEPTION(scope, { });
+
+        for (const auto& nextKey : newKeys) {
+            if (!includesMonthOrMonthCode) {
+                if (nextKey == vm.propertyNames->month || nextKey == vm.propertyNames->monthCode)
+                    includesMonthOrMonthCode = true;
+            }
+
+            JSValue propValue = additionalFields->get(globalObject, nextKey);
+            RETURN_IF_EXCEPTION(scope, { });
+            if (!propValue.isUndefined()) {
+                PutPropertySlot slot(merged, true);
+                merged->putOwnDataProperty(vm, nextKey, propValue, slot);
+                RETURN_IF_EXCEPTION(scope, { });
+            }
+        }
+    }
+
+    if (!includesMonthOrMonthCode) {
+        JSValue month = fields->get(globalObject, vm.propertyNames->month);
+        RETURN_IF_EXCEPTION(scope, { });
+        if (!month.isUndefined()) {
+            PutPropertySlot slot(merged, true);
+            merged->putOwnDataProperty(vm, vm.propertyNames->month, month, slot);
+            RETURN_IF_EXCEPTION(scope, { });
+        }
+
+        JSValue monthCode = fields->get(globalObject, vm.propertyNames->monthCode);
+        RETURN_IF_EXCEPTION(scope, { });
+        if (!monthCode.isUndefined()) {
+            PutPropertySlot slot(merged, true);
+            merged->putOwnDataProperty(vm, vm.propertyNames->monthCode, monthCode, slot);
+            RETURN_IF_EXCEPTION(scope, { });
+        }
+    }
+
+    return merged;
+}
+
+// https://tc39.es/proposal-temporal/#sup-temporal.calendar.prototype.mergefields
+JSC_DEFINE_HOST_FUNCTION(temporalCalendarPrototypeFuncMergeFields, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* calendar = jsDynamicCast<TemporalCalendar*>(vm, callFrame->thisValue());
+    if (!calendar)
+        return throwVMTypeError(globalObject, scope, "Temporal.Calendar.prototype.mergeFields called on value that's not a Calendar"_s);
+
+    auto* fields = callFrame->argument(0).toObject(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    auto* additionalFields = callFrame->argument(1).toObject(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    if (calendar->isISO8601())
+        RELEASE_AND_RETURN(scope, JSValue::encode(defaultMergeFields(globalObject, fields, additionalFields)));
+
+    auto copyObject = [](JSGlobalObject* globalObject, JSObject* object) -> JSObject* {
+        VM& vm = globalObject->vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
+
+        auto* copied = constructEmptyObject(globalObject);
+
+        PropertyNameArray keys(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
+        object->methodTable(vm)->getOwnPropertyNames(object, globalObject, keys, DontEnumPropertiesMode::Include);
+        RETURN_IF_EXCEPTION(scope, { });
+
+        for (const auto& key : keys) {
+            JSValue propValue = object->get(globalObject, key);
+            RETURN_IF_EXCEPTION(scope, { });
+            if (!propValue.isUndefined()) {
+                PutPropertySlot slot(copied, true);
+                copied->putOwnDataProperty(vm, key, propValue, slot);
+                RETURN_IF_EXCEPTION(scope, { });
+            }
+        }
+
+        return copied;
+    };
+
+    auto* fieldsCopied = copyObject(globalObject, fields);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    auto* additionalFieldsCopied = copyObject(globalObject, additionalFields);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    JSValue newMonth = jsUndefined();
+    JSValue newMonthCode = jsUndefined();
+    JSValue newYear = jsUndefined();
+    JSValue newEra = jsUndefined();
+    JSValue newEraYear = jsUndefined();
+    {
+        PropertyNameArray keys(vm, PropertyNameMode::Strings, PrivateSymbolMode::Exclude);
+        additionalFieldsCopied->methodTable(vm)->getOwnPropertyNames(additionalFieldsCopied, globalObject, keys, DontEnumPropertiesMode::Include);
+        RETURN_IF_EXCEPTION(scope, { });
+
+        for (const auto& key : keys) {
+            JSValue propValue = additionalFieldsCopied->get(globalObject, key);
+            RETURN_IF_EXCEPTION(scope, { });
+            if (!propValue.isUndefined()) {
+                if (key == vm.propertyNames->month)
+                    newMonth = propValue;
+                else if (key == vm.propertyNames->monthCode)
+                    newMonthCode = propValue;
+                else if (key == vm.propertyNames->year)
+                    newYear = propValue;
+                else if (key == vm.propertyNames->era)
+                    newEra = propValue;
+                else if (key == vm.propertyNames->eraYear)
+                    newEraYear = propValue;
+                else {
+                    PutPropertySlot slot(fieldsCopied, true);
+                    fieldsCopied->putOwnDataProperty(vm, key, propValue, slot);
+                    RETURN_IF_EXCEPTION(scope, { });
+                }
+            }
+        }
+    }
+
+    if (!newMonth.isUndefined() || !newMonthCode.isUndefined()) {
+        {
+            PutPropertySlot slot(fieldsCopied, true);
+            fieldsCopied->putOwnDataProperty(vm, vm.propertyNames->month, newMonth, slot);
+            RETURN_IF_EXCEPTION(scope, { });
+        }
+        {
+            PutPropertySlot slot(fieldsCopied, true);
+            fieldsCopied->putOwnDataProperty(vm, vm.propertyNames->monthCode, newMonthCode, slot);
+            RETURN_IF_EXCEPTION(scope, { });
+        }
+    }
+
+    if (!newYear.isUndefined() || !newEra.isUndefined() || !newEraYear.isUndefined()) {
+        {
+            PutPropertySlot slot(fieldsCopied, true);
+            fieldsCopied->putOwnDataProperty(vm, vm.propertyNames->year, newYear, slot);
+            RETURN_IF_EXCEPTION(scope, { });
+        }
+        {
+            PutPropertySlot slot(fieldsCopied, true);
+            fieldsCopied->putOwnDataProperty(vm, vm.propertyNames->era, newEra, slot);
+            RETURN_IF_EXCEPTION(scope, { });
+        }
+        {
+            PutPropertySlot slot(fieldsCopied, true);
+            fieldsCopied->putOwnDataProperty(vm, vm.propertyNames->eraYear, newEraYear, slot);
+            RETURN_IF_EXCEPTION(scope, { });
+        }
+    }
+
+    return JSValue::encode(fieldsCopied);
+}
+
+// https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.tostring
+JSC_DEFINE_HOST_FUNCTION(temporalCalendarPrototypeFuncToString, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* calendar = jsDynamicCast<TemporalCalendar*>(vm, callFrame->thisValue());
+    if (!calendar)
+        return throwVMTypeError(globalObject, scope, "Temporal.Calendar.prototype.toString called on value that's not a Calendar"_s);
+
+    return JSValue::encode(jsString(vm, intlAvailableCalendars()[calendar->identifier()]));
+}
+
+// https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.tojson
+JSC_DEFINE_HOST_FUNCTION(temporalCalendarPrototypeFuncToJSON, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    return JSValue::encode(callFrame->thisValue().toString(globalObject));
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/TemporalCalendarPrototype.h (0 => 281788)


--- trunk/Source/_javascript_Core/runtime/TemporalCalendarPrototype.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TemporalCalendarPrototype.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSObject.h"
+
+namespace JSC {
+
+class TemporalCalendarPrototype final : public JSNonFinalObject {
+public:
+    using Base = JSNonFinalObject;
+    static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
+
+    template<typename CellType, SubspaceAccess>
+    static IsoSubspace* subspaceFor(VM& vm)
+    {
+        STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(TemporalCalendarPrototype, Base);
+        return &vm.plainObjectSpace;
+    }
+
+    static TemporalCalendarPrototype* create(VM&, JSGlobalObject*, Structure*);
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+    DECLARE_INFO;
+
+private:
+    TemporalCalendarPrototype(VM&, Structure*);
+    void finishCreation(VM&, JSGlobalObject*);
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/TemporalObject.cpp (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/TemporalObject.cpp	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/TemporalObject.cpp	2021-08-31 01:56:19 UTC (rev 281788)
@@ -1,5 +1,6 @@
 /*
  *  Copyright (C) 2021 Igalia S.L. All rights reserved.
+ *  Copyright (C) 2021 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -20,10 +21,13 @@
 #include "config.h"
 #include "TemporalObject.h"
 
+#include "FunctionPrototype.h"
 #include "JSCJSValueInlines.h"
 #include "JSGlobalObject.h"
 #include "JSObjectInlines.h"
 #include "ObjectPrototype.h"
+#include "TemporalCalendarConstructor.h"
+#include "TemporalCalendarPrototype.h"
 #include "TemporalNow.h"
 
 namespace JSC {
@@ -30,6 +34,13 @@
 
 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(TemporalObject);
 
+static JSValue createCalendarConstructor(VM& vm, JSObject* object)
+{
+    TemporalObject* temporalObject = jsCast<TemporalObject*>(object);
+    JSGlobalObject* globalObject = temporalObject->globalObject(vm);
+    return TemporalCalendarConstructor::create(vm, TemporalCalendarConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<TemporalCalendarPrototype*>(globalObject->calendarStructure()->storedPrototypeObject()));
+}
+
 static JSValue createNowObject(VM& vm, JSObject* object)
 {
     TemporalObject* temporalObject = jsCast<TemporalObject*>(object);
@@ -45,6 +56,7 @@
 
 /* Source for TemporalObject.lut.h
 @begin temporalObjectTable
+  Calendar       createCalendarConstructor       DontEnum|PropertyCallback
   Now            createNowObject                 DontEnum|PropertyCallback
 @end
 */

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2021-08-31 01:56:19 UTC (rev 281788)
@@ -162,6 +162,7 @@
 #include "StructureChain.h"
 #include "StructureInlines.h"
 #include "SymbolObject.h"
+#include "TemporalCalendar.h"
 #include "TestRunnerUtils.h"
 #include "ThunkGenerators.h"
 #include "TypeProfiler.h"
@@ -1584,6 +1585,7 @@
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(symbolSpace, destructibleCellHeapCellType.get(), Symbol)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(symbolObjectSpace, cellHeapCellType.get(), SymbolObject)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(templateObjectDescriptorSpace, destructibleCellHeapCellType.get(), JSTemplateObjectDescriptor)
+DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalCalendarSpace, cellHeapCellType.get(), TemporalCalendar)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(uint8ArraySpace, cellHeapCellType.get(), JSUint8Array)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(uint8ClampedArraySpace, cellHeapCellType.get(), JSUint8ClampedArray)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(uint16ArraySpace, cellHeapCellType.get(), JSUint16Array)

Modified: trunk/Source/_javascript_Core/runtime/VM.h (281787 => 281788)


--- trunk/Source/_javascript_Core/runtime/VM.h	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -193,6 +193,7 @@
 class UnlinkedModuleProgramCodeBlock;
 class VirtualRegister;
 class VMEntryScope;
+class TemporalCalendar;
 class TopLevelGlobalObjectScope;
 class TypeProfiler;
 class TypeProfilerLog;
@@ -591,6 +592,7 @@
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(symbolSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(symbolObjectSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(templateObjectDescriptorSpace)
+    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalCalendarSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(uint8ArraySpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(uint8ClampedArraySpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(uint16ArraySpace)

Modified: trunk/Source/WTF/ChangeLog (281787 => 281788)


--- trunk/Source/WTF/ChangeLog	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/WTF/ChangeLog	2021-08-31 01:56:19 UTC (rev 281788)
@@ -1,3 +1,17 @@
+2021-08-30  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Implement Temporal.Calendar
+        https://bugs.webkit.org/show_bug.cgi?id=229651
+
+        Reviewed by Ross Kirsling.
+
+        Add UChar version of createStaticStringImpl to make immortal thread-safe StringImpl with UChar.
+
+        * wtf/text/StringImpl.cpp:
+        (WTF::StringImpl::createStaticStringImpl):
+        * wtf/text/StringImpl.h:
+        (WTF::StringImpl::createStaticStringImpl):
+
 2021-08-30  Sihui Liu  <[email protected]>
 
         Add stubs for Permissions API

Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (281787 => 281788)


--- trunk/Source/WTF/wtf/text/StringImpl.cpp	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp	2021-08-31 01:56:19 UTC (rev 281788)
@@ -284,16 +284,26 @@
     return createInternal(characters, length);
 }
 
-Ref<StringImpl> StringImpl::createStaticStringImpl(const char* characters, unsigned length)
+Ref<StringImpl> StringImpl::createStaticStringImpl(const LChar* characters, unsigned length)
 {
-    const LChar* lcharCharacters = reinterpret_cast<const LChar*>(characters);
-    ASSERT(charactersAreAllASCII(lcharCharacters, length));
-    Ref<StringImpl> result = createInternal(lcharCharacters, length);
-    result->setHash(StringHasher::computeHashAndMaskTop8Bits(lcharCharacters, length));
+    if (!length)
+        return *empty();
+    Ref<StringImpl> result = createInternal(characters, length);
+    result->hash();
     result->m_refCount |= s_refCountFlagIsStaticString;
     return result;
 }
 
+Ref<StringImpl> StringImpl::createStaticStringImpl(const UChar* characters, unsigned length)
+{
+    if (!length)
+        return *empty();
+    Ref<StringImpl> result = create8BitIfPossible(characters, length);
+    result->hash();
+    result->m_refCount |= s_refCountFlagIsStaticString;
+    return result;
+}
+
 Ref<StringImpl> StringImpl::create8BitIfPossible(const UChar* characters, unsigned length)
 {
     if (!characters || !length)

Modified: trunk/Source/WTF/wtf/text/StringImpl.h (281787 => 281788)


--- trunk/Source/WTF/wtf/text/StringImpl.h	2021-08-31 01:41:55 UTC (rev 281787)
+++ trunk/Source/WTF/wtf/text/StringImpl.h	2021-08-31 01:56:19 UTC (rev 281788)
@@ -259,7 +259,13 @@
     WTF_EXPORT_PRIVATE static Ref<StringImpl> createUninitialized(unsigned length, UChar*&);
     template<typename CharacterType> static RefPtr<StringImpl> tryCreateUninitialized(unsigned length, CharacterType*&);
 
-    WTF_EXPORT_PRIVATE static Ref<StringImpl> createStaticStringImpl(const char*, unsigned length);
+    static Ref<StringImpl> createStaticStringImpl(const char* characters, unsigned length)
+    {
+        ASSERT(charactersAreAllASCII(bitwise_cast<const LChar*>(characters), length));
+        return createStaticStringImpl(bitwise_cast<const LChar*>(characters), length);
+    }
+    WTF_EXPORT_PRIVATE static Ref<StringImpl> createStaticStringImpl(const LChar*, unsigned length);
+    WTF_EXPORT_PRIVATE static Ref<StringImpl> createStaticStringImpl(const UChar*, unsigned length);
 
     // Reallocate the StringImpl. The originalString must be only owned by the Ref,
     // and the buffer ownership must be BufferInternal. Just like the input pointer of realloc(),
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to