27 #include "function_object.h"
30 #include "operations.h"
49 char hexdigits[] =
"0123456789ABCDEF";
54 for (
int k = 0; k <
string.size(); k++) {
57 if (unescapedSet.
find(C) >= 0) {
58 if (encbufLen+1 >= encbufAlloc)
59 encbuf = (
UChar*)realloc(encbuf,(encbufAlloc *= 2)*
sizeof(
UChar));
60 encbuf[encbufLen++] = C;
63 unsigned char octets[4];
66 unsigned short zzzzzzz = C.uc;
70 else if (C.uc <= 0x07FF) {
71 unsigned short zzzzzz = C.uc & 0x3F;
72 unsigned short yyyyy = (C.uc >> 6) & 0x1F;
73 octets[0] = 0xC0 | yyyyy;
74 octets[1] = 0x80 | zzzzzz;
77 else if (C.uc >= 0xD800 && C.uc <= 0xDBFF) {
80 if (k + 1 >=
string.size()) {
82 exec->setException(err);
87 unsigned short Cnext =
UChar(
string[++k]).uc;
89 if (Cnext < 0xDC00 || Cnext > 0xDFFF) {
91 exec->setException(err);
96 unsigned short zzzzzz = Cnext & 0x3F;
97 unsigned short yyyy = (Cnext >> 6) & 0x0F;
98 unsigned short xx = C.uc & 0x03;
99 unsigned short wwww = (C.uc >> 2) & 0x0F;
100 unsigned short vvvv = (C.uc >> 6) & 0x0F;
101 unsigned short uuuuu = vvvv+1;
102 octets[0] = 0xF0 | (uuuuu >> 2);
103 octets[1] = 0x80 | ((uuuuu & 0x03) << 4) | wwww;
104 octets[2] = 0x80 | (xx << 4) | yyyy;
105 octets[3] = 0x80 | zzzzzz;
108 else if (C.uc >= 0xDC00 && C.uc <= 0xDFFF) {
110 exec->setException(err);
116 unsigned short zzzzzz = C.uc & 0x3F;
117 unsigned short yyyyyy = (C.uc >> 6) & 0x3F;
118 unsigned short xxxx = (C.uc >> 12) & 0x0F;
119 octets[0] = 0xE0 | xxxx;
120 octets[1] = 0x80 | yyyyyy;
121 octets[2] = 0x80 | zzzzzz;
125 while (encbufLen+3*octets_len >= encbufAlloc)
126 encbuf = (
UChar*)realloc(encbuf,(encbufAlloc *= 2)*
sizeof(
UChar));
128 for (
int j = 0; j < octets_len; j++) {
129 encbuf[encbufLen++] =
'%';
130 encbuf[encbufLen++] = hexdigits[octets[j] >> 4];
131 encbuf[encbufLen++] = hexdigits[octets[j] & 0x0F];
136 UString encoded(encbuf,encbufLen);
141 static bool decodeHex(
UChar hi,
UChar lo,
unsigned short *val)
144 if (hi.uc >=
'0' && hi.uc <=
'9')
145 *val = (hi.uc-
'0') << 4;
146 else if (hi.uc >=
'a' && hi.uc <=
'f')
147 *val = 10+(hi.uc-
'a') << 4;
148 else if (hi.uc >=
'A' && hi.uc <=
'F')
149 *val = 10+(hi.uc-
'A') << 4;
153 if (lo.uc >=
'0' && lo.uc <=
'9')
155 else if (lo.uc >=
'a' && lo.uc <=
'f')
156 *val |= 10+(lo.uc-
'a');
157 else if (lo.uc >=
'A' && lo.uc <=
'F')
158 *val |= 10+(lo.uc-
'A');
171 for (
int k = 0; k <
string.size(); k++) {
174 if (C !=
UChar(
'%')) {
176 if (decbufLen+1 >= decbufAlloc)
177 decbuf = (
UChar*)realloc(decbuf,(decbufAlloc *= 2)*
sizeof(
UChar));
178 decbuf[decbufLen++] = C;
184 if (k+2 >=
string.size()) {
186 exec->setException(err);
192 if (!decodeHex(
string[k+1],
string[k+2],&B)) {
194 exec->setException(err);
201 if (decbufLen+2 >= decbufAlloc)
202 decbuf = (
UChar*)realloc(decbuf,(decbufAlloc *= 2)*
sizeof(
UChar));
204 if ((B & 0x80) == 0) {
211 while (((B << n) & 0x80) != 0)
214 if (n < 2 || n > 4) {
216 exec->setException(err);
221 if (k+3*(n-1) >=
string.size()) {
223 exec->setException(err);
228 unsigned short octets[4];
230 for (
int j = 1; j < n; j++) {
233 !decodeHex(
string[k+1],
string[k+2],&B) ||
234 ((B & 0xC0) != 0x80)) {
236 exec->setException(err);
246 const unsigned long replacementChar = 0xFFFD;
249 unsigned long yyyyy = octets[0] & 0x1F;
250 unsigned long zzzzzz = octets[1] & 0x3F;
251 V = (yyyyy << 6) | zzzzzz;
255 C =
UChar((
unsigned short)V);
258 unsigned long xxxx = octets[0] & 0x0F;
259 unsigned long yyyyyy = octets[1] & 0x3F;
260 unsigned long zzzzzz = octets[2] & 0x3F;
261 V = (xxxx << 12) | (yyyyyy << 6) | zzzzzz;
264 if (V < 0x800 || V == 0xFFFE || V == 0xFFFF ||
265 (V >= 0xD800 && V <= 0xDFFF))
267 C =
UChar((
unsigned short)V);
271 unsigned long uuuuu = ((octets[0] & 0x07) << 2) | ((octets[1] >> 4) & 0x03);
272 unsigned long vvvv = uuuuu-1;
275 exec->setException(err);
279 unsigned long wwww = octets[1] & 0x0F;
280 unsigned long xx = (octets[2] >> 4) & 0x03;
281 unsigned long yyyy = octets[2] & 0x0F;
282 unsigned long zzzzzz = octets[3] & 0x3F;
283 unsigned short H = 0xD800 | (vvvv << 6) | (wwww << 2) | xx;
284 unsigned short L = 0xDC00 | (yyyy << 6) | zzzzzz;
285 decbuf[decbufLen++] =
UChar(H);
286 decbuf[decbufLen++] =
UChar(L);
291 if (reservedSet.
find(C) < 0) {
292 decbuf[decbufLen++] = C;
296 while (decbufLen+k-start+1 >= decbufAlloc)
297 decbuf = (
UChar*)realloc(decbuf,(decbufAlloc *= 2)*
sizeof(
UChar));
298 for (
int p = start; p <= k; p++)
299 decbuf[decbufLen++] =
string[p];
303 UString decoded(decbuf,decbufLen);
308 static UString uriReserved =
";/?:@&=+$,";
309 static UString uriAlpha =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
310 static UString DecimalDigit =
"0123456789";
311 static UString uriMark =
"-_.!~*'()";
312 static UString uriUnescaped = uriAlpha+DecimalDigit+uriMark;
316 const ClassInfo FunctionImp::info = {
"Function", &InternalFunctionImp::info, 0, 0};
322 ~Parameter() {
delete next; }
330 static_cast<
FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())
331 ), param(0L), line0(-1), line1(-1), sid(-1)
337 FunctionImp::~FunctionImp()
342 bool FunctionImp::implementsCall()
const
353 exec->
context().imp(),
this, &args);
355 newExec.setException(exec->exception());
358 processParameters(&newExec, args);
360 processVarDecls(&newExec);
362 ctx.setLines(line0,line0);
363 Debugger *dbg = exec->interpreter()->imp()->debugger();
365 if (!dbg->enterContext(&newExec)) {
374 ctx.setLines(line1,line1);
379 if (!dbg->exitContext(&newExec,comp)) {
387 if (newExec.hadException())
388 exec->setException(newExec.exception());
392 if (comp.complType() == Throw) {
394 printInfo(exec, n.c_str(), comp.value());
395 }
else if (comp.complType() == ReturnValue) {
397 printInfo(exec, n.c_str(), comp.value());
399 fprintf(stderr,
"%s returns: undefined\n", n.c_str());
402 if (comp.complType() == Throw) {
403 exec->setException(comp.value());
406 else if (comp.complType() == ReturnValue)
412 void FunctionImp::addParameter(
const Identifier &n)
414 Parameter **p = ¶m;
418 *p =
new Parameter(n);
421 Identifier FunctionImp::parameterProperty(
int index)
const
426 for (p = param; p && pos < index; p = p->next)
434 for (p = p->next; p; p = p->next)
441 UString FunctionImp::parameterString()
const
444 const Parameter *p = param;
448 s += p->name.ustring();
457 void FunctionImp::processParameters(
ExecState *exec,
const List &args)
462 fprintf(stderr,
"---------------------------------------------------\n"
463 "processing parameters for %s call\n",
464 name().isEmpty() ?
"(internal)" : name().ascii());
469 Parameter *p = param;
471 if (it != args.
end()) {
473 fprintf(stderr,
"setting parameter %s ", p->name.ascii());
474 printInfo(exec,
"to", *it);
476 variable.
put(exec, p->name, *it);
485 for (
int i = 0; i < args.
size(); i++)
486 printInfo(exec,
"setting argument", args[i]);
491 void FunctionImp::processVarDecls(
ExecState * )
498 if (propertyName == argumentsPropertyName) {
504 if (context->function() ==
this)
505 return static_cast<ActivationImp *>
506 (context->activationObject())->
get(exec, propertyName);
507 context = context->callingContext();
513 if (propertyName == lengthPropertyName) {
514 const Parameter * p = param;
523 if (propertyName == callerPropertyName) {
526 if (context->function() ==
this) {
528 if (cc && cc->function())
529 return Value(cc->function());
533 context = context->callingContext();
538 return InternalFunctionImp::get(exec, propertyName);
543 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
545 InternalFunctionImp::put(exec, propertyName, value, attr);
550 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
552 return InternalFunctionImp::hasProperty(exec, propertyName);
557 if (propertyName == argumentsPropertyName || propertyName == lengthPropertyName)
559 return InternalFunctionImp::deleteProperty(exec, propertyName);
565 const ClassInfo DeclaredFunctionImp::info = {
"Function", &FunctionImp::info, 0, 0};
574 line0 = body->firstLine();
575 line1 = body->lastLine();
576 sid = body->sourceId();
579 DeclaredFunctionImp::~DeclaredFunctionImp()
585 bool DeclaredFunctionImp::implementsConstruct()
const
594 Value p =
get(exec,prototypePropertyName);
595 if (p.
type() == ObjectType)
596 proto =
Object(static_cast<ObjectImp*>(p.imp()));
600 Object obj(
new ObjectImp(proto));
602 Value res = call(exec,obj,args);
604 if (res.
type() == ObjectType)
614 if (result.complType() == Throw || result.complType() == ReturnValue)
619 void DeclaredFunctionImp::processVarDecls(
ExecState *exec)
621 body->processVarDecls(exec);
630 class ShadowImp :
public ObjectImp {
632 ShadowImp(ObjectImp *_obj,
Identifier _prop) : obj(_obj), prop(_prop) {}
635 virtual const ClassInfo *classInfo()
const {
return &info; }
642 const ClassInfo ShadowImp::info = {
"Shadow", 0, 0, 0};
644 void ShadowImp::mark()
655 const ClassInfo ArgumentsImp::info = {
"Arguments", 0, 0, 0};
660 : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), activation(act)
663 putDirect(calleePropertyName, func, DontEnum);
664 putDirect(lengthPropertyName, args.
size(), DontEnum);
667 for (
int i = 0; arg != args.
end(); arg++, i++) {
670 Object shadow(
new ShadowImp(act,prop));
671 ObjectImp::put(exec,Identifier::from(i), shadow, DontEnum);
674 ObjectImp::put(exec,Identifier::from(i), *arg, DontEnum);
680 void ArgumentsImp::mark()
683 if (!activation->marked())
689 Value val = ObjectImp::get(exec,propertyName);
690 assert(SimpleNumber::is(val.imp()) || !val.imp()->isDestroyed());
692 if (obj.isValid() && obj.inherits(&ShadowImp::info)) {
693 ShadowImp *shadow =
static_cast<ShadowImp*
>(val.imp());
694 return activation->get(exec,shadow->prop);
702 const Value &value,
int attr)
704 Value val = ObjectImp::get(exec,propertyName);
706 if (obj.
isValid() && obj.inherits(&ShadowImp::info)) {
707 ShadowImp *shadow =
static_cast<ShadowImp*
>(val.imp());
708 activation->put(exec,shadow->prop,value,attr);
711 ObjectImp::put(exec,propertyName,value,attr);
717 const ClassInfo ActivationImp::info = {
"Activation", 0, 0, 0};
720 ActivationImp::ActivationImp(
FunctionImp *
function,
const List &arguments)
721 : _function(function), _arguments(true), _argumentsObject(0)
723 _arguments = arguments.
copy();
729 if (propertyName == argumentsPropertyName) {
731 ValueImp *v = getDirect(propertyName);
736 if (!_argumentsObject)
737 _argumentsObject =
new ArgumentsImp(exec, _function, _arguments, const_cast<ActivationImp*>(
this));
738 return Value(_argumentsObject);
740 return ObjectImp::get(exec, propertyName);
745 if (propertyName == argumentsPropertyName)
747 return ObjectImp::hasProperty(exec, propertyName);
752 if (propertyName == argumentsPropertyName)
754 return ObjectImp::deleteProperty(exec, propertyName);
757 void ActivationImp::mark()
760 if (_function && !_function->marked())
763 if (_argumentsObject && !_argumentsObject->marked())
764 _argumentsObject->mark();
775 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
779 CodeType GlobalFuncImp::codeType()
const
781 return id == Eval ? EvalCode : codeType();
784 bool GlobalFuncImp::implementsCall()
const
793 static const char do_not_escape[] =
794 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
795 "abcdefghijklmnopqrstuvwxyz"
802 if (x.
type() != StringType)
810 fprintf(stderr,
"eval(): %s\n", s.
ascii());
813 FunctionBodyNode *progNode = Parser::parse(s.
data(),s.
size(),&source,&errLine,&errMsg);
816 Debugger *dbg = exec->interpreter()->imp()->debugger();
818 bool cont = dbg->sourceParsed(exec,source->sid,s,errLine);
828 exec->interpreter()->imp()->addSourceCode(source);
834 exec->setException(err);
851 newExec.setException(exec->exception());
853 ctx.setLines(progNode->firstLine(),progNode->firstLine());
855 if (!dbg->enterContext(&newExec)) {
859 if (progNode->deref())
866 progNode->processVarDecls(&newExec);
871 ctx.setLines(progNode->lastLine(),progNode->lastLine());
872 if (dbg && !dbg->exitContext(&newExec,c))
875 else if (newExec.hadException())
876 exec->setException(newExec.exception());
877 else if (c.complType() == Throw)
878 exec->setException(c.value());
879 else if (c.isValueCompletion())
882 if (progNode->deref())
890 CString cstr = args[0].toString(exec).cstring();
891 const char* startptr = cstr.c_str();
892 while ( *startptr && isspace( *startptr ) )
897 base = args[1].toInt32(exec);
900 if (*startptr ==
'-') {
904 else if (*startptr ==
'+') {
909 bool leading0 =
false;
910 if ((base == 0 || base == 16) &&
911 (*startptr ==
'0' && (startptr[1] ==
'x' || startptr[1] ==
'X'))) {
915 else if (base == 0 && *startptr ==
'0') {
920 else if (base == 0) {
924 if (base < 2 || base > 36) {
930 for (; *startptr; startptr++) {
932 if (*startptr >=
'0' && *startptr <=
'9')
933 thisval = *startptr -
'0';
934 else if (*startptr >=
'a' && *startptr <=
'z')
935 thisval = 10 + *startptr -
'a';
936 else if (*startptr >=
'A' && *startptr <=
'Z')
937 thisval = 10 + *startptr -
'A';
939 if (thisval < 0 || thisval >= base)
947 if (index == 0 && !leading0)
950 res =
Number(
double(val)*sign);
955 UString str = args[0].toString(exec);
959 const char *c = str.
ascii();
962 isHex = (c[0] ==
'0' && (c[1] ==
'x' || c[1] ==
'X'));
971 res =
Boolean(isNaN(args[0].toNumber(exec)));
974 double n = args[0].toNumber(exec);
975 res =
Boolean(!isNaN(n) && !isInf(n));
979 res =
String(decodeURI(exec,args[0].toString(exec),uriReserved+
"#"));
981 case DecodeURIComponent:
982 res =
String(decodeURI(exec,args[0].toString(exec),
""));
985 res =
String(encodeURI(exec,args[0].toString(exec),uriReserved+uriUnescaped+
"#"));
987 case EncodeURIComponent:
988 res =
String(encodeURI(exec,args[0].toString(exec),uriUnescaped));
991 UString r =
"", s, str = args[0].toString(exec);
992 const UChar *c = str.data();
993 for (
int k = 0; k < str.size(); k++, c++) {
997 sprintf(tmp,
"%%u%04X", u);
999 }
else if (u != 0 && strchr(do_not_escape, (
char)u)) {
1003 sprintf(tmp,
"%%%02X", u);
1012 UString s =
"", str = args[0].toString(exec);
1013 int k = 0, len = str.
size();
1015 const UChar *c = str.data() + k;
1017 if (*c ==
UChar(
'%') && k <= len - 6 && *(c+1) ==
UChar(
'u')) {
1018 if (Lexer::isHexDigit((c+2)->uc) && Lexer::isHexDigit((c+3)->uc) &&
1019 Lexer::isHexDigit((c+4)->uc) && Lexer::isHexDigit((c+5)->uc)) {
1020 u = Lexer::convertUnicode((c+2)->uc, (c+3)->uc,
1021 (c+4)->uc, (c+5)->uc);
1025 }
else if (*c ==
UChar(
'%') && k <= len - 3 &&
1026 Lexer::isHexDigit((c+1)->uc) && Lexer::isHexDigit((c+2)->uc)) {
1027 u =
UChar(Lexer::convertHex((c+1)->uc, (c+2)->uc));
1039 puts(args[0].toString(exec).ascii());