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