00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "function_object.h"
00023 #include "internal.h"
00024 #include "function.h"
00025 #include "array_object.h"
00026 #include "nodes.h"
00027 #include "lexer.h"
00028 #include "debugger.h"
00029 #include "object.h"
00030
00031 #include <assert.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034
00035 using namespace KJS;
00036
00037
00038
00039 FunctionPrototypeImp::FunctionPrototypeImp(ExecState *exec)
00040 : InternalFunctionImp(0)
00041 {
00042 Value protect(this);
00043 put(exec, "toString", Object(new FunctionProtoFuncImp(exec, this, FunctionProtoFuncImp::ToString, 0)), DontEnum);
00044 put(exec, "apply", Object(new FunctionProtoFuncImp(exec, this, FunctionProtoFuncImp::Apply, 2)), DontEnum);
00045 put(exec, "call", Object(new FunctionProtoFuncImp(exec, this, FunctionProtoFuncImp::Call, 1)), DontEnum);
00046 }
00047
00048 FunctionPrototypeImp::~FunctionPrototypeImp()
00049 {
00050 }
00051
00052 bool FunctionPrototypeImp::implementsCall() const
00053 {
00054 return true;
00055 }
00056
00057
00058 Value FunctionPrototypeImp::call(ExecState *, Object &, const List &)
00059 {
00060 return Undefined();
00061 }
00062
00063
00064
00065 FunctionProtoFuncImp::FunctionProtoFuncImp(ExecState *exec,
00066 FunctionPrototypeImp *funcProto, int i, int len)
00067 : InternalFunctionImp(funcProto), id(i)
00068 {
00069 Value protect(this);
00070 put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
00071 }
00072
00073
00074 bool FunctionProtoFuncImp::implementsCall() const
00075 {
00076 return true;
00077 }
00078
00079 Value FunctionProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
00080 {
00081 Value result;
00082
00083 switch (id) {
00084 case ToString: {
00085
00086 if (thisObj.isNull() || !thisObj.inherits(&InternalFunctionImp::info)) {
00087 #ifndef NDEBUG
00088 fprintf(stderr,"attempted toString() call on null or non-function object\n");
00089 #endif
00090 Object err = Error::create(exec,TypeError);
00091 exec->setException(err);
00092 return err;
00093 }
00094 if (thisObj.inherits(&DeclaredFunctionImp::info)) {
00095 DeclaredFunctionImp *fi = static_cast<DeclaredFunctionImp*>
00096 (thisObj.imp());
00097 return String("function " + fi->name() + "(" +
00098 fi->parameterString() + ") " + fi->body->toString());
00099 } else if (thisObj.inherits(&FunctionImp::info) &&
00100 !static_cast<FunctionImp*>(thisObj.imp())->name().isNull()) {
00101 result = String("function " + static_cast<FunctionImp*>(thisObj.imp())->name() + "()");
00102 }
00103 else {
00104 result = String("(Internal function)");
00105 }
00106 }
00107 break;
00108 case Apply: {
00109 Value thisArg = args[0];
00110 Value argArray = args[1];
00111 Object func = thisObj;
00112
00113 if (!func.implementsCall()) {
00114 Object err = Error::create(exec,TypeError);
00115 exec->setException(err);
00116 return err;
00117 }
00118
00119 Object applyThis;
00120 if (thisArg.isA(NullType) || thisArg.isA(UndefinedType))
00121 applyThis = exec->interpreter()->globalObject();
00122 else
00123 applyThis = thisArg.toObject(exec);
00124
00125 List applyArgs;
00126 if (!argArray.isA(NullType) && !argArray.isA(UndefinedType)) {
00127 if ((argArray.isA(ObjectType) &&
00128 Object::dynamicCast(argArray).inherits(&ArrayInstanceImp::info)) ||
00129 Object::dynamicCast(argArray).inherits(&ArgumentsImp::info)) {
00130
00131 Object argArrayObj = Object::dynamicCast(argArray);
00132 unsigned int length = argArrayObj.get(exec,"length").toUInt32(exec);
00133 for (unsigned int i = 0; i < length; i++)
00134 applyArgs.append(argArrayObj.get(exec,UString::from(i)));
00135 }
00136 else {
00137 Object err = Error::create(exec,TypeError);
00138 exec->setException(err);
00139 return err;
00140 }
00141 }
00142 result = func.call(exec,applyThis,applyArgs);
00143 }
00144 break;
00145 case Call: {
00146 Value thisArg = args[0];
00147 Object func = thisObj;
00148
00149 if (!func.implementsCall()) {
00150 Object err = Error::create(exec,TypeError);
00151 exec->setException(err);
00152 return err;
00153 }
00154
00155 Object callThis;
00156 if (thisArg.isA(NullType) || thisArg.isA(UndefinedType))
00157 callThis = exec->interpreter()->globalObject();
00158 else
00159 callThis = thisArg.toObject(exec);
00160
00161 List callArgs = args.copy();
00162 callArgs.removeFirst();
00163 result = func.call(exec,callThis,callArgs);
00164 }
00165 break;
00166 }
00167
00168 return result;
00169 }
00170
00171
00172
00173 FunctionObjectImp::FunctionObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto)
00174 : InternalFunctionImp(funcProto)
00175 {
00176 Value protect(this);
00177 put(exec,"prototype", Object(funcProto), DontEnum|DontDelete|ReadOnly);
00178
00179
00180 put(exec,"length", Number(1), ReadOnly|DontDelete|DontEnum);
00181 }
00182
00183 FunctionObjectImp::~FunctionObjectImp()
00184 {
00185 }
00186
00187 bool FunctionObjectImp::implementsConstruct() const
00188 {
00189 return true;
00190 }
00191
00192
00193 Object FunctionObjectImp::construct(ExecState *exec, const List &args)
00194 {
00195 UString p("");
00196 UString body;
00197 int argsSize = args.size();
00198 if (argsSize == 0) {
00199 body = "";
00200 } else if (argsSize == 1) {
00201 body = args[0].toString(exec);
00202 } else {
00203 p = args[0].toString(exec);
00204 for (int k = 1; k < argsSize - 1; k++)
00205 p += "," + args[k].toString(exec);
00206 body = args[argsSize-1].toString(exec);
00207 }
00208
00209
00210 int sid;
00211 int errLine;
00212 UString errMsg;
00213 ProgramNode *progNode = Parser::parse(body.data(),body.size(),&sid,&errLine,&errMsg);
00214
00215
00216 Debugger *dbg = exec->interpreter()->imp()->debugger();
00217 if (dbg) {
00218 bool cont = dbg->sourceParsed(exec,sid,body,errLine);
00219 if (!cont) {
00220 dbg->imp()->abort();
00221 return Object(new ObjectImp());
00222 }
00223 }
00224
00225
00226 if (!progNode) {
00227 Object err = Error::create(exec,SyntaxError,errMsg.ascii(),errLine);
00228
00229
00230 exec->setException(err);
00231 return err;
00232 }
00233
00234 List scopeChain;
00235 scopeChain.append(exec->interpreter()->globalObject());
00236 FunctionBodyNode *bodyNode = progNode;
00237
00238 FunctionImp *fimp = new DeclaredFunctionImp(exec, UString::null, bodyNode,
00239 scopeChain);
00240 Object ret(fimp);
00241
00242
00243 int len = p.size();
00244 const UChar *c = p.data();
00245 int i = 0, params = 0;
00246 UString param;
00247 while (i < len) {
00248 while (*c == ' ' && i < len)
00249 c++, i++;
00250 if (Lexer::isIdentLetter(c->unicode())) {
00251 param = UString(c, 1);
00252 c++, i++;
00253 while (i < len && (Lexer::isIdentLetter(c->unicode()) ||
00254 Lexer::isDecimalDigit(c->unicode()))) {
00255 param += UString(c, 1);
00256 c++, i++;
00257 }
00258 while (i < len && *c == ' ')
00259 c++, i++;
00260 if (i == len) {
00261 fimp->addParameter(param);
00262 params++;
00263 break;
00264 } else if (*c == ',') {
00265 fimp->addParameter(param);
00266 params++;
00267 c++, i++;
00268 continue;
00269 }
00270 }
00271 Object err = Error::create(exec,SyntaxError,
00272 I18N_NOOP("Syntax error in parameter list"),
00273 -1);
00274 exec->setException(err);
00275 return err;
00276 }
00277
00278 fimp->put(exec,"length", Number(params),ReadOnly|DontDelete|DontEnum);
00279 List consArgs;
00280
00281 Object objCons = exec->interpreter()->builtinObject();
00282 Object prototype = objCons.construct(exec,List::empty());
00283 prototype.put(exec, "constructor",
00284 Object(fimp), DontEnum|DontDelete|ReadOnly);
00285 fimp->put(exec,"prototype",prototype,DontEnum|DontDelete|ReadOnly);
00286 fimp->put(exec,"arguments",Null(),DontEnum|DontDelete|ReadOnly);
00287 return ret;
00288 }
00289
00290 bool FunctionObjectImp::implementsCall() const
00291 {
00292 return true;
00293 }
00294
00295
00296 Value FunctionObjectImp::call(ExecState *exec, Object &, const List &args)
00297 {
00298 return construct(exec,args);
00299 }
00300