28 #include "function_object.h"
31 #include "operations.h"
50 char hexdigits[] =
"0123456789ABCDEF";
55 for (
int k = 0; k <
string.size(); k++) {
58 if (unescapedSet.
find(C) >= 0) {
59 if (encbufLen+1 >= encbufAlloc)
60 encbuf = (
UChar*)realloc(encbuf,(encbufAlloc *= 2)*
sizeof(
UChar));
61 encbuf[encbufLen++] = C;
64 unsigned char octets[4];
67 unsigned short zzzzzzz = C.uc;
71 else if (C.uc <= 0x07FF) {
72 unsigned short zzzzzz = C.uc & 0x3F;
73 unsigned short yyyyy = (C.uc >> 6) & 0x1F;
74 octets[0] = 0xC0 | yyyyy;
75 octets[1] = 0x80 | zzzzzz;
78 else if (C.uc >= 0xD800 && C.uc <= 0xDBFF) {
81 if (k + 1 >=
string.size()) {
83 exec->setException(err);
88 unsigned short Cnext =
UChar(
string[++k]).uc;
90 if (Cnext < 0xDC00 || Cnext > 0xDFFF) {
92 exec->setException(err);
97 unsigned short zzzzzz = Cnext & 0x3F;
98 unsigned short yyyy = (Cnext >> 6) & 0x0F;
99 unsigned short xx = C.uc & 0x03;
100 unsigned short wwww = (C.uc >> 2) & 0x0F;
101 unsigned short vvvv = (C.uc >> 6) & 0x0F;
102 unsigned short uuuuu = vvvv+1;
103 octets[0] = 0xF0 | (uuuuu >> 2);
104 octets[1] = 0x80 | ((uuuuu & 0x03) << 4) | wwww;
105 octets[2] = 0x80 | (xx << 4) | yyyy;
106 octets[3] = 0x80 | zzzzzz;
109 else if (C.uc >= 0xDC00 && C.uc <= 0xDFFF) {
111 exec->setException(err);
117 unsigned short zzzzzz = C.uc & 0x3F;
118 unsigned short yyyyyy = (C.uc >> 6) & 0x3F;
119 unsigned short xxxx = (C.uc >> 12) & 0x0F;
120 octets[0] = 0xE0 | xxxx;
121 octets[1] = 0x80 | yyyyyy;
122 octets[2] = 0x80 | zzzzzz;
126 while (encbufLen+3*octets_len >= encbufAlloc)
127 encbuf = (
UChar*)realloc(encbuf,(encbufAlloc *= 2)*
sizeof(
UChar));
129 for (
int j = 0; j < octets_len; j++) {
130 encbuf[encbufLen++] =
'%';
131 encbuf[encbufLen++] = hexdigits[octets[j] >> 4];
132 encbuf[encbufLen++] = hexdigits[octets[j] & 0x0F];
137 UString encoded(encbuf,encbufLen);
142 static bool decodeHex(
UChar hi,
UChar lo,
unsigned short *val)
145 if (hi.uc >=
'0' && hi.uc <=
'9')
146 *val = (hi.uc-
'0') << 4;
147 else if (hi.uc >=
'a' && hi.uc <=
'f')
148 *val = 10+(hi.uc-
'a') << 4;
149 else if (hi.uc >=
'A' && hi.uc <=
'F')
150 *val = 10+(hi.uc-
'A') << 4;
154 if (lo.uc >=
'0' && lo.uc <=
'9')
156 else if (lo.uc >=
'a' && lo.uc <=
'f')
157 *val |= 10+(lo.uc-
'a');
158 else if (lo.uc >=
'A' && lo.uc <=
'F')
159 *val |= 10+(lo.uc-
'A');
172 for (
int k = 0; k <
string.size(); k++) {
175 if (C !=
UChar(
'%')) {
177 if (decbufLen+1 >= decbufAlloc)
178 decbuf = (
UChar*)realloc(decbuf,(decbufAlloc *= 2)*
sizeof(
UChar));
179 decbuf[decbufLen++] = C;
185 if (k+2 >=
string.size()) {
187 exec->setException(err);
193 if (!decodeHex(
string[k+1],
string[k+2],&B)) {
195 exec->setException(err);
202 if (decbufLen+2 >= decbufAlloc)
203 decbuf = (
UChar*)realloc(decbuf,(decbufAlloc *= 2)*
sizeof(
UChar));
205 if ((B & 0x80) == 0) {
212 while (((B << n) & 0x80) != 0)
215 if (n < 2 || n > 4) {
217 exec->setException(err);
222 if (k+3*(n-1) >=
string.size()) {
224 exec->setException(err);
229 unsigned short octets[4];
231 for (
int j = 1; j < n; j++) {
234 !decodeHex(
string[k+1],
string[k+2],&B) ||
235 ((B & 0xC0) != 0x80)) {
237 exec->setException(err);
247 const unsigned long replacementChar = 0xFFFD;
250 unsigned long yyyyy = octets[0] & 0x1F;
251 unsigned long zzzzzz = octets[1] & 0x3F;
252 V = (yyyyy << 6) | zzzzzz;
256 C =
UChar((
unsigned short)V);
259 unsigned long xxxx = octets[0] & 0x0F;
260 unsigned long yyyyyy = octets[1] & 0x3F;
261 unsigned long zzzzzz = octets[2] & 0x3F;
262 V = (xxxx << 12) | (yyyyyy << 6) | zzzzzz;
265 if (V < 0x800 || V == 0xFFFE || V == 0xFFFF ||
266 (V >= 0xD800 && V <= 0xDFFF))
268 C =
UChar((
unsigned short)V);
272 unsigned long uuuuu = ((octets[0] & 0x07) << 2) | ((octets[1] >> 4) & 0x03);
273 unsigned long vvvv = uuuuu-1;
276 exec->setException(err);
280 unsigned long wwww = octets[1] & 0x0F;
281 unsigned long xx = (octets[2] >> 4) & 0x03;
282 unsigned long yyyy = octets[2] & 0x0F;
283 unsigned long zzzzzz = octets[3] & 0x3F;
284 unsigned short H = 0xD800 | (vvvv << 6) | (wwww << 2) | xx;
285 unsigned short L = 0xDC00 | (yyyy << 6) | zzzzzz;
286 decbuf[decbufLen++] =
UChar(H);
287 decbuf[decbufLen++] =
UChar(L);
292 if (reservedSet.
find(C) < 0) {
293 decbuf[decbufLen++] = C;
297 while (decbufLen+k-start+1 >= decbufAlloc)
298 decbuf = (
UChar*)realloc(decbuf,(decbufAlloc *= 2)*
sizeof(
UChar));
299 for (
int p = start; p <= k; p++)
300 decbuf[decbufLen++] =
string[p];
304 UString decoded(decbuf,decbufLen);
309 static UString uriReserved =
";/?:@&=+$,";
310 static UString uriAlpha =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
311 static UString DecimalDigit =
"0123456789";
312 static UString uriMark =
"-_.!~*'()";
313 static UString uriUnescaped = uriAlpha+DecimalDigit+uriMark;
317 const ClassInfo FunctionImp::info = {
"Function", &InternalFunctionImp::info, 0, 0};
323 ~Parameter() {
delete next; }
331 static_cast<
FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())
332 ), param(0L), line0(-1), line1(-1), sid(-1)
338 FunctionImp::~FunctionImp()
343 bool FunctionImp::implementsCall()
const
354 exec->
context().imp(),
this, &args);
356 newExec.setException(exec->exception());
359 processParameters(&newExec, args);
361 processVarDecls(&newExec);
363 ctx.setLines(line0,line0);
364 Debugger *dbg = exec->interpreter()->imp()->debugger();
366 if (!dbg->enterContext(&newExec)) {
375 ctx.setLines(line1,line1);
380 if (!dbg->exitContext(&newExec,comp)) {
388 if (newExec.hadException())
389 exec->setException(newExec.exception());
393 if (comp.complType() == Throw) {
395 printInfo(exec, n.c_str(), comp.value());
396 }
else if (comp.complType() == ReturnValue) {
398 printInfo(exec, n.c_str(), comp.value());
400 fprintf(stderr,
"%s returns: undefined\n", n.c_str());
403 if (comp.complType() == Throw) {
404 exec->setException(comp.value());
407 else if (comp.complType() == ReturnValue)
413 void FunctionImp::addParameter(
const Identifier &n)
415 Parameter **p = ¶m;
419 *p =
new Parameter(n);
422 Identifier FunctionImp::parameterProperty(
int index)
const
427 for (p = param; p && pos < index; p = p->next)
435 for (p = p->next; p; p = p->next)
442 UString FunctionImp::parameterString()
const
445 const Parameter *p = param;
449 s += p->name.ustring();
458 void FunctionImp::processParameters(
ExecState *exec,
const List &args)
463 fprintf(stderr,
"---------------------------------------------------\n"
464 "processing parameters for %s call\n",
465 name().isEmpty() ?
"(internal)" : name().ascii());
470 Parameter *p = param;
472 if (it != args.
end()) {
474 fprintf(stderr,
"setting parameter %s ", p->name.ascii());
475 printInfo(exec,
"to", *it);
477 variable.
put(exec, p->name, *it);
486 for (
int i = 0; i < args.
size(); i++)
487 printInfo(exec,
"setting argument", args[i]);
492 void FunctionImp::processVarDecls(
ExecState * )
499 if (propertyName == argumentsPropertyName) {
505 if (context->function() ==
this)
506 return static_cast<ActivationImp *>
507 (context->activationObject())->
get(exec, propertyName);
508 context = context->callingContext();
514 if (propertyName == lengthPropertyName) {
515 const Parameter * p = param;
524 if (propertyName == callerPropertyName) {
527 if (context->function() ==
this) {
529 if (cc && cc->function())
530 return Value(cc->function());
534 context = context->callingContext();
539 return InternalFunctionImp::get(exec, propertyName);
544 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
546 InternalFunctionImp::put(exec, propertyName, value, attr);
551 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
553 return InternalFunctionImp::hasProperty(exec, propertyName);
558 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
560 return InternalFunctionImp::deleteProperty(exec, propertyName);
566 const ClassInfo DeclaredFunctionImp::info = {
"Function", &FunctionImp::info, 0, 0};
575 line0 = body->firstLine();
576 line1 = body->lastLine();
577 sid = body->sourceId();
580 DeclaredFunctionImp::~DeclaredFunctionImp()
586 bool DeclaredFunctionImp::implementsConstruct()
const
595 Value p =
get(exec,prototypePropertyName);
596 if (p.
type() == ObjectType)
597 proto =
Object(static_cast<ObjectImp*>(p.imp()));
601 Object obj(
new ObjectImp(proto));
603 Value res = call(exec,obj,args);
605 if (res.
type() == ObjectType)
615 if (result.complType() == Throw || result.complType() == ReturnValue)
620 void DeclaredFunctionImp::processVarDecls(
ExecState *exec)
622 body->processVarDecls(exec);
631 class ShadowImp :
public ObjectImp {
633 ShadowImp(ObjectImp *_obj,
Identifier _prop) : obj(_obj), prop(_prop) {}
636 virtual const ClassInfo *classInfo()
const {
return &info; }
643 const ClassInfo ShadowImp::info = {
"Shadow", 0, 0, 0};
645 void ShadowImp::mark()
656 const ClassInfo ArgumentsImp::info = {
"Arguments", 0, 0, 0};
661 : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), activation(act)
664 putDirect(calleePropertyName, func, DontEnum);
665 putDirect(lengthPropertyName, args.
size(), DontEnum);
668 for (
int i = 0; arg != args.
end(); arg++, i++) {
671 Object shadow(
new ShadowImp(act,prop));
672 ObjectImp::put(exec,Identifier::from(i), shadow, DontEnum);
675 ObjectImp::put(exec,Identifier::from(i), *arg, DontEnum);
681 void ArgumentsImp::mark()
684 if (!activation->marked())
690 Value val = ObjectImp::get(exec,propertyName);
691 assert(SimpleNumber::is(val.imp()) || !val.imp()->isDestroyed());
693 if (obj.isValid() && obj.inherits(&ShadowImp::info)) {
694 ShadowImp *shadow =
static_cast<ShadowImp*
>(val.imp());
695 return activation->get(exec,shadow->prop);
703 const Value &value,
int attr)
705 Value val = ObjectImp::get(exec,propertyName);
707 if (obj.
isValid() && obj.inherits(&ShadowImp::info)) {
708 ShadowImp *shadow =
static_cast<ShadowImp*
>(val.imp());
709 activation->put(exec,shadow->prop,value,attr);
712 ObjectImp::put(exec,propertyName,value,attr);
718 const ClassInfo ActivationImp::info = {
"Activation", 0, 0, 0};
721 ActivationImp::ActivationImp(
FunctionImp *
function,
const List &arguments)
722 : _function(function), _arguments(true), _argumentsObject(0)
724 _arguments = arguments.
copy();
730 if (propertyName == argumentsPropertyName) {
732 ValueImp *v = getDirect(propertyName);
737 if (!_argumentsObject)
738 _argumentsObject =
new ArgumentsImp(exec, _function, _arguments, const_cast<ActivationImp*>(
this));
739 return Value(_argumentsObject);
741 return ObjectImp::get(exec, propertyName);
746 if (propertyName == argumentsPropertyName)
748 return ObjectImp::hasProperty(exec, propertyName);
753 if (propertyName == argumentsPropertyName)
755 return ObjectImp::deleteProperty(exec, propertyName);
758 void ActivationImp::mark()
761 if (_function && !_function->marked())
764 if (_argumentsObject && !_argumentsObject->marked())
765 _argumentsObject->mark();
776 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
780 CodeType GlobalFuncImp::codeType()
const
782 return id == Eval ? EvalCode : codeType();
785 bool GlobalFuncImp::implementsCall()
const
794 static const char do_not_escape[] =
795 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
796 "abcdefghijklmnopqrstuvwxyz"
803 if (x.
type() != StringType)
811 fprintf(stderr,
"eval(): %s\n", s.
ascii());
814 FunctionBodyNode *progNode = Parser::parse(s.
data(),s.
size(),&source,&errLine,&errMsg);
817 Debugger *dbg = exec->interpreter()->imp()->debugger();
819 bool cont = dbg->sourceParsed(exec,source->sid,s,errLine);
829 exec->interpreter()->imp()->addSourceCode(source);
835 exec->setException(err);
852 newExec.setException(exec->exception());
854 ctx.setLines(progNode->firstLine(),progNode->firstLine());
856 if (!dbg->enterContext(&newExec)) {
860 if (progNode->deref())
867 progNode->processVarDecls(&newExec);
872 ctx.setLines(progNode->lastLine(),progNode->lastLine());
873 if (dbg && !dbg->exitContext(&newExec,c))
876 else if (newExec.hadException())
877 exec->setException(newExec.exception());
878 else if (c.complType() == Throw)
879 exec->setException(c.value());
880 else if (c.isValueCompletion())
883 if (progNode->deref())
891 CString cstr = args[0].toString(exec).cstring();
892 const char* startptr = cstr.c_str();
893 while ( *startptr && isspace( *startptr ) )
898 base = args[1].toInt32(exec);
901 if (*startptr ==
'-') {
905 else if (*startptr ==
'+') {
910 bool leading0 =
false;
911 if ((base == 0 || base == 16) &&
912 (*startptr ==
'0' && (startptr[1] ==
'x' || startptr[1] ==
'X'))) {
916 else if (base == 0 && *startptr ==
'0') {
921 else if (base == 0) {
925 if (base < 2 || base > 36) {
931 for (; *startptr; startptr++) {
933 if (*startptr >=
'0' && *startptr <=
'9')
934 thisval = *startptr -
'0';
935 else if (*startptr >=
'a' && *startptr <=
'z')
936 thisval = 10 + *startptr -
'a';
937 else if (*startptr >=
'A' && *startptr <=
'Z')
938 thisval = 10 + *startptr -
'A';
940 if (thisval < 0 || thisval >= base)
948 if (index == 0 && !leading0)
951 res =
Number(
double(val)*sign);
956 UString str = args[0].toString(exec);
960 const char *c = str.
ascii();
963 isHex = (c[0] ==
'0' && (c[1] ==
'x' || c[1] ==
'X'));
972 res =
Boolean(isNaN(args[0].toNumber(exec)));
975 double n = args[0].toNumber(exec);
976 res =
Boolean(!isNaN(n) && !isInf(n));
980 res =
String(decodeURI(exec,args[0].toString(exec),uriReserved+
"#"));
982 case DecodeURIComponent:
983 res =
String(decodeURI(exec,args[0].toString(exec),
""));
986 res =
String(encodeURI(exec,args[0].toString(exec),uriReserved+uriUnescaped+
"#"));
988 case EncodeURIComponent:
989 res =
String(encodeURI(exec,args[0].toString(exec),uriUnescaped));
992 UString r =
"", s, str = args[0].toString(exec);
993 const UChar *c = str.data();
994 for (
int k = 0; k < str.size(); k++, c++) {
998 sprintf(tmp,
"%%u%04X", u);
1000 }
else if (u != 0 && strchr(do_not_escape, (
char)u)) {
1004 sprintf(tmp,
"%%%02X", u);
1013 UString s =
"", str = args[0].toString(exec);
1014 int k = 0, len = str.
size();
1016 const UChar *c = str.data() + k;
1018 if (*c ==
UChar(
'%') && k <= len - 6 && *(c+1) ==
UChar(
'u')) {
1019 if (Lexer::isHexDigit((c+2)->uc) && Lexer::isHexDigit((c+3)->uc) &&
1020 Lexer::isHexDigit((c+4)->uc) && Lexer::isHexDigit((c+5)->uc)) {
1021 u = Lexer::convertUnicode((c+2)->uc, (c+3)->uc,
1022 (c+4)->uc, (c+5)->uc);
1026 }
else if (*c ==
UChar(
'%') && k <= len - 3 &&
1027 Lexer::isHexDigit((c+1)->uc) && Lexer::isHexDigit((c+2)->uc)) {
1028 u =
UChar(Lexer::convertHex((c+1)->uc, (c+2)->uc));
1040 puts(args[0].toString(exec).ascii());