00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "function.h"
00026
00027 #include "internal.h"
00028 #include "function_object.h"
00029 #include "lexer.h"
00030 #include "nodes.h"
00031 #include "operations.h"
00032 #include "debugger.h"
00033 #include "context.h"
00034
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <stdlib.h>
00038 #include <assert.h>
00039 #include <string.h>
00040 #include <math.h>
00041 #include <ctype.h>
00042
00043 using namespace KJS;
00044
00045
00046
00047
00048 UString encodeURI(ExecState *exec, UString string, UString unescapedSet)
00049 {
00050 char hexdigits[] = "0123456789ABCDEF";
00051 int encbufAlloc = 2;
00052 UChar *encbuf = (UChar*)malloc(encbufAlloc*sizeof(UChar));
00053 int encbufLen = 0;
00054
00055 for (int k = 0; k < string.size(); k++) {
00056
00057 UChar C = string[k];
00058 if (unescapedSet.find(C) >= 0) {
00059 if (encbufLen+1 >= encbufAlloc)
00060 encbuf = (UChar*)realloc(encbuf,(encbufAlloc *= 2)*sizeof(UChar));
00061 encbuf[encbufLen++] = C;
00062 }
00063 else {
00064 unsigned char octets[4];
00065 int octets_len = 0;
00066 if (C.uc <= 0x007F) {
00067 unsigned short zzzzzzz = C.uc;
00068 octets[0] = zzzzzzz;
00069 octets_len = 1;
00070 }
00071 else if (C.uc <= 0x07FF) {
00072 unsigned short zzzzzz = C.uc & 0x3F;
00073 unsigned short yyyyy = (C.uc >> 6) & 0x1F;
00074 octets[0] = 0xC0 | yyyyy;
00075 octets[1] = 0x80 | zzzzzz;
00076 octets_len = 2;
00077 }
00078 else if (C.uc >= 0xD800 && C.uc <= 0xDBFF) {
00079
00080
00081 if (k + 1 >= string.size()) {
00082 Object err = Error::create(exec,URIError);
00083 exec->setException(err);
00084 free(encbuf);
00085 return UString();
00086 }
00087
00088 unsigned short Cnext = UChar(string[++k]).uc;
00089
00090 if (Cnext < 0xDC00 || Cnext > 0xDFFF) {
00091 Object err = Error::create(exec,URIError);
00092 exec->setException(err);
00093 free(encbuf);
00094 return UString();
00095 }
00096
00097 unsigned short zzzzzz = Cnext & 0x3F;
00098 unsigned short yyyy = (Cnext >> 6) & 0x0F;
00099 unsigned short xx = C.uc & 0x03;
00100 unsigned short wwww = (C.uc >> 2) & 0x0F;
00101 unsigned short vvvv = (C.uc >> 6) & 0x0F;
00102 unsigned short uuuuu = vvvv+1;
00103 octets[0] = 0xF0 | (uuuuu >> 2);
00104 octets[1] = 0x80 | ((uuuuu & 0x03) << 4) | wwww;
00105 octets[2] = 0x80 | (xx << 4) | yyyy;
00106 octets[3] = 0x80 | zzzzzz;
00107 octets_len = 4;
00108 }
00109 else if (C.uc >= 0xDC00 && C.uc <= 0xDFFF) {
00110 Object err = Error::create(exec,URIError);
00111 exec->setException(err);
00112 free(encbuf);
00113 return UString();
00114 }
00115 else {
00116
00117 unsigned short zzzzzz = C.uc & 0x3F;
00118 unsigned short yyyyyy = (C.uc >> 6) & 0x3F;
00119 unsigned short xxxx = (C.uc >> 12) & 0x0F;
00120 octets[0] = 0xE0 | xxxx;
00121 octets[1] = 0x80 | yyyyyy;
00122 octets[2] = 0x80 | zzzzzz;
00123 octets_len = 3;
00124 }
00125
00126 while (encbufLen+3*octets_len >= encbufAlloc)
00127 encbuf = (UChar*)realloc(encbuf,(encbufAlloc *= 2)*sizeof(UChar));
00128
00129 for (int j = 0; j < octets_len; j++) {
00130 encbuf[encbufLen++] = '%';
00131 encbuf[encbufLen++] = hexdigits[octets[j] >> 4];
00132 encbuf[encbufLen++] = hexdigits[octets[j] & 0x0F];
00133 }
00134 }
00135 }
00136
00137 UString encoded(encbuf,encbufLen);
00138 free(encbuf);
00139 return encoded;
00140 }
00141
00142 static bool decodeHex(UChar hi, UChar lo, unsigned short *val)
00143 {
00144 *val = 0;
00145 if (hi.uc >= '0' && hi.uc <= '9')
00146 *val = (hi.uc-'0') << 4;
00147 else if (hi.uc >= 'a' && hi.uc <= 'f')
00148 *val = 10+(hi.uc-'a') << 4;
00149 else if (hi.uc >= 'A' && hi.uc <= 'F')
00150 *val = 10+(hi.uc-'A') << 4;
00151 else
00152 return false;
00153
00154 if (lo.uc >= '0' && lo.uc <= '9')
00155 *val |= (lo.uc-'0');
00156 else if (lo.uc >= 'a' && lo.uc <= 'f')
00157 *val |= 10+(lo.uc-'a');
00158 else if (lo.uc >= 'A' && lo.uc <= 'F')
00159 *val |= 10+(lo.uc-'A');
00160 else
00161 return false;
00162
00163 return true;
00164 }
00165
00166 UString decodeURI(ExecState *exec, UString string, UString reservedSet)
00167 {
00168 int decbufAlloc = 2;
00169 UChar *decbuf = (UChar*)malloc(decbufAlloc*sizeof(UChar));
00170 int decbufLen = 0;
00171
00172 for (int k = 0; k < string.size(); k++) {
00173 UChar C = string[k];
00174
00175 if (C != UChar('%')) {
00176
00177 if (decbufLen+1 >= decbufAlloc)
00178 decbuf = (UChar*)realloc(decbuf,(decbufAlloc *= 2)*sizeof(UChar));
00179 decbuf[decbufLen++] = C;
00180 continue;
00181 }
00182
00183
00184 int start = k;
00185 if (k+2 >= string.size()) {
00186 Object err = Error::create(exec,URIError);
00187 exec->setException(err);
00188 free(decbuf);
00189 return UString();
00190 }
00191
00192 unsigned short B;
00193 if (!decodeHex(string[k+1],string[k+2],&B)) {
00194 Object err = Error::create(exec,URIError);
00195 exec->setException(err);
00196 free(decbuf);
00197 return UString();
00198 }
00199
00200 k += 2;
00201
00202 if (decbufLen+2 >= decbufAlloc)
00203 decbuf = (UChar*)realloc(decbuf,(decbufAlloc *= 2)*sizeof(UChar));
00204
00205 if ((B & 0x80) == 0) {
00206
00207 C = B;
00208 }
00209 else {
00210
00211 int n = 0;
00212 while (((B << n) & 0x80) != 0)
00213 n++;
00214
00215 if (n < 2 || n > 4) {
00216 Object err = Error::create(exec,URIError);
00217 exec->setException(err);
00218 free(decbuf);
00219 return UString();
00220 }
00221
00222 if (k+3*(n-1) >= string.size()) {
00223 Object err = Error::create(exec,URIError);
00224 exec->setException(err);
00225 free(decbuf);
00226 return UString();
00227 }
00228
00229 unsigned short octets[4];
00230 octets[0] = B;
00231 for (int j = 1; j < n; j++) {
00232 k++;
00233 if ((UChar(string[k]) != UChar('%')) ||
00234 !decodeHex(string[k+1],string[k+2],&B) ||
00235 ((B & 0xC0) != 0x80)) {
00236 Object err = Error::create(exec,URIError);
00237 exec->setException(err);
00238 free(decbuf);
00239 return UString();
00240 }
00241
00242 k += 2;
00243 octets[j] = B;
00244 }
00245
00246
00247 const unsigned long replacementChar = 0xFFFD;
00248 unsigned long V;
00249 if (n == 2) {
00250 unsigned long yyyyy = octets[0] & 0x1F;
00251 unsigned long zzzzzz = octets[1] & 0x3F;
00252 V = (yyyyy << 6) | zzzzzz;
00253
00254 if (V < 0xFF)
00255 V = replacementChar;
00256 C = UChar((unsigned short)V);
00257 }
00258 else if (n == 3) {
00259 unsigned long xxxx = octets[0] & 0x0F;
00260 unsigned long yyyyyy = octets[1] & 0x3F;
00261 unsigned long zzzzzz = octets[2] & 0x3F;
00262 V = (xxxx << 12) | (yyyyyy << 6) | zzzzzz;
00263
00264
00265 if (V < 0x800 || V == 0xFFFE || V == 0xFFFF ||
00266 (V >= 0xD800 && V <= 0xDFFF))
00267 V = replacementChar;
00268 C = UChar((unsigned short)V);
00269 }
00270 else {
00271 assert(n == 4);
00272 unsigned long uuuuu = ((octets[0] & 0x07) << 2) | ((octets[1] >> 4) & 0x03);
00273 unsigned long vvvv = uuuuu-1;
00274 if (vvvv > 0x0F) {
00275 Object err = Error::create(exec,URIError);
00276 exec->setException(err);
00277 free(decbuf);
00278 return UString();
00279 }
00280 unsigned long wwww = octets[1] & 0x0F;
00281 unsigned long xx = (octets[2] >> 4) & 0x03;
00282 unsigned long yyyy = octets[2] & 0x0F;
00283 unsigned long zzzzzz = octets[3] & 0x3F;
00284 unsigned short H = 0xD800 | (vvvv << 6) | (wwww << 2) | xx;
00285 unsigned short L = 0xDC00 | (yyyy << 6) | zzzzzz;
00286 decbuf[decbufLen++] = UChar(H);
00287 decbuf[decbufLen++] = UChar(L);
00288 continue;
00289 }
00290 }
00291
00292 if (reservedSet.find(C) < 0) {
00293 decbuf[decbufLen++] = C;
00294 }
00295 else {
00296 while (decbufLen+k-start >= decbufAlloc)
00297 decbuf = (UChar*)realloc(decbuf,(decbufAlloc *= 2)*sizeof(UChar));
00298 for (int p = start; p < k; p++)
00299 decbuf[decbufLen++] = string[p];
00300 }
00301 }
00302
00303 UString decoded(decbuf,decbufLen);
00304 free(decbuf);
00305 return decoded;
00306 }
00307
00308 static UString uriReserved = ";/?:@&=+$,";
00309 static UString uriAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
00310 static UString DecimalDigit = "0123456789";
00311 static UString uriMark = "-_.!~*'()";
00312 static UString uriUnescaped = uriAlpha+DecimalDigit+uriMark;
00313
00314
00315
00316 const ClassInfo FunctionImp::info = {"Function", &InternalFunctionImp::info, 0, 0};
00317
00318 namespace KJS {
00319 class Parameter {
00320 public:
00321 Parameter(const Identifier &n) : name(n), next(0L) { }
00322 ~Parameter() { delete next; }
00323 Identifier name;
00324 Parameter *next;
00325 };
00326 }
00327
00328 FunctionImp::FunctionImp(ExecState *exec, const Identifier &n)
00329 : InternalFunctionImp(
00330 static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())
00331 ), param(0L), line0(-1), line1(-1), sid(-1)
00332 {
00333
00334 ident = n;
00335 }
00336
00337 FunctionImp::~FunctionImp()
00338 {
00339 delete param;
00340 }
00341
00342 bool FunctionImp::implementsCall() const
00343 {
00344 return true;
00345 }
00346
00347 Value FunctionImp::call(ExecState *exec, Object &thisObj, const List &args)
00348 {
00349 Object &globalObj = exec->dynamicInterpreter()->globalObject();
00350
00351
00352 ContextImp ctx(globalObj, exec->dynamicInterpreter()->imp(), thisObj, sid, codeType(),
00353 exec->context().imp(), this, &args);
00354 ExecState newExec(exec->dynamicInterpreter(), &ctx);
00355 newExec.setException(exec->exception());
00356
00357
00358 processParameters(&newExec, args);
00359
00360 processVarDecls(&newExec);
00361
00362 ctx.setLines(line0,line0);
00363 Debugger *dbg = exec->interpreter()->imp()->debugger();
00364 if (dbg) {
00365 if (!dbg->enterContext(&newExec)) {
00366
00367 dbg->imp()->abort();
00368 return Undefined();
00369 }
00370 }
00371
00372 Completion comp = execute(&newExec);
00373
00374 ctx.setLines(line1,line1);
00375 if (dbg) {
00376 Object func(this);
00377
00378
00379 if (!dbg->exitContext(&newExec,comp)) {
00380
00381 dbg->imp()->abort();
00382 return Undefined();
00383 }
00384 }
00385
00386
00387 if (newExec.hadException())
00388 exec->setException(newExec.exception());
00389
00390 #ifdef KJS_VERBOSE
00391 CString n = ident.isEmpty() ? CString("(internal)") : ident.ustring().cstring();
00392 if (comp.complType() == Throw) {
00393 n += " throws";
00394 printInfo(exec, n.c_str(), comp.value());
00395 } else if (comp.complType() == ReturnValue) {
00396 n += " returns";
00397 printInfo(exec, n.c_str(), comp.value());
00398 } else
00399 fprintf(stderr, "%s returns: undefined\n", n.c_str());
00400 #endif
00401
00402 if (comp.complType() == Throw) {
00403 exec->setException(comp.value());
00404 return comp.value();
00405 }
00406 else if (comp.complType() == ReturnValue)
00407 return comp.value();
00408 else
00409 return Undefined();
00410 }
00411
00412 void FunctionImp::addParameter(const Identifier &n)
00413 {
00414 Parameter **p = ¶m;
00415 while (*p)
00416 p = &(*p)->next;
00417
00418 *p = new Parameter(n);
00419 }
00420
00421 Identifier FunctionImp::parameterProperty(int index) const
00422 {
00423
00424 int pos = 0;
00425 Parameter *p;
00426 for (p = param; p && pos < index; p = p->next)
00427 pos++;
00428
00429 if (!p)
00430 return Identifier::null();
00431
00432
00433 Identifier name = p->name;
00434 for (p = p->next; p; p = p->next)
00435 if (p->name == name)
00436 return Identifier::null();
00437
00438 return name;
00439 }
00440
00441 UString FunctionImp::parameterString() const
00442 {
00443 UString s;
00444 const Parameter *p = param;
00445 while (p) {
00446 if (!s.isEmpty())
00447 s += ", ";
00448 s += p->name.ustring();
00449 p = p->next;
00450 }
00451
00452 return s;
00453 }
00454
00455
00456
00457 void FunctionImp::processParameters(ExecState *exec, const List &args)
00458 {
00459 Object variable = exec->context().imp()->variableObject();
00460
00461 #ifdef KJS_VERBOSE
00462 fprintf(stderr, "---------------------------------------------------\n"
00463 "processing parameters for %s call\n",
00464 name().isEmpty() ? "(internal)" : name().ascii());
00465 #endif
00466
00467 if (param) {
00468 ListIterator it = args.begin();
00469 Parameter *p = param;
00470 while (p) {
00471 if (it != args.end()) {
00472 #ifdef KJS_VERBOSE
00473 fprintf(stderr, "setting parameter %s ", p->name.ascii());
00474 printInfo(exec,"to", *it);
00475 #endif
00476 variable.put(exec, p->name, *it);
00477 it++;
00478 } else
00479 variable.put(exec, p->name, Undefined());
00480 p = p->next;
00481 }
00482 }
00483 #ifdef KJS_VERBOSE
00484 else {
00485 for (int i = 0; i < args.size(); i++)
00486 printInfo(exec,"setting argument", args[i]);
00487 }
00488 #endif
00489 }
00490
00491 void FunctionImp::processVarDecls(ExecState * )
00492 {
00493 }
00494
00495 Value FunctionImp::get(ExecState *exec, const Identifier &propertyName) const
00496 {
00497
00498 if (propertyName == argumentsPropertyName) {
00499
00500 ContextImp *context = exec->context().imp();
00501
00502
00503 while (context) {
00504 if (context->function() == this)
00505 return static_cast<ActivationImp *>
00506 (context->activationObject())->get(exec, propertyName);
00507 context = context->callingContext();
00508 }
00509 return Null();
00510 }
00511
00512
00513 if (propertyName == lengthPropertyName) {
00514 const Parameter * p = param;
00515 int count = 0;
00516 while (p) {
00517 ++count;
00518 p = p->next;
00519 }
00520 return Number(count);
00521 }
00522
00523 return InternalFunctionImp::get(exec, propertyName);
00524 }
00525
00526 void FunctionImp::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
00527 {
00528 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
00529 return;
00530 InternalFunctionImp::put(exec, propertyName, value, attr);
00531 }
00532
00533 bool FunctionImp::hasProperty(ExecState *exec, const Identifier &propertyName) const
00534 {
00535 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
00536 return true;
00537 return InternalFunctionImp::hasProperty(exec, propertyName);
00538 }
00539
00540 bool FunctionImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
00541 {
00542 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
00543 return false;
00544 return InternalFunctionImp::deleteProperty(exec, propertyName);
00545 }
00546
00547
00548
00549
00550 const ClassInfo DeclaredFunctionImp::info = {"Function", &FunctionImp::info, 0, 0};
00551
00552 DeclaredFunctionImp::DeclaredFunctionImp(ExecState *exec, const Identifier &n,
00553 FunctionBodyNode *b, const ScopeChain &sc)
00554 : FunctionImp(exec,n), body(b)
00555 {
00556 Value protect(this);
00557 body->ref();
00558 setScope(sc);
00559 line0 = body->firstLine();
00560 line1 = body->lastLine();
00561 sid = body->sourceId();
00562 }
00563
00564 DeclaredFunctionImp::~DeclaredFunctionImp()
00565 {
00566 if ( body->deref() )
00567 delete body;
00568 }
00569
00570 bool DeclaredFunctionImp::implementsConstruct() const
00571 {
00572 return true;
00573 }
00574
00575
00576 Object DeclaredFunctionImp::construct(ExecState *exec, const List &args)
00577 {
00578 Object proto;
00579 Value p = get(exec,prototypePropertyName);
00580 if (p.type() == ObjectType)
00581 proto = Object(static_cast<ObjectImp*>(p.imp()));
00582 else
00583 proto = exec->lexicalInterpreter()->builtinObjectPrototype();
00584
00585 Object obj(new ObjectImp(proto));
00586
00587 Value res = call(exec,obj,args);
00588
00589 if (res.type() == ObjectType)
00590 return Object::dynamicCast(res);
00591 else
00592 return obj;
00593 }
00594
00595 Completion DeclaredFunctionImp::execute(ExecState *exec)
00596 {
00597 Completion result = body->execute(exec);
00598
00599 if (result.complType() == Throw || result.complType() == ReturnValue)
00600 return result;
00601 return Completion(Normal, Undefined());
00602 }
00603
00604 void DeclaredFunctionImp::processVarDecls(ExecState *exec)
00605 {
00606 body->processVarDecls(exec);
00607 }
00608
00609
00610
00611 namespace KJS {
00612
00613
00614
00615 class ShadowImp : public ObjectImp {
00616 public:
00617 ShadowImp(ObjectImp *_obj, Identifier _prop) : obj(_obj), prop(_prop) {}
00618 virtual void mark();
00619
00620 virtual const ClassInfo *classInfo() const { return &info; }
00621 static const ClassInfo info;
00622
00623 ObjectImp *obj;
00624 Identifier prop;
00625 };
00626
00627 const ClassInfo ShadowImp::info = {"Shadow", 0, 0, 0};
00628
00629 void ShadowImp::mark()
00630 {
00631 ObjectImp::mark();
00632 if (!obj->marked())
00633 obj->mark();
00634 }
00635
00636 }
00637
00638
00639
00640 const ClassInfo ArgumentsImp::info = {"Arguments", 0, 0, 0};
00641
00642
00643 ArgumentsImp::ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args,
00644 ActivationImp *act)
00645 : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), activation(act)
00646 {
00647 Value protect(this);
00648 putDirect(calleePropertyName, func, DontEnum);
00649 putDirect(lengthPropertyName, args.size(), DontEnum);
00650 if (!args.isEmpty()) {
00651 ListIterator arg = args.begin();
00652 for (int i = 0; arg != args.end(); arg++, i++) {
00653 Identifier prop = func->parameterProperty(i);
00654 if (!prop.isEmpty()) {
00655 Object shadow(new ShadowImp(act,prop));
00656 ObjectImp::put(exec,Identifier::from(i), shadow, DontEnum);
00657 }
00658 else {
00659 ObjectImp::put(exec,Identifier::from(i), *arg, DontEnum);
00660 }
00661 }
00662 }
00663 }
00664
00665 void ArgumentsImp::mark()
00666 {
00667 ObjectImp::mark();
00668 if (!activation->marked())
00669 activation->mark();
00670 }
00671
00672 Value ArgumentsImp::get(ExecState *exec, const Identifier &propertyName) const
00673 {
00674 Value val = ObjectImp::get(exec,propertyName);
00675 assert(SimpleNumber::is(val.imp()) || !val.imp()->isDestroyed());
00676 Object obj = Object::dynamicCast(val);
00677 if (obj.isValid() && obj.inherits(&ShadowImp::info)) {
00678 ShadowImp *shadow = static_cast<ShadowImp*>(val.imp());
00679 return activation->get(exec,shadow->prop);
00680 }
00681 else {
00682 return val;
00683 }
00684 }
00685
00686 void ArgumentsImp::put(ExecState *exec, const Identifier &propertyName,
00687 const Value &value, int attr)
00688 {
00689 Value val = ObjectImp::get(exec,propertyName);
00690 Object obj = Object::dynamicCast(val);
00691 if (obj.isValid() && obj.inherits(&ShadowImp::info)) {
00692 ShadowImp *shadow = static_cast<ShadowImp*>(val.imp());
00693 activation->put(exec,shadow->prop,value,attr);
00694 }
00695 else {
00696 ObjectImp::put(exec,propertyName,value,attr);
00697 }
00698 }
00699
00700
00701
00702 const ClassInfo ActivationImp::info = {"Activation", 0, 0, 0};
00703
00704
00705 ActivationImp::ActivationImp(FunctionImp *function, const List &arguments)
00706 : _function(function), _arguments(true), _argumentsObject(0)
00707 {
00708 _arguments = arguments.copy();
00709
00710 }
00711
00712 Value ActivationImp::get(ExecState *exec, const Identifier &propertyName) const
00713 {
00714 if (propertyName == argumentsPropertyName) {
00715
00716 ValueImp *v = getDirect(propertyName);
00717 if (v)
00718 return Value(v);
00719
00720
00721 if (!_argumentsObject)
00722 _argumentsObject = new ArgumentsImp(exec, _function, _arguments, const_cast<ActivationImp*>(this));
00723 return Value(_argumentsObject);
00724 }
00725 return ObjectImp::get(exec, propertyName);
00726 }
00727
00728 bool ActivationImp::hasProperty(ExecState *exec, const Identifier &propertyName) const
00729 {
00730 if (propertyName == argumentsPropertyName)
00731 return true;
00732 return ObjectImp::hasProperty(exec, propertyName);
00733 }
00734
00735 bool ActivationImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
00736 {
00737 if (propertyName == argumentsPropertyName)
00738 return false;
00739 return ObjectImp::deleteProperty(exec, propertyName);
00740 }
00741
00742 void ActivationImp::mark()
00743 {
00744 ObjectImp::mark();
00745 if (_function && !_function->marked())
00746 _function->mark();
00747 _arguments.mark();
00748 if (_argumentsObject && !_argumentsObject->marked())
00749 _argumentsObject->mark();
00750 }
00751
00752
00753
00754
00755 GlobalFuncImp::GlobalFuncImp(ExecState * , FunctionPrototypeImp *funcProto,
00756 int i, int len, const Identifier &_ident)
00757 : InternalFunctionImp(funcProto), id(i)
00758 {
00759 Value protect(this);
00760 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
00761 ident = _ident;
00762 }
00763
00764 CodeType GlobalFuncImp::codeType() const
00765 {
00766 return id == Eval ? EvalCode : codeType();
00767 }
00768
00769 bool GlobalFuncImp::implementsCall() const
00770 {
00771 return true;
00772 }
00773
00774 Value GlobalFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
00775 {
00776 Value res;
00777
00778 static const char do_not_escape[] =
00779 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00780 "abcdefghijklmnopqrstuvwxyz"
00781 "0123456789"
00782 "*+-./@_";
00783
00784 switch (id) {
00785 case Eval: {
00786 Value x = args[0];
00787 if (x.type() != StringType)
00788 return x;
00789 else {
00790 UString s = x.toString(exec);
00791
00792 int errLine;
00793 UString errMsg;
00794 #ifdef KJS_VERBOSE
00795 fprintf(stderr, "eval(): %s\n", s.ascii());
00796 #endif
00797 SourceCode *source;
00798 FunctionBodyNode *progNode = Parser::parse(s.data(),s.size(),&source,&errLine,&errMsg);
00799
00800
00801 Debugger *dbg = exec->interpreter()->imp()->debugger();
00802 if (dbg) {
00803 bool cont = dbg->sourceParsed(exec,source->sid,s,errLine);
00804 if (!cont) {
00805 source->deref();
00806 dbg->imp()->abort();
00807 if (progNode)
00808 delete progNode;
00809 return Undefined();
00810 }
00811 }
00812
00813 exec->interpreter()->imp()->addSourceCode(source);
00814
00815
00816 if (!progNode) {
00817 Object err = Error::create(exec,SyntaxError,errMsg.ascii(),errLine);
00818 err.put(exec,"sid",Number(source->sid));
00819 exec->setException(err);
00820 source->deref();
00821 return err;
00822 }
00823
00824 source->deref();
00825 progNode->ref();
00826
00827
00828 ContextImp ctx(exec->dynamicInterpreter()->globalObject(),
00829 exec->dynamicInterpreter()->imp(),
00830 thisObj,
00831 source->sid,
00832 EvalCode,
00833 exec->context().imp());
00834
00835 ExecState newExec(exec->dynamicInterpreter(), &ctx);
00836 newExec.setException(exec->exception());
00837
00838 ctx.setLines(progNode->firstLine(),progNode->firstLine());
00839 if (dbg) {
00840 if (!dbg->enterContext(&newExec)) {
00841
00842 dbg->imp()->abort();
00843
00844 if (progNode->deref())
00845 delete progNode;
00846 return Undefined();
00847 }
00848 }
00849
00850
00851 progNode->processVarDecls(&newExec);
00852 Completion c = progNode->execute(&newExec);
00853
00854 res = Undefined();
00855
00856 ctx.setLines(progNode->lastLine(),progNode->lastLine());
00857 if (dbg && !dbg->exitContext(&newExec,c))
00858
00859 dbg->imp()->abort();
00860 else if (newExec.hadException())
00861 exec->setException(newExec.exception());
00862 else if (c.complType() == Throw)
00863 exec->setException(c.value());
00864 else if (c.isValueCompletion())
00865 res = c.value();
00866
00867 if (progNode->deref())
00868 delete progNode;
00869
00870 return res;
00871 }
00872 break;
00873 }
00874 case ParseInt: {
00875 CString cstr = args[0].toString(exec).cstring();
00876 const char* startptr = cstr.c_str();
00877 while ( *startptr && isspace( *startptr ) )
00878 ++startptr;
00879
00880 int base = 0;
00881 if (args.size() > 1)
00882 base = args[1].toInt32(exec);
00883
00884 double sign = 1;
00885 if (*startptr == '-') {
00886 sign = -1;
00887 startptr++;
00888 }
00889 else if (*startptr == '+') {
00890 sign = 1;
00891 startptr++;
00892 }
00893
00894 bool leading0 = false;
00895 if ((base == 0 || base == 16) &&
00896 (*startptr == '0' && (startptr[1] == 'x' || startptr[1] == 'X'))) {
00897 startptr += 2;
00898 base = 16;
00899 }
00900 else if (base == 0 && *startptr == '0') {
00901 base = 8;
00902 leading0 = true;
00903 startptr++;
00904 }
00905 else if (base == 0) {
00906 base = 10;
00907 }
00908
00909 if (base < 2 || base > 36) {
00910 res = Number(NaN);
00911 }
00912 else {
00913 long double val = 0;
00914 int index = 0;
00915 for (; *startptr; startptr++) {
00916 int thisval = -1;
00917 if (*startptr >= '0' && *startptr <= '9')
00918 thisval = *startptr - '0';
00919 else if (*startptr >= 'a' && *startptr <= 'z')
00920 thisval = 10 + *startptr - 'a';
00921 else if (*startptr >= 'A' && *startptr <= 'Z')
00922 thisval = 10 + *startptr - 'A';
00923
00924 if (thisval < 0 || thisval >= base)
00925 break;
00926
00927 val *= base;
00928 val += thisval;
00929 index++;
00930 }
00931
00932 if (index == 0 && !leading0)
00933 res = Number(NaN);
00934 else
00935 res = Number(double(val)*sign);
00936 }
00937 break;
00938 }
00939 case ParseFloat: {
00940 UString str = args[0].toString(exec);
00941
00942 bool isHex = false;
00943 if (str.is8Bit()) {
00944 const char *c = str.ascii();
00945 while (isspace(*c))
00946 c++;
00947 isHex = (c[0] == '0' && (c[1] == 'x' || c[1] == 'X'));
00948 }
00949 if (isHex)
00950 res = Number(0);
00951 else
00952 res = Number(str.toDouble( true , false ));
00953 }
00954 break;
00955 case IsNaN:
00956 res = Boolean(isNaN(args[0].toNumber(exec)));
00957 break;
00958 case IsFinite: {
00959 double n = args[0].toNumber(exec);
00960 res = Boolean(!isNaN(n) && !isInf(n));
00961 break;
00962 }
00963 case DecodeURI:
00964 res = String(decodeURI(exec,args[0].toString(exec),uriReserved+"#"));
00965 break;
00966 case DecodeURIComponent:
00967 res = String(decodeURI(exec,args[0].toString(exec),""));
00968 break;
00969 case EncodeURI:
00970 res = String(encodeURI(exec,args[0].toString(exec),uriReserved+uriUnescaped+"#"));
00971 break;
00972 case EncodeURIComponent:
00973 res = String(encodeURI(exec,args[0].toString(exec),uriUnescaped));
00974 break;
00975 case Escape: {
00976 UString r = "", s, str = args[0].toString(exec);
00977 const UChar *c = str.data();
00978 for (int k = 0; k < str.size(); k++, c++) {
00979 int u = c->uc;
00980 if (u > 255) {
00981 char tmp[7];
00982 sprintf(tmp, "%%u%04X", u);
00983 s = UString(tmp);
00984 } else if (u != 0 && strchr(do_not_escape, (char)u)) {
00985 s = UString(c, 1);
00986 } else {
00987 char tmp[4];
00988 sprintf(tmp, "%%%02X", u);
00989 s = UString(tmp);
00990 }
00991 r += s;
00992 }
00993 res = String(r);
00994 break;
00995 }
00996 case UnEscape: {
00997 UString s = "", str = args[0].toString(exec);
00998 int k = 0, len = str.size();
00999 while (k < len) {
01000 const UChar *c = str.data() + k;
01001 UChar u;
01002 if (*c == UChar('%') && k <= len - 6 && *(c+1) == UChar('u')) {
01003 if (Lexer::isHexDigit((c+2)->uc) && Lexer::isHexDigit((c+3)->uc) &&
01004 Lexer::isHexDigit((c+4)->uc) && Lexer::isHexDigit((c+5)->uc)) {
01005 u = Lexer::convertUnicode((c+2)->uc, (c+3)->uc,
01006 (c+4)->uc, (c+5)->uc);
01007 c = &u;
01008 k += 5;
01009 }
01010 } else if (*c == UChar('%') && k <= len - 3 &&
01011 Lexer::isHexDigit((c+1)->uc) && Lexer::isHexDigit((c+2)->uc)) {
01012 u = UChar(Lexer::convertHex((c+1)->uc, (c+2)->uc));
01013 c = &u;
01014 k += 2;
01015 }
01016 k++;
01017 s += UString(c, 1);
01018 }
01019 res = String(s);
01020 break;
01021 }
01022 case KJSPrint:
01023 #ifndef NDEBUG
01024 puts(args[0].toString(exec).ascii());
01025 #endif
01026 break;
01027 }
01028
01029 return res;
01030 }