+2008-01-16 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Darin.
+
+ Fix for http://bugs.webkit.org/show_bug.cgi?id=16901
+ Convert remaining JS function objects to use the new PrototypeFunction class
+
+ - Moves Boolean, Function, RegExp, Number, Object and Global functions to their
+ own static function implementations so that they can be used with the
+ PrototypeFunction class. SunSpider says this is 1.003x as fast.
+
+ * kjs/JSGlobalObject.cpp:
+ (KJS::JSGlobalObject::reset):
+ * kjs/array_object.h:
+ * kjs/bool_object.cpp:
+ (KJS::BooleanInstance::BooleanInstance):
+ (KJS::BooleanPrototype::BooleanPrototype):
+ (KJS::booleanProtoFuncToString):
+ (KJS::booleanProtoFuncValueOf):
+ (KJS::BooleanObjectImp::BooleanObjectImp):
+ (KJS::BooleanObjectImp::implementsConstruct):
+ (KJS::BooleanObjectImp::construct):
+ (KJS::BooleanObjectImp::callAsFunction):
+ * kjs/bool_object.h:
+ (KJS::BooleanInstance::classInfo):
+ * kjs/error_object.cpp:
+ (KJS::ErrorPrototype::ErrorPrototype):
+ (KJS::errorProtoFuncToString):
+ * kjs/error_object.h:
+ * kjs/function.cpp:
+ (KJS::globalFuncEval):
+ (KJS::globalFuncParseInt):
+ (KJS::globalFuncParseFloat):
+ (KJS::globalFuncIsNaN):
+ (KJS::globalFuncIsFinite):
+ (KJS::globalFuncDecodeURI):
+ (KJS::globalFuncDecodeURIComponent):
+ (KJS::globalFuncEncodeURI):
+ (KJS::globalFuncEncodeURIComponent):
+ (KJS::globalFuncEscape):
+ (KJS::globalFuncUnEscape):
+ (KJS::globalFuncKJSPrint):
+ (KJS::PrototypeFunction::PrototypeFunction):
+ * kjs/function.h:
+ * kjs/function_object.cpp:
+ (KJS::FunctionPrototype::FunctionPrototype):
+ (KJS::functionProtoFuncToString):
+ (KJS::functionProtoFuncApply):
+ (KJS::functionProtoFuncCall):
+ * kjs/function_object.h:
+ * kjs/number_object.cpp:
+ (KJS::NumberPrototype::NumberPrototype):
+ (KJS::numberProtoFuncToString):
+ (KJS::numberProtoFuncToLocaleString):
+ (KJS::numberProtoFuncValueOf):
+ (KJS::numberProtoFuncToFixed):
+ (KJS::numberProtoFuncToExponential):
+ (KJS::numberProtoFuncToPrecision):
+ * kjs/number_object.h:
+ (KJS::NumberInstance::classInfo):
+ (KJS::NumberObjectImp::classInfo):
+ (KJS::NumberObjectImp::):
+ * kjs/object_object.cpp:
+ (KJS::ObjectPrototype::ObjectPrototype):
+ (KJS::objectProtoFuncValueOf):
+ (KJS::objectProtoFuncHasOwnProperty):
+ (KJS::objectProtoFuncIsPrototypeOf):
+ (KJS::objectProtoFuncDefineGetter):
+ (KJS::objectProtoFuncDefineSetter):
+ (KJS::objectProtoFuncLookupGetter):
+ (KJS::objectProtoFuncLookupSetter):
+ (KJS::objectProtoFuncPropertyIsEnumerable):
+ (KJS::objectProtoFuncToLocaleString):
+ (KJS::objectProtoFuncToString):
+ * kjs/object_object.h:
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpPrototype::RegExpPrototype):
+ (KJS::regExpProtoFuncTest):
+ (KJS::regExpProtoFuncExec):
+ (KJS::regExpProtoFuncCompile):
+ (KJS::regExpProtoFuncToString):
+ * kjs/regexp_object.h:
+
2008-01-16 Cameron Zwarich <cwzwarich@uwaterloo.ca>
Reviewed by Maciej & Darin.
d()->booleanPrototype = new BooleanPrototype(exec, d()->objectPrototype, d()->functionPrototype);
d()->numberPrototype = new NumberPrototype(exec, d()->objectPrototype, d()->functionPrototype);
d()->datePrototype = new DatePrototype(exec, d()->objectPrototype);
- d()->regExpPrototype = new RegExpPrototype(exec, d()->objectPrototype, d()->functionPrototype);;
+ d()->regExpPrototype = new RegExpPrototype(exec, d()->objectPrototype, d()->functionPrototype);
d()->errorPrototype = new ErrorPrototype(exec, d()->objectPrototype, d()->functionPrototype);
d()->evalErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "EvalError", "EvalError");
// Set global functions.
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "eval", globalFuncEval), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 2, "parseInt", globalFuncParseInt), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "parseFloat", globalFuncParseFloat), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "isNaN", globalFuncIsNaN), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "isFinite", globalFuncIsFinite), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "escape", globalFuncEscape), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "unescape", globalFuncUnescape), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "decodeURI", globalFuncDecodeURI), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "decodeURIComponent", globalFuncDecodeURIComponent), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "encodeURI", globalFuncEncodeURI), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "encodeURIComponent", globalFuncEncodeURIComponent), DontEnum);
#ifndef NDEBUG
- putDirectFunction(new GlobalFuncImp(exec, d()->functionPrototype, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "kjsprint", globalFuncKJSPrint), DontEnum);
#endif
// Set prototype, and also insert the object prototype at the end of the chain.
-// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
-// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003 Apple Computer, Inc.
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "operations.h"
#include <wtf/Assertions.h>
-using namespace KJS;
+namespace KJS {
// ------------------------------ BooleanInstance ---------------------------
-const ClassInfo BooleanInstance::info = {"Boolean", 0, 0};
+const ClassInfo BooleanInstance::info = { "Boolean", 0, 0 };
-BooleanInstance::BooleanInstance(JSObject *proto)
- : JSWrapperObject(proto)
+BooleanInstance::BooleanInstance(JSObject* proto)
+ : JSWrapperObject(proto)
{
}
// ------------------------------ BooleanPrototype --------------------------
+// Functions
+static JSValue* booleanProtoFuncToString(ExecState*, JSObject*, const List&);
+static JSValue* booleanProtoFuncValueOf(ExecState*, JSObject*, const List&);
+
// ECMA 15.6.4
-BooleanPrototype::BooleanPrototype(ExecState* exec, ObjectPrototype* objectProto, FunctionPrototype* funcProto)
- : BooleanInstance(objectProto)
+BooleanPrototype::BooleanPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
+ : BooleanInstance(objectPrototype)
{
- putDirectFunction(new BooleanProtoFunc(exec, funcProto, BooleanProtoFunc::ToString, 0, exec->propertyNames().toString), DontEnum);
- putDirectFunction(new BooleanProtoFunc(exec, funcProto, BooleanProtoFunc::ValueOf, 0, exec->propertyNames().valueOf), DontEnum);
- setInternalValue(jsBoolean(false));
+ setInternalValue(jsBoolean(false));
+
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum);
}
-// ------------------------------ BooleanProtoFunc --------------------------
+// ------------------------------ Functions --------------------------
+
+// ECMA 15.6.4.2 + 15.6.4.3
-BooleanProtoFunc::BooleanProtoFunc(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
- : InternalFunctionImp(funcProto, name)
- , id(i)
+JSValue* booleanProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
{
- putDirect(exec->propertyNames().length, len, DontDelete|ReadOnly|DontEnum);
-}
+ if (!thisObj->inherits(&BooleanInstance::info))
+ return throwError(exec, TypeError);
+ JSValue* v = static_cast<BooleanInstance*>(thisObj)->internalValue();
+ ASSERT(v);
-// ECMA 15.6.4.2 + 15.6.4.3
-JSValue *BooleanProtoFunc::callAsFunction(ExecState* exec, JSObject *thisObj, const List &/*args*/)
+ return jsString(v->toString(exec));
+}
+JSValue* booleanProtoFuncValueOf(ExecState* exec, JSObject* thisObj, const List&)
{
- // no generic function. "this" has to be a Boolean object
- if (!thisObj->inherits(&BooleanInstance::info))
- return throwError(exec, TypeError);
-
- // execute "toString()" or "valueOf()", respectively
+ if (!thisObj->inherits(&BooleanInstance::info))
+ return throwError(exec, TypeError);
- JSValue *v = static_cast<BooleanInstance*>(thisObj)->internalValue();
- ASSERT(v);
+ JSValue* v = static_cast<BooleanInstance*>(thisObj)->internalValue();
+ ASSERT(v);
- if (id == ToString)
- return jsString(v->toString(exec));
- return jsBoolean(v->toBoolean(exec)); /* TODO: optimize for bool case */
+ // TODO: optimize for bool case
+ return jsBoolean(v->toBoolean(exec));
}
// ------------------------------ BooleanObjectImp -----------------------------
-BooleanObjectImp::BooleanObjectImp(ExecState* exec, FunctionPrototype* funcProto, BooleanPrototype* booleanProto)
- : InternalFunctionImp(funcProto)
+BooleanObjectImp::BooleanObjectImp(ExecState* exec, FunctionPrototype* functionPrototype, BooleanPrototype* booleanPrototype)
+ : InternalFunctionImp(functionPrototype)
{
- putDirect(exec->propertyNames().prototype, booleanProto, DontEnum|DontDelete|ReadOnly);
+ putDirect(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
- // no. of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);
+ // no. of arguments for constructor
+ putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
bool BooleanObjectImp::implementsConstruct() const
{
- return true;
+ return true;
}
// ECMA 15.6.2
-JSObject *BooleanObjectImp::construct(ExecState *exec, const List &args)
+JSObject* BooleanObjectImp::construct(ExecState* exec, const List& args)
{
- BooleanInstance *obj(new BooleanInstance(exec->lexicalGlobalObject()->booleanPrototype()));
-
- bool b;
- if (args.size() > 0)
- b = args[0]->toBoolean(exec);
- else
- b = false;
-
- obj->setInternalValue(jsBoolean(b));
-
- return obj;
+ BooleanInstance* obj(new BooleanInstance(exec->lexicalGlobalObject()->booleanPrototype()));
+ obj->setInternalValue(jsBoolean(args[0]->toBoolean(exec)));
+ return obj;
}
// ECMA 15.6.1
-JSValue *BooleanObjectImp::callAsFunction(ExecState *exec, JSObject *, const List &args)
+JSValue* BooleanObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
{
- if (args.isEmpty())
- return jsBoolean(false);
- else
- return jsBoolean(args[0]->toBoolean(exec)); /* TODO: optimize for bool case */
+ // TODO: optimize for bool case
+ return jsBoolean(args[0]->toBoolean(exec));
}
+} // namespace KJS
-// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
namespace KJS {
- class BooleanInstance : public JSWrapperObject {
- public:
- BooleanInstance(JSObject *proto);
+ class BooleanInstance : public JSWrapperObject {
+ public:
+ BooleanInstance(JSObject* proto);
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
- /**
- * @internal
- *
- * The initial value of Boolean.prototype (and thus all objects created
- * with the Boolean constructor
- */
- class BooleanPrototype : public BooleanInstance {
- public:
- BooleanPrototype(ExecState *exec,
- ObjectPrototype *objectProto,
- FunctionPrototype *funcProto);
- };
+ /**
+ * @internal
+ *
+ * The initial value of Boolean.prototype (and thus all objects created
+ * with the Boolean constructor
+ */
+ class BooleanPrototype : public BooleanInstance {
+ public:
+ BooleanPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);
+ };
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Boolean.prototype object
- */
- class BooleanProtoFunc : public InternalFunctionImp {
- public:
- BooleanProtoFunc(ExecState*, FunctionPrototype*, int i, int len, const Identifier&);
+ /**
+ * @internal
+ *
+ * The initial value of the the global variable's "Boolean" property
+ */
+ class BooleanObjectImp : public InternalFunctionImp {
+ public:
+ BooleanObjectImp(ExecState*, FunctionPrototype*, BooleanPrototype*);
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+ virtual bool implementsConstruct() const;
+ virtual JSObject* construct(ExecState*, const List&);
- enum { ToString, ValueOf };
- private:
- int id;
- };
+ virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
+ };
- /**
- * @internal
- *
- * The initial value of the the global variable's "Boolean" property
- */
- class BooleanObjectImp : public InternalFunctionImp {
- friend class BooleanProtoFunc;
- public:
- BooleanObjectImp(ExecState *exec, FunctionPrototype *funcProto,
- BooleanPrototype *booleanProto);
+} // namespace KJS
- virtual bool implementsConstruct() const;
- virtual JSObject *construct(ExecState *exec, const List &args);
-
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
- };
-
-} // namespace
-
-#endif
+#endif // BOOL_OBJECT_H_
// ------------------------------ ErrorPrototype ----------------------------
// ECMA 15.9.4
-ErrorPrototype::ErrorPrototype(ExecState* exec, ObjectPrototype* objectProto, FunctionPrototype* funcProto)
- : JSObject(objectProto)
+ErrorPrototype::ErrorPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
+ : JSObject(objectPrototype)
{
// The constructor will be added later in ErrorObjectImp's constructor
put(exec, exec->propertyNames().name, jsString("Error"), DontEnum);
put(exec, exec->propertyNames().message, jsString("Unknown error"), DontEnum);
- putDirectFunction(new ErrorProtoFuncToString(exec, funcProto), DontEnum);
-}
-
-// ------------------------------ ErrorProtoFunc ----------------------------
-ErrorProtoFuncToString::ErrorProtoFuncToString(ExecState* exec, FunctionPrototype* funcProto)
- : InternalFunctionImp(funcProto, exec->propertyNames().toString)
-{
- putDirect(exec->propertyNames().length, jsNumber(0), DontDelete|ReadOnly|DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum);
}
-JSValue* ErrorProtoFuncToString::callAsFunction(ExecState* exec, JSObject* thisObj, const List&)
+JSValue* errorProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
{
UString s = "Error";
ErrorPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);
};
- class ErrorProtoFuncToString : public InternalFunctionImp {
- public:
- ErrorProtoFuncToString(ExecState*, FunctionPrototype*);
-
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- };
+ JSValue* errorProtoFuncToString(ExecState*, JSObject*, const List&);
class ErrorObjectImp : public InternalFunctionImp {
public:
{
}
-// ------------------------------ GlobalFunc -----------------------------------
-
-
-GlobalFuncImp::GlobalFuncImp(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
- : InternalFunctionImp(funcProto, name)
- , id(i)
-{
- putDirect(exec->propertyNames().length, len, DontDelete|ReadOnly|DontEnum);
-}
+// ------------------------------ Global Functions -----------------------------------
static JSValue* encode(ExecState* exec, const List& args, const char* do_not_escape)
{
return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );
}
-JSValue* GlobalFuncImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
-{
- JSValue* res = jsUndefined();
-
- static const char do_not_escape[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "*+-./@_";
-
- static const char do_not_escape_when_encoding_URI_component[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "!'()*-._~";
- static const char do_not_escape_when_encoding_URI[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "!#$&'()*+,-./:;=?@_~";
- static const char do_not_unescape_when_decoding_URI[] =
- "#$&+,/:;=?@";
-
- switch (id) {
- case Eval: { // eval()
- JSValue* x = args[0];
- if (!x->isString())
+JSValue* globalFuncEval(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ JSValue* x = args[0];
+ if (!x->isString())
return x;
- else {
- UString s = x->toString(exec);
-
- int sourceId;
- int errLine;
- UString errMsg;
- RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(UString(), 0, s.data(), s.size(), &sourceId, &errLine, &errMsg);
-
- Debugger* dbg = exec->dynamicGlobalObject()->debugger();
- if (dbg) {
- bool cont = dbg->sourceParsed(exec, sourceId, UString(), s, 0, errLine, errMsg);
- if (!cont)
+
+ UString s = x->toString(exec);
+
+ int sourceId;
+ int errLine;
+ UString errMsg;
+ RefPtr<EvalNode> evalNode = parser().parse<EvalNode>(UString(), 0, s.data(), s.size(), &sourceId, &errLine, &errMsg);
+
+ Debugger* dbg = exec->dynamicGlobalObject()->debugger();
+ if (dbg) {
+ bool cont = dbg->sourceParsed(exec, sourceId, UString(), s, 0, errLine, errMsg);
+ if (!cont)
return jsUndefined();
- }
+ }
- // no program node means a syntax occurred
- if (!evalNode)
- return throwError(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
+ // No program node means a syntax occurred
+ if (!evalNode)
+ return throwError(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
- bool switchGlobal = thisObj && thisObj != exec->dynamicGlobalObject() && thisObj->isGlobalObject();
+ bool switchGlobal = thisObj && thisObj != exec->dynamicGlobalObject() && thisObj->isGlobalObject();
- // enter a new execution context
- exec->dynamicGlobalObject()->tearOffActivation(exec);
- JSGlobalObject* globalObject = switchGlobal ? static_cast<JSGlobalObject*>(thisObj) : exec->dynamicGlobalObject();
- ExecState newExec(globalObject, evalNode.get(), exec);
-
- if (switchGlobal) {
- newExec.pushScope(thisObj);
- newExec.setVariableObject(static_cast<JSGlobalObject*>(thisObj));
- }
- JSValue* value = evalNode->execute(&newExec);
- if (switchGlobal)
- newExec.popScope();
+ // enter a new execution context
+ exec->dynamicGlobalObject()->tearOffActivation(exec);
+ JSGlobalObject* globalObject = switchGlobal ? static_cast<JSGlobalObject*>(thisObj) : exec->dynamicGlobalObject();
+ ExecState newExec(globalObject, evalNode.get(), exec);
- if (newExec.completionType() == Throw) {
- exec->setException(value);
- return value;
- }
- return value ? value : jsUndefined();
- }
+ if (switchGlobal) {
+ newExec.pushScope(thisObj);
+ newExec.setVariableObject(static_cast<JSGlobalObject*>(thisObj));
}
- case ParseInt:
- res = jsNumber(parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));
- break;
- case ParseFloat:
- res = jsNumber(parseFloat(args[0]->toString(exec)));
- break;
- case IsNaN:
- res = jsBoolean(isnan(args[0]->toNumber(exec)));
- break;
- case IsFinite: {
+ JSValue* value = evalNode->execute(&newExec);
+ if (switchGlobal)
+ newExec.popScope();
+
+ if (newExec.completionType() == Throw) {
+ exec->setException(value);
+ return value;
+ }
+
+ return value ? value : jsUndefined();
+}
+
+JSValue* globalFuncParseInt(ExecState* exec, JSObject*, const List& args)
+{
+ return jsNumber(parseInt(args[0]->toString(exec), args[1]->toInt32(exec)));
+}
+
+JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, const List& args)
+{
+ return jsNumber(parseFloat(args[0]->toString(exec)));
+}
+
+JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, const List& args)
+{
+ return jsBoolean(isnan(args[0]->toNumber(exec)));
+}
+
+JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, const List& args)
+{
double n = args[0]->toNumber(exec);
- res = jsBoolean(!isnan(n) && !isinf(n));
- break;
- }
- case DecodeURI:
- res = decode(exec, args, do_not_unescape_when_decoding_URI, true);
- break;
- case DecodeURIComponent:
- res = decode(exec, args, "", true);
- break;
- case EncodeURI:
- res = encode(exec, args, do_not_escape_when_encoding_URI);
- break;
- case EncodeURIComponent:
- res = encode(exec, args, do_not_escape_when_encoding_URI_component);
- break;
- case Escape:
- {
- UString r = "", s, str = args[0]->toString(exec);
- const UChar* c = str.data();
- for (int k = 0; k < str.size(); k++, c++) {
+ return jsBoolean(!isnan(n) && !isinf(n));
+}
+
+JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, const List& args)
+{
+ static const char do_not_unescape_when_decoding_URI[] =
+ "#$&+,/:;=?@";
+
+ return decode(exec, args, do_not_unescape_when_decoding_URI, true);
+}
+
+JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, const List& args)
+{
+ return decode(exec, args, "", true);
+}
+
+JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, const List& args)
+{
+ static const char do_not_escape_when_encoding_URI[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "!#$&'()*+,-./:;=?@_~";
+
+ return encode(exec, args, do_not_escape_when_encoding_URI);
+}
+
+JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, const List& args)
+{
+ static const char do_not_escape_when_encoding_URI_component[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "!'()*-._~";
+
+ return encode(exec, args, do_not_escape_when_encoding_URI_component);
+}
+
+JSValue* globalFuncEscape(ExecState* exec, JSObject*, const List& args)
+{
+ static const char do_not_escape[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "*+-./@_";
+
+ UString r = "", s, str = args[0]->toString(exec);
+ const UChar* c = str.data();
+ for (int k = 0; k < str.size(); k++, c++) {
int u = c->uc;
if (u > 255) {
- char tmp[7];
- sprintf(tmp, "%%u%04X", u);
- s = UString(tmp);
- } else if (u != 0 && strchr(do_not_escape, (char)u)) {
- s = UString(c, 1);
- } else {
- char tmp[4];
- sprintf(tmp, "%%%02X", u);
- s = UString(tmp);
+ char tmp[7];
+ sprintf(tmp, "%%u%04X", u);
+ s = UString(tmp);
+ } else if (u != 0 && strchr(do_not_escape, (char)u))
+ s = UString(c, 1);
+ else {
+ char tmp[4];
+ sprintf(tmp, "%%%02X", u);
+ s = UString(tmp);
}
r += s;
- }
- res = jsString(r);
- break;
}
- case UnEscape:
- {
- UString s = "", str = args[0]->toString(exec);
- int k = 0, len = str.size();
- while (k < len) {
+
+ return jsString(r);
+}
+
+JSValue* globalFuncUnescape(ExecState* exec, JSObject*, const List& args)
+{
+ UString s = "", str = args[0]->toString(exec);
+ int k = 0, len = str.size();
+ while (k < len) {
const UChar* c = str.data() + k;
UChar u;
- if (*c == UChar('%') && k <= len - 6 && *(c+1) == UChar('u')) {
- if (Lexer::isHexDigit((c+2)->uc) && Lexer::isHexDigit((c+3)->uc) &&
- Lexer::isHexDigit((c+4)->uc) && Lexer::isHexDigit((c+5)->uc)) {
- u = Lexer::convertUnicode((c+2)->uc, (c+3)->uc,
- (c+4)->uc, (c+5)->uc);
- c = &u;
- k += 5;
- }
- } else if (*c == UChar('%') && k <= len - 3 &&
- Lexer::isHexDigit((c+1)->uc) && Lexer::isHexDigit((c+2)->uc)) {
- u = UChar(Lexer::convertHex((c+1)->uc, (c+2)->uc));
- c = &u;
- k += 2;
+ if (*c == UChar('%') && k <= len - 6 && *(c + 1) == UChar('u')) {
+ if (Lexer::isHexDigit((c + 2)->uc) && Lexer::isHexDigit((c + 3)->uc) && Lexer::isHexDigit((c + 4)->uc) && Lexer::isHexDigit((c + 5)->uc)) {
+ u = Lexer::convertUnicode((c + 2)->uc, (c + 3)->uc, (c + 4)->uc, (c + 5)->uc);
+ c = &u;
+ k += 5;
+ }
+ } else if (*c == UChar('%') && k <= len - 3 && Lexer::isHexDigit((c + 1)->uc) && Lexer::isHexDigit((c + 2)->uc)) {
+ u = UChar(Lexer::convertHex((c+1)->uc, (c+2)->uc));
+ c = &u;
+ k += 2;
}
k++;
s += UString(c, 1);
- }
- res = jsString(s);
- break;
}
+
+ return jsString(s);
+}
+
#ifndef NDEBUG
- case KJSPrint:
+JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, const List& args)
+{
puts(args[0]->toString(exec).ascii());
- break;
-#endif
- }
-
- return res;
+ return jsUndefined();
}
+#endif
// ------------------------------ PrototypeFunction -------------------------------
put(exec, exec->propertyNames().length, jsNumber(len), DontDelete | ReadOnly | DontEnum);
}
+PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, JSMemberFunction function)
+ : InternalFunctionImp(functionPrototype, name)
+ , m_function(function)
+{
+ ASSERT_ARG(function, function);
+ put(exec, exec->propertyNames().length, jsNumber(len), DontDelete | ReadOnly | DontEnum);
+}
+
JSValue* PrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
{
return m_function(exec, thisObj, args);
Identifier m_name;
};
- /**
- * @internal
- *
- * The initial value of Function.prototype (and thus all objects created
- * with the Function constructor)
- */
- class FunctionPrototype : public InternalFunctionImp {
- public:
- FunctionPrototype(ExecState *exec);
- virtual ~FunctionPrototype();
-
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
- };
-
class FunctionImp : public InternalFunctionImp {
friend class ActivationImp;
public:
typedef KJS::JSValue* (*JSMemberFunction)(ExecState*, JSObject*, const List&);
PrototypeFunction(ExecState*, int len, const Identifier&, JSMemberFunction);
+ PrototypeFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, JSMemberFunction);
virtual JSValue* callAsFunction(ExecState* exec, JSObject* thisObj, const List&);
const JSMemberFunction m_function;
};
- class GlobalFuncImp : public InternalFunctionImp {
- public:
- GlobalFuncImp(ExecState*, FunctionPrototype*, int i, int len, const Identifier&);
- virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List& args);
- enum { Eval, ParseInt, ParseFloat, IsNaN, IsFinite, Escape, UnEscape,
- DecodeURI, DecodeURIComponent, EncodeURI, EncodeURIComponent
+
+ // Global Functions
+ JSValue* globalFuncEval(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncParseInt(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncParseFloat(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncIsNaN(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncIsFinite(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncDecodeURI(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncEncodeURI(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncEscape(ExecState*, JSObject*, const List&);
+ JSValue* globalFuncUnescape(ExecState*, JSObject*, const List&);
#ifndef NDEBUG
- , KJSPrint
+ JSValue* globalFuncKJSPrint(ExecState*, JSObject*, const List&);
#endif
-};
- private:
- int id;
- };
- static const double mantissaOverflowLowerBound = 9007199254740992.0;
- double parseIntOverflow(const char* s, int length, int radix);
+ static const double mantissaOverflowLowerBound = 9007199254740992.0;
+ double parseIntOverflow(const char*, int length, int radix);
} // namespace
#include <string.h>
#include <wtf/Assertions.h>
-using namespace KJS;
+namespace KJS {
// ------------------------------ FunctionPrototype -------------------------
-FunctionPrototype::FunctionPrototype(ExecState *exec)
+static JSValue* functionProtoFuncToString(ExecState*, JSObject*, const List&);
+static JSValue* functionProtoFuncApply(ExecState*, JSObject*, const List&);
+static JSValue* functionProtoFuncCall(ExecState*, JSObject*, const List&);
+
+FunctionPrototype::FunctionPrototype(ExecState* exec)
{
- static const Identifier* applyPropertyName = new Identifier("apply");
- static const Identifier* callPropertyName = new Identifier("call");
+ static const Identifier* applyPropertyName = new Identifier("apply");
+ static const Identifier* callPropertyName = new Identifier("call");
- putDirect(exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
- putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::ToString, 0, exec->propertyNames().toString), DontEnum);
- putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Apply, 2, *applyPropertyName), DontEnum);
- putDirectFunction(new FunctionProtoFunc(exec, this, FunctionProtoFunc::Call, 1, *callPropertyName), DontEnum);
-}
+ putDirect(exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
-FunctionPrototype::~FunctionPrototype()
-{
+ putDirectFunction(new PrototypeFunction(exec, this, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, this, 2, *applyPropertyName, functionProtoFuncApply), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, this, 1, *callPropertyName, functionProtoFuncCall), DontEnum);
}
// ECMA 15.3.4
-JSValue *FunctionPrototype::callAsFunction(ExecState*, JSObject* /*thisObj*/, const List &/*args*/)
+JSValue* FunctionPrototype::callAsFunction(ExecState*, JSObject*, const List&)
{
- return jsUndefined();
+ return jsUndefined();
}
-// ------------------------------ FunctionProtoFunc -------------------------
-
-FunctionProtoFunc::FunctionProtoFunc(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
- : InternalFunctionImp(funcProto, name)
- , id(i)
-{
- putDirect(exec->propertyNames().length, len, DontDelete | ReadOnly | DontEnum);
-}
+// Functions
-JSValue* FunctionProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
+JSValue* functionProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
{
- JSValue* result = NULL;
-
- switch (id) {
- case ToString:
if (!thisObj || !thisObj->inherits(&InternalFunctionImp::info)) {
#ifndef NDEBUG
- fprintf(stderr,"attempted toString() call on null or non-function object\n");
+ fprintf(stderr,"attempted toString() call on null or non-function object\n");
#endif
- return throwError(exec, TypeError);
+ return throwError(exec, TypeError);
}
+
if (thisObj->inherits(&FunctionImp::info)) {
- FunctionImp *fi = static_cast<FunctionImp*>(thisObj);
- return jsString("function " + fi->functionName().ustring() + "(" +
- fi->body->paramString() + ") " + fi->body->toString());
- } else if (thisObj->inherits(&InternalFunctionImp::info) &&
- !static_cast<InternalFunctionImp*>(thisObj)->functionName().isNull()) {
- result = jsString("\nfunction " + static_cast<InternalFunctionImp*>(thisObj)->functionName().ustring() + "() {\n"
- " [native code]\n}\n");
- } else {
- result = jsString("[function]");
+ FunctionImp* fi = static_cast<FunctionImp*>(thisObj);
+ return jsString("function " + fi->functionName().ustring() + "(" + fi->body->paramString() + ") " + fi->body->toString());
}
- break;
- case Apply: {
- JSValue *thisArg = args[0];
- JSValue *argArray = args[1];
- JSObject *func = thisObj;
- if (!func->implementsCall())
- return throwError(exec, TypeError);
+ if (thisObj->inherits(&InternalFunctionImp::info) && !static_cast<InternalFunctionImp*>(thisObj)->functionName().isNull())
+ return jsString("\nfunction " + static_cast<InternalFunctionImp*>(thisObj)->functionName().ustring() + "() {\n [native code]\n}\n");
+
+ return jsString("[function]");
+}
+
+JSValue* functionProtoFuncApply(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ if (!thisObj->implementsCall())
+ return throwError(exec, TypeError);
- JSObject *applyThis;
+ JSValue* thisArg = args[0];
+ JSValue* argArray = args[1];
+
+ JSObject* applyThis;
if (thisArg->isUndefinedOrNull())
- applyThis = exec->dynamicGlobalObject();
+ applyThis = exec->dynamicGlobalObject();
else
- applyThis = thisArg->toObject(exec);
+ applyThis = thisArg->toObject(exec);
List applyArgs;
if (!argArray->isUndefinedOrNull()) {
- if (argArray->isObject() &&
- (static_cast<JSObject *>(argArray)->inherits(&ArrayInstance::info) ||
- static_cast<JSObject *>(argArray)->inherits(&Arguments::info))) {
-
- JSObject *argArrayObj = static_cast<JSObject *>(argArray);
- unsigned int length = argArrayObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
- for (unsigned int i = 0; i < length; i++)
- applyArgs.append(argArrayObj->get(exec,i));
- }
- else
- return throwError(exec, TypeError);
+ if (argArray->isObject() &&
+ (static_cast<JSObject*>(argArray)->inherits(&ArrayInstance::info) ||
+ static_cast<JSObject*>(argArray)->inherits(&Arguments::info))) {
+
+ JSObject* argArrayObj = static_cast<JSObject*>(argArray);
+ unsigned int length = argArrayObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned int i = 0; i < length; i++)
+ applyArgs.append(argArrayObj->get(exec, i));
+ } else
+ return throwError(exec, TypeError);
}
- result = func->call(exec,applyThis,applyArgs);
- }
- break;
- case Call: {
- JSValue *thisArg = args[0];
- JSObject *func = thisObj;
- if (!func->implementsCall())
- return throwError(exec, TypeError);
+ return thisObj->call(exec, applyThis, applyArgs);
+}
+
+JSValue* functionProtoFuncCall(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ if (!thisObj->implementsCall())
+ return throwError(exec, TypeError);
+
+ JSValue* thisArg = args[0];
- JSObject *callThis;
+ JSObject* callThis;
if (thisArg->isUndefinedOrNull())
- callThis = exec->dynamicGlobalObject();
+ callThis = exec->dynamicGlobalObject();
else
- callThis = thisArg->toObject(exec);
+ callThis = thisArg->toObject(exec);
List argsTail;
args.getSlice(1, argsTail);
- result = func->call(exec, callThis, argsTail);
- }
- break;
- }
-
- return result;
+ return thisObj->call(exec, callThis, argsTail);
}
// ------------------------------ FunctionObjectImp ----------------------------
-FunctionObjectImp::FunctionObjectImp(ExecState* exec, FunctionPrototype* funcProto)
- : InternalFunctionImp(funcProto)
+FunctionObjectImp::FunctionObjectImp(ExecState* exec, FunctionPrototype* functionPrototype)
+ : InternalFunctionImp(functionPrototype)
{
- putDirect(exec->propertyNames().prototype, funcProto, DontEnum|DontDelete|ReadOnly);
+ putDirect(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
- // no. of arguments for constructor
- putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly|DontDelete|DontEnum);
-}
-
-FunctionObjectImp::~FunctionObjectImp()
-{
+ // Number of arguments for constructor
+ putDirect(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
}
bool FunctionObjectImp::implementsConstruct() const
{
- return true;
+ return true;
}
// ECMA 15.3.2 The Function Constructor
JSObject* FunctionObjectImp::construct(ExecState* exec, const List& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
{
- UString p("");
- UString body;
- int argsSize = args.size();
- if (argsSize == 0) {
- body = "";
- } else if (argsSize == 1) {
- body = args[0]->toString(exec);
- } else {
- p = args[0]->toString(exec);
- for (int k = 1; k < argsSize - 1; k++)
- p += "," + args[k]->toString(exec);
- body = args[argsSize-1]->toString(exec);
- }
-
- // parse the source code
- int sourceId;
- int errLine;
- UString errMsg;
- RefPtr<FunctionBodyNode> functionBody = parser().parse<FunctionBodyNode>(sourceURL, lineNumber, body.data(), body.size(), &sourceId, &errLine, &errMsg);
-
- // notify debugger that source has been parsed
- Debugger *dbg = exec->dynamicGlobalObject()->debugger();
- if (dbg) {
- // send empty sourceURL to indicate constructed code
- bool cont = dbg->sourceParsed(exec, sourceId, UString(), body, lineNumber, errLine, errMsg);
- if (!cont) {
- dbg->imp()->abort();
- return new JSObject();
+ UString p("");
+ UString body;
+ int argsSize = args.size();
+ if (argsSize == 0)
+ body = "";
+ else if (argsSize == 1)
+ body = args[0]->toString(exec);
+ else {
+ p = args[0]->toString(exec);
+ for (int k = 1; k < argsSize - 1; k++)
+ p += "," + args[k]->toString(exec);
+ body = args[argsSize - 1]->toString(exec);
}
- }
-
- // no program node == syntax error - throw a syntax error
- if (!functionBody)
- // we can't return a Completion(Throw) here, so just set the exception
- // and return it
- return throwError(exec, SyntaxError, errMsg, errLine, sourceId, sourceURL);
- ScopeChain scopeChain;
- scopeChain.push(exec->lexicalGlobalObject());
+ // parse the source code
+ int sourceId;
+ int errLine;
+ UString errMsg;
+ RefPtr<FunctionBodyNode> functionBody = parser().parse<FunctionBodyNode>(sourceURL, lineNumber, body.data(), body.size(), &sourceId, &errLine, &errMsg);
+
+ // notify debugger that source has been parsed
+ Debugger* dbg = exec->dynamicGlobalObject()->debugger();
+ if (dbg) {
+ // send empty sourceURL to indicate constructed code
+ bool cont = dbg->sourceParsed(exec, sourceId, UString(), body, lineNumber, errLine, errMsg);
+ if (!cont) {
+ dbg->imp()->abort();
+ return new JSObject();
+ }
+ }
- FunctionImp* fimp = new FunctionImp(exec, functionName, functionBody.get(), scopeChain);
-
- // parse parameter list. throw syntax error on illegal identifiers
- int len = p.size();
- const UChar *c = p.data();
- int i = 0, params = 0;
- UString param;
- while (i < len) {
- while (*c == ' ' && i < len)
- c++, i++;
- if (Lexer::isIdentStart(c->uc)) { // else error
- param = UString(c, 1);
- c++, i++;
- while (i < len && (Lexer::isIdentPart(c->uc))) {
- param += UString(c, 1);
- c++, i++;
- }
- while (i < len && *c == ' ')
- c++, i++;
- if (i == len) {
- functionBody->parameters().append(Identifier(param));
- params++;
- break;
- } else if (*c == ',') {
- functionBody->parameters().append(Identifier(param));
- params++;
- c++, i++;
- continue;
- } // else error
- }
- return throwError(exec, SyntaxError, "Syntax error in parameter list");
- }
+ // No program node == syntax error - throw a syntax error
+ if (!functionBody)
+ // We can't return a Completion(Throw) here, so just set the exception
+ // and return it
+ return throwError(exec, SyntaxError, errMsg, errLine, sourceId, sourceURL);
+
+ ScopeChain scopeChain;
+ scopeChain.push(exec->lexicalGlobalObject());
+
+ FunctionImp* fimp = new FunctionImp(exec, functionName, functionBody.get(), scopeChain);
+
+ // parse parameter list. throw syntax error on illegal identifiers
+ int len = p.size();
+ const UChar* c = p.data();
+ int i = 0, params = 0;
+ UString param;
+ while (i < len) {
+ while (*c == ' ' && i < len)
+ c++, i++;
+ if (Lexer::isIdentStart(c->uc)) { // else error
+ param = UString(c, 1);
+ c++, i++;
+ while (i < len && (Lexer::isIdentPart(c->uc))) {
+ param += UString(c, 1);
+ c++, i++;
+ }
+ while (i < len && *c == ' ')
+ c++, i++;
+ if (i == len) {
+ functionBody->parameters().append(Identifier(param));
+ params++;
+ break;
+ } else if (*c == ',') {
+ functionBody->parameters().append(Identifier(param));
+ params++;
+ c++, i++;
+ continue;
+ } // else error
+ }
+ return throwError(exec, SyntaxError, "Syntax error in parameter list");
+ }
- List consArgs;
+ List consArgs;
- JSObject* objCons = exec->lexicalGlobalObject()->objectConstructor();
- JSObject* prototype = objCons->construct(exec, exec->emptyList());
- prototype->put(exec, exec->propertyNames().constructor, fimp, DontEnum|DontDelete|ReadOnly);
- fimp->put(exec, exec->propertyNames().prototype, prototype, Internal|DontDelete);
- return fimp;
+ JSObject* objCons = exec->lexicalGlobalObject()->objectConstructor();
+ JSObject* prototype = objCons->construct(exec, exec->emptyList());
+ prototype->put(exec, exec->propertyNames().constructor, fimp, DontEnum | DontDelete | ReadOnly);
+ fimp->put(exec, exec->propertyNames().prototype, prototype, Internal | DontDelete);
+ return fimp;
}
// ECMA 15.3.2 The Function Constructor
JSObject* FunctionObjectImp::construct(ExecState* exec, const List& args)
{
- return construct(exec, args, "anonymous", UString(), 0);
+ return construct(exec, args, "anonymous", UString(), 0);
}
// ECMA 15.3.1 The Function Constructor Called as a Function
-JSValue* FunctionObjectImp::callAsFunction(ExecState* exec, JSObject* /*thisObj*/, const List &args)
+JSValue* FunctionObjectImp::callAsFunction(ExecState* exec, JSObject*, const List& args)
{
- return construct(exec, args);
+ return construct(exec, args);
}
+
+} // namespace KJS
namespace KJS {
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Function.prototype object
- */
- class FunctionProtoFunc : public InternalFunctionImp {
- public:
- FunctionProtoFunc(ExecState*, FunctionPrototype*, int i, int len, const Identifier&);
-
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
-
- enum { ToString, Apply, Call };
- private:
- int id;
- };
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Function" property
- */
- class FunctionObjectImp : public InternalFunctionImp {
- public:
- FunctionObjectImp(ExecState*, FunctionPrototype*);
- virtual ~FunctionObjectImp();
-
- virtual bool implementsConstruct() const;
- virtual JSObject* construct(ExecState*, const List& args);
- virtual JSObject* construct(ExecState*, const List& args, const Identifier& functionName, const UString& sourceURL, int lineNumber);
- virtual JSValue* callAsFunction(ExecState*, JSObject* thisObj, const List& args);
- };
-
-} // namespace
+ /**
+ * @internal
+ *
+ * The initial value of Function.prototype (and thus all objects created
+ * with the Function constructor)
+ */
+ class FunctionPrototype : public InternalFunctionImp {
+ public:
+ FunctionPrototype(ExecState*);
+
+ virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
+ };
+
+ /**
+ * @internal
+ *
+ * The initial value of the the global variable's "Function" property
+ */
+ class FunctionObjectImp : public InternalFunctionImp {
+ public:
+ FunctionObjectImp(ExecState*, FunctionPrototype*);
+
+ virtual bool implementsConstruct() const;
+ virtual JSObject* construct(ExecState*, const List&);
+ virtual JSObject* construct(ExecState*, const List&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
+ virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
+ };
+
+} // namespace KJS
#endif // _FUNCTION_OBJECT_H_
: JSWrapperObject(proto)
{
}
+
// ------------------------------ NumberPrototype ---------------------------
+static JSValue* numberProtoFuncToString(ExecState*, JSObject*, const List&);
+static JSValue* numberProtoFuncToLocaleString(ExecState*, JSObject*, const List&);
+static JSValue* numberProtoFuncValueOf(ExecState*, JSObject*, const List&);
+static JSValue* numberProtoFuncToFixed(ExecState*, JSObject*, const List&);
+static JSValue* numberProtoFuncToExponential(ExecState*, JSObject*, const List&);
+static JSValue* numberProtoFuncToPrecision(ExecState*, JSObject*, const List&);
+
// ECMA 15.7.4
-NumberPrototype::NumberPrototype(ExecState* exec, ObjectPrototype* objProto, FunctionPrototype* funcProto)
- : NumberInstance(objProto)
+NumberPrototype::NumberPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
+ : NumberInstance(objectPrototype)
{
setInternalValue(jsNumber(0));
// The constructor will be added later, after NumberObjectImp has been constructed
- putDirectFunction(new NumberProtoFunc(exec, funcProto, NumberProtoFunc::ToString, 1, exec->propertyNames().toString), DontEnum);
- putDirectFunction(new NumberProtoFunc(exec, funcProto, NumberProtoFunc::ToLocaleString, 0, exec->propertyNames().toLocaleString), DontEnum);
- putDirectFunction(new NumberProtoFunc(exec, funcProto, NumberProtoFunc::ValueOf, 0, exec->propertyNames().valueOf), DontEnum);
- putDirectFunction(new NumberProtoFunc(exec, funcProto, NumberProtoFunc::ToFixed, 1, exec->propertyNames().toFixed), DontEnum);
- putDirectFunction(new NumberProtoFunc(exec, funcProto, NumberProtoFunc::ToExponential, 1, exec->propertyNames().toExponential), DontEnum);
- putDirectFunction(new NumberProtoFunc(exec, funcProto, NumberProtoFunc::ToPrecision, 1, exec->propertyNames().toPrecision), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);
}
+// ------------------------------ Functions ---------------------------
-// ------------------------------ NumberProtoFunc ---------------------------
-
-NumberProtoFunc::NumberProtoFunc(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
- : InternalFunctionImp(funcProto, name)
- , id(i)
-{
- putDirect(exec->propertyNames().length, len, DontDelete|ReadOnly|DontEnum);
-}
+// ECMA 15.7.4.2 - 15.7.4.7
static UString integer_part_noexp(double d)
{
return static_cast<double>(result);
}
-static JSValue* numberToString(ExecState* exec, JSValue* v, const List& args)
+
+JSValue* numberProtoFuncToString(ExecState* exec, JSObject* thisObj, const List& args)
{
+ if (!thisObj->inherits(&NumberInstance::info))
+ return throwError(exec, TypeError);
+
+ JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
+
double radixAsDouble = args[0]->toInteger(exec); // nan -> 0
if (radixAsDouble == 10 || args[0]->isUndefined())
return jsString(v->toString(exec));
return jsString(startOfResultString);
}
-static JSValue* numberToFixed(ExecState* exec, JSValue* v, const List& args)
+JSValue* numberProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const List&)
{
+ if (!thisObj->inherits(&NumberInstance::info))
+ return throwError(exec, TypeError);
+
+ // TODO
+ return jsString(static_cast<NumberInstance*>(thisObj)->internalValue()->toString(exec));
+}
+
+JSValue* numberProtoFuncValueOf(ExecState* exec, JSObject* thisObj, const List&)
+{
+ if (!thisObj->inherits(&NumberInstance::info))
+ return throwError(exec, TypeError);
+
+ return static_cast<NumberInstance*>(thisObj)->internalValue()->toJSNumber(exec);
+}
+
+JSValue* numberProtoFuncToFixed(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ if (!thisObj->inherits(&NumberInstance::info))
+ return throwError(exec, TypeError);
+
+ JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
+
JSValue* fractionDigits = args[0];
double df = fractionDigits->toInteger(exec);
if (!(df >= 0 && df <= 20))
buf[i++] = static_cast<char>('0' + exponential % 10);
}
-static JSValue* numberToExponential(ExecState* exec, JSValue* v, const List& args)
+JSValue* numberProtoFuncToExponential(ExecState* exec, JSObject* thisObj, const List& args)
{
+ if (!thisObj->inherits(&NumberInstance::info))
+ return throwError(exec, TypeError);
+
+ JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
+
double x = v->toNumber(exec);
if (isnan(x) || isinf(x))
return jsString(buf);
}
-
-static JSValue* numberToPrecision(ExecState* exec, JSValue* v, const List& args)
+
+JSValue* numberProtoFuncToPrecision(ExecState* exec, JSObject* thisObj, const List& args)
{
+ if (!thisObj->inherits(&NumberInstance::info))
+ return throwError(exec, TypeError);
+
+ JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
+
double doublePrecision = args[0]->toIntegerPreserveNaN(exec);
double x = v->toNumber(exec);
if (args[0]->isUndefined() || isnan(x) || isinf(x))
return jsString(s + "0." + char_sequence('0', -(e + 1)) + m);
}
-// ECMA 15.7.4.2 - 15.7.4.7
-JSValue* NumberProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
-{
- // no generic function. "this" has to be a Number object
- if (!thisObj->inherits(&NumberInstance::info))
- return throwError(exec, TypeError);
-
- JSValue* v = static_cast<NumberInstance*>(thisObj)->internalValue();
- switch (id) {
- case ToString:
- return numberToString(exec, v, args);
- case ToLocaleString: /* TODO */
- return jsString(v->toString(exec));
- case ValueOf:
- return v->toJSNumber(exec);
- case ToFixed:
- return numberToFixed(exec, v, args);
- case ToExponential:
- return numberToExponential(exec, v, args);
- case ToPrecision:
- return numberToPrecision(exec, v, args);
- }
- return 0;
-}
-
// ------------------------------ NumberObjectImp ------------------------------
const ClassInfo NumberObjectImp::info = { "Function", &InternalFunctionImp::info, &numberTable };
namespace KJS {
- class NumberInstance : public JSWrapperObject {
- public:
- NumberInstance(JSObject *proto);
+ class NumberInstance : public JSWrapperObject {
+ public:
+ NumberInstance(JSObject* prototype);
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
- /**
- * @internal
- *
- * The initial value of Number.prototype (and thus all objects created
- * with the Number constructor
- */
- class NumberPrototype : public NumberInstance {
- public:
- NumberPrototype(ExecState *exec,
- ObjectPrototype *objProto,
- FunctionPrototype *funcProto);
- };
+ /**
+ * @internal
+ *
+ * The initial value of Number.prototype (and thus all objects created
+ * with the Number constructor
+ */
+ class NumberPrototype : public NumberInstance {
+ public:
+ NumberPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);
+ };
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Number.prototype object
- */
- class NumberProtoFunc : public InternalFunctionImp {
- public:
- NumberProtoFunc(ExecState*, FunctionPrototype*, int i, int len, const Identifier&);
+ /**
+ * @internal
+ *
+ * The initial value of the the global variable's "Number" property
+ */
+ class NumberObjectImp : public InternalFunctionImp {
+ public:
+ NumberObjectImp(ExecState*, FunctionPrototype*, NumberPrototype*);
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+ virtual bool implementsConstruct() const;
+ virtual JSObject* construct(ExecState*, const List&);
- enum { ToString, ToLocaleString, ValueOf, ToFixed, ToExponential, ToPrecision };
- private:
- int id;
- };
+ virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
- /**
- * @internal
- *
- * The initial value of the the global variable's "Number" property
- */
- class NumberObjectImp : public InternalFunctionImp {
- public:
- NumberObjectImp(ExecState *exec,
- FunctionPrototype *funcProto,
- NumberPrototype *numberProto);
+ bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ JSValue* getValueProperty(ExecState*, int token) const;
- virtual bool implementsConstruct() const;
- virtual JSObject *construct(ExecState *exec, const List &args);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
- virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
+ enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
- bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
- JSValue *getValueProperty(ExecState *exec, int token) const;
+ JSObject* construct(const List&);
+ };
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
+} // namespace KJS
- JSObject *construct(const List &);
- };
-
-} // namespace
-
-#endif
+#endif // NUMBER_OBJECT_H_
-// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "function_object.h"
#include <stdio.h>
-using namespace KJS;
+namespace KJS {
// ------------------------------ ObjectPrototype --------------------------------
-ObjectPrototype::ObjectPrototype(ExecState* exec, FunctionPrototype* funcProto)
- : JSObject() // [[Prototype]] is null
+static JSValue* objectProtoFuncValueOf(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncHasOwnProperty(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncDefineGetter(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncDefineSetter(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncLookupGetter(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncLookupSetter(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncToLocaleString(ExecState*, JSObject*, const List&);
+static JSValue* objectProtoFuncToString(ExecState*, JSObject*, const List&);
+
+ObjectPrototype::ObjectPrototype(ExecState* exec, FunctionPrototype* functionPrototype)
+ : JSObject() // [[Prototype]] is null
{
static const Identifier* hasOwnPropertyPropertyName = new Identifier("hasOwnProperty");
static const Identifier* propertyIsEnumerablePropertyName = new Identifier("propertyIsEnumerable");
static const Identifier* lookupGetterPropertyName = new Identifier("__lookupGetter__");
static const Identifier* lookupSetterPropertyName = new Identifier("__lookupSetter__");
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ToString, 0, exec->propertyNames().toString), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ToLocaleString, 0, exec->propertyNames().toLocaleString), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::ValueOf, 0, exec->propertyNames().valueOf), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::HasOwnProperty, 1, *hasOwnPropertyPropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::PropertyIsEnumerable, 1, *propertyIsEnumerablePropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::IsPrototypeOf, 1, *isPrototypeOfPropertyName), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *hasOwnPropertyPropertyName, objectProtoFuncHasOwnProperty), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *propertyIsEnumerablePropertyName, objectProtoFuncPropertyIsEnumerable), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *isPrototypeOfPropertyName, objectProtoFuncIsPrototypeOf), DontEnum);
// Mozilla extensions
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineGetter, 2, *defineGetterPropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::DefineSetter, 2, *defineSetterPropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupGetter, 1, *lookupGetterPropertyName), DontEnum);
- putDirectFunction(new ObjectProtoFunc(exec, funcProto, ObjectProtoFunc::LookupSetter, 1, *lookupSetterPropertyName), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 2, *defineGetterPropertyName, objectProtoFuncDefineGetter), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 2, *defineSetterPropertyName, objectProtoFuncDefineSetter), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *lookupGetterPropertyName, objectProtoFuncLookupGetter), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 1, *lookupSetterPropertyName, objectProtoFuncLookupSetter), DontEnum);
}
-// ------------------------------ ObjectProtoFunc --------------------------------
+// ------------------------------ Functions --------------------------------
-ObjectProtoFunc::ObjectProtoFunc(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
- : InternalFunctionImp(funcProto, name)
- , id(i)
+// ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
+
+JSValue* objectProtoFuncValueOf(ExecState*, JSObject* thisObj, const List&)
{
- putDirect(exec->propertyNames().length, len, DontDelete|ReadOnly|DontEnum);
+ return thisObj;
}
+JSValue* objectProtoFuncHasOwnProperty(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ return jsBoolean(thisObj->hasOwnProperty(exec, Identifier(args[0]->toString(exec))));
+}
-// ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
+JSValue* objectProtoFuncIsPrototypeOf(ExecState*, JSObject* thisObj, const List& args)
+{
+ if (!args[0]->isObject())
+ return jsBoolean(false);
+
+ JSValue* v = static_cast<JSObject*>(args[0])->prototype();
+
+ while (true) {
+ if (!v->isObject())
+ return jsBoolean(false);
+ if (thisObj == static_cast<JSObject*>(v))\v
+ return jsBoolean(true);
+ v = static_cast<JSObject*>(v)->prototype();
+ }
+}
+
+JSValue* objectProtoFuncDefineGetter(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ if (!args[1]->isObject() || !static_cast<JSObject*>(args[1])->implementsCall())
+ return throwError(exec, SyntaxError, "invalid getter usage");
+
+ thisObj->defineGetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1]));
+ return jsUndefined();
+}
+
+JSValue* objectProtoFuncDefineSetter(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ if (!args[1]->isObject() || !static_cast<JSObject*>(args[1])->implementsCall())
+ return throwError(exec, SyntaxError, "invalid setter usage");
+
+ thisObj->defineSetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1]));
+ return jsUndefined();
+}
-JSValue *ObjectProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
+JSValue* objectProtoFuncLookupGetter(ExecState* exec, JSObject* thisObj, const List& args)
{
- switch (id) {
- case ValueOf:
- return thisObj;
- case HasOwnProperty:
- return jsBoolean(thisObj->hasOwnProperty(exec, Identifier(args[0]->toString(exec))));
- case IsPrototypeOf: {
- if (!args[0]->isObject())
- return jsBoolean(false);
-
- JSValue *v = static_cast<JSObject *>(args[0])->prototype();
-
- while (true) {
- if (!v->isObject())
- return jsBoolean(false);
-
- if (thisObj == static_cast<JSObject *>(v))\v
- return jsBoolean(true);
-
- v = static_cast<JSObject *>(v)->prototype();
- }
+ Identifier propertyName = Identifier(args[0]->toString(exec));
+ JSObject* obj = thisObj;
+ while (true) {
+ JSValue* v = obj->getDirect(propertyName);
+ if (v) {
+ if (v->type() != GetterSetterType)
+ return jsUndefined();
+ JSObject* funcObj = static_cast<GetterSetterImp*>(v)->getGetter();
+ if (!funcObj)
+ return jsUndefined();
+ return funcObj;
}
- case DefineGetter:
- case DefineSetter: {
- if (!args[1]->isObject() ||
- !static_cast<JSObject *>(args[1])->implementsCall()) {
- if (id == DefineGetter)
- return throwError(exec, SyntaxError, "invalid getter usage");
- else
- return throwError(exec, SyntaxError, "invalid setter usage");
- }
-
- if (id == DefineGetter)
- thisObj->defineGetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1]));
- else
- thisObj->defineSetter(exec, Identifier(args[0]->toString(exec)), static_cast<JSObject *>(args[1]));
+
+ if (!obj->prototype() || !obj->prototype()->isObject())
return jsUndefined();
+ obj = static_cast<JSObject*>(obj->prototype());
+ }
+}
+
+JSValue* objectProtoFuncLookupSetter(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ Identifier propertyName = Identifier(args[0]->toString(exec));
+ JSObject* obj = thisObj;
+ while (true) {
+ JSValue* v = obj->getDirect(propertyName);
+ if (v) {
+ if (v->type() != GetterSetterType)
+ return jsUndefined();
+ JSObject* funcObj = static_cast<GetterSetterImp*>(v)->getSetter();
+ if (!funcObj)
+ return jsUndefined();
+ return funcObj;
}
- case LookupGetter:
- case LookupSetter: {
- Identifier propertyName = Identifier(args[0]->toString(exec));
-
- JSObject *obj = thisObj;
- while (true) {
- JSValue *v = obj->getDirect(propertyName);
-
- if (v) {
- if (v->type() != GetterSetterType)
- return jsUndefined();
-
- JSObject *funcObj;
-
- if (id == LookupGetter)
- funcObj = static_cast<GetterSetterImp *>(v)->getGetter();
- else
- funcObj = static_cast<GetterSetterImp *>(v)->getSetter();
-
- if (!funcObj)
- return jsUndefined();
- else
- return funcObj;
- }
-
- if (!obj->prototype() || !obj->prototype()->isObject())
- return jsUndefined();
-
- obj = static_cast<JSObject *>(obj->prototype());
- }
- }
- case PropertyIsEnumerable:
- return jsBoolean(thisObj->propertyIsEnumerable(exec, Identifier(args[0]->toString(exec))));
- case ToLocaleString:
- return jsString(thisObj->toString(exec));
- case ToString:
- default:
- return jsString("[object " + thisObj->className() + "]");
+
+ if (!obj->prototype() || !obj->prototype()->isObject())
+ return jsUndefined();
+ obj = static_cast<JSObject*>(obj->prototype());
}
}
+JSValue* objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ return jsBoolean(thisObj->propertyIsEnumerable(exec, Identifier(args[0]->toString(exec))));
+}
+
+JSValue* objectProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const List&)
+{
+ return jsString(thisObj->toString(exec));
+}
+
+JSValue* objectProtoFuncToString(ExecState*, JSObject* thisObj, const List&)
+{
+ return jsString("[object " + thisObj->className() + "]");
+}
+
// ------------------------------ ObjectObjectImp --------------------------------
ObjectObjectImp::ObjectObjectImp(ExecState* exec, ObjectPrototype* objProto, FunctionPrototype* funcProto)
return construct(exec, args);
}
+} // namespace KJS
-// -*- c-basic-offset: 2 -*-
/*
- * This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
namespace KJS {
- class FunctionPrototype;
-
- /**
- * @internal
- *
- * The initial value of Object.prototype (and thus all objects created
- * with the Object constructor
- */
- class ObjectPrototype : public JSObject {
- public:
- ObjectPrototype(ExecState *exec, FunctionPrototype *funcProto);
- };
-
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Object.prototype object
- */
- class ObjectProtoFunc : public InternalFunctionImp {
- public:
- ObjectProtoFunc(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier&);
-
- virtual JSValue *callAsFunction(ExecState *, JSObject *, const List &args);
-
- enum { ToString, ToLocaleString, ValueOf, HasOwnProperty, IsPrototypeOf, PropertyIsEnumerable,
- DefineGetter, DefineSetter, LookupGetter, LookupSetter };
- private:
- int id;
- };
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Object" property
- */
- class ObjectObjectImp : public InternalFunctionImp {
- public:
-
- ObjectObjectImp(ExecState *exec,
- ObjectPrototype *objProto,
- FunctionPrototype *funcProto);
-
- virtual bool implementsConstruct() const;
- virtual JSObject *construct(ExecState *, const List &args);
- virtual JSValue *callAsFunction(ExecState *, JSObject *, const List &args);
- };
-
-} // namespace
-
-#endif
+ /**
+ * @internal
+ *
+ * The initial value of Object.prototype (and thus all objects created
+ * with the Object constructor
+ */
+ class ObjectPrototype : public JSObject {
+ public:
+ ObjectPrototype(ExecState*, FunctionPrototype*);
+ };
+
+ /**
+ * @internal
+ *
+ * The initial value of the the global variable's "Object" property
+ */
+ class ObjectObjectImp : public InternalFunctionImp {
+ public:
+ ObjectObjectImp(ExecState*, ObjectPrototype*, FunctionPrototype*);
+
+ virtual bool implementsConstruct() const;
+ virtual JSObject* construct(ExecState*, const List&);
+ virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
+ };
+
+} // namespace KJS
+
+#endif // _OBJECT_OBJECT_H_
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
// ------------------------------ RegExpPrototype ---------------------------
+static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, const List&);
+static JSValue* regExpProtoFuncExec(ExecState*, JSObject*, const List&);
+static JSValue* regExpProtoFuncCompile(ExecState*, JSObject*, const List&);
+static JSValue* regExpProtoFuncToString(ExecState*, JSObject*, const List&);
+
// ECMA 15.10.5
const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0 };
-RegExpPrototype::RegExpPrototype(ExecState *exec,
- ObjectPrototype *objProto,
- FunctionPrototype *funcProto)
- : JSObject(objProto)
+RegExpPrototype::RegExpPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
+ : JSObject(objectPrototype)
{
- static const Identifier* compilePropertyName = new Identifier("compile");
- static const Identifier* execPropertyName = new Identifier("exec");
- static const Identifier* testPropertyName = new Identifier("test");
-
- putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Compile, 0, *compilePropertyName), DontEnum);
- putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Exec, 0, *execPropertyName), DontEnum);
- putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::Test, 0, *testPropertyName), DontEnum);
- putDirectFunction(new RegExpProtoFunc(exec, funcProto, RegExpProtoFunc::ToString, 0, exec->propertyNames().toString), DontEnum);
+ static const Identifier* compilePropertyName = new Identifier("compile");
+ static const Identifier* execPropertyName = new Identifier("exec");
+ static const Identifier* testPropertyName = new Identifier("test");
+
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, *compilePropertyName, regExpProtoFuncCompile), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, *execPropertyName, regExpProtoFuncExec), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, *testPropertyName, regExpProtoFuncTest), DontEnum);
+ putDirectFunction(new PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
}
-// ------------------------------ RegExpProtoFunc ---------------------------
+// ------------------------------ Functions ---------------------------
+
+JSValue* regExpProtoFuncTest(ExecState* exec, JSObject* thisObj, const List& args)
+{
+ if (!thisObj->inherits(&RegExpImp::info))
+ return throwError(exec, TypeError);
+
+ return static_cast<RegExpImp*>(thisObj)->test(exec, args);
+}
-RegExpProtoFunc::RegExpProtoFunc(ExecState* exec, FunctionPrototype* funcProto, int i, int len, const Identifier& name)
- : InternalFunctionImp(funcProto, name), id(i)
+JSValue* regExpProtoFuncExec(ExecState* exec, JSObject* thisObj, const List& args)
{
- putDirect(exec->propertyNames().length, len, DontDelete | ReadOnly | DontEnum);
+ if (!thisObj->inherits(&RegExpImp::info))
+ return throwError(exec, TypeError);
+
+ return static_cast<RegExpImp*>(thisObj)->exec(exec, args);
}
-JSValue *RegExpProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
+JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject* thisObj, const List& args)
{
- if (!thisObj->inherits(&RegExpImp::info)) {
- if (thisObj->inherits(&RegExpPrototype::info)) {
- switch (id) {
- case ToString: return jsString("//");
- }
- }
-
- return throwError(exec, TypeError);
- }
+ if (!thisObj->inherits(&RegExpImp::info))
+ return throwError(exec, TypeError);
- switch (id) {
- case Test:
- return static_cast<RegExpImp*>(thisObj)->test(exec, args);
- case Exec:
- return static_cast<RegExpImp*>(thisObj)->exec(exec, args);
- case Compile:
- {
RefPtr<RegExp> regExp;
JSValue* arg0 = args[0];
JSValue* arg1 = args[1];
if (arg0->isObject(&RegExpImp::info)) {
- if (!arg1->isUndefined())
- return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
- regExp = static_cast<RegExpImp*>(arg0)->regExp();
+ if (!arg1->isUndefined())
+ return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
+ regExp = static_cast<RegExpImp*>(arg0)->regExp();
} else {
- UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);
- UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
- regExp = new RegExp(pattern, flags);
+ UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);
+ UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
+ regExp = new RegExp(pattern, flags);
}
if (!regExp->isValid())
- return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+ return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
static_cast<RegExpImp*>(thisObj)->setRegExp(regExp.release());
static_cast<RegExpImp*>(thisObj)->put(exec, exec->propertyNames().lastIndex, jsNumber(0), DontDelete|DontEnum);
return jsUndefined();
- }
- case ToString:
- UString result = "/" + thisObj->get(exec, exec->propertyNames().source)->toString(exec) + "/";
- if (thisObj->get(exec, exec->propertyNames().global)->toBoolean(exec)) {
- result += "g";
- }
- if (thisObj->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec)) {
- result += "i";
- }
- if (thisObj->get(exec, exec->propertyNames().multiline)->toBoolean(exec)) {
- result += "m";
+}
+
+JSValue* regExpProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
+{
+ if (!thisObj->inherits(&RegExpImp::info)) {
+ if (thisObj->inherits(&RegExpPrototype::info))
+ return jsString("//");
+ return throwError(exec, TypeError);
}
+
+ UString result = "/" + thisObj->get(exec, exec->propertyNames().source)->toString(exec) + "/";
+ if (thisObj->get(exec, exec->propertyNames().global)->toBoolean(exec))
+ result += "g";
+ if (thisObj->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec))
+ result += "i";
+ if (thisObj->get(exec, exec->propertyNames().multiline)->toBoolean(exec))
+ result += "m";
return jsString(result);
- }
- return jsUndefined();
+ return jsUndefined();
}
// ------------------------------ RegExpImp ------------------------------------
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
class RegExpPrototype : public JSObject {
public:
RegExpPrototype(ExecState*, ObjectPrototype*, FunctionPrototype*);
+
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
};
- class RegExpProtoFunc : public InternalFunctionImp {
- public:
- enum { Compile, Exec, Test, ToString };
-
- RegExpProtoFunc(ExecState*, FunctionPrototype*, int id, int len, const Identifier&);
- virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
-
- private:
- int id;
- };
-
class RegExpImp : public JSObject {
public:
enum { Global, IgnoreCase, Multiline, Source, LastIndex };