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