OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // ------------------------------------------------------------------- | 5 // ------------------------------------------------------------------- |
6 | 6 |
7 (function(global, utils) { | 7 (function(global, utils) { |
8 | 8 |
9 "use strict"; | 9 "use strict"; |
10 | 10 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 if (t == timezone_cache_time) { | 42 if (t == timezone_cache_time) { |
43 return timezone_cache_timezone; | 43 return timezone_cache_timezone; |
44 } | 44 } |
45 var timezone = %DateLocalTimezone(t); | 45 var timezone = %DateLocalTimezone(t); |
46 timezone_cache_time = t; | 46 timezone_cache_time = t; |
47 timezone_cache_timezone = timezone; | 47 timezone_cache_timezone = timezone; |
48 return timezone; | 48 return timezone; |
49 } | 49 } |
50 | 50 |
51 | 51 |
52 function UTC(time) { | |
53 if (NUMBER_IS_NAN(time)) return time; | |
54 // local_time_offset is needed before the call to DaylightSavingsOffset, | |
55 // so it may be uninitialized. | |
56 return %DateToUTC(time); | |
57 } | |
58 | |
59 | |
60 // ECMA 262 - 15.9.1.11 | 52 // ECMA 262 - 15.9.1.11 |
61 function MakeTime(hour, min, sec, ms) { | 53 function MakeTime(hour, min, sec, ms) { |
62 if (!IsFinite(hour)) return NaN; | 54 if (!IsFinite(hour)) return NaN; |
63 if (!IsFinite(min)) return NaN; | 55 if (!IsFinite(min)) return NaN; |
64 if (!IsFinite(sec)) return NaN; | 56 if (!IsFinite(sec)) return NaN; |
65 if (!IsFinite(ms)) return NaN; | 57 if (!IsFinite(ms)) return NaN; |
66 return TO_INTEGER(hour) * msPerHour | 58 return TO_INTEGER(hour) * msPerHour |
67 + TO_INTEGER(min) * msPerMinute | 59 + TO_INTEGER(min) * msPerMinute |
68 + TO_INTEGER(sec) * msPerSecond | 60 + TO_INTEGER(sec) * msPerSecond |
69 + TO_INTEGER(ms); | 61 + TO_INTEGER(ms); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 | 100 |
109 | 101 |
110 // ECMA 262 - 15.9.1.14 | 102 // ECMA 262 - 15.9.1.14 |
111 function TimeClip(time) { | 103 function TimeClip(time) { |
112 if (!IsFinite(time)) return NaN; | 104 if (!IsFinite(time)) return NaN; |
113 if (MathAbs(time) > MAX_TIME_MS) return NaN; | 105 if (MathAbs(time) > MAX_TIME_MS) return NaN; |
114 return TO_INTEGER(time) + 0; | 106 return TO_INTEGER(time) + 0; |
115 } | 107 } |
116 | 108 |
117 | 109 |
118 // The Date cache is used to limit the cost of parsing the same Date | |
119 // strings over and over again. | |
120 var Date_cache = { | |
121 // Cached time value. | |
122 time: 0, | |
123 // String input for which the cached time is valid. | |
124 string: null | |
125 }; | |
126 | |
127 | |
128 function DateConstructor(year, month, date, hours, minutes, seconds, ms) { | |
129 if (IS_UNDEFINED(new.target)) { | |
130 // ECMA 262 - 15.9.2 | |
131 return %_Call(DateToString, new GlobalDate()); | |
132 } | |
133 | |
134 // ECMA 262 - 15.9.3 | |
135 var argc = %_ArgumentsLength(); | |
136 var value; | |
137 var result; | |
138 if (argc == 0) { | |
139 value = %DateCurrentTime(); | |
140 result = %NewObject(GlobalDate, new.target); | |
141 SET_UTC_DATE_VALUE(result, value); | |
142 } else if (argc == 1) { | |
143 if (IS_NUMBER(year)) { | |
144 value = TimeClip(year); | |
145 | |
146 } else if (IS_STRING(year)) { | |
147 // Probe the Date cache. If we already have a time value for the | |
148 // given time, we re-use that instead of parsing the string again. | |
149 CheckDateCacheCurrent(); | |
150 var cache = Date_cache; | |
151 if (cache.string === year) { | |
152 value = cache.time; | |
153 } else { | |
154 value = DateParse(year); | |
155 if (!NUMBER_IS_NAN(value)) { | |
156 cache.time = value; | |
157 cache.string = year; | |
158 } | |
159 } | |
160 | |
161 } else if (IS_DATE(year)) { | |
162 value = UTC_DATE_VALUE(year); | |
163 | |
164 } else { | |
165 var time = TO_PRIMITIVE(year); | |
166 value = IS_STRING(time) ? DateParse(time) : TO_NUMBER(time); | |
167 } | |
168 result = %NewObject(GlobalDate, new.target); | |
169 SET_UTC_DATE_VALUE(result, value); | |
170 } else { | |
171 year = TO_NUMBER(year); | |
172 month = TO_NUMBER(month); | |
173 date = argc > 2 ? TO_NUMBER(date) : 1; | |
174 hours = argc > 3 ? TO_NUMBER(hours) : 0; | |
175 minutes = argc > 4 ? TO_NUMBER(minutes) : 0; | |
176 seconds = argc > 5 ? TO_NUMBER(seconds) : 0; | |
177 ms = argc > 6 ? TO_NUMBER(ms) : 0; | |
178 year = (!NUMBER_IS_NAN(year) && | |
179 0 <= TO_INTEGER(year) && | |
180 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year; | |
181 var day = MakeDay(year, month, date); | |
182 var time = MakeTime(hours, minutes, seconds, ms); | |
183 value = MakeDate(day, time); | |
184 result = %NewObject(GlobalDate, new.target); | |
185 SET_LOCAL_DATE_VALUE(result, value); | |
186 } | |
187 | |
188 return result; | |
189 } | |
190 | |
191 | |
192 var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; | 110 var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; |
193 var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', | 111 var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', |
194 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; | 112 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; |
195 | 113 |
196 | 114 |
197 function TwoDigitString(value) { | 115 function TwoDigitString(value) { |
198 return value < 10 ? "0" + value : "" + value; | 116 return value < 10 ? "0" + value : "" + value; |
199 } | 117 } |
200 | 118 |
201 | 119 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 } | 171 } |
254 | 172 |
255 | 173 |
256 function DatePrintString(date) { | 174 function DatePrintString(date) { |
257 CHECK_DATE(date); | 175 CHECK_DATE(date); |
258 return DateString(date) + ' ' + TimeString(date); | 176 return DateString(date) + ' ' + TimeString(date); |
259 } | 177 } |
260 | 178 |
261 // ------------------------------------------------------------------- | 179 // ------------------------------------------------------------------- |
262 | 180 |
263 // Reused output buffer. Used when parsing date strings. | |
264 var parse_buffer = new InternalArray(8); | |
265 | |
266 // ECMA 262 - 15.9.4.2 | |
267 function DateParse(string) { | |
268 var arr = %DateParseString(string, parse_buffer); | |
269 if (IS_NULL(arr)) return NaN; | |
270 | |
271 var day = MakeDay(arr[0], arr[1], arr[2]); | |
272 var time = MakeTime(arr[3], arr[4], arr[5], arr[6]); | |
273 var date = MakeDate(day, time); | |
274 | |
275 if (IS_NULL(arr[7])) { | |
276 return TimeClip(UTC(date)); | |
277 } else { | |
278 return TimeClip(date - arr[7] * 1000); | |
279 } | |
280 } | |
281 | |
282 | |
283 // ECMA 262 - 15.9.4.3 | |
284 function DateUTC(year, month, date, hours, minutes, seconds, ms) { | |
285 year = TO_NUMBER(year); | |
286 month = TO_NUMBER(month); | |
287 var argc = %_ArgumentsLength(); | |
288 date = argc > 2 ? TO_NUMBER(date) : 1; | |
289 hours = argc > 3 ? TO_NUMBER(hours) : 0; | |
290 minutes = argc > 4 ? TO_NUMBER(minutes) : 0; | |
291 seconds = argc > 5 ? TO_NUMBER(seconds) : 0; | |
292 ms = argc > 6 ? TO_NUMBER(ms) : 0; | |
293 year = (!NUMBER_IS_NAN(year) && | |
294 0 <= TO_INTEGER(year) && | |
295 TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year; | |
296 var day = MakeDay(year, month, date); | |
297 var time = MakeTime(hours, minutes, seconds, ms); | |
298 return TimeClip(MakeDate(day, time)); | |
299 } | |
300 | |
301 | |
302 // ECMA 262 - 15.9.4.4 | |
303 function DateNow() { | |
304 return %DateCurrentTime(); | |
305 } | |
306 | |
307 | |
308 // ECMA 262 - 15.9.5.2 | 181 // ECMA 262 - 15.9.5.2 |
309 function DateToString() { | 182 function DateToString() { |
310 CHECK_DATE(this); | 183 CHECK_DATE(this); |
311 var t = UTC_DATE_VALUE(this) | 184 var t = UTC_DATE_VALUE(this) |
312 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 185 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
313 var time_zone_string = LocalTimezoneString(this) | 186 var time_zone_string = LocalTimezoneString(this) |
314 return DatePrintString(this) + time_zone_string; | 187 return DatePrintString(this) + time_zone_string; |
315 } | 188 } |
316 | 189 |
317 | 190 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 | 225 |
353 // ECMA 262 - 15.9.5.7 | 226 // ECMA 262 - 15.9.5.7 |
354 function DateToLocaleTimeString() { | 227 function DateToLocaleTimeString() { |
355 CHECK_DATE(this); | 228 CHECK_DATE(this); |
356 var t = UTC_DATE_VALUE(this); | 229 var t = UTC_DATE_VALUE(this); |
357 if (NUMBER_IS_NAN(t)) return kInvalidDate; | 230 if (NUMBER_IS_NAN(t)) return kInvalidDate; |
358 return TimeString(this); | 231 return TimeString(this); |
359 } | 232 } |
360 | 233 |
361 | 234 |
362 // ECMA 262 - 15.9.5.8 | |
363 function DateValueOf() { | |
364 CHECK_DATE(this); | |
365 return UTC_DATE_VALUE(this); | |
366 } | |
367 | |
368 | |
369 // ECMA 262 - 15.9.5.9 | 235 // ECMA 262 - 15.9.5.9 |
370 function DateGetTime() { | 236 function DateGetTime() { |
371 CHECK_DATE(this); | 237 CHECK_DATE(this); |
372 return UTC_DATE_VALUE(this); | 238 return UTC_DATE_VALUE(this); |
373 } | 239 } |
374 | 240 |
375 | 241 |
376 // ECMA 262 - 15.9.5.10 | 242 // ECMA 262 - 15.9.5.10 |
377 function DateGetFullYear() { | 243 function DateGetFullYear() { |
378 CHECK_DATE(this); | 244 CHECK_DATE(this); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 // Notice that this does not follow ECMA 262 completely. ECMA 262 | 598 // Notice that this does not follow ECMA 262 completely. ECMA 262 |
733 // says that toGMTString should be the same Function object as | 599 // says that toGMTString should be the same Function object as |
734 // toUTCString. JSC does not do this, so for compatibility we do not | 600 // toUTCString. JSC does not do this, so for compatibility we do not |
735 // do that either. Instead, we create a new function whose name | 601 // do that either. Instead, we create a new function whose name |
736 // property will return toGMTString. | 602 // property will return toGMTString. |
737 function DateToGMTString() { | 603 function DateToGMTString() { |
738 return %_Call(DateToUTCString, this); | 604 return %_Call(DateToUTCString, this); |
739 } | 605 } |
740 | 606 |
741 | 607 |
742 function PadInt(n, digits) { | |
743 if (digits == 1) return n; | |
744 return n < %_MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n; | |
745 } | |
746 | |
747 | |
748 // ECMA 262 - 20.3.4.36 | |
749 function DateToISOString() { | |
750 CHECK_DATE(this); | |
751 var t = UTC_DATE_VALUE(this); | |
752 if (NUMBER_IS_NAN(t)) throw MakeRangeError(kInvalidTimeValue); | |
753 var year = UTC_YEAR(this); | |
754 var year_string; | |
755 if (year >= 0 && year <= 9999) { | |
756 year_string = PadInt(year, 4); | |
757 } else { | |
758 if (year < 0) { | |
759 year_string = "-" + PadInt(-year, 6); | |
760 } else { | |
761 year_string = "+" + PadInt(year, 6); | |
762 } | |
763 } | |
764 return year_string + | |
765 '-' + PadInt(UTC_MONTH(this) + 1, 2) + | |
766 '-' + PadInt(UTC_DAY(this), 2) + | |
767 'T' + PadInt(UTC_HOUR(this), 2) + | |
768 ':' + PadInt(UTC_MIN(this), 2) + | |
769 ':' + PadInt(UTC_SEC(this), 2) + | |
770 '.' + PadInt(UTC_MS(this), 3) + | |
771 'Z'; | |
772 } | |
773 | |
774 | |
775 // 20.3.4.37 Date.prototype.toJSON ( key ) | 608 // 20.3.4.37 Date.prototype.toJSON ( key ) |
776 function DateToJSON(key) { | 609 function DateToJSON(key) { |
777 var o = TO_OBJECT(this); | 610 var o = TO_OBJECT(this); |
778 var tv = TO_PRIMITIVE_NUMBER(o); | 611 var tv = TO_PRIMITIVE_NUMBER(o); |
779 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) { | 612 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) { |
780 return null; | 613 return null; |
781 } | 614 } |
782 return o.toISOString(); | 615 return o.toISOString(); |
783 } | 616 } |
784 | 617 |
785 | 618 |
786 var date_cache_version_holder; | 619 var date_cache_version_holder; |
787 var date_cache_version = NaN; | 620 var date_cache_version = NaN; |
788 | 621 |
789 | 622 |
790 function CheckDateCacheCurrent() { | 623 function CheckDateCacheCurrent() { |
791 if (!date_cache_version_holder) { | 624 if (!date_cache_version_holder) { |
792 date_cache_version_holder = %DateCacheVersion(); | 625 date_cache_version_holder = %DateCacheVersion(); |
793 if (!date_cache_version_holder) return; | 626 if (!date_cache_version_holder) return; |
794 } | 627 } |
795 if (date_cache_version_holder[0] == date_cache_version) { | 628 if (date_cache_version_holder[0] == date_cache_version) { |
796 return; | 629 return; |
797 } | 630 } |
798 date_cache_version = date_cache_version_holder[0]; | 631 date_cache_version = date_cache_version_holder[0]; |
799 | 632 |
800 // Reset the timezone cache: | 633 // Reset the timezone cache: |
801 timezone_cache_time = NaN; | 634 timezone_cache_time = NaN; |
802 timezone_cache_timezone = UNDEFINED; | 635 timezone_cache_timezone = UNDEFINED; |
803 | |
804 // Reset the date cache: | |
805 Date_cache.time = NaN; | |
806 Date_cache.string = null; | |
807 } | |
808 | |
809 | |
810 function CreateDate(time) { | |
811 var date = new GlobalDate(); | |
812 date.setTime(time); | |
813 return date; | |
814 } | 636 } |
815 | 637 |
816 // ------------------------------------------------------------------- | 638 // ------------------------------------------------------------------- |
817 | 639 |
818 %SetCode(GlobalDate, DateConstructor); | |
819 %FunctionSetPrototype(GlobalDate, new GlobalObject()); | 640 %FunctionSetPrototype(GlobalDate, new GlobalObject()); |
820 | 641 |
821 // Set up non-enumerable properties of the Date object itself. | |
822 utils.InstallFunctions(GlobalDate, DONT_ENUM, [ | |
823 "UTC", DateUTC, | |
824 "parse", DateParse, | |
825 "now", DateNow | |
826 ]); | |
827 | |
828 // Set up non-enumerable constructor property of the Date prototype object. | |
829 %AddNamedProperty(GlobalDate.prototype, "constructor", GlobalDate, DONT_ENUM); | |
830 | |
831 // Set up non-enumerable functions of the Date prototype object and | 642 // Set up non-enumerable functions of the Date prototype object and |
832 // set their names. | 643 // set their names. |
833 utils.InstallFunctions(GlobalDate.prototype, DONT_ENUM, [ | 644 utils.InstallFunctions(GlobalDate.prototype, DONT_ENUM, [ |
834 "toString", DateToString, | 645 "toString", DateToString, |
835 "toDateString", DateToDateString, | 646 "toDateString", DateToDateString, |
836 "toTimeString", DateToTimeString, | 647 "toTimeString", DateToTimeString, |
837 "toLocaleString", DateToLocaleString, | 648 "toLocaleString", DateToLocaleString, |
838 "toLocaleDateString", DateToLocaleDateString, | 649 "toLocaleDateString", DateToLocaleDateString, |
839 "toLocaleTimeString", DateToLocaleTimeString, | 650 "toLocaleTimeString", DateToLocaleTimeString, |
840 "valueOf", DateValueOf, | |
841 "getTime", DateGetTime, | 651 "getTime", DateGetTime, |
842 "getFullYear", DateGetFullYear, | 652 "getFullYear", DateGetFullYear, |
843 "getUTCFullYear", DateGetUTCFullYear, | 653 "getUTCFullYear", DateGetUTCFullYear, |
844 "getMonth", DateGetMonth, | 654 "getMonth", DateGetMonth, |
845 "getUTCMonth", DateGetUTCMonth, | 655 "getUTCMonth", DateGetUTCMonth, |
846 "getDate", DateGetDate, | 656 "getDate", DateGetDate, |
847 "getUTCDate", DateGetUTCDate, | 657 "getUTCDate", DateGetUTCDate, |
848 "getDay", DateGetDay, | 658 "getDay", DateGetDay, |
849 "getUTCDay", DateGetUTCDay, | 659 "getUTCDay", DateGetUTCDay, |
850 "getHours", DateGetHours, | 660 "getHours", DateGetHours, |
(...skipping 17 matching lines...) Expand all Loading... |
868 "setDate", DateSetDate, | 678 "setDate", DateSetDate, |
869 "setUTCDate", DateSetUTCDate, | 679 "setUTCDate", DateSetUTCDate, |
870 "setMonth", DateSetMonth, | 680 "setMonth", DateSetMonth, |
871 "setUTCMonth", DateSetUTCMonth, | 681 "setUTCMonth", DateSetUTCMonth, |
872 "setFullYear", DateSetFullYear, | 682 "setFullYear", DateSetFullYear, |
873 "setUTCFullYear", DateSetUTCFullYear, | 683 "setUTCFullYear", DateSetUTCFullYear, |
874 "toGMTString", DateToGMTString, | 684 "toGMTString", DateToGMTString, |
875 "toUTCString", DateToUTCString, | 685 "toUTCString", DateToUTCString, |
876 "getYear", DateGetYear, | 686 "getYear", DateGetYear, |
877 "setYear", DateSetYear, | 687 "setYear", DateSetYear, |
878 "toISOString", DateToISOString, | |
879 "toJSON", DateToJSON | 688 "toJSON", DateToJSON |
880 ]); | 689 ]); |
881 | 690 |
882 %InstallToContext(["create_date_fun", CreateDate]); | |
883 | |
884 }) | 691 }) |
OLD | NEW |