Changeset 285178 in webkit


Ignore:
Timestamp:
Nov 2, 2021 12:57:41 PM (9 months ago)
Author:
commit-queue@webkit.org
Message:

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

Patch by Philip Chimento <pchimento@igalia.com> on 2021-11-02
Reviewed by Yusuke Suzuki.

JSTests:

  • stress/temporal-instant.js: Added.

(shouldBe):
(shouldNotBe):
(shouldThrow):
(instants.forEach):
(shouldThrow.new.Temporal.Instant):
(const.maxValue.new.Temporal.Instant):
(shouldBe.epoch.subtract):

  • test262/config.yaml: No need to ignore all Temporal.Instant tests anymore, only the ones for the unimplemented methods.

Source/JavaScriptCore:

  • CMakeLists.txt:
  • DerivedSources-input.xcfilelist:
  • DerivedSources-output.xcfilelist:
  • DerivedSources.make:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • runtime/ISO8601.cpp:

(JSC::ISO8601::parseInstant): Add a parsing function for Instant strings

reusing as much as possible from the other parsing functions.

(JSC::ISO8601::ExactTime::fromISOPartsAndOffset): Static method for

creating from ISO calendar components and UTC offset.

(JSC::ISO8601::checkedCastDoubleToInt128): Helper function for checking

whether a double can fit into an int128 without overflow.

(JSC::ISO8601::ExactTime::add const):
(JSC::ISO8601::ExactTime::round):
(JSC::ISO8601::ExactTime::difference const):
(JSC::ISO8601::ExactTime::round const):

  • runtime/ISO8601.h:

(JSC::ISO8601::ExactTime::ExactTime): Add an ExactTime type that wraps

an Int128 and can do the basic operations. This type can be reused in
Temporal.ZonedDateTime.

(JSC::ISO8601::ExactTime::fromEpochSeconds):
(JSC::ISO8601::ExactTime::fromEpochMilliseconds):
(JSC::ISO8601::ExactTime::fromEpochMicroseconds):
(JSC::ISO8601::ExactTime::epochSeconds const):
(JSC::ISO8601::ExactTime::epochMilliseconds const):
(JSC::ISO8601::ExactTime::epochMicroseconds const):
(JSC::ISO8601::ExactTime::epochNanoseconds const):
(JSC::ISO8601::ExactTime::nanosecondsFraction const):
(JSC::ISO8601::ExactTime::asString const):
(JSC::ISO8601::ExactTime::isValid const):
(JSC::ISO8601::ExactTime::operator< const):
(JSC::ISO8601::ExactTime::operator<= const):
(JSC::ISO8601::ExactTime::operator== const):
(JSC::ISO8601::ExactTime::operator!= const):
(JSC::ISO8601::ExactTime::operator>= const):
(JSC::ISO8601::ExactTime::operator> const):

  • runtime/IntlDateTimeFormat.h:
  • runtime/IntlDateTimeFormatPrototype.cpp:

(JSC::IntlDateTimeFormat::handleDateTimeValue): Add a minimal

implementation of the HandleDateTimeValue abstract op from the
Temporal specification, only covering Temporal.Instant.

(JSC::JSC_DEFINE_HOST_FUNCTION): Use it in the existing

Intl.DateTimeFormat methods.

  • runtime/JSBigInt.cpp:

(JSC::JSBigInt::createFrom): Add an overload that takes an Int128.

  • runtime/JSBigInt.h: Remove declaration for nonexistent toUint64Heap().
  • runtime/JSDateMath.cpp: Move timeToMS() into WTF.
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildrenImpl):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::instantStructure):

  • runtime/TemporalDuration.cpp:

(JSC::TemporalDuration::toLimitedDuration): Added.

  • runtime/TemporalDuration.h:
  • runtime/TemporalInstant.cpp: Added.

