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