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