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 "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) 39extern "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 50using namespace WTF; 51 52namespace JSC { 53 54ASSERT_CLASS_FITS_IN_CELL(DateConstructor); 55 56static EncodedJSValue JSC_HOST_CALL dateParse(ExecState*); 57static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*); 58static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState*); 59 60DateConstructor::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 73JSObject* 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 127static 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 133ConstructType DateConstructor::getConstructData(ConstructData& constructData) 134{ 135 constructData.native.function = constructWithDateConstructor; 136 return ConstructTypeHost; 137} 138 139// ECMA 15.9.2 140static 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 153CallType DateConstructor::getCallData(CallData& callData) 154{ 155 callData.native.function = callDate; 156 return CallTypeHost; 157} 158 159static EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec) 160{ 161 return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec)))); 162} 163 164static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*) 165{ 166 return JSValue::encode(jsNumber(jsCurrentTime())); 167} 168 169static 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