1 /* 2 * Copyright (C) 1999-2000 Harri Porten (porten (at) 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 "JSStringBuilder.h" 32 #include "ObjectPrototype.h" 33 #include <math.h> 34 #include <time.h> 35 #include <wtf/DateMath.h> 36 #include <wtf/MathExtras.h> 37 38 #if OS(WINCE) && !PLATFORM(QT) 39 extern "C" time_t time(time_t* timer); // Provided by libce. 40 #endif 41 42 #if HAVE(SYS_TIME_H) 43 #include <sys/time.h> 44 #endif 45 46 #if HAVE(SYS_TIMEB_H) 47 #include <sys/timeb.h> 48 #endif 49 50 using namespace WTF; 51 52 namespace JSC { 53 54 ASSERT_CLASS_FITS_IN_CELL(DateConstructor); 55 56 static EncodedJSValue JSC_HOST_CALL dateParse(ExecState*); 57 static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*); 58 static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState*); 59 60 DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure, DatePrototype* datePrototype) 61 : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, datePrototype->classInfo()->className)) 62 { 63 putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly); 64 65 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum); 66 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum); 67 putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().now, dateNow), DontEnum); 68 69 putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete); 70 } 71 72 // ECMA 15.9.3 73 JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) 74 { 75 int numArgs = args.size(); 76 77 double value; 78 79 if (numArgs == 0) // new Date() ECMA 15.9.3.3 80 value = jsCurrentTime(); 81 else if (numArgs == 1) { 82 if (args.at(0).inherits(&DateInstance::s_info)) 83 value = asDateInstance(args.at(0))->internalNumber(); 84 else { 85 JSValue primitive = args.at(0).toPrimitive(exec); 86 if (primitive.isString()) 87 value = parseDate(exec, primitive.getString(exec)); 88 else 89 value = primitive.toNumber(exec); 90 } 91 } else { 92 double doubleArguments[7] = { 93 args.at(0).toNumber(exec), 94 args.at(1).toNumber(exec), 95 args.at(2).toNumber(exec), 96 args.at(3).toNumber(exec), 97 args.at(4).toNumber(exec), 98 args.at(5).toNumber(exec), 99 args.at(6).toNumber(exec) 100 }; 101 if (isnan(doubleArguments[0]) 102 || isnan(doubleArguments[1]) 103 || (numArgs >= 3 && isnan(doubleArguments[2])) 104 || (numArgs >= 4 && isnan(doubleArguments[3])) 105 || (numArgs >= 5 && isnan(doubleArguments[4])) 106 || (numArgs >= 6 && isnan(doubleArguments[5])) 107 || (numArgs >= 7 && isnan(doubleArguments[6]))) 108 value = NaN; 109 else { 110 GregorianDateTime t; 111 int year = JSC::toInt32(doubleArguments[0]); 112 t.year = (year >= 0 && year <= 99) ? year : year - 1900; 113 t.month = JSC::toInt32(doubleArguments[1]); 114 t.monthDay = (numArgs >= 3) ? JSC::toInt32(doubleArguments[2]) : 1; 115 t.hour = JSC::toInt32(doubleArguments[3]); 116 t.minute = JSC::toInt32(doubleArguments[4]); 117 t.second = JSC::toInt32(doubleArguments[5]); 118 t.isDST = -1; 119 double ms = (numArgs >= 7) ? doubleArguments[6] : 0; 120 value = gregorianDateTimeToMS(exec, t, ms, false); 121 } 122 } 123 124 return new (exec) DateInstance(exec, globalObject->dateStructure(), value); 125 } 126 127 static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(ExecState* exec) 128 { 129 ArgList args(exec); 130 return JSValue::encode(constructDate(exec, asInternalFunction(exec->callee())->globalObject(), args)); 131 } 132 133 ConstructType DateConstructor::getConstructData(ConstructData& constructData) 134 { 135 constructData.native.function = constructWithDateConstructor; 136 return ConstructTypeHost; 137 } 138 139 // ECMA 15.9.2 140 static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec) 141 { 142 time_t localTime = time(0); 143 tm localTM; 144 getLocalTime(&localTime, &localTM); 145 GregorianDateTime ts(exec, localTM); 146 DateConversionBuffer date; 147 DateConversionBuffer time; 148 formatDate(ts, date); 149 formatTime(ts, time); 150 return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time)); 151 } 152 153 CallType DateConstructor::getCallData(CallData& callData) 154 { 155 callData.native.function = callDate; 156 return CallTypeHost; 157 } 158 159 static EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec) 160 { 161 return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec)))); 162 } 163 164 static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*) 165 { 166 return JSValue::encode(jsNumber(jsCurrentTime())); 167 } 168 169 static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState* exec) 170 { 171 double doubleArguments[7] = { 172 exec->argument(0).toNumber(exec), 173 exec->argument(1).toNumber(exec), 174 exec->argument(2).toNumber(exec), 175 exec->argument(3).toNumber(exec), 176 exec->argument(4).toNumber(exec), 177 exec->argument(5).toNumber(exec), 178 exec->argument(6).toNumber(exec) 179 }; 180 int n = exec->argumentCount(); 181 if (isnan(doubleArguments[0]) 182 || isnan(doubleArguments[1]) 183 || (n >= 3 && isnan(doubleArguments[2])) 184 || (n >= 4 && isnan(doubleArguments[3])) 185 || (n >= 5 && isnan(doubleArguments[4])) 186 || (n >= 6 && isnan(doubleArguments[5])) 187 || (n >= 7 && isnan(doubleArguments[6]))) 188 return JSValue::encode(jsNaN()); 189 190 GregorianDateTime t; 191 int year = JSC::toInt32(doubleArguments[0]); 192 t.year = (year >= 0 && year <= 99) ? year : year - 1900; 193 t.month = JSC::toInt32(doubleArguments[1]); 194 t.monthDay = (n >= 3) ? JSC::toInt32(doubleArguments[2]) : 1; 195 t.hour = JSC::toInt32(doubleArguments[3]); 196 t.minute = JSC::toInt32(doubleArguments[4]); 197 t.second = JSC::toInt32(doubleArguments[5]); 198 double ms = (n >= 7) ? doubleArguments[6] : 0; 199 return JSValue::encode(jsNumber(timeClip(gregorianDateTimeToMS(exec, t, ms, true)))); 200 } 201 202 } // namespace JSC 203