Diff
Added: trunk/JSTests/ChakraCore/test/Date/DateCtr.baseline-jsc (0 => 269320)
--- trunk/JSTests/ChakraCore/test/Date/DateCtr.baseline-jsc (rev 0)
+++ trunk/JSTests/ChakraCore/test/Date/DateCtr.baseline-jsc 2020-11-03 19:26:49 UTC (rev 269320)
@@ -0,0 +1,15 @@
+1970-01-10T00:00:01.000Z
+1974-01-01T00:00:00.000Z
+1970-01-01T00:00:01.974Z
+1974-10-01T07:00:00.000Z
+1974-10-24T07:00:00.000Z
+1974-10-24T07:00:00.000Z
+1974-10-24T07:20:00.000Z
+1974-10-24T07:20:30.000Z
+1974-10-24T07:20:30.040Z
+1974-10-24T07:20:30.040Z
+-098001-12-01T07:52:58.000Z
+1999-12-01T08:00:00.000Z
+Invalid Date
+Invalid Date
+Invalid Date
Modified: trunk/JSTests/ChakraCore.yaml (269319 => 269320)
--- trunk/JSTests/ChakraCore.yaml 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/ChakraCore.yaml 2020-11-03 19:26:49 UTC (rev 269320)
@@ -480,7 +480,7 @@
- path: ChakraCore/test/Conversions/bug1.js
cmd: runChakra :pass, "NoException", "", []
- path: ChakraCore/test/Date/DateCtr.js
- cmd: runChakra :baseline, "NoException", "DateCtr.baseline", []
+ cmd: runChakra :baseline, "NoException", "DateCtr.baseline-jsc", []
- path: ChakraCore/test/Date/DateParse.js
# JSC accepts different Date parsing syntax.
cmd: runChakra :skip, "NoException", "DateParse_es5.baseline", []
Modified: trunk/JSTests/ChangeLog (269319 => 269320)
--- trunk/JSTests/ChangeLog 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/ChangeLog 2020-11-03 19:26:49 UTC (rev 269320)
@@ -1,3 +1,24 @@
+2020-11-03 Yusuke Suzuki <[email protected]>
+
+ REGRESSION (r254038): Simple.com money transfer UI is very laggy (multiple seconds per keypress)
+ https://bugs.webkit.org/show_bug.cgi?id=218348
+
+ Reviewed by Darin Adler.
+
+ * ChakraCore.yaml:
+ * ChakraCore/test/Date/DateCtr.baseline-jsc: Added. The time before America/Los_Angeles timezone is effective should be handled as UTC-0752.
+ * complex.yaml:
+ * complex/timezone-offset-before-america-los-angeles-is-defined.js: Added for UTC-0752.
+ (shouldBe):
+ * microbenchmarks/local-date-constructor.js: Added for microbenchmarking.
+ (test):
+ * mozilla/ecma/Date/15.9.5.16.js:
+ * mozilla/ecma/Date/15.9.5.18.js:
+ * mozilla/ecma/Date/15.9.5.22-1.js:
+ * mozilla/ecma/Date/15.9.5.22-2.js:
+ * mozilla/ecma/Date/15.9.5.35-1.js:
+ When year is 0, America/Los_Angeles timezone is not effective, and mozilla test harness does not handle this timezone difference correctly.
+
2020-10-28 Saam Barati <[email protected]>
Better cache our serialization of the outer TDZ environment when creating FunctionExecutables during bytecode generation
Added: trunk/JSTests/complex/timezone-offset-before-america-los-angeles-is-defined.js (0 => 269320)
--- trunk/JSTests/complex/timezone-offset-before-america-los-angeles-is-defined.js (rev 0)
+++ trunk/JSTests/complex/timezone-offset-before-america-los-angeles-is-defined.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -0,0 +1,14 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+// When it is 1111, timezone America/Los_Angeles is not effective yet.
+// So, timezone offset is defined by America/Los_Angeles's longitude
+// (118.2347W), thus, UTC-0752. Its timezone offset is 472.
+shouldBe(new Date(1111, 1).getTimezoneOffset(), 472);
+// After timezone America/Los_Angeles is effective, its timezone offset is 480.
+shouldBe(new Date(2000, 1).getTimezoneOffset(), 480);
+
+shouldBe(new Date(1111, 1).getTime(), -27104774822000);
+shouldBe(new Date(2000, 1).getTime(), 949392000000);
Modified: trunk/JSTests/complex.yaml (269319 => 269320)
--- trunk/JSTests/complex.yaml 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/complex.yaml 2020-11-03 19:26:49 UTC (rev 269320)
@@ -31,3 +31,6 @@
- path: complex/timezone-offset-apia.js
cmd: runComplexTest [], [], "TZ=Pacific/Apia", "--useDollarVM=1"
+
+- path: complex/timezone-offset-before-america-los-angeles-is-defined.js
+ cmd: runComplexTest [], [], "TZ=America/Los_Angeles", "--useDollarVM=1"
Added: trunk/JSTests/microbenchmarks/local-date-constructor.js (0 => 269320)
--- trunk/JSTests/microbenchmarks/local-date-constructor.js (rev 0)
+++ trunk/JSTests/microbenchmarks/local-date-constructor.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -0,0 +1,50 @@
+function test() {
+ a = {
+ 2016: {
+ begin: new Date("2016-03-13T00:00:00").getTime(),
+ end: new Date("2016-11-06T00:00:00").getTime()
+ },
+ 2017: {
+ begin: new Date("2017-03-12T00:00:00").getTime(),
+ end: new Date("2017-11-05T00:00:00").getTime()
+ },
+ 2018: {
+ begin: new Date("2018-03-11T00:00:00").getTime(),
+ end: new Date("2018-11-04T00:00:00").getTime()
+ },
+ 2019: {
+ begin: new Date("2019-03-10T00:00:00").getTime(),
+ end: new Date("2019-11-03T00:00:00").getTime()
+ },
+ 2020: {
+ begin: new Date("2020-03-08T00:00:00").getTime(),
+ end: new Date("2020-11-01T00:00:00").getTime()
+ },
+ 2021: {
+ begin: new Date("2021-03-14T00:00:00").getTime(),
+ end: new Date("2021-11-07T00:00:00").getTime()
+ },
+ 2022: {
+ begin: new Date("2022-03-13T00:00:00").getTime(),
+ end: new Date("2022-11-06T00:00:00").getTime()
+ },
+ 2023: {
+ begin: new Date("2023-03-12T00:00:00").getTime(),
+ end: new Date("2023-11-05T00:00:00").getTime()
+ },
+ 2024: {
+ begin: new Date("2024-03-10T00:00:00").getTime(),
+ end: new Date("2024-11-03T00:00:00").getTime()
+ },
+ 2025: {
+ begin: new Date("2025-03-09T00:00:00").getTime(),
+ end: new Date("2025-11-02T00:00:00").getTime()
+ }
+ }
+ return a;
+}
+noInline(test);
+
+let count = 10000;
+for (var i = 0; i < count; i++)
+ test();
Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.16.js (269319 => 269320)
--- trunk/JSTests/mozilla/ecma/Date/15.9.5.16.js 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.16.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -55,7 +55,6 @@
TimeInYear(2002)+TimeInYear(2003)+TimeInYear(2004);
addTestCase( now );
- addTestCase( TIME_YEAR_0 );
addTestCase( TIME_1970 );
addTestCase( TIME_1900 );
addTestCase( TIME_2000 );
Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.18.js (269319 => 269320)
--- trunk/JSTests/mozilla/ecma/Date/15.9.5.18.js 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.18.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -56,7 +56,6 @@
TimeInYear(2002)+TimeInYear(2003)+TimeInYear(2004);
addTestCase( now );
- addTestCase( TIME_YEAR_0 );
addTestCase( TIME_1970 );
addTestCase( TIME_1900 );
addTestCase( TIME_2000 );
Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.22-1.js (269319 => 269320)
--- trunk/JSTests/mozilla/ecma/Date/15.9.5.22-1.js 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.22-1.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -58,7 +58,6 @@
// addTestCase( now );
- addTestCase( TIME_YEAR_0 );
addTestCase( TIME_1970 );
addTestCase( TIME_1900 );
addTestCase( TIME_2000 );
Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.22-2.js (269319 => 269320)
--- trunk/JSTests/mozilla/ecma/Date/15.9.5.22-2.js 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.22-2.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -56,8 +56,8 @@
var UTC_JAN_1_2005 = TIME_2000 + TimeInYear(2000)+TimeInYear(2001)+
TimeInYear(2002)+TimeInYear(2003)+TimeInYear(2004);
+/*
addTestCase( TIME_YEAR_0 );
-/*
addTestCase( TIME_1970 );
addTestCase( TIME_1900 );
addTestCase( TIME_2000 );
Modified: trunk/JSTests/mozilla/ecma/Date/15.9.5.35-1.js (269319 => 269320)
--- trunk/JSTests/mozilla/ecma/Date/15.9.5.35-1.js 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/JSTests/mozilla/ecma/Date/15.9.5.35-1.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -58,9 +58,9 @@
UTCDateFromTime(SetUTCMonth(0,11)),
LocalDateFromTime(SetUTCMonth(0,11)) );
- addNewTestCase( "TDATE = new Date(0);(TDATE).setUTCMonth(3,4);TDATE",
- UTCDateFromTime(SetUTCMonth(0,3,4)),
- LocalDateFromTime(SetUTCMonth(0,3,4)) );
+ addNewTestCase( "TDATE = new Date(0);(TDATE).setUTCMonth(3,27);TDATE",
+ UTCDateFromTime(SetUTCMonth(0,3,27)),
+ LocalDateFromTime(SetUTCMonth(0,3,27)) );
}
Modified: trunk/LayoutTests/ChangeLog (269319 => 269320)
--- trunk/LayoutTests/ChangeLog 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/ChangeLog 2020-11-03 19:26:49 UTC (rev 269320)
@@ -1,3 +1,25 @@
+2020-11-03 Yusuke Suzuki <[email protected]>
+
+ REGRESSION (r254038): Simple.com money transfer UI is very laggy (multiple seconds per keypress)
+ https://bugs.webkit.org/show_bug.cgi?id=218348
+
+ Reviewed by Darin Adler.
+
+ * js/date-constructor-expected.txt: The time before America/Los_Angeles timezone is effective should be handled as UTC-0752. Use 1995 to test the intent correctly.
+ * js/date-timeClip-large-values-expected.txt: Ditto about old timezone.
+ * js/dom/script-tests/date-DST-time-cusps.js: Our timezone database was broken. Nov 02 2014 01:00:00 is not PDT.
+ (1.toString.match):
+ * js/dom/script-tests/date-big-setdate.js: Fix and adjust for right DST periods.
+ (1.toString.match):
+ * js/script-tests/date-constructor.js:
+ (object.valueOf):
+ * platform/mac/fast/AppleScript/date-expected.txt: Ditto, 1800 does not have America/Los_Angeles.
+ * platform/mac/fast/AppleScript/date.html:
+ * storage/indexeddb/modern/date-basic-expected.txt: Nov 04 1955 is PST, not PDT.
+ * storage/indexeddb/modern/date-basic-private-expected.txt: Ditto.
+ * storage/indexeddb/modern/get-keyrange-expected.txt: Ditto.
+ * storage/indexeddb/modern/get-keyrange-private-expected.txt: Ditto.
+
2020-11-03 Commit Queue <[email protected]>
Unreviewed, reverting r268564, r268957, and r268962.
Modified: trunk/LayoutTests/js/date-constructor-expected.txt (269319 => 269320)
--- trunk/LayoutTests/js/date-constructor-expected.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/date-constructor-expected.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -4,26 +4,26 @@
PASS isNaN(new Date("")) is true
-PASS new Date(1111).getTime() is 1111
-PASS new Date(object).getTime() is 1111
-PASS new Date(new Date(1111)).getTime() is 1111
-PASS new Date(new Date(1111).toString()).getTime() is 1000
-PASS new Date(1111, 1).getTime() - timeZoneOffset is -27104803200000
-PASS new Date(1111, 1, 1).getTime() - timeZoneOffset is -27104803200000
-PASS new Date(1111, 1, 1, 1).getTime() - timeZoneOffset is -27104799600000
-PASS new Date(1111, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799540000
-PASS new Date(1111, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799539000
-PASS new Date(1111, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(1111, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(new Date(1111, 1)).getTime() - timeZoneOffset is -27104803200000
-PASS new Date(new Date(1111, 1, 1)).getTime() - timeZoneOffset is -27104803200000
-PASS new Date(new Date(1111, 1, 1, 1)).getTime() - timeZoneOffset is -27104799600000
-PASS new Date(new Date(1111, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is -27104799539000
-PASS new Date(new Date(1111, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(new Date(1111, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is -27104799538999
-PASS new Date(new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is -27104799538999
+PASS new Date(1995).getTime() is 1995
+PASS new Date(object).getTime() is 1995
+PASS new Date(new Date(1995)).getTime() is 1995
+PASS new Date(new Date(1995).toString()).getTime() is 1000
+PASS new Date(1995, 1).getTime() - timeZoneOffset is 791596800000
+PASS new Date(1995, 1, 1).getTime() - timeZoneOffset is 791596800000
+PASS new Date(1995, 1, 1, 1).getTime() - timeZoneOffset is 791600400000
+PASS new Date(1995, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600460000
+PASS new Date(1995, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461000
+PASS new Date(1995, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461001
+PASS new Date(1995, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461001
+PASS new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461001
+PASS new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset is 791600461001
+PASS new Date(new Date(1995, 1)).getTime() - timeZoneOffset is 791596800000
+PASS new Date(new Date(1995, 1, 1)).getTime() - timeZoneOffset is 791596800000
+PASS new Date(new Date(1995, 1, 1, 1)).getTime() - timeZoneOffset is 791600400000
+PASS new Date(new Date(1995, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is 791600461000
+PASS new Date(new Date(1995, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is 791600461001
+PASS new Date(new Date(1995, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is 791600461001
+PASS new Date(new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset is 791600461001
PASS Number(new Date(new Date(Infinity, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset) is Number.NaN
PASS Number(new Date(new Date(1, Infinity, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset) is Number.NaN
PASS Number(new Date(new Date(1, 1, Infinity, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset) is Number.NaN
Modified: trunk/LayoutTests/js/date-timeClip-large-values-expected.txt (269319 => 269320)
--- trunk/LayoutTests/js/date-timeClip-large-values-expected.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/date-timeClip-large-values-expected.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -52,14 +52,14 @@
PASS new Date(8.64e15).setMonth(new Date(8.64e15).getMonth() + 1).valueOf() is NaN
Testing setYear()
PASS new Date(0).setYear(Infinity).valueOf() is NaN
-FAIL new Date(0).setYear(1.79769e+308).valueOf() should be NaN. Was -62135596800000.
-FAIL new Date(0).setYear(-1.79769e+308).valueOf() should be NaN. Was -62135596800000.
+FAIL new Date(0).setYear(1.79769e+308).valueOf() should be NaN. Was -62135597222000.
+FAIL new Date(0).setYear(-1.79769e+308).valueOf() should be NaN. Was -62135597222000.
PASS new Date(8.64e15).setYear(new Date(8.64e15).getFullYear()).valueOf() is 8.64e15
PASS new Date(8.64e15).setYear(new Date(8.64e15).getFullYear() + 1).valueOf() is NaN
Testing setFullYear()
PASS new Date(0).setFullYear(Infinity).valueOf() is NaN
-FAIL new Date(0).setFullYear(1.79769e+308).valueOf() should be NaN. Was -62135596800000.
-FAIL new Date(0).setFullYear(-1.79769e+308).valueOf() should be NaN. Was -62135596800000.
+FAIL new Date(0).setFullYear(1.79769e+308).valueOf() should be NaN. Was -62135597222000.
+FAIL new Date(0).setFullYear(-1.79769e+308).valueOf() should be NaN. Was -62135597222000.
PASS new Date(8.64e15).setFullYear(new Date(8.64e15).getFullYear()).valueOf() is 8.64e15
PASS new Date(8.64e15).setFullYear(new Date(8.64e15).getFullYear() + 1).valueOf() is NaN
Testing setUTCMilliseconds()
Modified: trunk/LayoutTests/js/dom/script-tests/date-DST-time-cusps.js (269319 => 269320)
--- trunk/LayoutTests/js/dom/script-tests/date-DST-time-cusps.js 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/dom/script-tests/date-DST-time-cusps.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -11,7 +11,7 @@
testCases.push(["(new Date('Mar 09 2014 03:00:00')).getHours()", "3"]);
testCases.push(["(new Date('Mar 09 2014 03:00:00')).getTimezoneOffset()", "420"]);
testCases.push(["(new Date('Nov 02 2014 01:00:00')).getHours()", "1"]);
- testCases.push(["(new Date('Nov 02 2014 01:00:00')).getTimezoneOffset()", "480"]);
+ testCases.push(["(new Date('Nov 02 2014 01:00:00')).getTimezoneOffset()", "420"]);
}
var errors = [];
Modified: trunk/LayoutTests/js/dom/script-tests/date-big-setdate.js (269319 => 269320)
--- trunk/LayoutTests/js/dom/script-tests/date-big-setdate.js 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/dom/script-tests/date-big-setdate.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -23,17 +23,17 @@
if ((new Date(2009, 9, 1)).toString().match("PDT")) {
// Added a special case that should represent a change in DST. DST did not actually
// change on this date but because of the wierdness of how _javascript_Dates are
-// expected to interpolate DST as opposed to reflect acurate history, this day
+ // expected to interpolate DST as opposed to reflect acurate history, this day
// (April 5th 1970) should show a DST change.
- testCases.push([new Date(0), 97, 98]);
+ testCases.push([new Date(0), 146, 147]); // DST in 1970 is 4/26 14:00 - 10/25 14:00. And since epoch 0 is 16:00, 147 dates (4/26) is already in DST.
// Added more special cases. These dates match the recent DST changes in the US.
// These tests check that the new changes are correctly propogated to the past and
// all of the tests should show DST occurring on the same date.
- testCases.push([new Date(1970, 0,0,0,0,0,0), 98, 99]);
- testCases.push([new Date(1998, 0,0,0,0,0,0), 98, 99]);
- testCases.push([new Date(2026, 0,0,0,0,0,0), 98, 99]);
- testCases.push([new Date(2054, 0,0,0,0,0,0), 98, 99]);
+ testCases.push([new Date(1970, 0,0,0,0,0,0), 147, 148]); // DST in 1970 is 4/26 14:00 - 10/25 14:00
+ testCases.push([new Date(1998, 0,0,0,0,0,0), 126, 127]); // DST in 1998 is 4/5 14:00 - 10/25 14:00
+ testCases.push([new Date(2026, 0,0,0,0,0,0), 98, 99]); // DST in 2026 is 3/8 14:00 - 11/1 14:00
+ testCases.push([new Date(2054, 0,0,0,0,0,0), 98, 99]); // DST in 2054 is 3/8 14:00 - 11/1 14:00
}
var errors = [];
@@ -42,7 +42,6 @@
var d = new Date(c);
c.setDate(testCases[i][1]);
d.setDate(testCases[i][2]);
-
var actual = d.valueOf() - c.valueOf();
var expected = millisecondsPerDay - millisecondsPerHour;
if (actual != expected) {
Modified: trunk/LayoutTests/js/script-tests/date-constructor.js (269319 => 269320)
--- trunk/LayoutTests/js/script-tests/date-constructor.js 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/js/script-tests/date-constructor.js 2020-11-03 19:26:49 UTC (rev 269320)
@@ -7,7 +7,7 @@
);
var object = new Object;
-object.valueOf = function() { return 1111; }
+object.valueOf = function() { return 1995; }
object.toString = function() { return "2222"; }
shouldBe('isNaN(new Date(""))', 'true');
@@ -14,28 +14,28 @@
var timeZoneOffset = Date.parse("Dec 25 1995") - Date.parse("Dec 25 1995 GMT");
-shouldBe('new Date(1111).getTime()', '1111');
-shouldBe('new Date(object).getTime()', '1111');
-shouldBe('new Date(new Date(1111)).getTime()', '1111');
-shouldBe('new Date(new Date(1111).toString()).getTime()', '1000');
+shouldBe('new Date(1995).getTime()', '1995');
+shouldBe('new Date(object).getTime()', '1995');
+shouldBe('new Date(new Date(1995)).getTime()', '1995');
+shouldBe('new Date(new Date(1995).toString()).getTime()', '1000');
-shouldBe('new Date(1111, 1).getTime() - timeZoneOffset', '-27104803200000');
-shouldBe('new Date(1111, 1, 1).getTime() - timeZoneOffset', '-27104803200000');
-shouldBe('new Date(1111, 1, 1, 1).getTime() - timeZoneOffset', '-27104799600000');
-shouldBe('new Date(1111, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799540000');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799539000');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '-27104799538999');
+shouldBe('new Date(1995, 1).getTime() - timeZoneOffset', '791596800000');
+shouldBe('new Date(1995, 1, 1).getTime() - timeZoneOffset', '791596800000');
+shouldBe('new Date(1995, 1, 1, 1).getTime() - timeZoneOffset', '791600400000');
+shouldBe('new Date(1995, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600460000');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461000');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1).getTime() - timeZoneOffset', '791600461001');
-shouldBe('new Date(new Date(1111, 1)).getTime() - timeZoneOffset', '-27104803200000');
-shouldBe('new Date(new Date(1111, 1, 1)).getTime() - timeZoneOffset', '-27104803200000');
-shouldBe('new Date(new Date(1111, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799600000');
-shouldBe('new Date(new Date(1111, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799539000');
-shouldBe('new Date(new Date(1111, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(new Date(1111, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799538999');
-shouldBe('new Date(new Date(1111, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '-27104799538999');
+shouldBe('new Date(new Date(1995, 1)).getTime() - timeZoneOffset', '791596800000');
+shouldBe('new Date(new Date(1995, 1, 1)).getTime() - timeZoneOffset', '791596800000');
+shouldBe('new Date(new Date(1995, 1, 1, 1)).getTime() - timeZoneOffset', '791600400000');
+shouldBe('new Date(new Date(1995, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '791600461000');
+shouldBe('new Date(new Date(1995, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(new Date(1995, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '791600461001');
+shouldBe('new Date(new Date(1995, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset', '791600461001');
shouldBe("Number(new Date(new Date(Infinity, 1, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset)", 'Number.NaN');
shouldBe("Number(new Date(new Date(1, Infinity, 1, 1, 1, 1, 1, 1, 1)).getTime() - timeZoneOffset)", 'Number.NaN');
@@ -53,9 +53,9 @@
shouldBe("new Date(Date.parse('1 Mar 1000 GMT')).toGMTString()", "\"Sat, 01 Mar 1000 00:00:00 GMT\"");
// In Firefox, the results of the following tests are timezone-dependent, which likely implies that the implementation is not quite correct.
-// Our results are even worse, though, as the dates are clipped: (new Date(1111, 1201).getTime()) == (new Date(1111, 601).getTime())
-// shouldBe('new Date(1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111).getTime() - timeZoneOffset', '-24085894227889');
-// shouldBe('new Date(new Date(1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111)).getTime() - timeZoneOffset', '-24085894227889');
+// Our results are even worse, though, as the dates are clipped: (new Date(1995, 1201).getTime()) == (new Date(1995, 601).getTime())
+// shouldBe('new Date(1995, 1995, 1995, 1995, 1995, 1995, 1995, 1995).getTime() - timeZoneOffset', '-24085894227889');
+// shouldBe('new Date(new Date(1995, 1995, 1995, 1995, 1995, 1995, 1995, 1995)).getTime() - timeZoneOffset', '-24085894227889');
// Regression test for Bug 26978 (https://bugs.webkit.org/show_bug.cgi?id=26978)
var testStr = "";
Modified: trunk/LayoutTests/platform/mac/fast/AppleScript/date-expected.txt (269319 => 269320)
--- trunk/LayoutTests/platform/mac/fast/AppleScript/date-expected.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/platform/mac/fast/AppleScript/date-expected.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -4,5 +4,5 @@
00000001383EC400 ('ldt ')
0000000056871300 ('ldt ')
0000000000000000 ('ldt ')
-FFFFFFFF3C637000 ('ldt ')
+FFFFFFFF3C636E5A ('ldt ')
"Invalid Date" ('utxt')
Modified: trunk/LayoutTests/platform/mac/fast/AppleScript/date.html (269319 => 269320)
--- trunk/LayoutTests/platform/mac/fast/AppleScript/date.html 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/platform/mac/fast/AppleScript/date.html 2020-11-03 19:26:49 UTC (rev 269320)
@@ -37,7 +37,7 @@
// 0x00000000 == Fri Jan 01 1904 00:00:00
log(appleScriptController.doJavaScript("new Date(1904,0,1)"));
- // 0xffffffff3c637000 == Wed Jan 01 1800 00:00:00
+ // 0xffffffff3c636e5a == Wed Jan 01 1800 00:00:00, this is because America/Los_Angeles timzeone is not effective at 1800.
log(appleScriptController.doJavaScript("new Date(1800,0,1)"));
// invalid date
Modified: trunk/LayoutTests/storage/indexeddb/modern/date-basic-expected.txt (269319 => 269320)
--- trunk/LayoutTests/storage/indexeddb/modern/date-basic-expected.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/storage/indexeddb/modern/date-basic-expected.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -9,13 +9,13 @@
indexedDB.open(dbname)
Initial upgrade needed: Old version - 0 New version - 1
Initial upgrade versionchange transaction complete
-Success getting key 'Fri Nov 04 1955 17:00:00 GMT-0700 (PDT)' of type object, result is 'Flux capacitor' of type string
+Success getting key 'Fri Nov 04 1955 16:00:00 GMT-0800 (PST)' of type object, result is 'Flux capacitor' of type string
Key is a Date object, btw
Success getting key 'Sat Nov 12 1955 10:00:00 GMT-0800 (PST)' of type object, result is 'Fish under the sea' of type string
Key is a Date object, btw
Success getting key 'Wed Oct 21 2015 09:00:00 GMT-0700 (PDT)' of type object, result is 'Hoverboards' of type string
Key is a Date object, btw
-Success getting key 'a' of type string, result is 'Fri Nov 04 1955 17:00:00 GMT-0700 (PDT)' of type object
+Success getting key 'a' of type string, result is 'Fri Nov 04 1955 16:00:00 GMT-0800 (PST)' of type object
Result is a Date object, btw
Success getting key 'b' of type string, result is 'Sat Nov 12 1955 10:00:00 GMT-0800 (PST)' of type object
Result is a Date object, btw
Modified: trunk/LayoutTests/storage/indexeddb/modern/date-basic-private-expected.txt (269319 => 269320)
--- trunk/LayoutTests/storage/indexeddb/modern/date-basic-private-expected.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/storage/indexeddb/modern/date-basic-private-expected.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -9,13 +9,13 @@
indexedDB.open(dbname)
Initial upgrade needed: Old version - 0 New version - 1
Initial upgrade versionchange transaction complete
-Success getting key 'Fri Nov 04 1955 17:00:00 GMT-0700 (PDT)' of type object, result is 'Flux capacitor' of type string
+Success getting key 'Fri Nov 04 1955 16:00:00 GMT-0800 (PST)' of type object, result is 'Flux capacitor' of type string
Key is a Date object, btw
Success getting key 'Sat Nov 12 1955 10:00:00 GMT-0800 (PST)' of type object, result is 'Fish under the sea' of type string
Key is a Date object, btw
Success getting key 'Wed Oct 21 2015 09:00:00 GMT-0700 (PDT)' of type object, result is 'Hoverboards' of type string
Key is a Date object, btw
-Success getting key 'a' of type string, result is 'Fri Nov 04 1955 17:00:00 GMT-0700 (PDT)' of type object
+Success getting key 'a' of type string, result is 'Fri Nov 04 1955 16:00:00 GMT-0800 (PST)' of type object
Result is a Date object, btw
Success getting key 'b' of type string, result is 'Sat Nov 12 1955 10:00:00 GMT-0800 (PST)' of type object
Result is a Date object, btw
Modified: trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-expected.txt (269319 => 269320)
--- trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-expected.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-expected.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -123,13 +123,13 @@
Result is PosInf
Success getting keyRange [Infinity (Open), a (Open)]
Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
Result is Fish under the sea
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
Result is Fish under the sea
readonly transaction complete
PASS successfullyParsed is true
Modified: trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-private-expected.txt (269319 => 269320)
--- trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-private-expected.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/LayoutTests/storage/indexeddb/modern/get-keyrange-private-expected.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -123,13 +123,13 @@
Result is PosInf
Success getting keyRange [Infinity (Open), a (Open)]
Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Closed)]
Result is Fish under the sea
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Closed), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
Result is Flux capacitor
-Success getting keyRange [Fri Nov 04 1955 17:00:00 GMT-0700 (PDT) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
+Success getting keyRange [Fri Nov 04 1955 16:00:00 GMT-0800 (PST) (Open), Wed Oct 21 2015 09:00:00 GMT-0700 (PDT) (Open)]
Result is Fish under the sea
readonly transaction complete
PASS successfullyParsed is true
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (269319 => 269320)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -911,6 +911,7 @@
runtime/JSCell.h
runtime/JSCellInlines.h
runtime/JSDataView.h
+ runtime/JSDateMath.h
runtime/JSDestructibleObject.h
runtime/JSDestructibleObjectHeapCellType.h
runtime/JSExportMacros.h
Modified: trunk/Source/_javascript_Core/ChangeLog (269319 => 269320)
--- trunk/Source/_javascript_Core/ChangeLog 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-11-03 19:26:49 UTC (rev 269320)
@@ -1,3 +1,56 @@
+2020-11-03 Yusuke Suzuki <[email protected]>
+
+ REGRESSION (r254038): Simple.com money transfer UI is very laggy (multiple seconds per keypress)
+ https://bugs.webkit.org/show_bug.cgi?id=218348
+
+ Reviewed by Darin Adler.
+
+ We have depth-1 LocalTimeOffset cache to avoid repeatedly calling `localtime_r`. But this depth-1 cache can be easily missed if
+ we parse Dates of multiple years. Instead of increasing depth as a work-around, this patch starts using ICU TimeZone cache.
+ This is used in SpiderMonkey and V8 too, and it is the right direction since ICU knows tzdata and can do more sophisticated caching.
+
+ Microbenchmark shows 24x improvement.
+
+ ToT Patched
+
+ local-date-constructor 2026.8715+-11.2909 ^ 85.0022+-1.0548 ^ definitely 23.8449x faster
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * Sources.txt:
+ * runtime/DateConstructor.cpp:
+ (JSC::millisecondsFromComponents):
+ (JSC::constructDate):
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ * runtime/DateInstance.cpp:
+ (JSC::DateInstance::calculateGregorianDateTime const):
+ (JSC::DateInstance::calculateGregorianDateTimeUTC const):
+ * runtime/DateInstance.h:
+ * runtime/DatePrototype.cpp:
+ (JSC::setNewValueFromTimeArgs):
+ (JSC::setNewValueFromDateArgs):
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ * runtime/JSDateMath.cpp:
+ (JSC::OpaqueICUTimeZoneDeleter::operator()):
+ (JSC::localTimeOffset):
+ (JSC::DateCache::gregorianDateTimeToMS):
+ (JSC::DateCache::msToGregorianDateTime):
+ (JSC::DateCache::parseDate):
+ (JSC::DateCache::cachedDateInstanceData):
+ (JSC::DateCache::timeZoneCacheSlow):
+ (JSC::DateCache::reset):
+ (JSC::gregorianDateTimeToMS): Deleted.
+ (JSC::msToGregorianDateTime): Deleted.
+ (JSC::parseDate): Deleted.
+ * runtime/JSDateMath.h:
+ (JSC::DateCache::timeZoneCache):
+ * runtime/VM.cpp:
+ (JSC::VM::resetDateCache): Deleted.
+ * runtime/VM.h:
+ (JSC::VM::resetDateCache):
+ * runtime/VMEntryScope.cpp:
+ (JSC::VMEntryScope::VMEntryScope):
+
2020-11-03 Keith Rollin <[email protected]>
Extend check-for-inappropriate-files-in-framework to WebKitLegacy and _javascript_Core
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (269319 => 269320)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2020-11-03 19:26:49 UTC (rev 269320)
@@ -1859,6 +1859,7 @@
E3850B15226ED641009ABF9C /* DFGMinifiedIDInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3850B14226ED63E009ABF9C /* DFGMinifiedIDInlines.h */; };
E38652E3237CA0C900E1D5EE /* BlockDirectoryBits.h in Headers */ = {isa = PBXBuildFile; fileRef = E38652E2237CA0C800E1D5EE /* BlockDirectoryBits.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3893A1D2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E3893A1C2203A7C600E79A74 /* AsyncFromSyncIteratorPrototype.lut.h */; };
+ E38E8790254B978400F6F9E4 /* JSDateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */; };
E39006212208BFC4001019CF /* SubspaceAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = E39006202208BFC3001019CF /* SubspaceAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
E392E6F824D25FA600B20767 /* B3BottomTupleValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E392E6F624D25FA600B20767 /* B3BottomTupleValue.cpp */; };
E392E6F924D25FA900B20767 /* B3BottomTupleValue.h in Headers */ = {isa = PBXBuildFile; fileRef = E392E6F724D25FA600B20767 /* B3BottomTupleValue.h */; };
@@ -11388,6 +11389,7 @@
33B2A548226543BF005A0F79 /* FTLLowerDFGToB3.cpp in Sources */,
5C4196622270E0000047B7CD /* InspectorBackendDispatcherCompatibility.cpp in Sources */,
E366441E254409B30001876F /* IntlListFormat.cpp in Sources */,
+ E38E8790254B978400F6F9E4 /* JSDateMath.cpp in Sources */,
536B319E1F735F160037FC33 /* LowLevelInterpreter.cpp in Sources */,
0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */,
Modified: trunk/Source/_javascript_Core/Sources.txt (269319 => 269320)
--- trunk/Source/_javascript_Core/Sources.txt 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/Sources.txt 2020-11-03 19:26:49 UTC (rev 269320)
@@ -864,7 +864,7 @@
runtime/JSCustomGetterSetterFunction.cpp
runtime/JSDataView.cpp
runtime/JSDataViewPrototype.cpp
-runtime/JSDateMath.cpp
+runtime/JSDateMath.cpp @no-unify // Confine U_SHOW_CPLUSPLUS_API's effect to this file.
runtime/JSDestructibleObjectHeapCellType.cpp
runtime/JSFinalizationRegistry.cpp
runtime/JSFunction.cpp
Modified: trunk/Source/_javascript_Core/runtime/DateConstructor.cpp (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/DateConstructor.cpp 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/DateConstructor.cpp 2020-11-03 19:26:49 UTC (rev 269320)
@@ -94,7 +94,7 @@
t.setMinute(JSC::toInt32(doubleArguments[4]));
t.setSecond(JSC::toInt32(doubleArguments[5]));
t.setIsDST(-1);
- return gregorianDateTimeToMS(vm.dateCache, t, doubleArguments[6], timeType);
+ return vm.dateCache.gregorianDateTimeToMS(t, doubleArguments[6], timeType);
}
// ECMA 15.9.3
@@ -118,7 +118,7 @@
if (primitive.isString()) {
String primitiveString = asString(primitive)->value(globalObject);
RETURN_IF_EXCEPTION(scope, nullptr);
- value = parseDate(globalObject, vm, primitiveString);
+ value = vm.dateCache.parseDate(globalObject, vm, primitiveString);
RETURN_IF_EXCEPTION(scope, nullptr);
} else
value = primitive.toNumber(globalObject);
@@ -146,7 +146,7 @@
{
VM& vm = globalObject->vm();
GregorianDateTime ts;
- msToGregorianDateTime(vm.dateCache, WallTime::now().secondsSinceEpoch().milliseconds(), WTF::LocalTime, ts);
+ vm.dateCache.msToGregorianDateTime(WallTime::now().secondsSinceEpoch().milliseconds(), WTF::LocalTime, ts);
return JSValue::encode(jsNontrivialString(vm, formatDateTime(ts, DateTimeFormatDateAndTime, false)));
}
@@ -156,7 +156,7 @@
auto scope = DECLARE_THROW_SCOPE(vm);
String dateStr = callFrame->argument(0).toWTFString(globalObject);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
- RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(parseDate(globalObject, vm, dateStr))));
+ RELEASE_AND_RETURN(scope, JSValue::encode(jsNumber(vm.dateCache.parseDate(globalObject, vm, dateStr))));
}
JSValue dateNowImpl()
Modified: trunk/Source/_javascript_Core/runtime/DateInstance.cpp (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/DateInstance.cpp 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/DateInstance.cpp 2020-11-03 19:26:49 UTC (rev 269320)
@@ -52,7 +52,7 @@
return "Date"_s;
}
-const GregorianDateTime* DateInstance::calculateGregorianDateTime(VM::DateCache& cache) const
+const GregorianDateTime* DateInstance::calculateGregorianDateTime(DateCache& cache) const
{
double milli = internalNumber();
if (std::isnan(milli))
@@ -59,16 +59,16 @@
return nullptr;
if (!m_data)
- m_data = cache.dateInstanceCache.add(milli);
+ m_data = cache.cachedDateInstanceData(milli);
if (m_data->m_gregorianDateTimeCachedForMS != milli) {
- msToGregorianDateTime(cache, milli, WTF::LocalTime, m_data->m_cachedGregorianDateTime);
+ cache.msToGregorianDateTime(milli, WTF::LocalTime, m_data->m_cachedGregorianDateTime);
m_data->m_gregorianDateTimeCachedForMS = milli;
}
return &m_data->m_cachedGregorianDateTime;
}
-const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(VM::DateCache& cache) const
+const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(DateCache& cache) const
{
double milli = internalNumber();
if (std::isnan(milli))
@@ -75,10 +75,10 @@
return nullptr;
if (!m_data)
- m_data = cache.dateInstanceCache.add(milli);
+ m_data = cache.cachedDateInstanceData(milli);
if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) {
- msToGregorianDateTime(cache, milli, WTF::UTCTime, m_data->m_cachedGregorianDateTimeUTC);
+ cache.msToGregorianDateTime(milli, WTF::UTCTime, m_data->m_cachedGregorianDateTimeUTC);
m_data->m_gregorianDateTimeUTCCachedForMS = milli;
}
return &m_data->m_cachedGregorianDateTimeUTC;
Modified: trunk/Source/_javascript_Core/runtime/DateInstance.h (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/DateInstance.h 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/DateInstance.h 2020-11-03 19:26:49 UTC (rev 269320)
@@ -60,7 +60,7 @@
DECLARE_EXPORT_INFO;
- const GregorianDateTime* gregorianDateTime(VM::DateCache& cache) const
+ const GregorianDateTime* gregorianDateTime(DateCache& cache) const
{
if (m_data && m_data->m_gregorianDateTimeCachedForMS == internalNumber())
return &m_data->m_cachedGregorianDateTime;
@@ -67,7 +67,7 @@
return calculateGregorianDateTime(cache);
}
- const GregorianDateTime* gregorianDateTimeUTC(VM::DateCache& cache) const
+ const GregorianDateTime* gregorianDateTimeUTC(DateCache& cache) const
{
if (m_data && m_data->m_gregorianDateTimeUTCCachedForMS == internalNumber())
return &m_data->m_cachedGregorianDateTimeUTC;
@@ -86,8 +86,8 @@
JS_EXPORT_PRIVATE DateInstance(VM&, Structure*);
void finishCreation(VM&);
JS_EXPORT_PRIVATE void finishCreation(VM&, double);
- JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTime(VM::DateCache&) const;
- JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTimeUTC(VM::DateCache&) const;
+ JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTime(DateCache&) const;
+ JS_EXPORT_PRIVATE const GregorianDateTime* calculateGregorianDateTimeUTC(DateCache&) const;
double m_internalNumber { PNaN };
mutable RefPtr<DateInstanceData> m_data;
Modified: trunk/Source/_javascript_Core/runtime/DatePrototype.cpp (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/DatePrototype.cpp 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/DatePrototype.cpp 2020-11-03 19:26:49 UTC (rev 269320)
@@ -696,7 +696,7 @@
return JSValue::encode(jsNaN());
}
- double newUTCDate = gregorianDateTimeToMS(cache, gregorianDateTime, ms, inputTimeType);
+ double newUTCDate = cache.gregorianDateTimeToMS(gregorianDateTime, ms, inputTimeType);
double result = timeClip(newUTCDate);
thisDateObj->setInternalNumber(result);
return JSValue::encode(jsNumber(result));
@@ -723,7 +723,7 @@
GregorianDateTime gregorianDateTime;
if (numArgsToUse == 3 && std::isnan(milli))
- msToGregorianDateTime(cache, 0, WTF::UTCTime, gregorianDateTime);
+ cache.msToGregorianDateTime(0, WTF::UTCTime, gregorianDateTime);
else {
ms = milli - floor(milli / msPerSecond) * msPerSecond;
const GregorianDateTime* other = inputTimeType == WTF::UTCTime
@@ -741,7 +741,7 @@
return JSValue::encode(jsNaN());
}
- double newUTCDate = gregorianDateTimeToMS(cache, gregorianDateTime, ms, inputTimeType);
+ double newUTCDate = cache.gregorianDateTimeToMS(gregorianDateTime, ms, inputTimeType);
double result = timeClip(newUTCDate);
thisDateObj->setInternalNumber(result);
return JSValue::encode(jsNumber(result));
@@ -840,7 +840,7 @@
if (std::isnan(milli))
// Based on ECMA 262 B.2.5 (setYear)
// the time must be reset to +0 if it is NaN.
- msToGregorianDateTime(cache, 0, WTF::UTCTime, gregorianDateTime);
+ cache.msToGregorianDateTime(0, WTF::UTCTime, gregorianDateTime);
else {
double secs = floor(milli / msPerSecond);
ms = milli - secs * msPerSecond;
@@ -856,7 +856,7 @@
}
gregorianDateTime.setYear(toInt32((year >= 0 && year <= 99) ? (year + 1900) : year));
- double timeInMilliseconds = gregorianDateTimeToMS(cache, gregorianDateTime, ms, WTF::LocalTime);
+ double timeInMilliseconds = cache.gregorianDateTimeToMS(gregorianDateTime, ms, WTF::LocalTime);
double result = timeClip(timeInMilliseconds);
thisDateObj->setInternalNumber(result);
return JSValue::encode(jsNumber(result));
Modified: trunk/Source/_javascript_Core/runtime/JSDateMath.cpp (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/JSDateMath.cpp 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/JSDateMath.cpp 2020-11-03 19:26:49 UTC (rev 269320)
@@ -76,70 +76,47 @@
#include "VM.h"
#include <limits>
+// icu::TimeZone and icu::BasicTimeZone features are only available in ICU C++ APIs.
+// We use these C++ APIs as an exception.
+#undef U_SHOW_CPLUSPLUS_API
+#define U_SHOW_CPLUSPLUS_API 1
+#include <unicode/basictz.h>
+#include <unicode/timezone.h>
+#undef U_SHOW_CPLUSPLUS_API
+#define U_SHOW_CPLUSPLUS_API 0
+
namespace JSC {
+void OpaqueICUTimeZoneDeleter::operator()(OpaqueICUTimeZone* timeZone)
+{
+ if (timeZone)
+ delete bitwise_cast<icu::TimeZone*>(timeZone);
+}
+
// Get the combined UTC + DST offset for the time passed in.
//
// NOTE: The implementation relies on the fact that no time zones have
// more than one daylight savings offset change per month.
// If this function is called with NaN it returns NaN.
-static LocalTimeOffset localTimeOffset(VM::DateCache& dateCache, double ms, WTF::TimeType inputTimeType = WTF::UTCTime)
+static LocalTimeOffset localTimeOffset(DateCache& dateCache, double millisecondsFromEpoch, WTF::TimeType inputTimeType = WTF::UTCTime)
{
- LocalTimeOffsetCache& cache = inputTimeType == WTF::LocalTime
- ? dateCache.localTimeOffsetCache : dateCache.utcTimeOffsetCache;
-
- double start = cache.start;
- double end = cache.end;
-
- if (start <= ms) {
- // If the time fits in the cached interval, return the cached offset.
- if (ms <= end)
- return cache.offset;
-
- // Compute a possible new interval end.
- double newEnd = end + cache.increment;
-
- if (ms <= newEnd) {
- LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd, inputTimeType);
- if (cache.offset == endOffset) {
- // If the offset at the end of the new interval still matches
- // the offset in the cache, we grow the cached time interval
- // and return the offset.
- cache.end = newEnd;
- cache.increment = WTF::msPerMonth;
- return endOffset;
- }
- LocalTimeOffset offset = calculateLocalTimeOffset(ms, inputTimeType);
- if (offset == endOffset) {
- // The offset at the given time is equal to the offset at the
- // new end of the interval, so that means that we've just skipped
- // the point in time where the DST offset change occurred. Updated
- // the interval to reflect this and reset the increment.
- cache.start = ms;
- cache.end = newEnd;
- cache.increment = WTF::msPerMonth;
- } else {
- // The interval contains a DST offset change and the given time is
- // before it. Adjust the increment to avoid a linear search for
- // the offset change point and change the end of the interval.
- cache.increment /= 3;
- cache.end = ms;
- }
- // Update the offset in the cache and return it.
- cache.offset = offset;
- return offset;
- }
+ auto& timeZoneCache = *bitwise_cast<icu::TimeZone*>(dateCache.timeZoneCache());
+ int32_t rawOffset = 0;
+ int32_t dstOffset = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ if (inputTimeType != WTF::LocalTime) {
+ constexpr bool isLocalTime = false;
+ timeZoneCache.getOffset(millisecondsFromEpoch, isLocalTime, rawOffset, dstOffset, status);
+ } else {
+ // icu::TimeZone is a timezone instance which inherits icu::BasicTimeZone.
+ // https://unicode-org.atlassian.net/browse/ICU-13705 will move getOffsetFromLocal to icu::TimeZone.
+ static_cast<const icu::BasicTimeZone&>(timeZoneCache).getOffsetFromLocal(millisecondsFromEpoch, icu::BasicTimeZone::kFormer, icu::BasicTimeZone::kFormer, rawOffset, dstOffset, status);
}
-
- // Compute the DST offset for the time and shrink the cache interval
- // to only contain the time. This allows fast repeated DST offset
- // computations for the same time.
- LocalTimeOffset offset = calculateLocalTimeOffset(ms, inputTimeType);
- cache.offset = offset;
- cache.start = ms;
- cache.end = ms;
- cache.increment = WTF::msPerMonth;
- return offset;
+ // The above can fail if input date is invalid: NaN etc.
+ // We can return any values in this case since later we fail when computing non timezone offset part anyway.
+ if (U_FAILURE(status))
+ return { false, 0 };
+ return { !!dstOffset, rawOffset + dstOffset };
}
static inline double timeToMS(double hour, double min, double sec, double ms)
@@ -147,49 +124,35 @@
return (((hour * WTF::minutesPerHour + min) * WTF::secondsPerMinute + sec) * WTF::msPerSecond + ms);
}
-double gregorianDateTimeToMS(VM::DateCache& cache, const GregorianDateTime& t, double milliSeconds, WTF::TimeType inputTimeType)
+double DateCache::gregorianDateTimeToMS(const GregorianDateTime& t, double milliseconds, WTF::TimeType inputTimeType)
{
double day = dateToDaysFrom1970(t.year(), t.month(), t.monthDay());
- double ms = timeToMS(t.hour(), t.minute(), t.second(), milliSeconds);
+ double ms = timeToMS(t.hour(), t.minute(), t.second(), milliseconds);
double localTimeResult = (day * WTF::msPerDay) + ms;
double localToUTCTimeOffset = inputTimeType == WTF::LocalTime
- ? localTimeOffset(cache, localTimeResult, inputTimeType).offset : 0;
+ ? localTimeOffset(*this, localTimeResult, inputTimeType).offset : 0;
return localTimeResult - localToUTCTimeOffset;
}
// input is UTC
-void msToGregorianDateTime(VM::DateCache& cache, double ms, WTF::TimeType outputTimeType, GregorianDateTime& tm)
+void DateCache::msToGregorianDateTime(double millisecondsFromEpoch, WTF::TimeType outputTimeType, GregorianDateTime& tm)
{
LocalTimeOffset localTime;
if (outputTimeType == WTF::LocalTime) {
- localTime = localTimeOffset(cache, ms);
- ms += localTime.offset;
+ localTime = localTimeOffset(*this, millisecondsFromEpoch);
+ millisecondsFromEpoch += localTime.offset;
}
- tm = GregorianDateTime(ms, localTime);
+ tm = GregorianDateTime(millisecondsFromEpoch, localTime);
}
-static double parseDate(VM::DateCache& cache, const char* dateString)
+double DateCache::parseDate(JSGlobalObject* globalObject, VM& vm, const String& date)
{
- bool isLocalTime;
- double value = WTF::parseES5DateFromNullTerminatedCharacters(dateString, isLocalTime);
- if (std::isnan(value))
- value = WTF::parseDateFromNullTerminatedCharacters(dateString, isLocalTime);
-
- if (isLocalTime)
- value -= localTimeOffset(cache, value, WTF::LocalTime).offset;
-
- return value;
-}
-
-double parseDate(JSGlobalObject* globalObject, VM& vm, const String& date)
-{
auto scope = DECLARE_THROW_SCOPE(vm);
- auto& cache = vm.dateCache;
- if (date == cache.cachedDateString)
- return cache.cachedDateStringValue;
+ if (date == m_cachedDateString)
+ return m_cachedDateStringValue;
auto expectedString = date.tryGetUtf8();
if (!expectedString) {
if (expectedString.error() == UTF8ConversionError::OutOfMemory)
@@ -200,11 +163,47 @@
return std::numeric_limits<double>::quiet_NaN();
}
+ auto parseDateImpl = [this] (const char* dateString) {
+ bool isLocalTime;
+ double value = WTF::parseES5DateFromNullTerminatedCharacters(dateString, isLocalTime);
+ if (std::isnan(value))
+ value = WTF::parseDateFromNullTerminatedCharacters(dateString, isLocalTime);
+
+ if (isLocalTime)
+ value -= localTimeOffset(*this, value, WTF::LocalTime).offset;
+
+ return value;
+ };
+
auto dateUtf8 = expectedString.value();
- double value = parseDate(cache, dateUtf8.data());
- cache.cachedDateString = date;
- cache.cachedDateStringValue = value;
+ double value = parseDateImpl(dateUtf8.data());
+ m_cachedDateString = date;
+ m_cachedDateStringValue = value;
return value;
}
+// To confine icu::TimeZone destructor invocation in this file.
+DateCache::DateCache() = default;
+DateCache::~DateCache() = default;
+
+Ref<DateInstanceData> DateCache::cachedDateInstanceData(double millisecondsFromEpoch)
+{
+ return *m_dateInstanceCache.add(millisecondsFromEpoch);
+}
+
+void DateCache::timeZoneCacheSlow()
+{
+ // Do not use icu::TimeZone::createDefault. ICU internally has a cache for timezone and createDefault returns this cached value.
+ ASSERT(!m_timeZoneCache);
+ m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(icu::TimeZone::detectHostTimeZone()));
+}
+
+void DateCache::reset()
+{
+ m_timeZoneCache.reset();
+ m_cachedDateString = String();
+ m_cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
+ m_dateInstanceCache.reset();
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSDateMath.h (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/JSDateMath.h 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/JSDateMath.h 2020-11-03 19:26:49 UTC (rev 269320)
@@ -42,7 +42,7 @@
#pragma once
-#include "VMInlines.h"
+#include "DateInstanceCache.h"
#include <wtf/DateMath.h>
#include <wtf/GregorianDateTime.h>
@@ -49,11 +49,44 @@
namespace JSC {
class JSGlobalObject;
+class OpaqueICUTimeZone;
class VM;
-JS_EXPORT_PRIVATE void msToGregorianDateTime(VM::DateCache&, double, WTF::TimeType outputTimeType, GregorianDateTime&);
-JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM::DateCache&, const GregorianDateTime&, double, WTF::TimeType inputTimeType);
-JS_EXPORT_PRIVATE double getUTCOffset(VM::DateCache&);
-JS_EXPORT_PRIVATE double parseDate(JSGlobalObject*, VM&, const WTF::String&);
+// We do not expose icu::TimeZone in this header file. And we cannot use icu::TimeZone forward declaration
+// because icu namespace can be an alias to icu$verNum namespace.
+struct OpaqueICUTimeZoneDeleter {
+ JS_EXPORT_PRIVATE void operator()(OpaqueICUTimeZone*);
+};
+class DateCache {
+ WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(DateCache);
+public:
+ DateCache();
+ ~DateCache();
+
+ JS_EXPORT_PRIVATE void reset();
+
+ OpaqueICUTimeZone* timeZoneCache()
+ {
+ if (!m_timeZoneCache)
+ timeZoneCacheSlow();
+ return m_timeZoneCache.get();
+ }
+
+ Ref<DateInstanceData> cachedDateInstanceData(double millisecondsFromEpoch);
+
+ void msToGregorianDateTime(double millisecondsFromEpoch, WTF::TimeType outputTimeType, GregorianDateTime&);
+ double gregorianDateTimeToMS(const GregorianDateTime&, double milliseconds, WTF::TimeType inputTimeType);
+ double parseDate(JSGlobalObject*, VM&, const WTF::String&);
+
+private:
+ void timeZoneCacheSlow();
+
+ std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter> m_timeZoneCache;
+ String m_cachedDateString;
+ double m_cachedDateStringValue;
+ DateInstanceCache m_dateInstanceCache;
+};
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/VM.cpp 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp 2020-11-03 19:26:49 UTC (rev 269320)
@@ -889,15 +889,6 @@
{
}
-void VM::resetDateCache()
-{
- dateCache.utcTimeOffsetCache.reset();
- dateCache.localTimeOffsetCache.reset();
- dateCache.cachedDateString = String();
- dateCache.cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
- dateCache.dateInstanceCache.reset();
-}
-
void VM::whenIdle(Function<void()>&& callback)
{
if (!entryScope) {
Modified: trunk/Source/_javascript_Core/runtime/VM.h (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/VM.h 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2020-11-03 19:26:49 UTC (rev 269320)
@@ -32,7 +32,6 @@
#include "CodeSpecializationKind.h"
#include "CompleteSubspace.h"
#include "ConcurrentJSLock.h"
-#include "DateInstanceCache.h"
#include "DeleteAllCodeEffort.h"
#include "DisallowVMEntry.h"
#include "ExceptionEventLocation.h"
@@ -44,6 +43,7 @@
#include "IsoCellSet.h"
#include "IsoSubspace.h"
#include "JSCJSValue.h"
+#include "JSDateMath.h"
#include "JSLock.h"
#include "MacroAssemblerCodeRef.h"
#include "Microtask.h"
@@ -981,14 +981,6 @@
JSObject* stringRecursionCheckFirstObject { nullptr };
HashSet<JSObject*> stringRecursionCheckVisitedObjects;
- struct DateCache {
- DateInstanceCache dateInstanceCache;
- LocalTimeOffsetCache utcTimeOffsetCache;
- LocalTimeOffsetCache localTimeOffsetCache;
-
- String cachedDateString;
- double cachedDateStringValue;
- };
DateCache dateCache;
std::unique_ptr<Profiler::Database> m_perBytecodeProfiler;
@@ -1018,7 +1010,7 @@
RTTraceList* m_rtTraceList;
#endif
- JS_EXPORT_PRIVATE void resetDateCache();
+ void resetDateCache() { dateCache.reset(); }
RegExpCache* regExpCache() { return m_regExpCache; }
#if ENABLE(REGEXP_TRACING)
Modified: trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp (269319 => 269320)
--- trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp 2020-11-03 19:14:17 UTC (rev 269319)
+++ trunk/Source/_javascript_Core/runtime/VMEntryScope.cpp 2020-11-03 19:26:49 UTC (rev 269320)
@@ -43,6 +43,8 @@
// Reset the date cache between JS invocations to force the VM to
// observe time zone changes.
+ // FIXME: We should clear it only when we know the timezone has been changed.
+ // https://bugs.webkit.org/show_bug.cgi?id=218365
vm.resetDateCache();
if (vm.watchdog())