Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (283008 => 283009)
--- trunk/Source/_javascript_Core/ChangeLog 2021-09-23 21:35:39 UTC (rev 283008)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-09-23 21:50:51 UTC (rev 283009)
@@ -1,3 +1,28 @@
+2021-09-23 Philip Chimento <[email protected]>
+
+ Various tweaks in preparation for Temporal.Instant
+ https://bugs.webkit.org/show_bug.cgi?id=230331
+
+ Reviewed by Yusuke Suzuki.
+
+ * runtime/TemporalDuration.cpp:
+ (JSC::TemporalDuration::fromDurationLike): Use
+ temporalUnitPropertyName().
+ (JSC::TemporalDuration::toISO8601Duration): Improve error message to
+ include the invalid string.
+ (JSC::TemporalDuration::with const): Use temporalUnitPropertyName().
+ (JSC::TemporalDuration::toString): Use formatSecondsStringFraction().
+ * runtime/TemporalObject.cpp:
+ (JSC::ellipsizeAt): Add helper to ellipsize string at certain length.
+ (JSC::temporalUnitPropertyName): Move code from TemporalDuration into
+ a function which will be reused in other Temporal types.
+ (JSC::temporalFractionalSecondDigits): Handle NaN as per
+ specification, and improve error message to include the invalid
+ value.
+ (JSC::formatSecondsStringFraction): Move code from TemporalDuration
+ into a function which will be reused in other Temporal types.
+ * runtime/TemporalObject.h:
+
2021-09-23 Devin Rousso <[email protected]>
Web Inspector: Graphics: add instrumentation for new `CanvasRenderingContext2DSettings`
Modified: trunk/Source/_javascript_Core/runtime/TemporalDuration.cpp (283008 => 283009)
--- trunk/Source/_javascript_Core/runtime/TemporalDuration.cpp 2021-09-23 21:35:39 UTC (rev 283008)
+++ trunk/Source/_javascript_Core/runtime/TemporalDuration.cpp 2021-09-23 21:50:51 UTC (rev 283009)
@@ -28,6 +28,7 @@
#include "IntlObjectInlines.h"
#include "JSCInlines.h"
+#include "TemporalObject.h"
#include <wtf/text/StringBuilder.h>
namespace JSC {
@@ -34,18 +35,6 @@
static constexpr double nanosecondsPerDay = 24.0 * 60 * 60 * 1000 * 1000 * 1000;
-static PropertyName propertyName(VM& vm, unsigned index)
-{
- ASSERT(index < numberOfTemporalUnits);
- switch (static_cast<TemporalUnit>(index)) {
-#define JSC_TEMPORAL_DURATION_PROPERTY_NAME(name, capitalizedName) case TemporalUnit::capitalizedName: return vm.propertyNames->name##s;
- JSC_TEMPORAL_UNITS(JSC_TEMPORAL_DURATION_PROPERTY_NAME)
-#undef JSC_TEMPORAL_DURATION_PROPERTY_NAME
- }
-
- RELEASE_ASSERT_NOT_REACHED();
-}
-
const ClassInfo TemporalDuration::s_info = { "Object", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(TemporalDuration) };
TemporalDuration* TemporalDuration::create(VM& vm, Structure* structure, ISO8601::Duration&& duration)
@@ -100,7 +89,7 @@
ISO8601::Duration result;
auto hasRelevantProperty = false;
for (size_t i = 0; i < numberOfTemporalUnits; i++) {
- JSValue value = durationLike->get(globalObject, propertyName(vm, i));
+ JSValue value = durationLike->get(globalObject, temporalUnitPropertyName(vm, static_cast<TemporalUnit>(i)));
RETURN_IF_EXCEPTION(scope, { });
if (value.isUndefined()) {
@@ -143,7 +132,8 @@
auto parsedDuration = ISO8601::parseDuration(string);
if (!parsedDuration) {
- throwRangeError(globalObject, scope, "Could not parse Duration string"_s);
+ // 3090: 308 digits * 10 fields + 10 designators
+ throwRangeError(globalObject, scope, makeString("'"_s, ellipsizeAt(3090, string), "' is not a valid Duration string"_s));
return { };
}
@@ -241,7 +231,7 @@
ISO8601::Duration result;
auto hasRelevantProperty = false;
for (size_t i = 0; i < numberOfTemporalUnits; i++) {
- JSValue value = durationLike->get(globalObject, propertyName(vm, i));
+ JSValue value = durationLike->get(globalObject, temporalUnitPropertyName(vm, static_cast<TemporalUnit>(i)));
RETURN_IF_EXCEPTION(scope, { });
if (value.isUndefined()) {
@@ -550,8 +540,7 @@
// https://tc39.es/proposal-temporal/#sec-temporal-temporaldurationtostring
String TemporalDuration::toString(const ISO8601::Duration& duration, std::tuple<Precision, unsigned> precision)
{
- auto [precisionType, precisionValue] = precision;
- ASSERT(precisionType == Precision::Auto || precisionValue < 10);
+ ASSERT(std::get<0>(precision) == Precision::Auto || std::get<1>(precision) < 10);
auto balancedMicroseconds = duration.microseconds() + std::trunc(duration.nanoseconds() / 1000);
auto balancedNanoseconds = std::fmod(duration.nanoseconds(), 1000);
@@ -598,17 +587,7 @@
builder.append(formatInteger(balancedSeconds));
auto fraction = std::abs(balancedMilliseconds) * 1e6 + std::abs(balancedMicroseconds) * 1e3 + std::abs(balancedNanoseconds);
- if ((precisionType == Precision::Auto && fraction) || (precisionType == Precision::Fixed && precisionValue)) {
- auto padded = makeString('.', pad('0', 9, fraction));
- if (precisionType == Precision::Fixed)
- builder.append(StringView(padded).left(padded.length() - (9 - precisionValue)));
- else {
- auto lengthWithoutTrailingZeroes = padded.length();
- while (padded[lengthWithoutTrailingZeroes - 1] == '0')
- lengthWithoutTrailingZeroes--;
- builder.append(StringView(padded).left(lengthWithoutTrailingZeroes));
- }
- }
+ formatSecondsStringFraction(builder, fraction, precision);
builder.append('S');
}
Modified: trunk/Source/_javascript_Core/runtime/TemporalObject.cpp (283008 => 283009)
--- trunk/Source/_javascript_Core/runtime/TemporalObject.cpp 2021-09-23 21:35:39 UTC (rev 283008)
+++ trunk/Source/_javascript_Core/runtime/TemporalObject.cpp 2021-09-23 21:50:51 UTC (rev 283009)
@@ -37,6 +37,8 @@
#include "TemporalPlainTimePrototype.h"
#include "TemporalTimeZoneConstructor.h"
#include "TemporalTimeZonePrototype.h"
+#include <wtf/text/StringConcatenate.h>
+#include <wtf/unicode/CharacterNames.h>
namespace JSC {
@@ -125,6 +127,28 @@
return unit.endsWith("s") ? unit.left(unit.length() - 1) : unit;
}
+// For use in error messages where a string value is potentially unbounded
+WTF::String ellipsizeAt(unsigned maxLength, const WTF::String& string)
+{
+ WTF::String copy { string };
+ if (string.length() > maxLength) {
+ copy.truncate(maxLength - 1);
+ copy.append(horizontalEllipsis);
+ }
+ return copy;
+}
+
+PropertyName temporalUnitPropertyName(VM& vm, TemporalUnit unit)
+{
+ switch (unit) {
+#define JSC_TEMPORAL_DURATION_PROPERTY_NAME(name, capitalizedName) case TemporalUnit::capitalizedName: return vm.propertyNames->name##s;
+ JSC_TEMPORAL_UNITS(JSC_TEMPORAL_DURATION_PROPERTY_NAME)
+#undef JSC_TEMPORAL_DURATION_PROPERTY_NAME
+ }
+
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
std::optional<TemporalUnit> temporalUnitType(StringView unit)
{
StringView singular = singularUnit(unit);
@@ -228,8 +252,8 @@
if (value.isNumber()) {
double doubleValue = value.asNumber();
- if (doubleValue < 0 || doubleValue > 9) {
- throwRangeError(globalObject, scope, "fractionalSecondDigits is out of range"_s);
+ if (!(doubleValue >= 0 && doubleValue <= 9)) {
+ throwRangeError(globalObject, scope, makeString("fractionalSecondDigits must be 'auto' or 0 through 9, not "_s, doubleValue));
return std::nullopt;
}
@@ -240,7 +264,7 @@
RETURN_IF_EXCEPTION(scope, std::nullopt);
if (stringValue != "auto")
- throwRangeError(globalObject, scope, "fractionalSecondDigits is out of range"_s);
+ throwRangeError(globalObject, scope, makeString("fractionalSecondDigits must be 'auto' or 0 through 9, not "_s, ellipsizeAt(100, stringValue)));
return std::nullopt;
}
@@ -309,6 +333,22 @@
"roundingMode must be either \"ceil\", \"floor\", \"trunc\", or \"halfExpand\""_s, fallback);
}
+void formatSecondsStringFraction(StringBuilder& builder, unsigned fraction, std::tuple<Precision, unsigned> precision)
+{
+ auto [precisionType, precisionValue] = precision;
+ if ((precisionType == Precision::Auto && fraction) || (precisionType == Precision::Fixed && precisionValue)) {
+ auto padded = makeString('.', pad('0', 9, fraction));
+ if (precisionType == Precision::Fixed)
+ builder.append(StringView(padded).left(padded.length() - (9 - precisionValue)));
+ else {
+ auto lengthWithoutTrailingZeroes = padded.length();
+ while (padded[lengthWithoutTrailingZeroes - 1] == '0')
+ lengthWithoutTrailingZeroes--;
+ builder.append(StringView(padded).left(lengthWithoutTrailingZeroes));
+ }
+ }
+}
+
// MaximumTemporalDurationRoundingIncrement ( unit )
// https://tc39.es/proposal-temporal/#sec-temporal-maximumtemporaldurationroundingincrement
std::optional<double> maximumRoundingIncrement(TemporalUnit unit)
Modified: trunk/Source/_javascript_Core/runtime/TemporalObject.h (283008 => 283009)
--- trunk/Source/_javascript_Core/runtime/TemporalObject.h 2021-09-23 21:35:39 UTC (rev 283008)
+++ trunk/Source/_javascript_Core/runtime/TemporalObject.h 2021-09-23 21:50:51 UTC (rev 283009)
@@ -93,6 +93,8 @@
unsigned increment;
};
+WTF::String ellipsizeAt(unsigned maxLength, const WTF::String&);
+PropertyName temporalUnitPropertyName(VM&, TemporalUnit);
std::optional<TemporalUnit> temporalUnitType(StringView);
std::optional<TemporalUnit> temporalLargestUnit(JSGlobalObject*, JSObject* options, std::initializer_list<TemporalUnit> disallowedUnits, TemporalUnit autoValue);
std::optional<TemporalUnit> temporalSmallestUnit(JSGlobalObject*, JSObject* options, std::initializer_list<TemporalUnit> disallowedUnits);
@@ -99,6 +101,7 @@
std::optional<unsigned> temporalFractionalSecondDigits(JSGlobalObject*, JSObject* options);
PrecisionData secondsStringPrecision(JSGlobalObject*, JSObject* options);
RoundingMode temporalRoundingMode(JSGlobalObject*, JSObject*, RoundingMode);
+void formatSecondsStringFraction(StringBuilder&, unsigned fraction, std::tuple<Precision, unsigned>);
std::optional<double> maximumRoundingIncrement(TemporalUnit);
double temporalRoundingIncrement(JSGlobalObject*, JSObject* options, std::optional<double> dividend, bool inclusive);
double roundNumberToIncrement(double, double increment, RoundingMode);