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