Changeset 285178 in webkit
- Timestamp:
- Nov 2, 2021 12:57:41 PM (9 months ago)
- Location:
- trunk
- Files:
-
- 7 added
- 27 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/temporal-instant.js (added)
-
JSTests/test262/config.yaml (modified) (6 diffs)
-
Source/JavaScriptCore/CMakeLists.txt (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (1 diff)
-
Source/JavaScriptCore/DerivedSources-input.xcfilelist (modified) (1 diff)
-
Source/JavaScriptCore/DerivedSources-output.xcfilelist (modified) (1 diff)
-
Source/JavaScriptCore/DerivedSources.make (modified) (1 diff)
-
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (modified) (5 diffs)
-
Source/JavaScriptCore/Sources.txt (modified) (1 diff)
-
Source/JavaScriptCore/runtime/ISO8601.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/ISO8601.h (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/IntlDateTimeFormat.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/JSBigInt.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSBigInt.h (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/JSDateMath.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSGlobalObject.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/JSGlobalObject.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/TemporalDuration.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/TemporalDuration.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/TemporalInstant.cpp (added)
-
Source/JavaScriptCore/runtime/TemporalInstant.h (added)
-
Source/JavaScriptCore/runtime/TemporalInstantConstructor.cpp (added)
-
Source/JavaScriptCore/runtime/TemporalInstantConstructor.h (added)
-
Source/JavaScriptCore/runtime/TemporalInstantPrototype.cpp (added)
-
Source/JavaScriptCore/runtime/TemporalInstantPrototype.h (added)
-
Source/JavaScriptCore/runtime/TemporalObject.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/TemporalObject.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/VM.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/VM.h (modified) (2 diffs)
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/wtf/CheckedArithmetic.h (modified) (9 diffs)
-
Source/WTF/wtf/DateMath.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r285167 r285178 1 2021-11-02 Philip Chimento <pchimento@igalia.com> 2 3 [JSC] Implement Temporal.Instant 4 https://bugs.webkit.org/show_bug.cgi?id=229826 5 6 Reviewed by Yusuke Suzuki. 7 8 * stress/temporal-instant.js: Added. 9 (shouldBe): 10 (shouldNotBe): 11 (shouldThrow): 12 (instants.forEach): 13 (shouldThrow.new.Temporal.Instant): 14 (const.maxValue.new.Temporal.Instant): 15 (shouldBe.epoch.subtract): 16 * test262/config.yaml: No need to ignore all Temporal.Instant tests 17 anymore, only the ones for the unimplemented methods. 18 1 19 2021-11-02 Saam Barati <sbarati@apple.com> 2 20 -
trunk/JSTests/test262/config.yaml
r284435 r285178 24 24 paths: 25 25 - test/built-ins/Temporal/Calendar 26 - test/built-ins/Temporal/Instant 26 - test/built-ins/Temporal/Instant/prototype/toZonedDateTime 27 - test/built-ins/Temporal/Instant/prototype/toZonedDateTimeISO 27 28 - test/built-ins/Temporal/Now 28 29 - test/built-ins/Temporal/PlainDate … … 35 36 - test/built-ins/Temporal/ZonedDateTime 36 37 - test/intl402/Temporal/Calendar 37 - test/intl402/Temporal/Instant 38 - test/intl402/Temporal/Instant/prototype/toZonedDateTime 39 - test/intl402/Temporal/Instant/prototype/toZonedDateTimeISO 38 40 - test/intl402/Temporal/Now 39 41 - test/intl402/Temporal/PlainDate … … 248 250 - test/built-ins/Temporal/Duration/prototype/total/calendar-temporal-object.js 249 251 - test/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted.js 252 - test/built-ins/Temporal/Instant/prototype/toString/smallestunit-plurals-accepted.js 250 253 - test/built-ins/Temporal/PlainTime/compare/calendar-temporal-object.js 251 254 - test/built-ins/Temporal/PlainTime/from/calendar-temporal-object.js … … 272 275 - test/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js 273 276 - test/built-ins/Temporal/Duration/prototype/total/dateuntil-field.js 277 278 # Depends on Temporal.TimeZone 279 - test/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-non-integer.js 280 - test/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-out-of-range.js 281 - test/built-ins/Temporal/Instant/prototype/toString/timezone-getoffsetnanosecondsfor-wrong-type.js 282 - test/built-ins/Temporal/Instant/prototype/toString/timezone-string-datetime.js 283 - test/built-ins/Temporal/Instant/prototype/toString/timezone.js 274 284 275 285 # Depends on Temporal.ZonedDateTime … … 300 310 - test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js 301 311 - test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js 312 - test/built-ins/Temporal/Instant/compare/argument-zoneddatetime.js 313 - test/built-ins/Temporal/Instant/from/argument-zoneddatetime.js 314 - test/built-ins/Temporal/Instant/prototype/equals/argument-zoneddatetime.js 315 - test/built-ins/Temporal/Instant/prototype/since/argument-zoneddatetime.js 316 - test/built-ins/Temporal/Instant/prototype/until/argument-zoneddatetime.js 302 317 - test/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js 303 318 - test/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js … … 335 350 - test/built-ins/Temporal/Duration/prototype/round/round-negative-result.js 336 351 - test/built-ins/Temporal/Duration/prototype/subtract/balance-negative-result.js 352 - test/built-ins/Temporal/Instant/prototype/until/instant-string.js 337 353 - test/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js 338 354 - test/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js -
trunk/Source/JavaScriptCore/CMakeLists.txt
r284868 r285178 114 114 runtime/TemporalDurationConstructor.cpp 115 115 runtime/TemporalDurationPrototype.cpp 116 runtime/TemporalInstantConstructor.cpp 117 runtime/TemporalInstantPrototype.cpp 116 118 runtime/TemporalNow.cpp 117 119 runtime/TemporalObject.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r285173 r285178 1 2021-11-02 Philip Chimento <pchimento@igalia.com> 2 3 [JSC] Implement Temporal.Instant 4 https://bugs.webkit.org/show_bug.cgi?id=229826 5 6 Reviewed by Yusuke Suzuki. 7 8 * CMakeLists.txt: 9 * DerivedSources-input.xcfilelist: 10 * DerivedSources-output.xcfilelist: 11 * DerivedSources.make: 12 * JavaScriptCore.xcodeproj/project.pbxproj: 13 * Sources.txt: 14 * runtime/ISO8601.cpp: 15 (JSC::ISO8601::parseInstant): Add a parsing function for Instant strings 16 reusing as much as possible from the other parsing functions. 17 (JSC::ISO8601::ExactTime::fromISOPartsAndOffset): Static method for 18 creating from ISO calendar components and UTC offset. 19 (JSC::ISO8601::checkedCastDoubleToInt128): Helper function for checking 20 whether a double can fit into an int128 without overflow. 21 (JSC::ISO8601::ExactTime::add const): 22 (JSC::ISO8601::ExactTime::round): 23 (JSC::ISO8601::ExactTime::difference const): 24 (JSC::ISO8601::ExactTime::round const): 25 * runtime/ISO8601.h: 26 (JSC::ISO8601::ExactTime::ExactTime): Add an ExactTime type that wraps 27 an Int128 and can do the basic operations. This type can be reused in 28 Temporal.ZonedDateTime. 29 (JSC::ISO8601::ExactTime::fromEpochSeconds): 30 (JSC::ISO8601::ExactTime::fromEpochMilliseconds): 31 (JSC::ISO8601::ExactTime::fromEpochMicroseconds): 32 (JSC::ISO8601::ExactTime::epochSeconds const): 33 (JSC::ISO8601::ExactTime::epochMilliseconds const): 34 (JSC::ISO8601::ExactTime::epochMicroseconds const): 35 (JSC::ISO8601::ExactTime::epochNanoseconds const): 36 (JSC::ISO8601::ExactTime::nanosecondsFraction const): 37 (JSC::ISO8601::ExactTime::asString const): 38 (JSC::ISO8601::ExactTime::isValid const): 39 (JSC::ISO8601::ExactTime::operator< const): 40 (JSC::ISO8601::ExactTime::operator<= const): 41 (JSC::ISO8601::ExactTime::operator== const): 42 (JSC::ISO8601::ExactTime::operator!= const): 43 (JSC::ISO8601::ExactTime::operator>= const): 44 (JSC::ISO8601::ExactTime::operator> const): 45 * runtime/IntlDateTimeFormat.h: 46 * runtime/IntlDateTimeFormatPrototype.cpp: 47 (JSC::IntlDateTimeFormat::handleDateTimeValue): Add a minimal 48 implementation of the HandleDateTimeValue abstract op from the 49 Temporal specification, only covering Temporal.Instant. 50 (JSC::JSC_DEFINE_HOST_FUNCTION): Use it in the existing 51 Intl.DateTimeFormat methods. 52 * runtime/JSBigInt.cpp: 53 (JSC::JSBigInt::createFrom): Add an overload that takes an Int128. 54 * runtime/JSBigInt.h: Remove declaration for nonexistent toUint64Heap(). 55 * runtime/JSDateMath.cpp: Move timeToMS() into WTF. 56 * runtime/JSGlobalObject.cpp: 57 (JSC::JSGlobalObject::init): 58 (JSC::JSGlobalObject::visitChildrenImpl): 59 * runtime/JSGlobalObject.h: 60 (JSC::JSGlobalObject::instantStructure): 61 * runtime/TemporalDuration.cpp: 62 (JSC::TemporalDuration::toLimitedDuration): Added. 63 * runtime/TemporalDuration.h: 64 * runtime/TemporalInstant.cpp: Added. 65 (JSC::TemporalInstant::createStructure): 66 (JSC::TemporalInstant::TemporalInstant): 67 (JSC::TemporalInstant::create): 68 (JSC::TemporalInstant::tryCreateIfValid): 69 (JSC::TemporalInstant::toInstant): 70 (JSC::TemporalInstant::from): 71 (JSC::TemporalInstant::fromEpochSeconds): 72 (JSC::TemporalInstant::fromEpochMilliseconds): 73 (JSC::TemporalInstant::fromEpochMicroseconds): 74 (JSC::TemporalInstant::fromEpochNanoseconds): 75 (JSC::TemporalInstant::compare): 76 * runtime/TemporalInstant.h: Added. 77 * runtime/TemporalInstantConstructor.cpp: Added. 78 (JSC::TemporalInstantConstructor::create): 79 (JSC::TemporalInstantConstructor::createStructure): 80 (JSC::TemporalInstantConstructor::TemporalInstantConstructor): 81 (JSC::TemporalInstantConstructor::finishCreation): 82 (JSC::JSC_DEFINE_HOST_FUNCTION): 83 * runtime/TemporalInstantConstructor.h: Added. 84 * runtime/TemporalInstantPrototype.cpp: Added. 85 (JSC::TemporalInstantPrototype::create): 86 (JSC::TemporalInstantPrototype::createStructure): 87 (JSC::TemporalInstantPrototype::TemporalInstantPrototype): 88 (JSC::TemporalInstantPrototype::finishCreation): 89 (JSC::JSC_DEFINE_HOST_FUNCTION): 90 (JSC::JSC_DEFINE_CUSTOM_GETTER): 91 * runtime/TemporalInstantPrototype.h: Added. 92 * runtime/TemporalObject.cpp: 93 (JSC::createInstantConstructor): Added. 94 (JSC::formatSecondsStringPart): Added. 95 (JSC::abs): Added for clarity. 96 (JSC::roundNumberToIncrement): Add overload for Int128. 97 * runtime/TemporalObject.h: 98 * runtime/VM.cpp: 99 * runtime/VM.h: 100 1 101 2021-11-02 Ross Kirsling <ross.kirsling@sony.com> 2 102 -
trunk/Source/JavaScriptCore/DerivedSources-input.xcfilelist
r284460 r285178 176 176 $(PROJECT_DIR)/runtime/TemporalDurationConstructor.cpp 177 177 $(PROJECT_DIR)/runtime/TemporalDurationPrototype.cpp 178 $(PROJECT_DIR)/runtime/TemporalInstantConstructor.cpp 179 $(PROJECT_DIR)/runtime/TemporalInstantPrototype.cpp 178 180 $(PROJECT_DIR)/runtime/TemporalNow.cpp 179 181 $(PROJECT_DIR)/runtime/TemporalObject.cpp -
trunk/Source/JavaScriptCore/DerivedSources-output.xcfilelist
r284435 r285178 73 73 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalDurationConstructor.lut.h 74 74 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalDurationPrototype.lut.h 75 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalInstantConstructor.lut.h 76 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalInstantPrototype.lut.h 75 77 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalNow.lut.h 76 78 $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalObject.lut.h -
trunk/Source/JavaScriptCore/DerivedSources.make
r284507 r285178 201 201 TemporalDurationConstructor.lut.h \ 202 202 TemporalDurationPrototype.lut.h \ 203 TemporalInstantConstructor.lut.h \ 204 TemporalInstantPrototype.lut.h \ 203 205 TemporalNow.lut.h \ 204 206 TemporalObject.lut.h \ -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r284781 r285178 1975 1975 E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC15112EF272200184A1F /* SourceProviderCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1976 1976 E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1977 F6D67D4026F902E9006E0349 /* TemporalInstant.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D67D3A26F902E5006E0349 /* TemporalInstant.h */; }; 1978 F6D67D4226F902E9006E0349 /* TemporalInstantConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D67D3C26F902E7006E0349 /* TemporalInstantConstructor.h */; }; 1979 F6D67D4426F902E9006E0349 /* TemporalInstantPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D67D3E26F902E8006E0349 /* TemporalInstantPrototype.h */; }; 1980 F6D67D4726F9130C006E0349 /* TemporalInstantConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D67D4526F9130A006E0349 /* TemporalInstantConstructor.lut.h */; }; 1981 F6D67D4826F9130C006E0349 /* TemporalInstantPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = F6D67D4626F9130B006E0349 /* TemporalInstantPrototype.lut.h */; }; 1977 1982 F6F150212693D450004B98EF /* TemporalObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = F6F150202693D450004B98EF /* TemporalObject.lut.h */; }; 1978 1983 FE041553252EC0730091EB5D /* SlotVisitorMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = FE041552252EC0730091EB5D /* SlotVisitorMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 5371 5376 F692A87E0255597D01FF60F7 /* RegExp.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = RegExp.h; sourceTree = "<group>"; tabWidth = 8; }; 5372 5377 F692A8870255597D01FF60F7 /* JSCJSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCJSValue.cpp; sourceTree = "<group>"; tabWidth = 8; }; 5378 F6D67D3926F902E5006E0349 /* TemporalInstant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalInstant.cpp; sourceTree = "<group>"; }; 5379 F6D67D3A26F902E5006E0349 /* TemporalInstant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalInstant.h; sourceTree = "<group>"; }; 5380 F6D67D3B26F902E6006E0349 /* TemporalInstantConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalInstantConstructor.cpp; sourceTree = "<group>"; }; 5381 F6D67D3C26F902E7006E0349 /* TemporalInstantConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalInstantConstructor.h; sourceTree = "<group>"; }; 5382 F6D67D3D26F902E7006E0349 /* TemporalInstantPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalInstantPrototype.cpp; sourceTree = "<group>"; }; 5383 F6D67D3E26F902E8006E0349 /* TemporalInstantPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalInstantPrototype.h; sourceTree = "<group>"; }; 5384 F6D67D4526F9130A006E0349 /* TemporalInstantConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalInstantConstructor.lut.h; sourceTree = "<group>"; }; 5385 F6D67D4626F9130B006E0349 /* TemporalInstantPrototype.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalInstantPrototype.lut.h; sourceTree = "<group>"; }; 5373 5386 F6F150182693D33D004B98EF /* TemporalNow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalNow.h; sourceTree = "<group>"; }; 5374 5387 F6F150192693D33E004B98EF /* TemporalObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalObject.cpp; sourceTree = "<group>"; }; … … 7105 7118 E3C4630526DB5DE900896336 /* TemporalCalendarConstructor.lut.h */, 7106 7119 E3C4630626DB5DE900896336 /* TemporalCalendarPrototype.lut.h */, 7120 F6D67D4526F9130A006E0349 /* TemporalInstantConstructor.lut.h */, 7121 F6D67D4626F9130B006E0349 /* TemporalInstantPrototype.lut.h */, 7107 7122 F6F150202693D450004B98EF /* TemporalObject.lut.h */, 7108 7123 533B15DE1DC7F463004D500A /* WasmOps.h */, … … 8074 8089 A3C7EDB526B0DB37004C34C5 /* TemporalDurationPrototype.cpp */, 8075 8090 A3C7EDB026B0DB36004C34C5 /* TemporalDurationPrototype.h */, 8091 F6D67D3926F902E5006E0349 /* TemporalInstant.cpp */, 8092 F6D67D3A26F902E5006E0349 /* TemporalInstant.h */, 8093 F6D67D3B26F902E6006E0349 /* TemporalInstantConstructor.cpp */, 8094 F6D67D3C26F902E7006E0349 /* TemporalInstantConstructor.h */, 8095 F6D67D3D26F902E7006E0349 /* TemporalInstantPrototype.cpp */, 8096 F6D67D3E26F902E8006E0349 /* TemporalInstantPrototype.h */, 8076 8097 F6F1501B2693D33E004B98EF /* TemporalNow.cpp */, 8077 8098 F6F150182693D33D004B98EF /* TemporalNow.h */, … … 10817 10838 A3C7EDBA26B0DB38004C34C5 /* TemporalDurationConstructor.h in Headers */, 10818 10839 A3C7EDB626B0DB38004C34C5 /* TemporalDurationPrototype.h in Headers */, 10840 F6D67D4026F902E9006E0349 /* TemporalInstant.h in Headers */, 10841 F6D67D4226F902E9006E0349 /* TemporalInstantConstructor.h in Headers */, 10842 F6D67D4726F9130C006E0349 /* TemporalInstantConstructor.lut.h in Headers */, 10843 F6D67D4426F902E9006E0349 /* TemporalInstantPrototype.h in Headers */, 10844 F6D67D4826F9130C006E0349 /* TemporalInstantPrototype.lut.h in Headers */, 10819 10845 F6F150212693D450004B98EF /* TemporalObject.lut.h in Headers */, 10820 10846 E386FD7E26E867B800E4C28B /* TemporalPlainTime.h in Headers */, -
trunk/Source/JavaScriptCore/Sources.txt
r284781 r285178 1021 1021 runtime/TemporalDurationConstructor.cpp 1022 1022 runtime/TemporalDurationPrototype.cpp 1023 runtime/TemporalInstant.cpp 1024 runtime/TemporalInstantConstructor.cpp 1025 runtime/TemporalInstantPrototype.cpp 1023 1026 runtime/TemporalNow.cpp 1024 1027 runtime/TemporalObject.cpp -
trunk/Source/JavaScriptCore/runtime/ISO8601.cpp
r284075 r285178 30 30 #include "IntlObject.h" 31 31 #include "ParseInt.h" 32 #include <limits> 33 #include <wtf/CheckedArithmetic.h> 32 34 #include <wtf/DateMath.h> 33 35 #include <wtf/text/StringParsingBuffer.h> … … 878 880 } 879 881 882 std::optional<ExactTime> parseInstant(StringView string) 883 { 884 // https://tc39.es/proposal-temporal/#prod-TemporalInstantString 885 // TemporalInstantString : 886 // Date TimeZoneOffsetRequired 887 // Date DateTimeSeparator TimeSpec TimeZoneOffsetRequired 888 889 // https://tc39.es/proposal-temporal/#prod-TimeZoneOffsetRequired 890 // TimeZoneOffsetRequired : 891 // TimeZoneUTCOffset TimeZoneBracketedAnnotation_opt 892 893 return readCharactersForParsing(string, [](auto buffer) -> std::optional<ExactTime> { 894 auto datetime = parseDateTime(buffer); 895 if (!datetime) 896 return std::nullopt; 897 auto [date, maybeTime, maybeTimeZone] = datetime.value(); 898 if (!maybeTimeZone || (!maybeTimeZone->m_z && !maybeTimeZone->m_offset)) 899 return std::nullopt; 900 // FIXME: parse calendar annotation 901 if (!buffer.atEnd()) 902 return std::nullopt; 903 904 PlainTime time; 905 if (maybeTime) 906 time = maybeTime.value(); 907 908 int64_t offset = maybeTimeZone->m_z ? 0 : *maybeTimeZone->m_offset; 909 return { ExactTime::fromISOPartsAndOffset(date.year(), date.month(), date.day(), time.hour(), time.minute(), time.second(), time.millisecond(), time.microsecond(), time.nanosecond(), offset) }; 910 }); 911 } 912 880 913 // https://tc39.es/proposal-temporal/#sec-temporal-formattimezoneoffsetstring 881 914 String formatTimeZoneOffsetString(int64_t offset) … … 970 1003 } 971 1004 1005 ExactTime ExactTime::fromISOPartsAndOffset(int32_t y, uint8_t mon, uint8_t d, unsigned h, unsigned min, unsigned s, unsigned ms, unsigned micros, unsigned ns, int64_t offset) 1006 { 1007 ASSERT(y >= -999999 && y <= 999999); 1008 ASSERT(mon >= 1 && mon <= 12); 1009 ASSERT(d >= 1 && d <= 31); 1010 ASSERT(h <= 23); 1011 ASSERT(min <= 59); 1012 ASSERT(s <= 59); 1013 ASSERT(ms <= 999); 1014 ASSERT(micros <= 999); 1015 ASSERT(ns <= 999); 1016 1017 double dateDays = dateToDaysFrom1970(y, mon - 1, d); 1018 double timeMs = timeToMS(h, min, s, ms); 1019 double utcMs = dateDays * msPerDay + timeMs; 1020 Int128 utcNs = static_cast<Int128>(utcMs) * 1'000'000 + micros * 1000 + ns; 1021 return ExactTime { utcNs - offset }; 1022 } 1023 1024 using CheckedInt128 = Checked<Int128, RecordOverflow>; 1025 1026 static CheckedInt128 checkedCastDoubleToInt128(double n) 1027 { 1028 // Based on __fixdfti() and __fixunsdfti() from compiler_rt: 1029 // https://github.com/llvm/llvm-project/blob/f3671de5500ff1f8210419226a9603a7d83b1a31/compiler-rt/lib/builtins/fp_fixint_impl.inc 1030 // https://github.com/llvm/llvm-project/blob/f3671de5500ff1f8210419226a9603a7d83b1a31/compiler-rt/lib/builtins/fp_fixuint_impl.inc 1031 1032 static constexpr int significandBits = std::numeric_limits<double>::digits - 1; 1033 static constexpr int exponentBits = std::numeric_limits<uint64_t>::digits - std::numeric_limits<double>::digits; 1034 static constexpr int exponentBias = std::numeric_limits<double>::max_exponent - 1; 1035 static constexpr uint64_t implicitBit = uint64_t { 1 } << significandBits; 1036 static constexpr uint64_t significandMask = implicitBit - uint64_t { 1 }; 1037 static constexpr uint64_t signMask = uint64_t { 1 } << (significandBits + exponentBits); 1038 static constexpr uint64_t absMask = signMask - uint64_t { 1 }; 1039 1040 // Break n into sign, exponent, significand parts. 1041 const uint64_t bits = *reinterpret_cast<uint64_t*>(&n); 1042 const uint64_t nAbs = bits & absMask; 1043 const int sign = bits & signMask ? -1 : 1; 1044 const int exponent = (nAbs >> significandBits) - exponentBias; 1045 const uint64_t significand = (nAbs & significandMask) | implicitBit; 1046 1047 // If exponent is negative, the result is zero. 1048 if (exponent < 0) 1049 return { 0 }; 1050 1051 // If the value is too large for the integer type, overflow. 1052 if (exponent >= 128) 1053 return { WTF::ResultOverflowed }; 1054 1055 // If 0 <= exponent < significandBits, right shift to get the result. 1056 // Otherwise, shift left. 1057 Int128 result { significand }; 1058 if (exponent < significandBits) 1059 result >>= significandBits - exponent; 1060 else 1061 result <<= exponent - significandBits; 1062 result *= sign; 1063 return { result }; 1064 } 1065 1066 std::optional<ExactTime> ExactTime::add(Duration duration) const 1067 { 1068 ASSERT(!duration.years()); 1069 ASSERT(!duration.months()); 1070 ASSERT(!duration.weeks()); 1071 ASSERT(!duration.days()); 1072 1073 CheckedInt128 resultNs { m_epochNanoseconds }; 1074 1075 // The duration's hours, minutes, seconds, and milliseconds should be 1076 // able to be cast into a 64-bit int. 2*1e8 24-hour days is the maximum 1077 // time span for exact time, so if we already know that the duration exceeds 1078 // that, then we can bail out. 1079 1080 CheckedInt128 hours = checkedCastDoubleToInt128(duration.hours()); 1081 resultNs += hours * ExactTime::nsPerHour; 1082 CheckedInt128 minutes = checkedCastDoubleToInt128(duration.minutes()); 1083 resultNs += minutes * ExactTime::nsPerMinute; 1084 CheckedInt128 seconds = checkedCastDoubleToInt128(duration.seconds()); 1085 resultNs += seconds * ExactTime::nsPerSecond; 1086 CheckedInt128 milliseconds = checkedCastDoubleToInt128(duration.milliseconds()); 1087 resultNs += milliseconds * ExactTime::nsPerMillisecond; 1088 CheckedInt128 microseconds = checkedCastDoubleToInt128(duration.microseconds()); 1089 resultNs += microseconds * ExactTime::nsPerMicrosecond; 1090 resultNs += checkedCastDoubleToInt128(duration.nanoseconds()); 1091 if (resultNs.hasOverflowed()) 1092 return std::nullopt; 1093 1094 ExactTime result { resultNs.value() }; 1095 if (!result.isValid()) 1096 return std::nullopt; 1097 return result; 1098 } 1099 1100 Int128 ExactTime::round(Int128 quantity, unsigned increment, TemporalUnit unit, RoundingMode roundingMode) 1101 { 1102 Int128 incrementNs { increment }; 1103 switch (unit) { 1104 case TemporalUnit::Hour: incrementNs *= ExactTime::nsPerHour; break; 1105 case TemporalUnit::Minute: incrementNs *= ExactTime::nsPerMinute; break; 1106 case TemporalUnit::Second: incrementNs *= ExactTime::nsPerSecond; break; 1107 case TemporalUnit::Millisecond: incrementNs *= ExactTime::nsPerMillisecond; break; 1108 case TemporalUnit::Microsecond: incrementNs *= ExactTime::nsPerMicrosecond; break; 1109 case TemporalUnit::Nanosecond: break; 1110 default: 1111 ASSERT_NOT_REACHED(); 1112 } 1113 return roundNumberToIncrement(quantity, incrementNs, roundingMode); 1114 } 1115 1116 // DifferenceInstant ( ns1, ns2, roundingIncrement, smallestUnit, roundingMode ) 1117 // https://tc39.es/proposal-temporal/#sec-temporal-differenceinstant 1118 Int128 ExactTime::difference(ExactTime other, unsigned increment, TemporalUnit unit, RoundingMode roundingMode) const 1119 { 1120 Int128 diff = other.m_epochNanoseconds - m_epochNanoseconds; 1121 return round(diff, increment, unit, roundingMode); 1122 } 1123 1124 ExactTime ExactTime::round(unsigned increment, TemporalUnit unit, RoundingMode roundingMode) const 1125 { 1126 return ExactTime { round(m_epochNanoseconds, increment, unit, roundingMode) }; 1127 } 1128 972 1129 } // namespace ISO8601 973 1130 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/ISO8601.h
r284075 r285178 29 29 #include "IntlObject.h" 30 30 #include "TemporalObject.h" 31 #include <wtf/Int128.h> 31 32 32 33 namespace JSC { … … 80 81 }; 81 82 83 class ExactTime { 84 WTF_MAKE_FAST_ALLOCATED(ExactTime); 85 public: 86 constexpr ExactTime() = default; 87 constexpr ExactTime(const ExactTime&) = default; 88 constexpr explicit ExactTime(Int128 epochNanoseconds) : m_epochNanoseconds(epochNanoseconds) { } 89 90 static constexpr ExactTime fromEpochSeconds(int64_t epochSeconds) 91 { 92 return ExactTime(Int128 { epochSeconds } * ExactTime::nsPerSecond); 93 } 94 static constexpr ExactTime fromEpochMilliseconds(int64_t epochMilliseconds) 95 { 96 return ExactTime(Int128 { epochMilliseconds } * ExactTime::nsPerMillisecond); 97 } 98 static constexpr ExactTime fromEpochMicroseconds(int64_t epochMicroseconds) 99 { 100 return ExactTime(Int128 { epochMicroseconds } * ExactTime::nsPerMicrosecond); 101 } 102 static ExactTime fromISOPartsAndOffset(int32_t y, uint8_t mon, uint8_t d, unsigned h, unsigned min, unsigned s, unsigned ms, unsigned micros, unsigned ns, int64_t offset); 103 104 int64_t epochSeconds() const 105 { 106 ASSERT(isValid()); 107 return static_cast<int64_t>(m_epochNanoseconds / ExactTime::nsPerSecond); 108 } 109 int64_t epochMilliseconds() const 110 { 111 ASSERT(isValid()); 112 return static_cast<int64_t>(m_epochNanoseconds / ExactTime::nsPerMillisecond); 113 } 114 int64_t epochMicroseconds() const 115 { 116 ASSERT(isValid()); 117 return static_cast<int64_t>(m_epochNanoseconds / ExactTime::nsPerMicrosecond); 118 } 119 constexpr Int128 epochNanoseconds() const 120 { 121 ASSERT(isValid()); 122 return m_epochNanoseconds; 123 } 124 125 int nanosecondsFraction() const 126 { 127 return static_cast<int>(m_epochNanoseconds % ExactTime::nsPerSecond); 128 } 129 130 String asString() const 131 { 132 StringBuilder builder; 133 if (m_epochNanoseconds < 0) { 134 builder.append('-'); 135 asStringImpl(builder, -m_epochNanoseconds); 136 } else 137 asStringImpl(builder, m_epochNanoseconds); 138 return builder.toString(); 139 } 140 141 // IsValidEpochNanoseconds ( epochNanoseconds ) 142 // https://tc39.es/proposal-temporal/#sec-temporal-isvalidepochnanoseconds 143 constexpr bool isValid() const 144 { 145 return m_epochNanoseconds >= ExactTime::minValue && m_epochNanoseconds <= ExactTime::maxValue; 146 } 147 148 constexpr bool operator<(ExactTime other) const 149 { 150 return m_epochNanoseconds < other.m_epochNanoseconds; 151 } 152 constexpr bool operator<=(ExactTime other) const 153 { 154 return m_epochNanoseconds <= other.m_epochNanoseconds; 155 } 156 constexpr bool operator==(ExactTime other) const 157 { 158 return m_epochNanoseconds == other.m_epochNanoseconds; 159 } 160 constexpr bool operator!=(ExactTime other) const 161 { 162 return m_epochNanoseconds != other.m_epochNanoseconds; 163 } 164 constexpr bool operator>=(ExactTime other) const 165 { 166 return m_epochNanoseconds >= other.m_epochNanoseconds; 167 } 168 constexpr bool operator>(ExactTime other) const 169 { 170 return m_epochNanoseconds > other.m_epochNanoseconds; 171 } 172 173 std::optional<ExactTime> add(Duration) const; 174 Int128 difference(ExactTime other, unsigned increment, TemporalUnit, RoundingMode) const; 175 ExactTime round(unsigned increment, TemporalUnit, RoundingMode) const; 176 177 private: 178 static constexpr Int128 dayRangeSeconds { 86400'00000000 }; // 1e8 days 179 static constexpr Int128 nsPerMicrosecond { 1000 }; 180 static constexpr Int128 nsPerMillisecond { 1'000'000 }; 181 static constexpr Int128 nsPerSecond { 1'000'000'000 }; 182 static constexpr Int128 nsPerMinute = nsPerSecond * 60; 183 static constexpr Int128 nsPerHour = nsPerMinute * 60; 184 static constexpr Int128 minValue = -dayRangeSeconds * nsPerSecond; 185 static constexpr Int128 maxValue = dayRangeSeconds * nsPerSecond; 186 187 static void asStringImpl(StringBuilder& builder, Int128 value) 188 { 189 if (value > 9) 190 asStringImpl(builder, value / 10); 191 builder.append(static_cast<uint64_t>(value % 10) + '0'); 192 } 193 194 static Int128 round(Int128 quantity, unsigned increment, TemporalUnit, RoundingMode); 195 196 Int128 m_epochNanoseconds { }; 197 }; 198 82 199 class PlainTime { 83 200 WTF_MAKE_FAST_ALLOCATED(PlainTime); … … 169 286 bool isValidDuration(const Duration&); 170 287 288 std::optional<ExactTime> parseInstant(StringView); 289 171 290 } // namespace ISO8601 172 291 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h
r283445 r285178 95 95 UDateIntervalFormat* createDateIntervalFormatIfNecessary(JSGlobalObject*); 96 96 97 static double handleDateTimeValue(JSGlobalObject*, JSValue); 98 97 99 enum class Weekday : uint8_t { None, Narrow, Short, Long }; 98 100 enum class Era : uint8_t { None, Narrow, Short, Long }; -
trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp
r281790 r285178 33 33 #include "JSBoundFunction.h" 34 34 #include "JSCInlines.h" 35 #include "TemporalInstant.h" 35 36 #include <wtf/DateMath.h> 36 37 … … 91 92 } 92 93 94 // HandleDateTimeValue ( dateTimeFormat, x ) 95 // https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevalue 96 double IntlDateTimeFormat::handleDateTimeValue(JSGlobalObject* globalObject, JSValue x) 97 { 98 VM& vm = globalObject->vm(); 99 auto scope = DECLARE_THROW_SCOPE(vm); 100 101 if (x.isUndefined()) 102 RELEASE_AND_RETURN(scope, dateNowImpl().toNumber(globalObject)); 103 104 // FIXME: 105 // - Add all of the other Temporal types 106 // - Work in epoch nanoseconds 107 // - Return UDateFormat and UDateIntervalFormat depending on the type 108 TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, x); 109 if (instant) 110 return instant->exactTime().epochMilliseconds(); 111 112 RELEASE_AND_RETURN(scope, WTF::timeClip(x.toNumber(globalObject))); 113 } 114 93 115 JSC_DEFINE_HOST_FUNCTION(intlDateTimeFormatFuncFormatDateTime, (JSGlobalObject* globalObject, CallFrame* callFrame)) 94 116 { … … 101 123 102 124 JSValue date = callFrame->argument(0); 103 double value; 104 105 if (date.isUndefined()) 106 value = dateNowImpl().toNumber(globalObject); 107 else { 108 value = WTF::timeClip(date.toNumber(globalObject)); 109 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 110 } 125 double value = IntlDateTimeFormat::handleDateTimeValue(globalObject, date); 126 RETURN_IF_EXCEPTION(scope, { }); 111 127 112 128 RELEASE_AND_RETURN(scope, JSValue::encode(format->format(globalObject, value))); … … 157 173 158 174 JSValue date = callFrame->argument(0); 159 double value; 160 161 if (date.isUndefined()) 162 value = dateNowImpl().toNumber(globalObject); 163 else { 164 value = WTF::timeClip(date.toNumber(globalObject)); 165 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 166 } 175 double value = IntlDateTimeFormat::handleDateTimeValue(globalObject, date); 176 RETURN_IF_EXCEPTION(scope, { }); 167 177 168 178 RELEASE_AND_RETURN(scope, JSValue::encode(dateTimeFormat->formatToParts(globalObject, value))); … … 186 196 return throwVMTypeError(globalObject, scope, "startDate or endDate is undefined"_s); 187 197 188 double startDate = startDateValue.toNumber(globalObject);189 RETURN_IF_EXCEPTION(scope, { }); 190 double endDate = endDateValue.toNumber(globalObject);198 double startDate = IntlDateTimeFormat::handleDateTimeValue(globalObject, startDateValue); 199 RETURN_IF_EXCEPTION(scope, { }); 200 double endDate = IntlDateTimeFormat::handleDateTimeValue(globalObject, endDateValue); 191 201 RETURN_IF_EXCEPTION(scope, { }); 192 202 if (startDate > endDate) … … 213 223 return throwVMTypeError(globalObject, scope, "startDate or endDate is undefined"_s); 214 224 215 double startDate = startDateValue.toNumber(globalObject);216 RETURN_IF_EXCEPTION(scope, { }); 217 double endDate = endDateValue.toNumber(globalObject);225 double startDate = IntlDateTimeFormat::handleDateTimeValue(globalObject, startDateValue); 226 RETURN_IF_EXCEPTION(scope, { }); 227 double endDate = IntlDateTimeFormat::handleDateTimeValue(globalObject, endDateValue); 218 228 RETURN_IF_EXCEPTION(scope, { }); 219 229 if (startDate > endDate) -
trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp
r278338 r285178 56 56 #include <algorithm> 57 57 #include <wtf/Hasher.h> 58 #include <wtf/Int128.h> 58 59 #include <wtf/MathExtras.h> 59 60 … … 230 231 unsignedValue = value; 231 232 return createFromImpl(globalObject, unsignedValue, sign); 233 } 234 235 JSBigInt* JSBigInt::createFrom(JSGlobalObject* globalObject, Int128 value) 236 { 237 VM& vm = globalObject->vm(); 238 auto scope = DECLARE_THROW_SCOPE(vm); 239 240 if (!value) 241 RELEASE_AND_RETURN(scope, createZero(globalObject)); 242 243 UInt128 unsignedValue; 244 bool sign = false; 245 if (value < 0) { 246 unsignedValue = static_cast<UInt128>(-(value + 1)) + 1; 247 sign = true; 248 } else 249 unsignedValue = value; 250 251 if (unsignedValue <= UINT64_MAX) 252 RELEASE_AND_RETURN(scope, createFromImpl(globalObject, static_cast<uint64_t>(unsignedValue), sign)); 253 254 if constexpr (sizeof(Digit) == 8) { 255 JSBigInt* bigInt = createWithLength(globalObject, 2); 256 RETURN_IF_EXCEPTION(scope, nullptr); 257 258 Digit lowBits = static_cast<Digit>(static_cast<uint64_t>(unsignedValue)); 259 Digit highBits = static_cast<Digit>(static_cast<uint64_t>(unsignedValue >> 64)); 260 261 ASSERT(highBits); 262 263 bigInt->setDigit(0, lowBits); 264 bigInt->setDigit(1, highBits); 265 bigInt->setSign(sign); 266 return bigInt; 267 } 268 269 ASSERT(sizeof(Digit) == 4); 270 271 Digit digit0 = static_cast<Digit>(static_cast<uint64_t>(unsignedValue)); 272 Digit digit1 = static_cast<Digit>(static_cast<uint64_t>(unsignedValue >> 32)); 273 Digit digit2 = static_cast<Digit>(static_cast<uint64_t>(unsignedValue >> 64)); 274 Digit digit3 = static_cast<Digit>(static_cast<uint64_t>(unsignedValue >> 96)); 275 276 ASSERT(digit2 || digit3); 277 278 int length = digit3 ? 4 : 3; 279 JSBigInt* bigInt = createWithLength(globalObject, length); 280 RETURN_IF_EXCEPTION(scope, nullptr); 281 282 bigInt->setDigit(0, digit0); 283 bigInt->setDigit(1, digit1); 284 bigInt->setDigit(2, digit2); 285 if (digit3) 286 bigInt->setDigit(3, digit3); 287 bigInt->setSign(sign); 288 return bigInt; 232 289 } 233 290 -
trunk/Source/JavaScriptCore/runtime/JSBigInt.h
r278253 r285178 34 34 #include "MathCommon.h" 35 35 #include <wtf/CagedUniquePtr.h> 36 #include <wtf/Int128.h> 36 37 #include <wtf/text/StringBuilder.h> 37 38 #include <wtf/text/StringView.h> … … 75 76 JS_EXPORT_PRIVATE static JSBigInt* createFrom(JSGlobalObject*, int64_t value); 76 77 JS_EXPORT_PRIVATE static JSBigInt* createFrom(JSGlobalObject*, uint64_t value); 78 JS_EXPORT_PRIVATE static JSBigInt* createFrom(JSGlobalObject*, Int128 value); 77 79 static JSBigInt* createFrom(JSGlobalObject*, bool value); 78 80 static JSBigInt* createFrom(JSGlobalObject*, double value); … … 606 608 JS_EXPORT_PRIVATE static uint64_t toBigUInt64Heap(JSBigInt*); 607 609 608 JS_EXPORT_PRIVATE static std::optional<uint64_t> toUint64Heap(JSBigInt*);609 610 610 inline static size_t offsetOfData() 611 611 { -
trunk/Source/JavaScriptCore/runtime/JSDateMath.cpp
r279962 r285178 270 270 } 271 271 272 static inline double timeToMS(double hour, double min, double sec, double ms)273 {274 return (((hour * WTF::minutesPerHour + min) * WTF::secondsPerMinute + sec) * WTF::msPerSecond + ms);275 }276 277 272 double DateCache::gregorianDateTimeToMS(const GregorianDateTime& t, double milliseconds, WTF::TimeType inputTimeType) 278 273 { -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r284576 r285178 211 211 #include "TemporalDuration.h" 212 212 #include "TemporalDurationPrototype.h" 213 #include "TemporalInstant.h" 214 #include "TemporalInstantPrototype.h" 213 215 #include "TemporalObject.h" 214 216 #include "TemporalPlainTime.h" … … 1253 1255 TemporalDurationPrototype* durationPrototype = TemporalDurationPrototype::create(init.vm, TemporalDurationPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype())); 1254 1256 init.set(TemporalDuration::createStructure(init.vm, globalObject, durationPrototype)); 1257 }); 1258 1259 m_instantStructure.initLater( 1260 [] (const Initializer<Structure>& init) { 1261 JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner); 1262 TemporalInstantPrototype* instantPrototype = TemporalInstantPrototype::create(init.vm, TemporalInstantPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype())); 1263 init.set(TemporalInstant::createStructure(init.vm, globalObject, instantPrototype)); 1255 1264 }); 1256 1265 … … 2167 2176 thisObject->m_calendarStructure.visit(visitor); 2168 2177 thisObject->m_durationStructure.visit(visitor); 2178 thisObject->m_instantStructure.visit(visitor); 2169 2179 thisObject->m_plainTimeStructure.visit(visitor); 2170 2180 thisObject->m_timeZoneStructure.visit(visitor); -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r284590 r285178 335 335 LazyProperty<JSGlobalObject, Structure> m_calendarStructure; 336 336 LazyProperty<JSGlobalObject, Structure> m_durationStructure; 337 LazyProperty<JSGlobalObject, Structure> m_instantStructure; 337 338 LazyProperty<JSGlobalObject, Structure> m_plainTimeStructure; 338 339 LazyProperty<JSGlobalObject, Structure> m_timeZoneStructure; … … 893 894 Structure* calendarStructure() { return m_calendarStructure.get(this); } 894 895 Structure* durationStructure() { return m_durationStructure.get(this); } 896 Structure* instantStructure() { return m_instantStructure.get(this); } 895 897 Structure* plainTimeStructure() { return m_plainTimeStructure.get(this); } 896 898 Structure* timeZoneStructure() { return m_timeZoneStructure.get(this); } -
trunk/Source/JavaScriptCore/runtime/TemporalDuration.cpp
r283705 r285178 31 31 #include "TemporalObject.h" 32 32 #include <wtf/text/StringBuilder.h> 33 #include <wtf/text/StringConcatenate.h> 33 34 34 35 namespace JSC { … … 163 164 164 165 return TemporalDuration::create(vm, globalObject->durationStructure(), WTFMove(result)); 166 } 167 168 // ToLimitedTemporalDuration ( temporalDurationLike, disallowedFields ) 169 // https://tc39.es/proposal-temporal/#sec-temporal-tolimitedtemporalduration 170 ISO8601::Duration TemporalDuration::toLimitedDuration(JSGlobalObject* globalObject, JSValue itemValue, std::initializer_list<TemporalUnit> disallowedUnits) 171 { 172 VM& vm = globalObject->vm(); 173 auto scope = DECLARE_THROW_SCOPE(vm); 174 175 ISO8601::Duration duration = toISO8601Duration(globalObject, itemValue); 176 RETURN_IF_EXCEPTION(scope, { }); 177 178 if (!isValidDuration(duration)) { 179 throwRangeError(globalObject, scope, "Temporal.Duration properties must be finite and of consistent sign"_s); 180 return { }; 181 } 182 183 for (TemporalUnit unit : disallowedUnits) { 184 if (duration[unit]) { 185 throwRangeError(globalObject, scope, makeString("Adding "_s, temporalUnitPluralPropertyName(vm, unit).publicName(), " not supported by Temporal.Instant. Try Temporal.ZonedDateTime instead"_s)); 186 return { }; 187 } 188 } 189 190 return duration; 165 191 } 166 192 -
trunk/Source/JavaScriptCore/runtime/TemporalDuration.h
r282259 r285178 47 47 48 48 static TemporalDuration* toTemporalDuration(JSGlobalObject*, JSValue); 49 static ISO8601::Duration toLimitedDuration(JSGlobalObject*, JSValue, std::initializer_list<TemporalUnit> disallowedUnits); 49 50 static TemporalDuration* from(JSGlobalObject*, JSValue); 50 51 static JSValue compare(JSGlobalObject*, JSValue, JSValue); -
trunk/Source/JavaScriptCore/runtime/TemporalObject.cpp
r283705 r285178 33 33 #include "TemporalDurationConstructor.h" 34 34 #include "TemporalDurationPrototype.h" 35 #include "TemporalInstantConstructor.h" 36 #include "TemporalInstantPrototype.h" 35 37 #include "TemporalNow.h" 36 38 #include "TemporalPlainTimeConstructor.h" … … 38 40 #include "TemporalTimeZoneConstructor.h" 39 41 #include "TemporalTimeZonePrototype.h" 42 #include <wtf/Int128.h> 40 43 #include <wtf/text/StringConcatenate.h> 41 44 #include <wtf/unicode/CharacterNames.h> … … 64 67 JSGlobalObject* globalObject = temporalObject->globalObject(vm); 65 68 return TemporalDurationConstructor::create(vm, TemporalDurationConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<TemporalDurationPrototype*>(globalObject->durationStructure()->storedPrototypeObject())); 69 } 70 71 static JSValue createInstantConstructor(VM& vm, JSObject* object) 72 { 73 TemporalObject* temporalObject = jsCast<TemporalObject*>(object); 74 JSGlobalObject* globalObject = temporalObject->globalObject(vm); 75 return TemporalInstantConstructor::create(vm, TemporalInstantConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<TemporalInstantPrototype*>(globalObject->instantStructure()->storedPrototypeObject())); 66 76 } 67 77 … … 90 100 Calendar createCalendarConstructor DontEnum|PropertyCallback 91 101 Duration createDurationConstructor DontEnum|PropertyCallback 102 Instant createInstantConstructor DontEnum|PropertyCallback 92 103 Now createNowObject DontEnum|PropertyCallback 93 104 PlainTime createPlainTimeConstructor DontEnum|PropertyCallback … … 375 386 } 376 387 388 // FormatSecondsStringPart ( second, millisecond, microsecond, nanosecond, precision ) 389 // https://tc39.es/proposal-temporal/#sec-temporal-formatsecondsstringpart 390 void formatSecondsStringPart(StringBuilder& builder, unsigned second, unsigned fraction, PrecisionData precision) 391 { 392 if (precision.unit == TemporalUnit::Minute) 393 return; 394 395 builder.append(':', pad('0', 2, second)); 396 formatSecondsStringFraction(builder, fraction, precision.precision); 397 } 398 377 399 // MaximumTemporalDurationRoundingIncrement ( unit ) 378 400 // https://tc39.es/proposal-temporal/#sec-temporal-maximumtemporaldurationroundingincrement … … 436 458 } 437 459 460 static Int128 abs(Int128 x) 461 { 462 return x < 0 ? -x : x; 463 } 464 465 // Same as above, but with Int128 466 Int128 roundNumberToIncrement(Int128 x, Int128 increment, RoundingMode mode) 467 { 468 ASSERT(increment); 469 470 if (increment == 1) 471 return x; 472 473 Int128 quotient = x / increment; 474 Int128 remainder = x % increment; 475 if (!remainder) 476 return x; 477 478 bool sign = remainder < 0; 479 switch (mode) { 480 case RoundingMode::Ceil: 481 if (!sign) 482 quotient++; 483 break; 484 case RoundingMode::Floor: 485 if (sign) 486 quotient--; 487 break; 488 case RoundingMode::Trunc: 489 break; 490 case RoundingMode::HalfExpand: 491 // "half up away from zero" 492 if (abs(remainder * 2) >= increment) 493 quotient += sign ? -1 : 1; 494 break; 495 } 496 return quotient * increment; 497 } 498 438 499 TemporalOverflow toTemporalOverflow(JSGlobalObject* globalObject, JSObject* options) 439 500 { -
trunk/Source/JavaScriptCore/runtime/TemporalObject.h
r284213 r285178 23 23 #include "JSObject.h" 24 24 #include <variant> 25 #include <wtf/Int128.h> 25 26 26 27 namespace JSC { … … 106 107 RoundingMode temporalRoundingMode(JSGlobalObject*, JSObject*, RoundingMode); 107 108 void formatSecondsStringFraction(StringBuilder&, unsigned fraction, std::tuple<Precision, unsigned>); 109 void formatSecondsStringPart(StringBuilder&, unsigned second, unsigned fraction, PrecisionData); 108 110 std::optional<double> maximumRoundingIncrement(TemporalUnit); 109 111 double temporalRoundingIncrement(JSGlobalObject*, JSObject* options, std::optional<double> dividend, bool inclusive); 110 112 double roundNumberToIncrement(double, double increment, RoundingMode); 113 Int128 roundNumberToIncrement(Int128, Int128 increment, RoundingMode); 111 114 112 115 enum class TemporalOverflow : bool { -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r284435 r285178 168 168 #include "TemporalCalendar.h" 169 169 #include "TemporalDuration.h" 170 #include "TemporalInstant.h" 170 171 #include "TemporalPlainTime.h" 171 172 #include "TemporalTimeZone.h" … … 1598 1599 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalCalendarSpace, cellHeapCellType.get(), TemporalCalendar) 1599 1600 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalDurationSpace, cellHeapCellType.get(), TemporalDuration) 1601 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalInstantSpace, cellHeapCellType.get(), TemporalInstant) 1600 1602 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalPlainTimeSpace, cellHeapCellType.get(), TemporalPlainTime) 1601 1603 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalTimeZoneSpace, cellHeapCellType.get(), TemporalTimeZone) -
trunk/Source/JavaScriptCore/runtime/VM.h
r284435 r285178 188 188 class Symbol; 189 189 class TemporalDuration; 190 class TemporalInstant; 190 191 class TypedArrayController; 191 192 class UnlinkedCodeBlock; … … 602 603 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalCalendarSpace) 603 604 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalDurationSpace) 605 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalInstantSpace) 604 606 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalPlainTimeSpace) 605 607 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalTimeZoneSpace) -
trunk/Source/WTF/ChangeLog
r285159 r285178 1 2021-11-02 Philip Chimento <pchimento@igalia.com> 2 3 [JSC] Implement Temporal.Instant 4 https://bugs.webkit.org/show_bug.cgi?id=229826 5 6 Reviewed by Yusuke Suzuki. 7 8 * wtf/CheckedArithmetic.h: Don't use builtin operations if __int128 is 9 being emulated using WTF::Int128. Also work around Clang/Linux bug 10 where __builtin_mul_overflow() doesn't work on __int128. 11 See https://bugs.llvm.org/show_bug.cgi?id=16404 12 * wtf/DateMath.h: 13 (WTF::timeToMS): Moved from JSDateMath.h. 14 1 15 2021-11-02 Chris Dumez <cdumez@apple.com> 2 16 -
trunk/Source/WTF/wtf/CheckedArithmetic.h
r284330 r285178 292 292 { 293 293 #if COMPILER(GCC_COMPATIBLE) 294 ResultType temp; 295 if (__builtin_add_overflow(lhs, rhs, &temp)) 296 return false; 297 result = temp; 298 return true; 299 #else 294 #if !HAVE(INT128_T) 295 if constexpr (sizeof(LHS) <= sizeof(uint64_t) || sizeof(RHS) <= sizeof(uint64_t)) { 296 #endif 297 ResultType temp; 298 if (__builtin_add_overflow(lhs, rhs, &temp)) 299 return false; 300 result = temp; 301 return true; 302 #if !HAVE(INT128_T) 303 } 304 #endif 305 #endif 300 306 if (signsMatch(lhs, rhs)) { 301 307 if (lhs >= 0) { … … 310 316 result = lhs + rhs; 311 317 return true; 312 #endif313 318 } 314 319 … … 316 321 { 317 322 #if COMPILER(GCC_COMPATIBLE) 318 ResultType temp; 319 if (__builtin_sub_overflow(lhs, rhs, &temp)) 320 return false; 321 result = temp; 322 return true; 323 #else 323 #if !HAVE(INT128_T) 324 if constexpr (sizeof(LHS) <= sizeof(uint64_t) || sizeof(RHS) <= sizeof(uint64_t)) { 325 #endif 326 ResultType temp; 327 if (__builtin_sub_overflow(lhs, rhs, &temp)) 328 return false; 329 result = temp; 330 return true; 331 #if !HAVE(INT128_T) 332 } 333 #endif 334 #endif 324 335 if (!signsMatch(lhs, rhs)) { 325 336 if (lhs >= 0) { … … 333 344 result = lhs - rhs; 334 345 return true; 335 #endif336 346 } 337 347 … … 339 349 { 340 350 #if USE(MUL_OVERFLOW) 341 ResultType temp; 342 if (__builtin_mul_overflow(lhs, rhs, &temp)) 343 return false; 344 result = temp; 345 return true; 346 #else 351 // Don't use the builtin if the int128 type is WTF::[U]Int128Impl. 352 // Also don't use the builtin for __[u]int128_t on Clang/Linux. 353 // See https://bugs.llvm.org/show_bug.cgi?id=16404 354 #if !HAVE(INT128_T) || (COMPILER(CLANG) && OS(LINUX)) 355 if constexpr (sizeof(LHS) <= sizeof(uint64_t) || sizeof(RHS) <= sizeof(uint64_t)) { 356 #endif 357 ResultType temp; 358 if (__builtin_mul_overflow(lhs, rhs, &temp)) 359 return false; 360 result = temp; 361 return true; 362 #if !HAVE(INT128_T) || (COMPILER(CLANG) && OS(LINUX)) 363 } 364 #endif 365 #endif 347 366 if (signsMatch(lhs, rhs)) { 348 367 if (lhs >= 0) { … … 366 385 result = lhs * rhs; 367 386 return true; 368 #endif369 387 } 370 388 … … 386 404 static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN 387 405 { 406 ResultType temp; 388 407 #if COMPILER(GCC_COMPATIBLE) 408 #if !HAVE(INT128_T) 409 if constexpr (sizeof(LHS) <= sizeof(uint64_t) || sizeof(RHS) <= sizeof(uint64_t)) { 410 #endif 411 if (__builtin_add_overflow(lhs, rhs, &temp)) 412 return false; 413 result = temp; 414 return true; 415 #if !HAVE(INT128_T) 416 } 417 #endif 418 #endif 419 temp = lhs + rhs; 420 if (temp < lhs) 421 return false; 422 result = temp; 423 return true; 424 } 425 426 static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN 427 { 389 428 ResultType temp; 390 if (__builtin_add_overflow(lhs, rhs, &temp)) 429 #if COMPILER(GCC_COMPATIBLE) 430 #if !HAVE(INT128_T) 431 if constexpr (sizeof(LHS) <= sizeof(uint64_t) || sizeof(RHS) <= sizeof(uint64_t)) { 432 #endif 433 if (__builtin_sub_overflow(lhs, rhs, &temp)) 434 return false; 435 result = temp; 436 return true; 437 #if !HAVE(INT128_T) 438 } 439 #endif 440 #endif 441 temp = lhs - rhs; 442 if (temp > lhs) 391 443 return false; 392 444 result = temp; 393 445 return true; 394 #else395 ResultType temp = lhs + rhs;396 if (temp < lhs)397 return false;398 result = temp;399 return true;400 #endif401 }402 403 static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN404 {405 #if COMPILER(GCC_COMPATIBLE)406 ResultType temp;407 if (__builtin_sub_overflow(lhs, rhs, &temp))408 return false;409 result = temp;410 return true;411 #else412 ResultType temp = lhs - rhs;413 if (temp > lhs)414 return false;415 result = temp;416 return true;417 #endif418 446 } 419 447 … … 421 449 { 422 450 #if USE(MUL_OVERFLOW) 423 ResultType temp; 424 if (__builtin_mul_overflow(lhs, rhs, &temp)) 425 return false; 426 result = temp; 427 return true; 428 #else 451 // Don't use the builtin if the int128 type is WTF::Int128Impl. 452 // Also don't use the builtin for __int128_t on Clang/Linux. 453 // See https://bugs.llvm.org/show_bug.cgi?id=16404 454 #if !HAVE(INT128_T) || (COMPILER(CLANG) && OS(LINUX)) 455 if constexpr (sizeof(LHS) <= sizeof(uint64_t) || sizeof(RHS) <= sizeof(uint64_t)) { 456 #endif 457 ResultType temp; 458 if (__builtin_mul_overflow(lhs, rhs, &temp)) 459 return false; 460 result = temp; 461 return true; 462 #if !HAVE(INT128_T) || (COMPILER(CLANG) && OS(LINUX)) 463 } 464 #endif 465 #endif 429 466 if (!lhs || !rhs) { 430 467 result = 0; … … 435 472 result = lhs * rhs; 436 473 return true; 437 #endif438 474 } 439 475 -
trunk/Source/WTF/wtf/DateMath.h
r275109 r285178 389 389 } 390 390 391 inline double timeToMS(double hour, double min, double sec, double ms) 392 { 393 return (((hour * WTF::minutesPerHour + min) * WTF::secondsPerMinute + sec) * WTF::msPerSecond + ms); 394 } 395 391 396 // Returns combined offset in millisecond (UTC + DST). 392 397 WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime); … … 411 416 using WTF::secondsPerMinute; 412 417 using WTF::parseDateFromNullTerminatedCharacters; 418 using WTF::timeToMS; 413 419 using WTF::makeRFC2822DateString; 414 420 using WTF::LocalTimeOffset;
Note: See TracChangeset
for help on using the changeset viewer.