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