(JSC::TemporalInstant::createStructure):
(JSC::TemporalInstant::TemporalInstant):
(JSC::TemporalInstant::create):
(JSC::TemporalInstant::tryCreateIfValid):
(JSC::TemporalInstant::toInstant):
(JSC::TemporalInstant::from):
(JSC::TemporalInstant::fromEpochSeconds):
(JSC::TemporalInstant::fromEpochMilliseconds):
(JSC::TemporalInstant::fromEpochMicroseconds):
(JSC::TemporalInstant::fromEpochNanoseconds):
(JSC::TemporalInstant::compare):

  • runtime/TemporalInstant.h: Added.
  • runtime/TemporalInstantConstructor.cpp: Added.

(JSC::TemporalInstantConstructor::create):
(JSC::TemporalInstantConstructor::createStructure):
(JSC::TemporalInstantConstructor::TemporalInstantConstructor):
(JSC::TemporalInstantConstructor::finishCreation):
(JSC::JSC_DEFINE_HOST_FUNCTION):

  • runtime/TemporalInstantConstructor.h: Added.
  • runtime/TemporalInstantPrototype.cpp: Added.

(JSC::TemporalInstantPrototype::create):
(JSC::TemporalInstantPrototype::createStructure):
(JSC::TemporalInstantPrototype::TemporalInstantPrototype):
(JSC::TemporalInstantPrototype::finishCreation):
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSC_DEFINE_CUSTOM_GETTER):

  • runtime/TemporalInstantPrototype.h: Added.
  • runtime/TemporalObject.cpp:

(JSC::createInstantConstructor): Added.
(JSC::formatSecondsStringPart): Added.
(JSC::abs): Added for clarity.
(JSC::roundNumberToIncrement): Add overload for Int128.

  • runtime/TemporalObject.h:
  • runtime/VM.cpp:
  • runtime/VM.h:

Source/WTF:

  • wtf/CheckedArithmetic.h: Don't use builtin operations if int128 is being emulated using WTF::Int128. Also work around Clang/Linux bug where builtin_mul_overflow() doesn't work on int128. See https://bugs.llvm.org/show_bug.cgi?id=16404
  • wtf/DateMath.h:

(WTF::timeToMS): Moved from JSDateMath.h.

