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