| 1 | /* | 
| 2 |  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org) | 
| 3 |  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 
| 4 |  * | 
| 5 |  *  This library is free software; you can redistribute it and/or | 
| 6 |  *  modify it under the terms of the GNU Lesser General Public | 
| 7 |  *  License as published by the Free Software Foundation; either | 
| 8 |  *  version 2 of the License, or (at your option) any later version. | 
| 9 |  * | 
| 10 |  *  This library is distributed in the hope that it will be useful, | 
| 11 |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 12 |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
| 13 |  *  Lesser General Public License for more details. | 
| 14 |  * | 
| 15 |  *  You should have received a copy of the GNU Lesser General Public | 
| 16 |  *  License along with this library; if not, write to the Free Software | 
| 17 |  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 | 
| 18 |  *  USA | 
| 19 |  * | 
| 20 |  */ | 
| 21 |  | 
| 22 | #include "config.h" | 
| 23 | #include "DateConstructor.h" | 
| 24 |  | 
| 25 | #include "DateConversion.h" | 
| 26 | #include "DateInstance.h" | 
| 27 | #include "DatePrototype.h" | 
| 28 | #include "JSFunction.h" | 
| 29 | #include "JSGlobalObject.h" | 
| 30 | #include "JSString.h" | 
| 31 | #include "ObjectPrototype.h" | 
| 32 | #include "PrototypeFunction.h" | 
| 33 | #include <time.h> | 
| 34 | #include <wtf/DateMath.h> | 
| 35 | #include <wtf/MathExtras.h> | 
| 36 |  | 
| 37 | #if OS(WINCE) && !PLATFORM(QT) | 
| 38 | extern "C"  time_t time(time_t* timer); // Provided by libce. | 
| 39 | #endif | 
| 40 |  | 
| 41 | #if HAVE(SYS_TIME_H) | 
| 42 | #include <sys/time.h> | 
| 43 | #endif | 
| 44 |  | 
| 45 | #if HAVE(SYS_TIMEB_H) | 
| 46 | #include <sys/timeb.h> | 
| 47 | #endif | 
| 48 |  | 
| 49 | using namespace WTF; | 
| 50 |  | 
| 51 | namespace JSC { | 
| 52 |  | 
| 53 | ASSERT_CLASS_FITS_IN_CELL(DateConstructor); | 
| 54 |  | 
| 55 | static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const ArgList&); | 
| 56 | static JSValue JSC_HOST_CALL dateNow(ExecState*, JSObject*, JSValue, const ArgList&); | 
| 57 | static JSValue JSC_HOST_CALL dateUTC(ExecState*, JSObject*, JSValue, const ArgList&); | 
| 58 |  | 
| 59 | DateConstructor::DateConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype) | 
| 60 |     : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className)) | 
| 61 | { | 
| 62 |       putDirectWithoutTransition(propertyName: exec->propertyNames().prototype, value: datePrototype, attributes: DontEnum|DontDelete|ReadOnly); | 
| 63 |  | 
| 64 |       putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), attr: DontEnum); | 
| 65 |       putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), attr: DontEnum); | 
| 66 |       putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), attr: DontEnum); | 
| 67 |  | 
| 68 |       putDirectWithoutTransition(propertyName: exec->propertyNames().length, value: jsNumber(exec, i: 7), attributes: ReadOnly | DontEnum | DontDelete); | 
| 69 | } | 
| 70 |  | 
| 71 | // ECMA 15.9.3 | 
| 72 | JSObject* constructDate(ExecState* exec, const ArgList& args) | 
| 73 | { | 
| 74 |     int numArgs = args.size(); | 
| 75 |  | 
| 76 |     double value; | 
| 77 |  | 
| 78 |     if (numArgs == 0) // new Date() ECMA 15.9.3.3 | 
| 79 |         value = jsCurrentTime(); | 
| 80 |     else if (numArgs == 1) { | 
| 81 |         if (args.at(idx: 0).inherits(classInfo: &DateInstance::info)) | 
| 82 |             value = asDateInstance(value: args.at(idx: 0))->internalNumber(); | 
| 83 |         else { | 
| 84 |             JSValue primitive = args.at(idx: 0).toPrimitive(exec); | 
| 85 |             if (primitive.isString()) | 
| 86 |                 value = parseDate(exec, primitive.getString(exec)); | 
| 87 |             else | 
| 88 |                 value = primitive.toNumber(exec); | 
| 89 |         } | 
| 90 |     } else { | 
| 91 |         if (std::isnan(x: args.at(idx: 0).toNumber(exec)) | 
| 92 |                 || std::isnan(x: args.at(idx: 1).toNumber(exec)) | 
| 93 |                 || (numArgs >= 3 && std::isnan(x: args.at(idx: 2).toNumber(exec))) | 
| 94 |                 || (numArgs >= 4 && std::isnan(x: args.at(idx: 3).toNumber(exec))) | 
| 95 |                 || (numArgs >= 5 && std::isnan(x: args.at(idx: 4).toNumber(exec))) | 
| 96 |                 || (numArgs >= 6 && std::isnan(x: args.at(idx: 5).toNumber(exec))) | 
| 97 |                 || (numArgs >= 7 && std::isnan(x: args.at(idx: 6).toNumber(exec)))) | 
| 98 |             value = NaN; | 
| 99 |         else { | 
| 100 |             GregorianDateTime t; | 
| 101 |             int year = args.at(idx: 0).toInt32(exec); | 
| 102 |             t.year = (year >= 0 && year <= 99) ? year : year - 1900; | 
| 103 |             t.month = args.at(idx: 1).toInt32(exec); | 
| 104 |             t.monthDay = (numArgs >= 3) ? args.at(idx: 2).toInt32(exec) : 1; | 
| 105 |             t.hour = args.at(idx: 3).toInt32(exec); | 
| 106 |             t.minute = args.at(idx: 4).toInt32(exec); | 
| 107 |             t.second = args.at(idx: 5).toInt32(exec); | 
| 108 |             t.isDST = -1; | 
| 109 |             double ms = (numArgs >= 7) ? args.at(idx: 6).toNumber(exec) : 0; | 
| 110 |             value = gregorianDateTimeToMS(exec, t, ms, inputIsUTC: false); | 
| 111 |         } | 
| 112 |     } | 
| 113 |  | 
| 114 |     return new (exec) DateInstance(exec, value); | 
| 115 | } | 
| 116 |      | 
| 117 | static JSObject* constructWithDateConstructor(ExecState* exec, JSObject*, const ArgList& args) | 
| 118 | { | 
| 119 |     return constructDate(exec, args); | 
| 120 | } | 
| 121 |  | 
| 122 | ConstructType DateConstructor::getConstructData(ConstructData& constructData) | 
| 123 | { | 
| 124 |     constructData.native.function = constructWithDateConstructor; | 
| 125 |     return ConstructTypeHost; | 
| 126 | } | 
| 127 |  | 
| 128 | // ECMA 15.9.2 | 
| 129 | static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const ArgList&) | 
| 130 | { | 
| 131 |     GregorianDateTime ts; | 
| 132 |     msToGregorianDateTime(exec, currentTimeMS(), outputIsUTC: false, ts); | 
| 133 |     DateConversionBuffer date; | 
| 134 |     DateConversionBuffer time; | 
| 135 |     formatDate(ts, date); | 
| 136 |     formatTime(ts, time); | 
| 137 |     return jsNontrivialString(exec, s: makeString(string1: date, string2: " " , string3: time)); | 
| 138 | } | 
| 139 |  | 
| 140 | CallType DateConstructor::getCallData(CallData& callData) | 
| 141 | { | 
| 142 |     callData.native.function = callDate; | 
| 143 |     return CallTypeHost; | 
| 144 | } | 
| 145 |  | 
| 146 | static JSValue JSC_HOST_CALL dateParse(ExecState* exec, JSObject*, JSValue, const ArgList& args) | 
| 147 | { | 
| 148 |     return jsNumber(exec, d: parseDate(exec, args.at(idx: 0).toString(exec))); | 
| 149 | } | 
| 150 |  | 
| 151 | static JSValue JSC_HOST_CALL dateNow(ExecState* exec, JSObject*, JSValue, const ArgList&) | 
| 152 | { | 
| 153 |     return jsNumber(exec, d: jsCurrentTime()); | 
| 154 | } | 
| 155 |  | 
| 156 | static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const ArgList& args)  | 
| 157 | { | 
| 158 |     int n = args.size(); | 
| 159 |     if (std::isnan(x: args.at(idx: 0).toNumber(exec)) | 
| 160 |             || std::isnan(x: args.at(idx: 1).toNumber(exec)) | 
| 161 |             || (n >= 3 && std::isnan(x: args.at(idx: 2).toNumber(exec))) | 
| 162 |             || (n >= 4 && std::isnan(x: args.at(idx: 3).toNumber(exec))) | 
| 163 |             || (n >= 5 && std::isnan(x: args.at(idx: 4).toNumber(exec))) | 
| 164 |             || (n >= 6 && std::isnan(x: args.at(idx: 5).toNumber(exec))) | 
| 165 |             || (n >= 7 && std::isnan(x: args.at(idx: 6).toNumber(exec)))) | 
| 166 |         return jsNaN(exec); | 
| 167 |  | 
| 168 |     GregorianDateTime t; | 
| 169 |     int year = args.at(idx: 0).toInt32(exec); | 
| 170 |     t.year = (year >= 0 && year <= 99) ? year : year - 1900; | 
| 171 |     t.month = args.at(idx: 1).toInt32(exec); | 
| 172 |     t.monthDay = (n >= 3) ? args.at(idx: 2).toInt32(exec) : 1; | 
| 173 |     t.hour = args.at(idx: 3).toInt32(exec); | 
| 174 |     t.minute = args.at(idx: 4).toInt32(exec); | 
| 175 |     t.second = args.at(idx: 5).toInt32(exec); | 
| 176 |     double ms = (n >= 7) ? args.at(idx: 6).toNumber(exec) : 0; | 
| 177 |     return jsNumber(exec, d: timeClip(gregorianDateTimeToMS(exec, t, ms, inputIsUTC: true))); | 
| 178 | } | 
| 179 |  | 
| 180 | } // namespace JSC | 
| 181 |  |