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->dynamicInterpreter()->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->dynamicInterpreter()->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->dynamicInterpreter()->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->dynamicInterpreter()->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->lexicalInterpreter()->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