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
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 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->interpreter()->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->interpreter()->globalObject();
00341
00342
00343 ContextImp ctx(globalObj, exec->interpreter()->imp(), thisObj, sid, codeType(),
00344 exec->context().imp(), this, &args);
00345 ExecState newExec(exec->interpreter(), &ctx);
00346 newExec._exception = 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->_exception = 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->_exception = 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->interpreter()->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
00603
00604 class ShadowImp : public ObjectImp {
00605 public:
00606 ShadowImp(ObjectImp *_obj, Identifier _prop) : obj(_obj), prop(_prop) {}
00607 virtual void mark();
00608
00609 virtual const ClassInfo *classInfo() const { return &info; }
00610 static const ClassInfo info;
00611
00612 ObjectImp *obj;
00613 Identifier prop;
00614 };
00615
00616 const ClassInfo ShadowImp::info = {"Shadow", 0, 0, 0};
00617
00618 void ShadowImp::mark()
00619 {
00620 ObjectImp::mark();
00621 if (!obj->marked())
00622 obj->mark();
00623 }
00624
00625
00626
00627 const ClassInfo ArgumentsImp::info = {"Arguments", 0, 0, 0};
00628
00629
00630 ArgumentsImp::ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args,
00631 ActivationImp *act)
00632 : ObjectImp(exec->interpreter()->builtinObjectPrototype()), activation(act)
00633 {
00634 Value protect(this);
00635 putDirect(calleePropertyName, func, DontEnum);
00636 putDirect(lengthPropertyName, args.size(), DontEnum);
00637 if (!args.isEmpty()) {
00638 ListIterator arg = args.begin();
00639 for (int i = 0; arg != args.end(); arg++, i++) {
00640 Identifier prop = func->parameterProperty(i);
00641 if (!prop.isEmpty()) {
00642 Object shadow(new ShadowImp(act,prop));
00643 ObjectImp::put(exec,Identifier::from(i), shadow, DontEnum);
00644 }
00645 else {
00646 ObjectImp::put(exec,Identifier::from(i), *arg, DontEnum);
00647 }
00648 }
00649 }
00650 }
00651
00652 void ArgumentsImp::mark()
00653 {
00654 ObjectImp::mark();
00655 if (!activation->marked())
00656 activation->mark();
00657 }
00658
00659 Value ArgumentsImp::get(ExecState *exec, const Identifier &propertyName) const
00660 {
00661 Value val = ObjectImp::get(exec,propertyName);
00662 assert(SimpleNumber::is(val.imp()) || !val.imp()->isDestroyed());
00663 Object obj = Object::dynamicCast(val);
00664 if (obj.isValid() && obj.inherits(&ShadowImp::info)) {
00665 ShadowImp *shadow = static_cast<ShadowImp*>(val.imp());
00666 return activation->get(exec,shadow->prop);
00667 }
00668 else {
00669 return val;
00670 }
00671 }
00672
00673 void ArgumentsImp::put(ExecState *exec, const Identifier &propertyName,
00674 const Value &value, int attr)
00675 {
00676 Value val = ObjectImp::get(exec,propertyName);
00677 Object obj = Object::dynamicCast(val);
00678 if (obj.isValid() && obj.inherits(&ShadowImp::info)) {
00679 ShadowImp *shadow = static_cast<ShadowImp*>(val.imp());
00680 activation->put(exec,shadow->prop,value,attr);
00681 }
00682 else {
00683 ObjectImp::put(exec,propertyName,value,attr);
00684 }
00685 }
00686
00687
00688
00689 const ClassInfo ActivationImp::info = {"Activation", 0, 0, 0};
00690
00691
00692 ActivationImp::ActivationImp(FunctionImp *function, const List &arguments)
00693 : _function(function), _arguments(true), _argumentsObject(0)
00694 {
00695 _arguments = arguments.copy();
00696
00697 }
00698
00699 Value ActivationImp::get(ExecState *exec, const Identifier &propertyName) const
00700 {
00701 if (propertyName == argumentsPropertyName) {
00702 ValueImp *imp = getDirect(propertyName);
00703 if (imp)
00704 return Value(imp);
00705
00706 if (!_argumentsObject)
00707 _argumentsObject = new ArgumentsImp(exec, _function, _arguments, const_cast<ActivationImp*>(this));
00708 return Value(_argumentsObject);
00709 }
00710 return ObjectImp::get(exec, propertyName);
00711 }
00712
00713 bool ActivationImp::hasProperty(ExecState *exec, const Identifier &propertyName) const
00714 {
00715 if (propertyName == argumentsPropertyName)
00716 return true;
00717 return ObjectImp::hasProperty(exec, propertyName);
00718 }
00719
00720 bool ActivationImp::deleteProperty(ExecState *exec, const Identifier &propertyName)
00721 {
00722 if (propertyName == argumentsPropertyName)
00723 return false;
00724 return ObjectImp::deleteProperty(exec, propertyName);
00725 }
00726
00727 void ActivationImp::mark()
00728 {
00729 ObjectImp::mark();
00730 if (_function && !_function->marked())
00731 _function->mark();
00732 _arguments.mark();
00733 if (_argumentsObject && !_argumentsObject->marked())
00734 _argumentsObject->mark();
00735 }
00736
00737
00738
00739
00740 GlobalFuncImp::GlobalFuncImp(ExecState *, FunctionPrototypeImp *funcProto,
00741 int i, int len, const Identifier &_ident)
00742 : InternalFunctionImp(funcProto), id(i)
00743 {
00744 Value protect(this);
00745 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
00746 ident = _ident;
00747 }
00748
00749 CodeType GlobalFuncImp::codeType() const
00750 {
00751 return id == Eval ? EvalCode : codeType();
00752 }
00753
00754 bool GlobalFuncImp::implementsCall() const
00755 {
00756 return true;
00757 }
00758
00759 Value GlobalFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
00760 {
00761 Value res;
00762
00763 static const char non_escape[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00764 "abcdefghijklmnopqrstuvwxyz"
00765 "0123456789@*_+-./";
00766
00767 switch (id) {
00768 case Eval: {
00769 Value x = args[0];
00770 if (x.type() != StringType)
00771 return x;
00772 else {
00773 UString s = x.toString(exec);
00774
00775 int errLine;
00776 UString errMsg;
00777 #ifdef KJS_VERBOSE
00778 fprintf(stderr, "eval(): %s\n", s.ascii());
00779 #endif
00780 SourceCode *source;
00781 FunctionBodyNode *progNode = Parser::parse(s.data(),s.size(),&source,&errLine,&errMsg);
00782 if (progNode)
00783 progNode->setProgram(true);
00784
00785
00786 Debugger *dbg = exec->interpreter()->imp()->debugger();
00787 if (dbg) {
00788 bool cont = dbg->sourceParsed(exec,source->sid,s,errLine);
00789 if (!cont) {
00790 source->deref();
00791 dbg->imp()->abort();
00792 if (progNode)
00793 delete progNode;
00794 return Undefined();
00795 }
00796 }
00797
00798 exec->interpreter()->imp()->addSourceCode(source);
00799
00800
00801 if (!progNode) {
00802 Object err = Error::create(exec,SyntaxError,errMsg.ascii(),errLine);
00803 err.put(exec,"sid",Number(source->sid));
00804 exec->setException(err);
00805 source->deref();
00806 return err;
00807 }
00808
00809 source->deref();
00810 progNode->ref();
00811
00812
00813 ContextImp ctx(exec->interpreter()->globalObject(),
00814 exec->interpreter()->imp(),
00815 thisObj,
00816 source->sid,
00817 EvalCode,
00818 exec->context().imp());
00819
00820 ExecState newExec(exec->interpreter(), &ctx);
00821 newExec.setException(exec->exception());
00822
00823 ctx.setLines(progNode->firstLine(),progNode->firstLine());
00824 if (dbg) {
00825 if (!dbg->enterContext(&newExec)) {
00826
00827 dbg->imp()->abort();
00828
00829 if (progNode->deref())
00830 delete progNode;
00831 return Undefined();
00832 }
00833 }
00834
00835
00836 Completion c = progNode->execute(&newExec);
00837
00838 res = Undefined();
00839
00840 ctx.setLines(progNode->lastLine(),progNode->lastLine());
00841 if (dbg && !dbg->exitContext(&newExec,c))
00842
00843 dbg->imp()->abort();
00844 else if (newExec.hadException())
00845 exec->_exception = newExec.exception();
00846 else if (c.complType() == Throw)
00847 exec->setException(c.value());
00848 else if (c.isValueCompletion())
00849 res = c.value();
00850
00851 if (progNode->deref())
00852 delete progNode;
00853
00854 return res;
00855 }
00856 break;
00857 }
00858 case ParseInt: {
00859 CString cstr = args[0].toString(exec).cstring();
00860 const char* startptr = cstr.c_str();
00861 while ( *startptr && isspace( *startptr ) )
00862 ++startptr;
00863
00864 int base = 0;
00865 if (args.size() > 1)
00866 base = args[1].toInt32(exec);
00867
00868 double sign = 1;
00869 if (*startptr == '-') {
00870 sign = -1;
00871 startptr++;
00872 }
00873 else if (*startptr == '+') {
00874 sign = 1;
00875 startptr++;
00876 }
00877
00878 bool leading0 = false;
00879 if ((base == 0 || base == 16) &&
00880 (*startptr == '0' && (startptr[1] == 'x' || startptr[1] == 'X'))) {
00881 startptr += 2;
00882 base = 16;
00883 }
00884 else if (base == 0 && *startptr == '0') {
00885 base = 8;
00886 leading0 = true;
00887 startptr++;
00888 }
00889 else if (base == 0) {
00890 base = 10;
00891 }
00892
00893 if (base < 2 || base > 36) {
00894 res = Number(NaN);
00895 }
00896 else {
00897 long double val = 0;
00898 int index = 0;
00899 for (; *startptr; startptr++) {
00900 int thisval = -1;
00901 if (*startptr >= '0' && *startptr <= '9')
00902 thisval = *startptr - '0';
00903 else if (*startptr >= 'a' && *startptr <= 'z')
00904 thisval = 10 + *startptr - 'a';
00905 else if (*startptr >= 'A' && *startptr <= 'Z')
00906 thisval = 10 + *startptr - 'A';
00907
00908 if (thisval < 0 || thisval >= base)
00909 break;
00910
00911 val *= base;
00912 val += thisval;
00913 index++;
00914 }
00915
00916 if (index == 0 && !leading0)
00917 res = Number(NaN);
00918 else
00919 res = Number(double(val)*sign);
00920 }
00921 break;
00922 }
00923 case ParseFloat: {
00924 UString str = args[0].toString(exec);
00925
00926 bool isHex = false;
00927 if (str.is8Bit()) {
00928 const char *c = str.ascii();
00929 while (isspace(*c))
00930 c++;
00931 isHex = (c[0] == '0' && (c[1] == 'x' || c[1] == 'X'));
00932 }
00933 if (isHex)
00934 res = Number(0);
00935 else
00936 res = Number(str.toDouble( true , false ));
00937 }
00938 break;
00939 case IsNaN:
00940 res = Boolean(isNaN(args[0].toNumber(exec)));
00941 break;
00942 case IsFinite: {
00943 double n = args[0].toNumber(exec);
00944 res = Boolean(!isNaN(n) && !isInf(n));
00945 break;
00946 }
00947 case DecodeURI:
00948 res = String(decodeURI(exec,args[0].toString(exec),uriReserved+"#"));
00949 break;
00950 case DecodeURIComponent:
00951 res = String(decodeURI(exec,args[0].toString(exec),""));
00952 break;
00953 case EncodeURI:
00954 res = String(encodeURI(exec,args[0].toString(exec),uriReserved+uriUnescaped+"#"));
00955 break;
00956 case EncodeURIComponent:
00957 res = String(encodeURI(exec,args[0].toString(exec),uriUnescaped));
00958 break;
00959 case Escape: {
00960 UString r = "", s, str = args[0].toString(exec);
00961 const UChar *c = str.data();
00962 for (int k = 0; k < str.size(); k++, c++) {
00963 int u = c->uc;
00964 if (u > 255) {
00965 char tmp[7];
00966 sprintf(tmp, "%%u%04X", u);
00967 s = UString(tmp);
00968 } else if (strchr(non_escape, (char)u)) {
00969 s = UString(c, 1);
00970 } else {
00971 char tmp[4];
00972 sprintf(tmp, "%%%02X", u);
00973 s = UString(tmp);
00974 }
00975 r += s;
00976 }
00977 res = String(r);
00978 break;
00979 }
00980 case UnEscape: {
00981 UString s, str = args[0].toString(exec);
00982 int k = 0, len = str.size();
00983 while (k < len) {
00984 const UChar *c = str.data() + k;
00985 UChar u;
00986 if (*c == UChar('%') && k <= len - 6 && *(c+1) == UChar('u')) {
00987 if (Lexer::isHexDigit((c+2)->uc) && Lexer::isHexDigit((c+3)->uc) &&
00988 Lexer::isHexDigit((c+4)->uc) && Lexer::isHexDigit((c+5)->uc)) {
00989 u = Lexer::convertUnicode((c+2)->uc, (c+3)->uc,
00990 (c+4)->uc, (c+5)->uc);
00991 c = &u;
00992 k += 5;
00993 }
00994 } else if (*c == UChar('%') && k <= len - 3 &&
00995 Lexer::isHexDigit((c+1)->uc) && Lexer::isHexDigit((c+2)->uc)) {
00996 u = UChar(Lexer::convertHex((c+1)->uc, (c+2)->uc));
00997 c = &u;
00998 k += 2;
00999 }
01000 k++;
01001 s += UString(c, 1);
01002 }
01003 res = String(s);
01004 break;
01005 }
01006 case KJSPrint: {
01007 #ifndef NDEBUG
01008 UString str = args[0].toString(exec);
01009 puts(str.ascii());
01010 #endif
01011 break;
01012 }
01013 }
01014
01015 return res;
01016 }