Changeset 34854 in webkit for trunk/JavaScriptCore/kjs
- Timestamp:
- Jun 28, 2008, 2:22:01 PM (17 years ago)
- Location:
- trunk/JavaScriptCore/kjs
- Files:
-
- 17 edited
- 8 copied
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/AllInOneFile.cpp
r34843 r34854 44 44 #include "dtoa.cpp" 45 45 #include "error_object.cpp" 46 #include "FunctionConstructor.cpp" 46 47 #include "FunctionPrototype.cpp" 47 48 #include "grammar.cpp" … … 58 59 #include "nodes.cpp" 59 60 #include "nodes2string.cpp" 61 #include "NumberConstructor.cpp" 60 62 #include "NumberObject.cpp" 63 #include "NumberPrototype.cpp" 61 64 #include "JSObject.cpp" 62 65 #include "JSGlobalObject.cpp" 63 #include "object_object.cpp" 66 #include "ObjectConstructor.cpp" 67 #include "ObjectPrototype.cpp" 64 68 #include "operations.cpp" 65 69 #include "Parser.cpp" … … 73 77 #include "ustring.cpp" 74 78 #include "JSValue.cpp" 79 #include "JSVariableObject.cpp" 75 80 #include "wtf/FastMalloc.cpp" 76 81 #include "wtf/TCSystemAlloc.cpp" -
trunk/JavaScriptCore/kjs/ArrayConstructor.cpp
r34843 r34854 26 26 27 27 #include "ArrayPrototype.h" 28 #include "FunctionPrototype.h" 28 29 #include "JSArray.h" 29 30 #include "error_object.h" -
trunk/JavaScriptCore/kjs/ArrayConstructor.h
r34843 r34854 22 22 #define ArrayConstructor_h 23 23 24 #include " FunctionPrototype.h"24 #include "JSFunction.h" 25 25 26 26 namespace KJS { 27 27 28 28 class ArrayPrototype; 29 class FunctionPrototype; 29 30 30 31 class ArrayConstructor : public InternalFunction { -
trunk/JavaScriptCore/kjs/FunctionConstructor.cpp
r34853 r34854 20 20 21 21 #include "config.h" 22 #include "FunctionConstructor.h" 23 22 24 #include "FunctionPrototype.h" 23 25 #include "JSFunction.h" 24 26 #include "JSGlobalObject.h" 27 #include "JSString.h" 25 28 #include "Parser.h" 26 29 #include "debugger.h" 27 #include "JSArray.h"28 #include "JSFunction.h"29 #include "JSString.h"30 30 #include "lexer.h" 31 31 #include "nodes.h" 32 #include "JSObject.h"33 #include <stdio.h>34 #include <string.h>35 #include <wtf/Assertions.h>36 32 37 33 namespace KJS { 38 39 // ------------------------------ FunctionPrototype -------------------------40 41 static JSValue* functionProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);42 static JSValue* functionProtoFuncApply(ExecState*, JSObject*, JSValue*, const ArgList&);43 static JSValue* functionProtoFuncCall(ExecState*, JSObject*, JSValue*, const ArgList&);44 45 FunctionPrototype::FunctionPrototype(ExecState* exec)46 {47 putDirect(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);48 49 putDirectFunction(new (exec) PrototypeFunction(exec, this, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);50 putDirectFunction(new (exec) PrototypeFunction(exec, this, 2, exec->propertyNames().apply, functionProtoFuncApply), DontEnum);51 putDirectFunction(new (exec) PrototypeFunction(exec, this, 1, exec->propertyNames().call, functionProtoFuncCall), DontEnum);52 }53 54 static JSValue* callFunctionPrototype(ExecState*, JSObject*, JSValue*, const ArgList&)55 {56 return jsUndefined();57 }58 59 // ECMA 15.3.460 CallType FunctionPrototype::getCallData(CallData& callData)61 {62 callData.native.function = callFunctionPrototype;63 return CallTypeNative;64 }65 66 // Functions67 68 JSValue* functionProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)69 {70 if (!thisValue->isObject(&InternalFunction::info))71 return throwError(exec, TypeError);72 73 InternalFunction* function = static_cast<InternalFunction*>(thisValue);74 75 if (function->inherits(&JSFunction::info)) {76 JSFunction* fi = static_cast<JSFunction*>(thisValue);77 return jsString(exec, "function " + fi->functionName().ustring() + "(" + fi->body->paramString() + ") " + fi->body->toSourceString());78 }79 80 return jsString(exec, "function " + function->functionName().ustring() + "() {\n [native code]\n}");81 }82 83 JSValue* functionProtoFuncApply(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)84 {85 CallData callData;86 CallType callType = thisValue->getCallData(callData);87 if (callType == CallTypeNone)88 return throwError(exec, TypeError);89 90 JSValue* thisArg = args[0];91 JSValue* argArray = args[1];92 93 JSValue* applyThis;94 if (thisArg->isUndefinedOrNull())95 applyThis = exec->globalThisValue();96 else97 applyThis = thisArg->toObject(exec);98 99 ArgList applyArgs;100 if (!argArray->isUndefinedOrNull()) {101 if (argArray->isObject() &&102 (static_cast<JSObject*>(argArray)->inherits(&JSArray::info) ||103 static_cast<JSObject*>(argArray)->inherits(&Arguments::info))) {104 105 JSObject* argArrayObj = static_cast<JSObject*>(argArray);106 unsigned int length = argArrayObj->get(exec, exec->propertyNames().length)->toUInt32(exec);107 for (unsigned int i = 0; i < length; i++)108 applyArgs.append(argArrayObj->get(exec, i));109 } else110 return throwError(exec, TypeError);111 }112 113 return call(exec, thisValue, callType, callData, applyThis, applyArgs);114 }115 116 JSValue* functionProtoFuncCall(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)117 {118 CallData callData;119 CallType callType = thisValue->getCallData(callData);120 if (callType == CallTypeNone)121 return throwError(exec, TypeError);122 123 JSValue* thisArg = args[0];124 125 JSObject* callThis;126 if (thisArg->isUndefinedOrNull())127 callThis = exec->globalThisValue();128 else129 callThis = thisArg->toObject(exec);130 131 ArgList argsTail;132 args.getSlice(1, argsTail);133 return call(exec, thisValue, callType, callData, callThis, argsTail);134 }135 136 // ------------------------------ FunctionConstructor ----------------------------137 34 138 35 FunctionConstructor::FunctionConstructor(ExecState* exec, FunctionPrototype* functionPrototype) -
trunk/JavaScriptCore/kjs/FunctionConstructor.h
r34853 r34854 21 21 */ 22 22 23 #ifndef Function Prototype_h24 #define Function Prototype_h23 #ifndef FunctionConstructor_h 24 #define FunctionConstructor_h 25 25 26 #include "object_object.h"27 26 #include "JSFunction.h" 28 27 29 28 namespace KJS { 30 29 31 /** 32 * @internal 33 * 34 * The initial value of Function.prototype (and thus all objects created 35 * with the Function constructor) 36 */ 37 class FunctionPrototype : public InternalFunction { 38 public: 39 FunctionPrototype(ExecState*); 40 private: 41 virtual CallType getCallData(CallData&); 42 }; 30 class FunctionPrototype; 43 31 44 32 /** … … 60 48 } // namespace KJS 61 49 62 #endif // _FUNCTION_OBJECT_H_50 #endif // FunctionConstructor_h -
trunk/JavaScriptCore/kjs/FunctionPrototype.cpp
r34844 r34854 22 22 #include "FunctionPrototype.h" 23 23 24 #include "JSGlobalObject.h"25 #include "Parser.h"26 #include "debugger.h"27 #include "JSArray.h"28 #include "JSFunction.h"29 24 #include "JSString.h" 30 #include "lexer.h"31 #include "nodes.h"32 #include "JSObject.h"33 #include <stdio.h>34 #include <string.h>35 #include <wtf/Assertions.h>36 25 37 26 namespace KJS { 38 39 // ------------------------------ FunctionPrototype -------------------------40 27 41 28 static JSValue* functionProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); … … 134 121 } 135 122 136 // ------------------------------ FunctionConstructor ----------------------------137 138 FunctionConstructor::FunctionConstructor(ExecState* exec, FunctionPrototype* functionPrototype)139 : InternalFunction(functionPrototype, Identifier(exec, functionPrototype->classInfo()->className))140 {141 putDirect(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);142 143 // Number of arguments for constructor144 putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum);145 }146 147 static JSObject* constructWithFunctionConstructor(ExecState* exec, JSObject*, const ArgList& args)148 {149 return constructFunction(exec, args);150 }151 152 ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)153 {154 constructData.native.function = constructWithFunctionConstructor;155 return ConstructTypeNative;156 }157 158 static JSValue* callFunctionConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)159 {160 return constructFunction(exec, args);161 }162 163 // ECMA 15.3.1 The Function Constructor Called as a Function164 CallType FunctionConstructor::getCallData(CallData& callData)165 {166 callData.native.function = callFunctionConstructor;167 return CallTypeNative;168 }169 170 // ECMA 15.3.2 The Function Constructor171 JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)172 {173 UString p("");174 UString body;175 int argsSize = args.size();176 if (argsSize == 0)177 body = "";178 else if (argsSize == 1)179 body = args[0]->toString(exec);180 else {181 p = args[0]->toString(exec);182 for (int k = 1; k < argsSize - 1; k++)183 p += "," + args[k]->toString(exec);184 body = args[argsSize - 1]->toString(exec);185 }186 187 // parse the source code188 int sourceId;189 int errLine;190 UString errMsg;191 RefPtr<SourceProvider> source = UStringSourceProvider::create(body);192 RefPtr<FunctionBodyNode> functionBody = exec->parser()->parse<FunctionBodyNode>(exec, sourceURL, lineNumber, source, &sourceId, &errLine, &errMsg);193 194 // No program node == syntax error - throw a syntax error195 if (!functionBody)196 // We can't return a Completion(Throw) here, so just set the exception197 // and return it198 return throwError(exec, SyntaxError, errMsg, errLine, sourceId, sourceURL);199 200 functionBody->setSource(SourceRange(source, 0, source->length()));201 ScopeChain scopeChain(exec->lexicalGlobalObject(), exec->globalThisValue());202 203 JSFunction* function = new (exec) JSFunction(exec, functionName, functionBody.get(), scopeChain.node());204 205 // parse parameter list. throw syntax error on illegal identifiers206 int len = p.size();207 const UChar* c = p.data();208 int i = 0, params = 0;209 UString param;210 while (i < len) {211 while (*c == ' ' && i < len)212 c++, i++;213 if (Lexer::isIdentStart(c[0])) { // else error214 param = UString(c, 1);215 c++, i++;216 while (i < len && (Lexer::isIdentPart(c[0]))) {217 param.append(*c);218 c++, i++;219 }220 while (i < len && *c == ' ')221 c++, i++;222 if (i == len) {223 functionBody->parameters().append(Identifier(exec, param));224 params++;225 break;226 } else if (*c == ',') {227 functionBody->parameters().append(Identifier(exec, param));228 params++;229 c++, i++;230 continue;231 } // else error232 }233 return throwError(exec, SyntaxError, "Syntax error in parameter list");234 }235 236 JSObject* prototype = constructEmptyObject(exec);237 prototype->putDirect(exec->propertyNames().constructor, function, DontEnum);238 function->putDirect(exec->propertyNames().prototype, prototype, DontDelete);239 return function;240 }241 242 // ECMA 15.3.2 The Function Constructor243 JSObject* constructFunction(ExecState* exec, const ArgList& args)244 {245 return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1);246 }247 248 123 } // namespace KJS -
trunk/JavaScriptCore/kjs/FunctionPrototype.h
r34754 r34854 24 24 #define FunctionPrototype_h 25 25 26 #include "object_object.h"27 26 #include "JSFunction.h" 28 27 … … 42 41 }; 43 42 44 /**45 * @internal46 *47 * The initial value of the the global variable's "Function" property48 */49 class FunctionConstructor : public InternalFunction {50 public:51 FunctionConstructor(ExecState*, FunctionPrototype*);52 private:53 virtual ConstructType getConstructData(ConstructData&);54 virtual CallType getCallData(CallData&);55 };56 57 JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);58 JSObject* constructFunction(ExecState*, const ArgList&);59 60 43 } // namespace KJS 61 44 62 #endif // _FUNCTION_OBJECT_H_45 #endif // FunctionPrototype_h -
trunk/JavaScriptCore/kjs/JSFunction.cpp
r34838 r34854 28 28 29 29 #include "ExecState.h" 30 #include "FunctionPrototype.h" 30 31 #include "JSActivation.h" 31 32 #include "JSGlobalObject.h" 33 #include "JSString.h" 32 34 #include "Machine.h" 35 #include "ObjectPrototype.h" 33 36 #include "Parser.h" 34 37 #include "PropertyNameArray.h" 38 #include "ScopeChainMark.h" 35 39 #include "debugger.h" 36 40 #include "dtoa.h" 37 #include "FunctionPrototype.h"38 #include "JSString.h"39 41 #include "lexer.h" 40 42 #include "nodes.h" 41 43 #include "operations.h" 42 #include "ScopeChainMark.h"43 44 #include <errno.h> 44 45 #include <profiler/Profiler.h> -
trunk/JavaScriptCore/kjs/JSGlobalObject.cpp
r34843 r34854 31 31 #include "JSGlobalObject.h" 32 32 33 #include "ArrayConstructor.h" 34 #include "ArrayPrototype.h" 35 #include "BooleanConstructor.h" 36 #include "BooleanPrototype.h" 33 37 #include "CodeBlock.h" 34 #include "ArrayPrototype.h" 35 #include "ArrayConstructor.h" 36 #include "BooleanPrototype.h" 37 #include "BooleanConstructor.h" 38 #include "FunctionConstructor.h" 39 #include "FunctionPrototype.h" 40 #include "Machine.h" 41 #include "MathObject.h" 42 #include "NumberConstructor.h" 43 #include "NumberPrototype.h" 44 #include "ObjectConstructor.h" 45 #include "ObjectPrototype.h" 46 #include "RegExpObject.h" 47 #include "ScopeChainMark.h" 38 48 #include "date_object.h" 39 49 #include "debugger.h" 40 50 #include "error_object.h" 41 #include "FunctionPrototype.h"42 #include "Machine.h"43 #include "MathObject.h"44 #include "NumberObject.h"45 #include "object_object.h"46 #include "RegExpObject.h"47 #include "ScopeChainMark.h"48 51 #include "string_object.h" 49 52 -
trunk/JavaScriptCore/kjs/JSImmediate.cpp
r34843 r34854 25 25 #include "JSGlobalObject.h" 26 26 #include "JSNotAnObject.h" 27 #include "Number Object.h"27 #include "NumberPrototype.h" 28 28 29 29 namespace KJS { -
trunk/JavaScriptCore/kjs/MathObject.h
r34754 r34854 21 21 #define MathObject_h 22 22 23 #include " FunctionPrototype.h"23 #include "JSObject.h" 24 24 #include "lookup.h" 25 25 -
trunk/JavaScriptCore/kjs/NumberConstructor.cpp
r34853 r34854 21 21 22 22 #include "config.h" 23 #include "NumberConstructor.h" 24 #include "NumberConstructor.lut.h" 25 23 26 #include "NumberObject.h" 24 #include "NumberObject.lut.h" 25 26 #include "dtoa.h" 27 #include "error_object.h" 28 #include "operations.h" 29 #include <wtf/Assertions.h> 30 #include <wtf/MathExtras.h> 31 #include <wtf/Vector.h> 27 #include "NumberPrototype.h" 32 28 33 29 namespace KJS { 34 30 35 // ------------------------------ NumberObject ----------------------------36 37 const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };38 39 NumberObject::NumberObject(JSObject* proto)40 : JSWrapperObject(proto)41 {42 }43 44 JSValue* NumberObject::getJSNumber()45 {46 return internalValue();47 }48 49 // ------------------------------ NumberPrototype ---------------------------50 51 static JSValue* numberProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);52 static JSValue* numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);53 static JSValue* numberProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&);54 static JSValue* numberProtoFuncToFixed(ExecState*, JSObject*, JSValue*, const ArgList&);55 static JSValue* numberProtoFuncToExponential(ExecState*, JSObject*, JSValue*, const ArgList&);56 static JSValue* numberProtoFuncToPrecision(ExecState*, JSObject*, JSValue*, const ArgList&);57 58 // ECMA 15.7.459 60 NumberPrototype::NumberPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)61 : NumberObject(objectPrototype)62 {63 setInternalValue(jsNumber(exec, 0));64 65 // The constructor will be added later, after NumberConstructor has been constructed66 67 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);68 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);69 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);70 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);71 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);72 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);73 }74 75 // ------------------------------ Functions ---------------------------76 77 // ECMA 15.7.4.2 - 15.7.4.778 79 static UString integer_part_noexp(double d)80 {81 int decimalPoint;82 int sign;83 char* result = dtoa(d, 0, &decimalPoint, &sign, NULL);84 bool resultIsInfOrNan = (decimalPoint == 9999);85 size_t length = strlen(result);86 87 UString str = sign ? "-" : "";88 if (resultIsInfOrNan)89 str += result;90 else if (decimalPoint <= 0)91 str += "0";92 else {93 Vector<char, 1024> buf(decimalPoint + 1);94 95 if (static_cast<int>(length) <= decimalPoint) {96 strcpy(buf.data(), result);97 memset(buf.data() + length, '0', decimalPoint - length);98 } else99 strncpy(buf.data(), result, decimalPoint);100 101 buf[decimalPoint] = '\0';102 str.append(buf.data());103 }104 105 freedtoa(result);106 107 return str;108 }109 110 static UString char_sequence(char c, int count)111 {112 Vector<char, 2048> buf(count + 1, c);113 buf[count] = '\0';114 115 return UString(buf.data());116 }117 118 static double intPow10(int e)119 {120 // This function uses the "exponentiation by squaring" algorithm and121 // long double to quickly and precisely calculate integer powers of 10.0.122 123 // This is a handy workaround for <rdar://problem/4494756>124 125 if (e == 0)126 return 1.0;127 128 bool negative = e < 0;129 unsigned exp = negative ? -e : e;130 131 long double result = 10.0;132 bool foundOne = false;133 for (int bit = 31; bit >= 0; bit--) {134 if (!foundOne) {135 if ((exp >> bit) & 1)136 foundOne = true;137 } else {138 result = result * result;139 if ((exp >> bit) & 1)140 result = result * 10.0;141 }142 }143 144 if (negative)145 return static_cast<double>(1.0 / result);146 return static_cast<double>(result);147 }148 149 150 JSValue* numberProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)151 {152 JSValue* v = thisValue->getJSNumber();153 if (!v)154 return throwError(exec, TypeError);155 156 double radixAsDouble = args[0]->toInteger(exec); // nan -> 0157 if (radixAsDouble == 10 || args[0]->isUndefined())158 return jsString(exec, v->toString(exec));159 160 if (radixAsDouble < 2 || radixAsDouble > 36)161 return throwError(exec, RangeError, "toString() radix argument must be between 2 and 36");162 163 int radix = static_cast<int>(radixAsDouble);164 const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";165 // INT_MAX results in 1024 characters left of the dot with radix 2166 // give the same space on the right side. safety checks are in place167 // unless someone finds a precise rule.168 char s[2048 + 3];169 const char* lastCharInString = s + sizeof(s) - 1;170 double x = v->uncheckedGetNumber();171 if (isnan(x) || isinf(x))172 return jsString(exec, UString::from(x));173 174 bool isNegative = x < 0.0;175 if (isNegative)176 x = -x;177 178 double integerPart = floor(x);179 char* decimalPoint = s + sizeof(s) / 2;180 181 // convert integer portion182 char* p = decimalPoint;183 double d = integerPart;184 do {185 int remainderDigit = static_cast<int>(fmod(d, radix));186 *--p = digits[remainderDigit];187 d /= radix;188 } while ((d <= -1.0 || d >= 1.0) && s < p);189 190 if (isNegative)191 *--p = '-';192 char* startOfResultString = p;193 ASSERT(s <= startOfResultString);194 195 d = x - integerPart;196 p = decimalPoint;197 const double epsilon = 0.001; // TODO: guessed. base on radix ?198 bool hasFractionalPart = (d < -epsilon || d > epsilon);199 if (hasFractionalPart) {200 *p++ = '.';201 do {202 d *= radix;203 const int digit = static_cast<int>(d);204 *p++ = digits[digit];205 d -= digit;206 } while ((d < -epsilon || d > epsilon) && p < lastCharInString);207 }208 *p = '\0';209 ASSERT(p < s + sizeof(s));210 211 return jsString(exec, startOfResultString);212 }213 214 JSValue* numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)215 {216 // FIXME: Not implemented yet.217 218 JSValue* v = thisValue->getJSNumber();219 if (!v)220 return throwError(exec, TypeError);221 222 return jsString(exec, v->toString(exec));223 }224 225 JSValue* numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)226 {227 JSValue* v = thisValue->getJSNumber();228 if (!v)229 return throwError(exec, TypeError);230 231 return v;232 }233 234 JSValue* numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)235 {236 JSValue* v = thisValue->getJSNumber();237 if (!v)238 return throwError(exec, TypeError);239 240 JSValue* fractionDigits = args[0];241 double df = fractionDigits->toInteger(exec);242 if (!(df >= 0 && df <= 20))243 return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20");244 int f = (int)df;245 246 double x = v->uncheckedGetNumber();247 if (isnan(x))248 return jsString(exec, "NaN");249 250 UString s;251 if (x < 0) {252 s.append('-');253 x = -x;254 } else if (x == -0.0)255 x = 0;256 257 if (x >= pow(10.0, 21.0))258 return jsString(exec, s + UString::from(x));259 260 const double tenToTheF = pow(10.0, f);261 double n = floor(x * tenToTheF);262 if (fabs(n / tenToTheF - x) >= fabs((n + 1) / tenToTheF - x))263 n++;264 265 UString m = integer_part_noexp(n);266 267 int k = m.size();268 if (k <= f) {269 UString z;270 for (int i = 0; i < f + 1 - k; i++)271 z.append('0');272 m = z + m;273 k = f + 1;274 ASSERT(k == m.size());275 }276 int kMinusf = k - f;277 if (kMinusf < m.size())278 return jsString(exec, s + m.substr(0, kMinusf) + "." + m.substr(kMinusf));279 return jsString(exec, s + m.substr(0, kMinusf));280 }281 282 static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)283 {284 if (fractionalDigits <= 0)285 return;286 287 int fDigitsInResult = static_cast<int>(resultLength) - 1;288 buf[i++] = '.';289 if (fDigitsInResult > 0) {290 if (fractionalDigits < fDigitsInResult) {291 strncpy(buf + i, result + 1, fractionalDigits);292 i += fractionalDigits;293 } else {294 strcpy(buf + i, result + 1);295 i += static_cast<int>(resultLength) - 1;296 }297 }298 299 for (int j = 0; j < fractionalDigits - fDigitsInResult; j++)300 buf[i++] = '0';301 }302 303 static void exponentialPartToString(char* buf, int& i, int decimalPoint)304 {305 buf[i++] = 'e';306 buf[i++] = (decimalPoint >= 0) ? '+' : '-';307 // decimalPoint can't be more than 3 digits decimal given the308 // nature of float representation309 int exponential = decimalPoint - 1;310 if (exponential < 0)311 exponential *= -1;312 if (exponential >= 100)313 buf[i++] = static_cast<char>('0' + exponential / 100);314 if (exponential >= 10)315 buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);316 buf[i++] = static_cast<char>('0' + exponential % 10);317 }318 319 JSValue* numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)320 {321 JSValue* v = thisValue->getJSNumber();322 if (!v)323 return throwError(exec, TypeError);324 325 double x = v->uncheckedGetNumber();326 327 if (isnan(x) || isinf(x))328 return jsString(exec, UString::from(x));329 330 JSValue* fractionalDigitsValue = args[0];331 double df = fractionalDigitsValue->toInteger(exec);332 if (!(df >= 0 && df <= 20))333 return throwError(exec, RangeError, "toExponential() argument must between 0 and 20");334 int fractionalDigits = (int)df;335 bool includeAllDigits = fractionalDigitsValue->isUndefined();336 337 int decimalAdjust = 0;338 if (x && !includeAllDigits) {339 double logx = floor(log10(fabs(x)));340 x /= pow(10.0, logx);341 const double tenToTheF = pow(10.0, fractionalDigits);342 double fx = floor(x * tenToTheF) / tenToTheF;343 double cx = ceil(x * tenToTheF) / tenToTheF;344 345 if (fabs(fx - x) < fabs(cx - x))346 x = fx;347 else348 x = cx;349 350 decimalAdjust = static_cast<int>(logx);351 }352 353 if (isnan(x))354 return jsString(exec, "NaN");355 356 if (x == -0.0) // (-0.0).toExponential() should print as 0 instead of -0357 x = 0;358 359 int decimalPoint;360 int sign;361 char* result = dtoa(x, 0, &decimalPoint, &sign, NULL);362 size_t resultLength = strlen(result);363 decimalPoint += decimalAdjust;364 365 int i = 0;366 char buf[80]; // digit + '.' + fractionDigits (max 20) + 'e' + sign + exponent (max?)367 if (sign)368 buf[i++] = '-';369 370 if (decimalPoint == 999) // ? 9999 is the magical "result is Inf or NaN" value. what's 999??371 strcpy(buf + i, result);372 else {373 buf[i++] = result[0];374 375 if (includeAllDigits)376 fractionalDigits = static_cast<int>(resultLength) - 1;377 378 fractionalPartToString(buf, i, result, resultLength, fractionalDigits);379 exponentialPartToString(buf, i, decimalPoint);380 buf[i++] = '\0';381 }382 ASSERT(i <= 80);383 384 freedtoa(result);385 386 return jsString(exec, buf);387 }388 389 JSValue* numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)390 {391 JSValue* v = thisValue->getJSNumber();392 if (!v)393 return throwError(exec, TypeError);394 395 double doublePrecision = args[0]->toIntegerPreserveNaN(exec);396 double x = v->uncheckedGetNumber();397 if (args[0]->isUndefined() || isnan(x) || isinf(x))398 return jsString(exec, v->toString(exec));399 400 UString s;401 if (x < 0) {402 s = "-";403 x = -x;404 }405 406 if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN407 return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21");408 int precision = (int)doublePrecision;409 410 int e = 0;411 UString m;412 if (x) {413 e = static_cast<int>(log10(x));414 double tens = intPow10(e - precision + 1);415 double n = floor(x / tens);416 if (n < intPow10(precision - 1)) {417 e = e - 1;418 tens = intPow10(e - precision + 1);419 n = floor(x / tens);420 }421 422 if (fabs((n + 1.0) * tens - x) <= fabs(n * tens - x))423 ++n;424 // maintain n < 10^(precision)425 if (n >= intPow10(precision)) {426 n /= 10.0;427 e += 1;428 }429 ASSERT(intPow10(precision - 1) <= n);430 ASSERT(n < intPow10(precision));431 432 m = integer_part_noexp(n);433 if (e < -6 || e >= precision) {434 if (m.size() > 1)435 m = m.substr(0, 1) + "." + m.substr(1);436 if (e >= 0)437 return jsString(exec, s + m + "e+" + UString::from(e));438 return jsString(exec, s + m + "e-" + UString::from(-e));439 }440 } else {441 m = char_sequence('0', precision);442 e = 0;443 }444 445 if (e == precision - 1)446 return jsString(exec, s + m);447 if (e >= 0) {448 if (e + 1 < m.size())449 return jsString(exec, s + m.substr(0, e + 1) + "." + m.substr(e + 1));450 return jsString(exec, s + m);451 }452 return jsString(exec, s + "0." + char_sequence('0', -(e + 1)) + m);453 }454 455 // ------------------------------ NumberConstructor ------------------------------456 31 457 32 const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::numberTable }; -
trunk/JavaScriptCore/kjs/NumberConstructor.h
r34853 r34854 20 20 */ 21 21 22 #ifndef Number Object_h23 #define Number Object_h22 #ifndef NumberConstructor_h 23 #define NumberConstructor_h 24 24 25 #include "FunctionPrototype.h" 26 #include "JSWrapperObject.h" 25 #include "JSFunction.h" 27 26 28 27 namespace KJS { 29 28 30 class JSNumberCell; 31 32 class NumberObject : public JSWrapperObject { 33 public: 34 NumberObject(JSObject* prototype); 35 static const ClassInfo info; 36 37 private: 38 virtual const ClassInfo* classInfo() const { return &info; } 39 virtual JSValue* getJSNumber(); 40 }; 41 42 NumberObject* constructNumber(ExecState*, JSNumberCell*); 43 NumberObject* constructNumberFromImmediateNumber(ExecState*, JSValue*); 44 45 /** 46 * @internal 47 * 48 * The initial value of Number.prototype (and thus all objects created 49 * with the Number constructor 50 */ 51 class NumberPrototype : public NumberObject { 52 public: 53 NumberPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*); 54 }; 29 class FunctionPrototype; 30 class NumberPrototype; 55 31 56 32 /** … … 78 54 } // namespace KJS 79 55 80 #endif // Number Object_h56 #endif // NumberConstructor_h -
trunk/JavaScriptCore/kjs/NumberObject.cpp
r34821 r34854 22 22 #include "config.h" 23 23 #include "NumberObject.h" 24 #include "NumberObject.lut.h"25 26 #include "dtoa.h"27 #include "error_object.h"28 #include "operations.h"29 #include <wtf/Assertions.h>30 #include <wtf/MathExtras.h>31 #include <wtf/Vector.h>32 24 33 25 namespace KJS { 34 35 // ------------------------------ NumberObject ----------------------------36 26 37 27 const ClassInfo NumberObject::info = { "Number", 0, 0, 0 }; … … 47 37 } 48 38 49 // ------------------------------ NumberPrototype ---------------------------50 51 static JSValue* numberProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);52 static JSValue* numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);53 static JSValue* numberProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&);54 static JSValue* numberProtoFuncToFixed(ExecState*, JSObject*, JSValue*, const ArgList&);55 static JSValue* numberProtoFuncToExponential(ExecState*, JSObject*, JSValue*, const ArgList&);56 static JSValue* numberProtoFuncToPrecision(ExecState*, JSObject*, JSValue*, const ArgList&);57 58 // ECMA 15.7.459 60 NumberPrototype::NumberPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)61 : NumberObject(objectPrototype)62 {63 setInternalValue(jsNumber(exec, 0));64 65 // The constructor will be added later, after NumberConstructor has been constructed66 67 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);68 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);69 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);70 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);71 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);72 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);73 }74 75 // ------------------------------ Functions ---------------------------76 77 // ECMA 15.7.4.2 - 15.7.4.778 79 static UString integer_part_noexp(double d)80 {81 int decimalPoint;82 int sign;83 char* result = dtoa(d, 0, &decimalPoint, &sign, NULL);84 bool resultIsInfOrNan = (decimalPoint == 9999);85 size_t length = strlen(result);86 87 UString str = sign ? "-" : "";88 if (resultIsInfOrNan)89 str += result;90 else if (decimalPoint <= 0)91 str += "0";92 else {93 Vector<char, 1024> buf(decimalPoint + 1);94 95 if (static_cast<int>(length) <= decimalPoint) {96 strcpy(buf.data(), result);97 memset(buf.data() + length, '0', decimalPoint - length);98 } else99 strncpy(buf.data(), result, decimalPoint);100 101 buf[decimalPoint] = '\0';102 str.append(buf.data());103 }104 105 freedtoa(result);106 107 return str;108 }109 110 static UString char_sequence(char c, int count)111 {112 Vector<char, 2048> buf(count + 1, c);113 buf[count] = '\0';114 115 return UString(buf.data());116 }117 118 static double intPow10(int e)119 {120 // This function uses the "exponentiation by squaring" algorithm and121 // long double to quickly and precisely calculate integer powers of 10.0.122 123 // This is a handy workaround for <rdar://problem/4494756>124 125 if (e == 0)126 return 1.0;127 128 bool negative = e < 0;129 unsigned exp = negative ? -e : e;130 131 long double result = 10.0;132 bool foundOne = false;133 for (int bit = 31; bit >= 0; bit--) {134 if (!foundOne) {135 if ((exp >> bit) & 1)136 foundOne = true;137 } else {138 result = result * result;139 if ((exp >> bit) & 1)140 result = result * 10.0;141 }142 }143 144 if (negative)145 return static_cast<double>(1.0 / result);146 return static_cast<double>(result);147 }148 149 150 JSValue* numberProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)151 {152 JSValue* v = thisValue->getJSNumber();153 if (!v)154 return throwError(exec, TypeError);155 156 double radixAsDouble = args[0]->toInteger(exec); // nan -> 0157 if (radixAsDouble == 10 || args[0]->isUndefined())158 return jsString(exec, v->toString(exec));159 160 if (radixAsDouble < 2 || radixAsDouble > 36)161 return throwError(exec, RangeError, "toString() radix argument must be between 2 and 36");162 163 int radix = static_cast<int>(radixAsDouble);164 const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";165 // INT_MAX results in 1024 characters left of the dot with radix 2166 // give the same space on the right side. safety checks are in place167 // unless someone finds a precise rule.168 char s[2048 + 3];169 const char* lastCharInString = s + sizeof(s) - 1;170 double x = v->uncheckedGetNumber();171 if (isnan(x) || isinf(x))172 return jsString(exec, UString::from(x));173 174 bool isNegative = x < 0.0;175 if (isNegative)176 x = -x;177 178 double integerPart = floor(x);179 char* decimalPoint = s + sizeof(s) / 2;180 181 // convert integer portion182 char* p = decimalPoint;183 double d = integerPart;184 do {185 int remainderDigit = static_cast<int>(fmod(d, radix));186 *--p = digits[remainderDigit];187 d /= radix;188 } while ((d <= -1.0 || d >= 1.0) && s < p);189 190 if (isNegative)191 *--p = '-';192 char* startOfResultString = p;193 ASSERT(s <= startOfResultString);194 195 d = x - integerPart;196 p = decimalPoint;197 const double epsilon = 0.001; // TODO: guessed. base on radix ?198 bool hasFractionalPart = (d < -epsilon || d > epsilon);199 if (hasFractionalPart) {200 *p++ = '.';201 do {202 d *= radix;203 const int digit = static_cast<int>(d);204 *p++ = digits[digit];205 d -= digit;206 } while ((d < -epsilon || d > epsilon) && p < lastCharInString);207 }208 *p = '\0';209 ASSERT(p < s + sizeof(s));210 211 return jsString(exec, startOfResultString);212 }213 214 JSValue* numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)215 {216 // FIXME: Not implemented yet.217 218 JSValue* v = thisValue->getJSNumber();219 if (!v)220 return throwError(exec, TypeError);221 222 return jsString(exec, v->toString(exec));223 }224 225 JSValue* numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)226 {227 JSValue* v = thisValue->getJSNumber();228 if (!v)229 return throwError(exec, TypeError);230 231 return v;232 }233 234 JSValue* numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)235 {236 JSValue* v = thisValue->getJSNumber();237 if (!v)238 return throwError(exec, TypeError);239 240 JSValue* fractionDigits = args[0];241 double df = fractionDigits->toInteger(exec);242 if (!(df >= 0 && df <= 20))243 return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20");244 int f = (int)df;245 246 double x = v->uncheckedGetNumber();247 if (isnan(x))248 return jsString(exec, "NaN");249 250 UString s;251 if (x < 0) {252 s.append('-');253 x = -x;254 } else if (x == -0.0)255 x = 0;256 257 if (x >= pow(10.0, 21.0))258 return jsString(exec, s + UString::from(x));259 260 const double tenToTheF = pow(10.0, f);261 double n = floor(x * tenToTheF);262 if (fabs(n / tenToTheF - x) >= fabs((n + 1) / tenToTheF - x))263 n++;264 265 UString m = integer_part_noexp(n);266 267 int k = m.size();268 if (k <= f) {269 UString z;270 for (int i = 0; i < f + 1 - k; i++)271 z.append('0');272 m = z + m;273 k = f + 1;274 ASSERT(k == m.size());275 }276 int kMinusf = k - f;277 if (kMinusf < m.size())278 return jsString(exec, s + m.substr(0, kMinusf) + "." + m.substr(kMinusf));279 return jsString(exec, s + m.substr(0, kMinusf));280 }281 282 static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)283 {284 if (fractionalDigits <= 0)285 return;286 287 int fDigitsInResult = static_cast<int>(resultLength) - 1;288 buf[i++] = '.';289 if (fDigitsInResult > 0) {290 if (fractionalDigits < fDigitsInResult) {291 strncpy(buf + i, result + 1, fractionalDigits);292 i += fractionalDigits;293 } else {294 strcpy(buf + i, result + 1);295 i += static_cast<int>(resultLength) - 1;296 }297 }298 299 for (int j = 0; j < fractionalDigits - fDigitsInResult; j++)300 buf[i++] = '0';301 }302 303 static void exponentialPartToString(char* buf, int& i, int decimalPoint)304 {305 buf[i++] = 'e';306 buf[i++] = (decimalPoint >= 0) ? '+' : '-';307 // decimalPoint can't be more than 3 digits decimal given the308 // nature of float representation309 int exponential = decimalPoint - 1;310 if (exponential < 0)311 exponential *= -1;312 if (exponential >= 100)313 buf[i++] = static_cast<char>('0' + exponential / 100);314 if (exponential >= 10)315 buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);316 buf[i++] = static_cast<char>('0' + exponential % 10);317 }318 319 JSValue* numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)320 {321 JSValue* v = thisValue->getJSNumber();322 if (!v)323 return throwError(exec, TypeError);324 325 double x = v->uncheckedGetNumber();326 327 if (isnan(x) || isinf(x))328 return jsString(exec, UString::from(x));329 330 JSValue* fractionalDigitsValue = args[0];331 double df = fractionalDigitsValue->toInteger(exec);332 if (!(df >= 0 && df <= 20))333 return throwError(exec, RangeError, "toExponential() argument must between 0 and 20");334 int fractionalDigits = (int)df;335 bool includeAllDigits = fractionalDigitsValue->isUndefined();336 337 int decimalAdjust = 0;338 if (x && !includeAllDigits) {339 double logx = floor(log10(fabs(x)));340 x /= pow(10.0, logx);341 const double tenToTheF = pow(10.0, fractionalDigits);342 double fx = floor(x * tenToTheF) / tenToTheF;343 double cx = ceil(x * tenToTheF) / tenToTheF;344 345 if (fabs(fx - x) < fabs(cx - x))346 x = fx;347 else348 x = cx;349 350 decimalAdjust = static_cast<int>(logx);351 }352 353 if (isnan(x))354 return jsString(exec, "NaN");355 356 if (x == -0.0) // (-0.0).toExponential() should print as 0 instead of -0357 x = 0;358 359 int decimalPoint;360 int sign;361 char* result = dtoa(x, 0, &decimalPoint, &sign, NULL);362 size_t resultLength = strlen(result);363 decimalPoint += decimalAdjust;364 365 int i = 0;366 char buf[80]; // digit + '.' + fractionDigits (max 20) + 'e' + sign + exponent (max?)367 if (sign)368 buf[i++] = '-';369 370 if (decimalPoint == 999) // ? 9999 is the magical "result is Inf or NaN" value. what's 999??371 strcpy(buf + i, result);372 else {373 buf[i++] = result[0];374 375 if (includeAllDigits)376 fractionalDigits = static_cast<int>(resultLength) - 1;377 378 fractionalPartToString(buf, i, result, resultLength, fractionalDigits);379 exponentialPartToString(buf, i, decimalPoint);380 buf[i++] = '\0';381 }382 ASSERT(i <= 80);383 384 freedtoa(result);385 386 return jsString(exec, buf);387 }388 389 JSValue* numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)390 {391 JSValue* v = thisValue->getJSNumber();392 if (!v)393 return throwError(exec, TypeError);394 395 double doublePrecision = args[0]->toIntegerPreserveNaN(exec);396 double x = v->uncheckedGetNumber();397 if (args[0]->isUndefined() || isnan(x) || isinf(x))398 return jsString(exec, v->toString(exec));399 400 UString s;401 if (x < 0) {402 s = "-";403 x = -x;404 }405 406 if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN407 return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21");408 int precision = (int)doublePrecision;409 410 int e = 0;411 UString m;412 if (x) {413 e = static_cast<int>(log10(x));414 double tens = intPow10(e - precision + 1);415 double n = floor(x / tens);416 if (n < intPow10(precision - 1)) {417 e = e - 1;418 tens = intPow10(e - precision + 1);419 n = floor(x / tens);420 }421 422 if (fabs((n + 1.0) * tens - x) <= fabs(n * tens - x))423 ++n;424 // maintain n < 10^(precision)425 if (n >= intPow10(precision)) {426 n /= 10.0;427 e += 1;428 }429 ASSERT(intPow10(precision - 1) <= n);430 ASSERT(n < intPow10(precision));431 432 m = integer_part_noexp(n);433 if (e < -6 || e >= precision) {434 if (m.size() > 1)435 m = m.substr(0, 1) + "." + m.substr(1);436 if (e >= 0)437 return jsString(exec, s + m + "e+" + UString::from(e));438 return jsString(exec, s + m + "e-" + UString::from(-e));439 }440 } else {441 m = char_sequence('0', precision);442 e = 0;443 }444 445 if (e == precision - 1)446 return jsString(exec, s + m);447 if (e >= 0) {448 if (e + 1 < m.size())449 return jsString(exec, s + m.substr(0, e + 1) + "." + m.substr(e + 1));450 return jsString(exec, s + m);451 }452 return jsString(exec, s + "0." + char_sequence('0', -(e + 1)) + m);453 }454 455 // ------------------------------ NumberConstructor ------------------------------456 457 const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::numberTable };458 459 /* Source for NumberObject.lut.h460 @begin numberTable461 NaN NumberConstructor::NaNValue DontEnum|DontDelete|ReadOnly462 NEGATIVE_INFINITY NumberConstructor::NegInfinity DontEnum|DontDelete|ReadOnly463 POSITIVE_INFINITY NumberConstructor::PosInfinity DontEnum|DontDelete|ReadOnly464 MAX_VALUE NumberConstructor::MaxValue DontEnum|DontDelete|ReadOnly465 MIN_VALUE NumberConstructor::MinValue DontEnum|DontDelete|ReadOnly466 @end467 */468 NumberConstructor::NumberConstructor(ExecState* exec, FunctionPrototype* funcProto, NumberPrototype* numberProto)469 : InternalFunction(funcProto, Identifier(exec, numberProto->info.className))470 {471 // Number.Prototype472 putDirect(exec->propertyNames().prototype, numberProto, DontEnum|DontDelete|ReadOnly);473 474 // no. of arguments for constructor475 putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);476 }477 478 bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)479 {480 return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);481 }482 483 JSValue* NumberConstructor::getValueProperty(ExecState* exec, int token) const484 {485 // ECMA 15.7.3486 switch (token) {487 case NaNValue:488 return jsNaN(exec);489 case NegInfinity:490 return jsNumberCell(exec, -Inf);491 case PosInfinity:492 return jsNumberCell(exec, Inf);493 case MaxValue:494 return jsNumberCell(exec, 1.7976931348623157E+308);495 case MinValue:496 return jsNumberCell(exec, 5E-324);497 }498 ASSERT_NOT_REACHED();499 return jsNull();500 }501 502 // ECMA 15.7.1503 static JSObject* constructWithNumberConstructor(ExecState* exec, JSObject*, const ArgList& args)504 {505 NumberObject* obj = new (exec) NumberObject(exec->lexicalGlobalObject()->numberPrototype());506 double n = args.isEmpty() ? 0 : args[0]->toNumber(exec);507 obj->setInternalValue(jsNumber(exec, n));508 return obj;509 }510 511 ConstructType NumberConstructor::getConstructData(ConstructData& constructData)512 {513 constructData.native.function = constructWithNumberConstructor;514 return ConstructTypeNative;515 }516 517 // ECMA 15.7.2518 static JSValue* callNumberConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)519 {520 return jsNumber(exec, args.isEmpty() ? 0 : args[0]->toNumber(exec));521 }522 523 CallType NumberConstructor::getCallData(CallData& callData)524 {525 callData.native.function = callNumberConstructor;526 return CallTypeNative;527 }528 529 NumberObject* constructNumber(ExecState* exec, JSNumberCell* number)530 {531 NumberObject* obj = new (exec) NumberObject(exec->lexicalGlobalObject()->numberPrototype());532 obj->setInternalValue(number);533 return obj;534 }535 536 NumberObject* constructNumberFromImmediateNumber(ExecState* exec, JSValue* value)537 {538 NumberObject* obj = new (exec) NumberObject(exec->lexicalGlobalObject()->numberPrototype());539 obj->setInternalValue(value);540 return obj;541 }542 543 39 } // namespace KJS -
trunk/JavaScriptCore/kjs/NumberObject.h
r34821 r34854 1 1 // -*- c-basic-offset: 2 -*- 2 2 /* 3 * This file is part of the KDE libraries4 3 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 4 * Copyright (C) 2008 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 23 23 #define NumberObject_h 24 24 25 #include "FunctionPrototype.h"26 25 #include "JSWrapperObject.h" 27 26 … … 43 42 NumberObject* constructNumberFromImmediateNumber(ExecState*, JSValue*); 44 43 45 /**46 * @internal47 *48 * The initial value of Number.prototype (and thus all objects created49 * with the Number constructor50 */51 class NumberPrototype : public NumberObject {52 public:53 NumberPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);54 };55 56 /**57 * @internal58 *59 * The initial value of the the global variable's "Number" property60 */61 class NumberConstructor : public InternalFunction {62 public:63 NumberConstructor(ExecState*, FunctionPrototype*, NumberPrototype*);64 65 bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);66 JSValue* getValueProperty(ExecState*, int token) const;67 68 static const ClassInfo info;69 70 enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };71 72 private:73 virtual ConstructType getConstructData(ConstructData&);74 virtual CallType getCallData(CallData&);75 virtual const ClassInfo* classInfo() const { return &info; }76 };77 78 44 } // namespace KJS 79 45 -
trunk/JavaScriptCore/kjs/NumberPrototype.cpp
r34853 r34854 21 21 22 22 #include "config.h" 23 #include "NumberObject.h" 24 #include "NumberObject.lut.h" 23 #include "NumberPrototype.h" 25 24 26 25 #include "dtoa.h" … … 33 32 namespace KJS { 34 33 35 // ------------------------------ NumberObject ----------------------------36 37 const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };38 39 NumberObject::NumberObject(JSObject* proto)40 : JSWrapperObject(proto)41 {42 }43 44 JSValue* NumberObject::getJSNumber()45 {46 return internalValue();47 }48 49 // ------------------------------ NumberPrototype ---------------------------50 34 51 35 static JSValue* numberProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); … … 453 437 } 454 438 455 // ------------------------------ NumberConstructor ------------------------------456 457 const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::numberTable };458 459 /* Source for NumberObject.lut.h460 @begin numberTable461 NaN NumberConstructor::NaNValue DontEnum|DontDelete|ReadOnly462 NEGATIVE_INFINITY NumberConstructor::NegInfinity DontEnum|DontDelete|ReadOnly463 POSITIVE_INFINITY NumberConstructor::PosInfinity DontEnum|DontDelete|ReadOnly464 MAX_VALUE NumberConstructor::MaxValue DontEnum|DontDelete|ReadOnly465 MIN_VALUE NumberConstructor::MinValue DontEnum|DontDelete|ReadOnly466 @end467 */468 NumberConstructor::NumberConstructor(ExecState* exec, FunctionPrototype* funcProto, NumberPrototype* numberProto)469 : InternalFunction(funcProto, Identifier(exec, numberProto->info.className))470 {471 // Number.Prototype472 putDirect(exec->propertyNames().prototype, numberProto, DontEnum|DontDelete|ReadOnly);473 474 // no. of arguments for constructor475 putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);476 }477 478 bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)479 {480 return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);481 }482 483 JSValue* NumberConstructor::getValueProperty(ExecState* exec, int token) const484 {485 // ECMA 15.7.3486 switch (token) {487 case NaNValue:488 return jsNaN(exec);489 case NegInfinity:490 return jsNumberCell(exec, -Inf);491 case PosInfinity:492 return jsNumberCell(exec, Inf);493 case MaxValue:494 return jsNumberCell(exec, 1.7976931348623157E+308);495 case MinValue:496 return jsNumberCell(exec, 5E-324);497 }498 ASSERT_NOT_REACHED();499 return jsNull();500 }501 502 // ECMA 15.7.1503 static JSObject* constructWithNumberConstructor(ExecState* exec, JSObject*, const ArgList& args)504 {505 NumberObject* obj = new (exec) NumberObject(exec->lexicalGlobalObject()->numberPrototype());506 double n = args.isEmpty() ? 0 : args[0]->toNumber(exec);507 obj->setInternalValue(jsNumber(exec, n));508 return obj;509 }510 511 ConstructType NumberConstructor::getConstructData(ConstructData& constructData)512 {513 constructData.native.function = constructWithNumberConstructor;514 return ConstructTypeNative;515 }516 517 // ECMA 15.7.2518 static JSValue* callNumberConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)519 {520 return jsNumber(exec, args.isEmpty() ? 0 : args[0]->toNumber(exec));521 }522 523 CallType NumberConstructor::getCallData(CallData& callData)524 {525 callData.native.function = callNumberConstructor;526 return CallTypeNative;527 }528 529 NumberObject* constructNumber(ExecState* exec, JSNumberCell* number)530 {531 NumberObject* obj = new (exec) NumberObject(exec->lexicalGlobalObject()->numberPrototype());532 obj->setInternalValue(number);533 return obj;534 }535 536 NumberObject* constructNumberFromImmediateNumber(ExecState* exec, JSValue* value)537 {538 NumberObject* obj = new (exec) NumberObject(exec->lexicalGlobalObject()->numberPrototype());539 obj->setInternalValue(value);540 return obj;541 }542 543 439 } // namespace KJS -
trunk/JavaScriptCore/kjs/NumberPrototype.h
r34853 r34854 20 20 */ 21 21 22 #ifndef Number Object_h23 #define Number Object_h22 #ifndef NumberPrototype_h 23 #define NumberPrototype_h 24 24 25 #include "FunctionPrototype.h" 26 #include "JSWrapperObject.h" 25 #include "NumberObject.h" 27 26 28 27 namespace KJS { 29 30 class JSNumberCell;31 32 class NumberObject : public JSWrapperObject {33 public:34 NumberObject(JSObject* prototype);35 static const ClassInfo info;36 37 private:38 virtual const ClassInfo* classInfo() const { return &info; }39 virtual JSValue* getJSNumber();40 };41 42 NumberObject* constructNumber(ExecState*, JSNumberCell*);43 NumberObject* constructNumberFromImmediateNumber(ExecState*, JSValue*);44 28 45 29 /** … … 54 38 }; 55 39 56 /**57 * @internal58 *59 * The initial value of the the global variable's "Number" property60 */61 class NumberConstructor : public InternalFunction {62 public:63 NumberConstructor(ExecState*, FunctionPrototype*, NumberPrototype*);64 65 bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);66 JSValue* getValueProperty(ExecState*, int token) const;67 68 static const ClassInfo info;69 70 enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };71 72 private:73 virtual ConstructType getConstructData(ConstructData&);74 virtual CallType getCallData(CallData&);75 virtual const ClassInfo* classInfo() const { return &info; }76 };77 78 40 } // namespace KJS 79 41 80 #endif // Number Object_h42 #endif // NumberPrototype_h -
trunk/JavaScriptCore/kjs/ObjectConstructor.cpp
r34853 r34854 20 20 21 21 #include "config.h" 22 #include " object_object.h"22 #include "ObjectConstructor.h" 23 23 24 24 #include "JSGlobalObject.h" 25 #include "operations.h"26 25 #include "FunctionPrototype.h" 27 #include <stdio.h>28 26 29 27 namespace KJS { 30 31 // ------------------------------ ObjectPrototype --------------------------------32 33 static JSValue* objectProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&);34 static JSValue* objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValue*, const ArgList&);35 static JSValue* objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValue*, const ArgList&);36 static JSValue* objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValue*, const ArgList&);37 static JSValue* objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValue*, const ArgList&);38 static JSValue* objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValue*, const ArgList&);39 static JSValue* objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValue*, const ArgList&);40 static JSValue* objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue*, const ArgList&);41 static JSValue* objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);42 43 ObjectPrototype::ObjectPrototype(ExecState* exec, FunctionPrototype* functionPrototype)44 : JSObject() // [[Prototype]] is null45 {46 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);47 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);48 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);49 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum);50 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum);51 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum);52 53 // Mozilla extensions54 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum);55 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum);56 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum);57 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);58 }59 60 61 // ------------------------------ Functions --------------------------------62 63 // ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.764 65 JSValue* objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)66 {67 return thisValue->toThisObject(exec);68 }69 70 JSValue* objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)71 {72 return jsBoolean(thisValue->toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args[0]->toString(exec))));73 }74 75 JSValue* objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)76 {77 JSObject* thisObj = thisValue->toThisObject(exec);78 79 if (!args[0]->isObject())80 return jsBoolean(false);81 82 JSValue* v = static_cast<JSObject*>(args[0])->prototype();83 84 while (true) {85 if (!v->isObject())86 return jsBoolean(false);87 if (thisObj == v)88 89 return jsBoolean(true);90 v = static_cast<JSObject*>(v)->prototype();91 }92 }93 94 JSValue* objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)95 {96 CallData callData;97 if (args[1]->getCallData(callData) == CallTypeNone)98 return throwError(exec, SyntaxError, "invalid getter usage");99 thisValue->toThisObject(exec)->defineGetter(exec, Identifier(exec, args[0]->toString(exec)), static_cast<JSObject*>(args[1]));100 return jsUndefined();101 }102 103 JSValue* objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)104 {105 CallData callData;106 if (args[1]->getCallData(callData) == CallTypeNone)107 return throwError(exec, SyntaxError, "invalid setter usage");108 thisValue->toThisObject(exec)->defineSetter(exec, Identifier(exec, args[0]->toString(exec)), static_cast<JSObject*>(args[1]));109 return jsUndefined();110 }111 112 JSValue* objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)113 {114 return thisValue->toThisObject(exec)->lookupGetter(exec, Identifier(exec, args[0]->toString(exec)));115 }116 117 JSValue* objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)118 {119 return thisValue->toThisObject(exec)->lookupSetter(exec, Identifier(exec, args[0]->toString(exec)));120 }121 122 JSValue* objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)123 {124 return jsBoolean(thisValue->toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args[0]->toString(exec))));125 }126 127 JSValue* objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)128 {129 return jsString(exec, thisValue->toThisObject(exec)->toString(exec));130 }131 132 JSValue* objectProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)133 {134 return jsString(exec, "[object " + thisValue->toThisObject(exec)->className() + "]");135 }136 137 // ------------------------------ ObjectConstructor --------------------------------138 28 139 29 ObjectConstructor::ObjectConstructor(ExecState* exec, ObjectPrototype* objProto, FunctionPrototype* funcProto) -
trunk/JavaScriptCore/kjs/ObjectConstructor.h
r34853 r34854 19 19 */ 20 20 21 #ifndef _OBJECT_OBJECT_H_22 #define _OBJECT_OBJECT_H_21 #ifndef ObjectConstructor_h 22 #define ObjectConstructor_h 23 23 24 24 #include "JSFunction.h" … … 26 26 namespace KJS { 27 27 28 /** 29 * @internal 30 * 31 * The initial value of Object.prototype (and thus all objects created 32 * with the Object constructor 33 */ 34 class ObjectPrototype : public JSObject { 35 public: 36 ObjectPrototype(ExecState*, FunctionPrototype*); 37 }; 38 39 JSValue* objectProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); 28 class FunctionPrototype; 29 class ObjectPrototype; 40 30 41 31 /** … … 54 44 } // namespace KJS 55 45 56 #endif // _OBJECT_OBJECT_H_46 #endif // ObjectConstructor_h -
trunk/JavaScriptCore/kjs/ObjectPrototype.cpp
r34853 r34854 20 20 21 21 #include "config.h" 22 #include " object_object.h"22 #include "ObjectPrototype.h" 23 23 24 #include "JSGlobalObject.h"25 24 #include "operations.h" 26 25 #include "FunctionPrototype.h" 27 #include <stdio.h>28 26 29 27 namespace KJS { 30 31 // ------------------------------ ObjectPrototype --------------------------------32 28 33 29 static JSValue* objectProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&); … … 135 131 } 136 132 137 // ------------------------------ ObjectConstructor --------------------------------138 139 ObjectConstructor::ObjectConstructor(ExecState* exec, ObjectPrototype* objProto, FunctionPrototype* funcProto)140 : InternalFunction(funcProto, Identifier(exec, "Object"))141 {142 // ECMA 15.2.3.1143 putDirect(exec->propertyNames().prototype, objProto, DontEnum|DontDelete|ReadOnly);144 145 // no. of arguments for constructor146 putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);147 }148 149 // ECMA 15.2.2150 static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args)151 {152 JSValue* arg = args[0];153 if (arg->isUndefinedOrNull())154 return new (exec) JSObject(exec->lexicalGlobalObject()->objectPrototype());155 return arg->toObject(exec);156 }157 158 static JSObject* constructWithObjectConstructor(ExecState* exec, JSObject*, const ArgList& args)159 {160 return constructObject(exec, args);161 }162 163 ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)164 {165 constructData.native.function = constructWithObjectConstructor;166 return ConstructTypeNative;167 }168 169 static JSValue* callObjectConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)170 {171 return constructObject(exec, args);172 }173 174 CallType ObjectConstructor::getCallData(CallData& callData)175 {176 callData.native.function = callObjectConstructor;177 return CallTypeNative;178 }179 180 133 } // namespace KJS -
trunk/JavaScriptCore/kjs/ObjectPrototype.h
r34853 r34854 19 19 */ 20 20 21 #ifndef _OBJECT_OBJECT_H_22 #define _OBJECT_OBJECT_H_21 #ifndef ObjectPrototype_h 22 #define ObjectPrototype_h 23 23 24 #include "JS Function.h"24 #include "JSObject.h" 25 25 26 26 namespace KJS { 27 28 class FunctionPrototype; 27 29 28 30 /** … … 39 41 JSValue* objectProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&); 40 42 41 /**42 * @internal43 *44 * The initial value of the the global variable's "Object" property45 */46 class ObjectConstructor : public InternalFunction {47 public:48 ObjectConstructor(ExecState*, ObjectPrototype*, FunctionPrototype*);49 private:50 virtual ConstructType getConstructData(ConstructData&);51 virtual CallType getCallData(CallData&);52 };53 54 43 } // namespace KJS 55 44 56 #endif // _OBJECT_OBJECT_H_45 #endif // ObjectPrototype_h -
trunk/JavaScriptCore/kjs/RegExpObject.h
r34754 r34854 22 22 #define RegExpObject_h 23 23 24 #include "FunctionPrototype.h"25 24 #include "regexp.h" 26 25 27 26 namespace KJS { 28 27 28 class FunctionPrototype; 29 29 struct RegExpConstructorPrivate; 30 30 -
trunk/JavaScriptCore/kjs/Shell.cpp
r34843 r34854 23 23 #include "config.h" 24 24 25 #include "ObjectPrototype.h" 26 #include "ObjectConstructor.h" 27 25 28 #include "CodeGenerator.h" 26 29 #include "InitializeThreading.h" -
trunk/JavaScriptCore/kjs/error_object.h
r34754 r34854 22 22 #define ERROR_OBJECT_H_ 23 23 24 #include " FunctionPrototype.h"24 #include "JSFunction.h" 25 25 26 26 namespace KJS { 27 28 class FunctionPrototype; 27 29 28 30 class ErrorInstance : public JSObject { -
trunk/JavaScriptCore/kjs/internal.cpp
r34843 r34854 25 25 26 26 #include "ExecState.h" 27 #include "FunctionPrototype.h" 28 #include "JSObject.h" 29 #include "MathObject.h" 30 #include "NumberObject.h" 31 #include "RegExpObject.h" 27 32 #include "collector.h" 28 33 #include "date_object.h" 29 34 #include "debugger.h" 30 35 #include "error_object.h" 31 #include "FunctionPrototype.h"32 36 #include "lexer.h" 33 #include "MathObject.h"34 37 #include "nodes.h" 35 #include "NumberObject.h"36 #include "JSObject.h"37 #include "object_object.h"38 38 #include "operations.h" 39 #include "RegExpObject.h"40 39 #include "string_object.h" 41 40 #include <math.h> -
trunk/JavaScriptCore/kjs/nodes.cpp
r34852 r34854 29 29 #include "CodeGenerator.h" 30 30 #include "ExecState.h" 31 #include "FunctionPrototype.h"32 31 #include "JSGlobalObject.h" 33 32 #include "Parser.h" -
trunk/JavaScriptCore/kjs/string_object.h
r34821 r34854 23 23 #define STRING_OBJECT_H_ 24 24 25 #include "FunctionPrototype.h"26 25 #include "JSWrapperObject.h" 27 26 #include "JSString.h" … … 29 28 30 29 namespace KJS { 30 31 class FunctionPrototype; 31 32 32 33 class StringObject : public JSWrapperObject {
Note:
See TracChangeset
for help on using the changeset viewer.