Location:
trunk
Files:
7 added
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r285167 r285178  
     12021-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
    1192021-11-02  Saam Barati  <sbarati@apple.com>
    220
  • trunk/JSTests/test262/config.yaml

    r284435 r285178  
    2424  paths:
    2525    - 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
    2728    - test/built-ins/Temporal/Now
    2829    - test/built-ins/Temporal/PlainDate
     
    3536    - test/built-ins/Temporal/ZonedDateTime
    3637    - test/intl402/Temporal/Calendar
    37     - test/intl402/Temporal/Instant
     38    - test/intl402/Temporal/Instant/prototype/toZonedDateTime
     39    - test/intl402/Temporal/Instant/prototype/toZonedDateTimeISO
    3840    - test/intl402/Temporal/Now
    3941    - test/intl402/Temporal/PlainDate
     
    248250    - test/built-ins/Temporal/Duration/prototype/total/calendar-temporal-object.js
    249251    - test/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted.js
     252    - test/built-ins/Temporal/Instant/prototype/toString/smallestunit-plurals-accepted.js
    250253    - test/built-ins/Temporal/PlainTime/compare/calendar-temporal-object.js
    251254    - test/built-ins/Temporal/PlainTime/from/calendar-temporal-object.js
     
    272275    - test/built-ins/Temporal/Duration/prototype/subtract/order-of-operations.js
    273276    - 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
    274284
    275285    # Depends on Temporal.ZonedDateTime
     
    300310    - test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js
    301311    - 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
    302317    - test/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js
    303318    - test/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js
     
    335350    - test/built-ins/Temporal/Duration/prototype/round/round-negative-result.js
    336351    - test/built-ins/Temporal/Duration/prototype/subtract/balance-negative-result.js
     352    - test/built-ins/Temporal/Instant/prototype/until/instant-string.js
    337353    - test/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js
    338354    - test/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r284868 r285178  
    114114    runtime/TemporalDurationConstructor.cpp
    115115    runtime/TemporalDurationPrototype.cpp
     116    runtime/TemporalInstantConstructor.cpp
     117    runtime/TemporalInstantPrototype.cpp
    116118    runtime/TemporalNow.cpp
    117119    runtime/TemporalObject.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r285173 r285178  
     12021-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
    11012021-11-02  Ross Kirsling  <ross.kirsling@sony.com>
    2102
  • trunk/Source/JavaScriptCore/DerivedSources-input.xcfilelist

    r284460 r285178  
    176176$(PROJECT_DIR)/runtime/TemporalDurationConstructor.cpp
    177177$(PROJECT_DIR)/runtime/TemporalDurationPrototype.cpp
     178$(PROJECT_DIR)/runtime/TemporalInstantConstructor.cpp
     179$(PROJECT_DIR)/runtime/TemporalInstantPrototype.cpp
    178180$(PROJECT_DIR)/runtime/TemporalNow.cpp
    179181$(PROJECT_DIR)/runtime/TemporalObject.cpp
  • trunk/Source/JavaScriptCore/DerivedSources-output.xcfilelist

    r284435 r285178  
    7373$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalDurationConstructor.lut.h
    7474$(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
    7577$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalNow.lut.h
    7678$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/TemporalObject.lut.h
  • trunk/Source/JavaScriptCore/DerivedSources.make

    r284507 r285178  
    201201    TemporalDurationConstructor.lut.h \
    202202    TemporalDurationPrototype.lut.h \
     203    TemporalInstantConstructor.lut.h \
     204    TemporalInstantPrototype.lut.h \
    203205    TemporalNow.lut.h \
    204206    TemporalObject.lut.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r284781 r285178  
    19751975                E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC15112EF272200184A1F /* SourceProviderCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
    19761976                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 */; };
    19771982                F6F150212693D450004B98EF /* TemporalObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = F6F150202693D450004B98EF /* TemporalObject.lut.h */; };
    19781983                FE041553252EC0730091EB5D /* SlotVisitorMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = FE041552252EC0730091EB5D /* SlotVisitorMacros.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    53715376                F692A87E0255597D01FF60F7 /* RegExp.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = RegExp.h; sourceTree = "<group>"; tabWidth = 8; };
    53725377                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>"; };
    53735386                F6F150182693D33D004B98EF /* TemporalNow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporalNow.h; sourceTree = "<group>"; };
    53745387                F6F150192693D33E004B98EF /* TemporalObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TemporalObject.cpp; sourceTree = "<group>"; };
     
    71057118                                E3C4630526DB5DE900896336 /* TemporalCalendarConstructor.lut.h */,
    71067119                                E3C4630626DB5DE900896336 /* TemporalCalendarPrototype.lut.h */,
     7120                                F6D67D4526F9130A006E0349 /* TemporalInstantConstructor.lut.h */,
     7121                                F6D67D4626F9130B006E0349 /* TemporalInstantPrototype.lut.h */,
    71077122                                F6F150202693D450004B98EF /* TemporalObject.lut.h */,
    71087123                                533B15DE1DC7F463004D500A /* WasmOps.h */,
     
    80748089                                A3C7EDB526B0DB37004C34C5 /* TemporalDurationPrototype.cpp */,
    80758090                                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 */,
    80768097                                F6F1501B2693D33E004B98EF /* TemporalNow.cpp */,
    80778098                                F6F150182693D33D004B98EF /* TemporalNow.h */,
     
    1081710838                                A3C7EDBA26B0DB38004C34C5 /* TemporalDurationConstructor.h in Headers */,
    1081810839                                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 */,
    1081910845                                F6F150212693D450004B98EF /* TemporalObject.lut.h in Headers */,
    1082010846                                E386FD7E26E867B800E4C28B /* TemporalPlainTime.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r284781 r285178  
    10211021runtime/TemporalDurationConstructor.cpp
    10221022runtime/TemporalDurationPrototype.cpp
     1023runtime/TemporalInstant.cpp
     1024runtime/TemporalInstantConstructor.cpp
     1025runtime/TemporalInstantPrototype.cpp
    10231026runtime/TemporalNow.cpp
    10241027runtime/TemporalObject.cpp
  • trunk/Source/JavaScriptCore/runtime/ISO8601.cpp

    r284075 r285178  
    3030#include "IntlObject.h"
    3131#include "ParseInt.h"
     32#include <limits>
     33#include <wtf/CheckedArithmetic.h>
    3234#include <wtf/DateMath.h>
    3335#include <wtf/text/StringParsingBuffer.h>
     
    878880}
    879881
     882std::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
    880913// https://tc39.es/proposal-temporal/#sec-temporal-formattimezoneoffsetstring
    881914String formatTimeZoneOffsetString(int64_t offset)
     
    9701003}
    9711004
     1005ExactTime 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
     1024using CheckedInt128 = Checked<Int128, RecordOverflow>;
     1025
     1026static 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
     1066std::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
     1100Int128 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
     1118Int128 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
     1124ExactTime ExactTime::round(unsigned increment, TemporalUnit unit, RoundingMode roundingMode) const
     1125{
     1126    return ExactTime { round(m_epochNanoseconds, increment, unit, roundingMode) };
     1127}
     1128
    9721129} // namespace ISO8601
    9731130} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/ISO8601.h

    r284075 r285178  
    2929#include "IntlObject.h"
    3030#include "TemporalObject.h"
     31#include <wtf/Int128.h>
    3132
    3233namespace JSC {
     
    8081};
    8182
     83class ExactTime {
     84    WTF_MAKE_FAST_ALLOCATED(ExactTime);
     85public:
     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
     177private:
     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
    82199class PlainTime {
    83200    WTF_MAKE_FAST_ALLOCATED(PlainTime);
     
    169286bool isValidDuration(const Duration&);
    170287
     288std::optional<ExactTime> parseInstant(StringView);
     289
    171290} // namespace ISO8601
    172291} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h

    r283445 r285178  
    9595    UDateIntervalFormat* createDateIntervalFormatIfNecessary(JSGlobalObject*);
    9696
     97    static double handleDateTimeValue(JSGlobalObject*, JSValue);
     98
    9799    enum class Weekday : uint8_t { None, Narrow, Short, Long };
    98100    enum class Era : uint8_t { None, Narrow, Short, Long };
  • trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp

    r281790 r285178  
    3333#include "JSBoundFunction.h"
    3434#include "JSCInlines.h"
     35#include "TemporalInstant.h"
    3536#include <wtf/DateMath.h>
    3637
     
    9192}
    9293
     94// HandleDateTimeValue ( dateTimeFormat, x )
     95// https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevalue
     96double 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
    93115JSC_DEFINE_HOST_FUNCTION(intlDateTimeFormatFuncFormatDateTime, (JSGlobalObject* globalObject, CallFrame* callFrame))
    94116{
     
    101123
    102124    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, { });
    111127
    112128    RELEASE_AND_RETURN(scope, JSValue::encode(format->format(globalObject, value)));
     
    157173
    158174    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, { });
    167177
    168178    RELEASE_AND_RETURN(scope, JSValue::encode(dateTimeFormat->formatToParts(globalObject, value)));
     
    186196        return throwVMTypeError(globalObject, scope, "startDate or endDate is undefined"_s);
    187197
    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);
    191201    RETURN_IF_EXCEPTION(scope, { });
    192202    if (startDate > endDate)
     
    213223        return throwVMTypeError(globalObject, scope, "startDate or endDate is undefined"_s);
    214224
    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);
    218228    RETURN_IF_EXCEPTION(scope, { });
    219229    if (startDate > endDate)
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp

    r278338 r285178  
    5656#include <algorithm>
    5757#include <wtf/Hasher.h>
     58#include <wtf/Int128.h>
    5859#include <wtf/MathExtras.h>
    5960
     
    230231        unsignedValue = value;
    231232    return createFromImpl(globalObject, unsignedValue, sign);
     233}
     234
     235JSBigInt* 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;
    232289}
    233290
  • trunk/Source/JavaScriptCore/runtime/JSBigInt.h

    r278253 r285178  
    3434#include "MathCommon.h"
    3535#include <wtf/CagedUniquePtr.h>
     36#include <wtf/Int128.h>
    3637#include <wtf/text/StringBuilder.h>
    3738#include <wtf/text/StringView.h>
     
    7576    JS_EXPORT_PRIVATE static JSBigInt* createFrom(JSGlobalObject*, int64_t value);
    7677    JS_EXPORT_PRIVATE static JSBigInt* createFrom(JSGlobalObject*, uint64_t value);
     78    JS_EXPORT_PRIVATE static JSBigInt* createFrom(JSGlobalObject*, Int128 value);
    7779    static JSBigInt* createFrom(JSGlobalObject*, bool value);
    7880    static JSBigInt* createFrom(JSGlobalObject*, double value);
     
    606608    JS_EXPORT_PRIVATE static uint64_t toBigUInt64Heap(JSBigInt*);
    607609
    608     JS_EXPORT_PRIVATE static std::optional<uint64_t> toUint64Heap(JSBigInt*);
    609 
    610610    inline static size_t offsetOfData()
    611611    {
  • trunk/Source/JavaScriptCore/runtime/JSDateMath.cpp

    r279962 r285178  
    270270}
    271271
    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 
    277272double DateCache::gregorianDateTimeToMS(const GregorianDateTime& t, double milliseconds, WTF::TimeType inputTimeType)
    278273{
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r284576 r285178  
    211211#include "TemporalDuration.h"
    212212#include "TemporalDurationPrototype.h"
     213#include "TemporalInstant.h"
     214#include "TemporalInstantPrototype.h"
    213215#include "TemporalObject.h"
    214216#include "TemporalPlainTime.h"
     
    12531255                TemporalDurationPrototype* durationPrototype = TemporalDurationPrototype::create(init.vm, TemporalDurationPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype()));
    12541256                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));
    12551264            });
    12561265
     
    21672176    thisObject->m_calendarStructure.visit(visitor);
    21682177    thisObject->m_durationStructure.visit(visitor);
     2178    thisObject->m_instantStructure.visit(visitor);
    21692179    thisObject->m_plainTimeStructure.visit(visitor);
    21702180    thisObject->m_timeZoneStructure.visit(visitor);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r284590 r285178  
    335335    LazyProperty<JSGlobalObject, Structure> m_calendarStructure;
    336336    LazyProperty<JSGlobalObject, Structure> m_durationStructure;
     337    LazyProperty<JSGlobalObject, Structure> m_instantStructure;
    337338    LazyProperty<JSGlobalObject, Structure> m_plainTimeStructure;
    338339    LazyProperty<JSGlobalObject, Structure> m_timeZoneStructure;
     
    893894    Structure* calendarStructure() { return m_calendarStructure.get(this); }
    894895    Structure* durationStructure() { return m_durationStructure.get(this); }
     896    Structure* instantStructure() { return m_instantStructure.get(this); }
    895897    Structure* plainTimeStructure() { return m_plainTimeStructure.get(this); }
    896898    Structure* timeZoneStructure() { return m_timeZoneStructure.get(this); }
  • trunk/Source/JavaScriptCore/runtime/TemporalDuration.cpp

    r283705 r285178  
    3131#include "TemporalObject.h"
    3232#include <wtf/text/StringBuilder.h>
     33#include <wtf/text/StringConcatenate.h>
    3334
    3435namespace JSC {
     
    163164
    164165    return TemporalDuration::create(vm, globalObject->durationStructure(), WTFMove(result));
     166}
     167
     168// ToLimitedTemporalDuration ( temporalDurationLike, disallowedFields )
     169// https://tc39.es/proposal-temporal/#sec-temporal-tolimitedtemporalduration
     170ISO8601::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;
    165191}
    166192
  • trunk/Source/JavaScriptCore/runtime/TemporalDuration.h

    r282259 r285178  
    4747
    4848    static TemporalDuration* toTemporalDuration(JSGlobalObject*, JSValue);
     49    static ISO8601::Duration toLimitedDuration(JSGlobalObject*, JSValue, std::initializer_list<TemporalUnit> disallowedUnits);
    4950    static TemporalDuration* from(JSGlobalObject*, JSValue);
    5051    static JSValue compare(JSGlobalObject*, JSValue, JSValue);
  • trunk/Source/JavaScriptCore/runtime/TemporalObject.cpp

    r283705 r285178  
    3333#include "TemporalDurationConstructor.h"
    3434#include "TemporalDurationPrototype.h"
     35#include "TemporalInstantConstructor.h"
     36#include "TemporalInstantPrototype.h"
    3537#include "TemporalNow.h"
    3638#include "TemporalPlainTimeConstructor.h"
     
    3840#include "TemporalTimeZoneConstructor.h"
    3941#include "TemporalTimeZonePrototype.h"
     42#include <wtf/Int128.h>
    4043#include <wtf/text/StringConcatenate.h>
    4144#include <wtf/unicode/CharacterNames.h>
     
    6467    JSGlobalObject* globalObject = temporalObject->globalObject(vm);
    6568    return TemporalDurationConstructor::create(vm, TemporalDurationConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<TemporalDurationPrototype*>(globalObject->durationStructure()->storedPrototypeObject()));
     69}
     70
     71static 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()));
    6676}
    6777
     
    90100  Calendar       createCalendarConstructor       DontEnum|PropertyCallback
    91101  Duration       createDurationConstructor       DontEnum|PropertyCallback
     102  Instant        createInstantConstructor        DontEnum|PropertyCallback
    92103  Now            createNowObject                 DontEnum|PropertyCallback
    93104  PlainTime      createPlainTimeConstructor      DontEnum|PropertyCallback
     
    375386}
    376387
     388// FormatSecondsStringPart ( second, millisecond, microsecond, nanosecond, precision )
     389// https://tc39.es/proposal-temporal/#sec-temporal-formatsecondsstringpart
     390void 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
    377399// MaximumTemporalDurationRoundingIncrement ( unit )
    378400// https://tc39.es/proposal-temporal/#sec-temporal-maximumtemporaldurationroundingincrement
     
    436458}
    437459
     460static Int128 abs(Int128 x)
     461{
     462    return x < 0 ? -x : x;
     463}
     464
     465// Same as above, but with Int128
     466Int128 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
    438499TemporalOverflow toTemporalOverflow(JSGlobalObject* globalObject, JSObject* options)
    439500{
  • trunk/Source/JavaScriptCore/runtime/TemporalObject.h

    r284213 r285178  
    2323#include "JSObject.h"
    2424#include <variant>
     25#include <wtf/Int128.h>
    2526
    2627namespace JSC {
     
    106107RoundingMode temporalRoundingMode(JSGlobalObject*, JSObject*, RoundingMode);
    107108void formatSecondsStringFraction(StringBuilder&, unsigned fraction, std::tuple<Precision, unsigned>);
     109void formatSecondsStringPart(StringBuilder&, unsigned second, unsigned fraction, PrecisionData);
    108110std::optional<double> maximumRoundingIncrement(TemporalUnit);
    109111double temporalRoundingIncrement(JSGlobalObject*, JSObject* options, std::optional<double> dividend, bool inclusive);
    110112double roundNumberToIncrement(double, double increment, RoundingMode);
     113Int128 roundNumberToIncrement(Int128, Int128 increment, RoundingMode);
    111114
    112115enum class TemporalOverflow : bool {
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r284435 r285178  
    168168#include "TemporalCalendar.h"
    169169#include "TemporalDuration.h"
     170#include "TemporalInstant.h"
    170171#include "TemporalPlainTime.h"
    171172#include "TemporalTimeZone.h"
     
    15981599DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalCalendarSpace, cellHeapCellType.get(), TemporalCalendar)
    15991600DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalDurationSpace, cellHeapCellType.get(), TemporalDuration)
     1601DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalInstantSpace, cellHeapCellType.get(), TemporalInstant)
    16001602DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalPlainTimeSpace, cellHeapCellType.get(), TemporalPlainTime)
    16011603DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(temporalTimeZoneSpace, cellHeapCellType.get(), TemporalTimeZone)
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r284435 r285178  
    188188class Symbol;
    189189class TemporalDuration;
     190class TemporalInstant;
    190191class TypedArrayController;
    191192class UnlinkedCodeBlock;
     
    602603    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalCalendarSpace)
    603604    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalDurationSpace)
     605    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalInstantSpace)
    604606    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalPlainTimeSpace)
    605607    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(temporalTimeZoneSpace)
  • trunk/Source/WTF/ChangeLog

    r285159 r285178  
     12021-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
    1152021-11-02  Chris Dumez  <cdumez@apple.com>
    216
  • trunk/Source/WTF/wtf/CheckedArithmetic.h

    r284330 r285178  
    292292    {
    293293#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
    300306        if (signsMatch(lhs, rhs)) {
    301307            if (lhs >= 0) {
     
    310316        result = lhs + rhs;
    311317        return true;
    312 #endif
    313318    }
    314319
     
    316321    {
    317322#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
    324335        if (!signsMatch(lhs, rhs)) {
    325336            if (lhs >= 0) {
     
    333344        result = lhs - rhs;
    334345        return true;
    335 #endif
    336346    }
    337347
     
    339349    {
    340350#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
    347366        if (signsMatch(lhs, rhs)) {
    348367            if (lhs >= 0) {
     
    366385        result = lhs * rhs;
    367386        return true;
    368 #endif
    369387    }
    370388
     
    386404    static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
    387405    {
     406        ResultType temp;
    388407#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    {
    389428        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)
    391443            return false;
    392444        result = temp;
    393445        return true;
    394 #else
    395         ResultType temp = lhs + rhs;
    396         if (temp < lhs)
    397             return false;
    398         result = temp;
    399         return true;
    400 #endif
    401     }
    402 
    403     static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
    404     {
    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 #else
    412         ResultType temp = lhs - rhs;
    413         if (temp > lhs)
    414             return false;
    415         result = temp;
    416         return true;
    417 #endif
    418446    }
    419447
     
    421449    {
    422450#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
    429466        if (!lhs || !rhs) {
    430467            result = 0;
     
    435472        result = lhs * rhs;
    436473        return true;
    437 #endif
    438474    }
    439475
  • trunk/Source/WTF/wtf/DateMath.h

    r275109 r285178  
    389389}
    390390
     391inline 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
    391396// Returns combined offset in millisecond (UTC + DST).
    392397WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime);
     
    411416using WTF::secondsPerMinute;
    412417using WTF::parseDateFromNullTerminatedCharacters;
     418using WTF::timeToMS;
    413419using WTF::makeRFC2822DateString;
    414420using WTF::LocalTimeOffset;
Note: See TracChangeset for help on using the changeset viewer.