Skip to content

Commit 0bd75fb

Browse files
Date ctr spec compliance (#6845)
According to the spec, the Date ctr should use the TimeClip function. Since it did not, -0 was not converted to +0 in the ctr (See issue #5442). The ctr now uses JavascriptDate::TimeClip (moved from IntlEngineInterfaceExtensionObject.cpp). However, this does not fix the original issue, as the underlying JavascriptConversion::ToInteger function is also not spec compliant regarding the conversion from -0 to +0. This non-compliance is also true for the other ToIntXX and ToUintXX functions (Not covered by this PR). Fix #5442 Related to #6743
1 parent 7bcdec7 commit 0bd75fb

File tree

5 files changed

+48
-38
lines changed

5 files changed

+48
-38
lines changed

lib/Runtime/Language/JavascriptConversion.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) 2022 ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#include "RuntimeLanguagePch.h"
@@ -949,10 +950,9 @@ using namespace Js;
949950

950951
double JavascriptConversion::ToInteger(double val)
951952
{
952-
if(JavascriptNumber::IsNan(val))
953+
if(JavascriptNumber::IsNan(val) || JavascriptNumber::IsZero(val))
953954
return 0;
954-
if(JavascriptNumber::IsPosInf(val) || JavascriptNumber::IsNegInf(val) ||
955-
JavascriptNumber::IsZero(val))
955+
if(JavascriptNumber::IsPosInf(val) || JavascriptNumber::IsNegInf(val))
956956
{
957957
return val;
958958
}

lib/Runtime/Library/IntlEngineInterfaceExtensionObject.cpp

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3-
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
3+
// Copyright (c) 2022 ChakraCore Project Contributors. All rights reserved.
44
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
55
//-------------------------------------------------------------------------------------------------------
66
#include "RuntimeLibraryPch.h"
@@ -2513,39 +2513,6 @@ DEFINE_ISXLOCALEAVAILABLE(PR, uloc)
25132513
}
25142514

25152515
#ifdef INTL_ICU
2516-
// Implementation of ECMA 262 #sec-timeclip
2517-
// REVIEW(jahorto): Where is a better place for this function? JavascriptDate? DateUtilities? JavascriptConversion?
2518-
static double TimeClip(Var x)
2519-
{
2520-
double time = 0.0;
2521-
if (TaggedInt::Is(x))
2522-
{
2523-
time = TaggedInt::ToDouble(x);
2524-
}
2525-
else
2526-
{
2527-
AssertOrFailFast(JavascriptNumber::Is(x));
2528-
time = JavascriptNumber::GetValue(x);
2529-
2530-
// Only perform steps 1, 3, and 4 if the input was not a TaggedInt, since TaggedInts cant be infinite or -0
2531-
if (!NumberUtilities::IsFinite(time))
2532-
{
2533-
return NumberConstants::NaN;
2534-
}
2535-
2536-
// This performs both steps 3 and 4
2537-
time = JavascriptConversion::ToInteger(time);
2538-
}
2539-
2540-
// Step 2: If abs(time) > 8.64e15, return NaN.
2541-
if (Math::Abs(time) > 8.64e15)
2542-
{
2543-
return NumberConstants::NaN;
2544-
}
2545-
2546-
return time;
2547-
}
2548-
25492516
static void AddPartToPartsArray(ScriptContext *scriptContext, JavascriptArray *arr, int arrIndex, const char16 *src, int start, int end, JavascriptString *partType)
25502517
{
25512518
JavascriptString *partValue = JavascriptString::NewCopyBuffer(
@@ -2640,7 +2607,7 @@ DEFINE_ISXLOCALEAVAILABLE(PR, uloc)
26402607

26412608
// 1. Let x be TimeClip(x)
26422609
// 2. If x is NaN, throw a RangeError exception
2643-
double date = TimeClip(args[2]);
2610+
double date = JavascriptDate::TimeClip(args[2]);
26442611
if (JavascriptNumber::IsNan(date))
26452612
{
26462613
JavascriptError::ThrowRangeError(scriptContext, JSERR_InvalidDate);

lib/Runtime/Library/JavascriptDate.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) 2022 ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#include "RuntimeLibraryPch.h"
@@ -162,6 +163,8 @@ namespace Js
162163
timeValue = JavascriptConversion::ToNumber(value, scriptContext);
163164
}
164165
}
166+
167+
timeValue = TimeClip(JavascriptNumber::New(timeValue, scriptContext));
165168

166169
pDate->m_date.SetTvUtc(timeValue);
167170
return pDate;
@@ -215,6 +218,38 @@ namespace Js
215218
return pDate;
216219
}
217220

221+
// Implementation of ECMA 262 #sec-timeclip
222+
double JavascriptDate::TimeClip(Var x)
223+
{
224+
double time = 0.0;
225+
if (TaggedInt::Is(x))
226+
{
227+
time = TaggedInt::ToDouble(x);
228+
}
229+
else
230+
{
231+
AssertOrFailFast(JavascriptNumber::Is(x));
232+
time = JavascriptNumber::GetValue(x);
233+
234+
// Only perform steps 1, 3, and 4 if the input was not a TaggedInt, since TaggedInts cant be infinite or -0
235+
if (!NumberUtilities::IsFinite(time))
236+
{
237+
return NumberConstants::NaN;
238+
}
239+
240+
// This performs both steps 3 and 4
241+
time = JavascriptConversion::ToInteger(time);
242+
}
243+
244+
// Step 2: If abs(time) > 8.64e15, return NaN.
245+
if (Math::Abs(time) > 8.64e15)
246+
{
247+
return NumberConstants::NaN;
248+
}
249+
250+
return time;
251+
}
252+
218253
// Date.prototype[@@toPrimitive] as described in ES6 spec (Draft May 22, 2014) 20.3.4.45
219254
Var JavascriptDate::EntrySymbolToPrimitive(RecyclableObject* function, CallInfo callInfo, ...)
220255
{

lib/Runtime/Library/JavascriptDate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) 2022 ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56
#pragma once
@@ -127,6 +128,7 @@ namespace Js
127128
static Var EntryUTC(RecyclableObject* function, CallInfo callInfo, ...);
128129
static Var EntryValueOf(RecyclableObject* function, CallInfo callInfo, ...);
129130
static Var EntrySymbolToPrimitive(RecyclableObject* function, CallInfo callInfo, ...);
131+
static double JavascriptDate::TimeClip(Var x);
130132

131133
static JavascriptString* ToLocaleString(JavascriptDate* date, ScriptContext* requestContext);
132134
static JavascriptString* ToString(JavascriptDate* date, ScriptContext* requestContext);

test/Date/DateCtr.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//-------------------------------------------------------------------------------------------------------
22
// Copyright (C) Microsoft. All rights reserved.
3+
// Copyright (c) 2022 ChakraCore Project Contributors. All rights reserved.
34
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
45
//-------------------------------------------------------------------------------------------------------
56

@@ -59,6 +60,11 @@ function Test()
5960
d = new Date("", 1e81); if (!CHECK(d + "")) return; // WOOB 1139099
6061
d = new Date(); d.setSeconds(Number.MAX_VALUE); if (!CHECK(d + "")) return; // WOOB 1142298
6162
d = new Date(); d.setSeconds(-Number.MAX_VALUE); if (!CHECK(d + "")) return; // WOOB 1142298
63+
64+
// Issue #5442
65+
d = new Date(-0);
66+
if (!Object.is(d.getTime(), 0)) throw new Error("Expected getTime() to return +0");
67+
6268
console.log("PASS");
6369
}
6470

0 commit comments

Comments
 (0)