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