Toplevel.cpp

Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is [Open Source Virtual Machine.].
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Adobe System Incorporated.
00018  * Portions created by the Initial Developer are Copyright (C) 2004-2006
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Adobe AS3 Team
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 
00039 #include "avmplus.h"
00040 
00041 namespace avmplus
00042 {
00043 #undef DEBUG_EARLY_BINDING
00044 
00045     //
00046     // builtins
00047     //
00048     BEGIN_NATIVE_MAP(Toplevel)
00049         NATIVE_METHOD_FLAGS(escape, Toplevel::escape, 0)
00050         NATIVE_METHOD_FLAGS(unescape, Toplevel::unescape, 0)
00051         NATIVE_METHOD_FLAGS(decodeURI, Toplevel::decodeURI, 0)
00052         NATIVE_METHOD_FLAGS(decodeURIComponent, Toplevel::decodeURIComponent, 0)
00053         NATIVE_METHOD_FLAGS(encodeURI, Toplevel::encodeURI, 0)
00054         NATIVE_METHOD_FLAGS(encodeURIComponent, Toplevel::encodeURIComponent, 0)
00055         NATIVE_METHOD_FLAGS(isNaN, Toplevel::isNaN, 0)
00056         NATIVE_METHOD_FLAGS(isFinite, Toplevel::isFinite, 0)
00057         NATIVE_METHOD_FLAGS(parseInt, Toplevel::parseInt, 0)
00058         NATIVE_METHOD_FLAGS(parseFloat, Toplevel::parseFloat, 0)
00059         NATIVE_METHOD(isXMLName, Toplevel::isXMLName)       
00060     END_NATIVE_MAP()
00061 
00062 
00063     Toplevel::Toplevel(VTable* cvtable, ScriptObject* delegate)
00064         : ScriptObject(cvtable, delegate)
00065     {
00066         builtinClasses = (ClassClosure**) core()->GetGC()->Alloc(sizeof(ClassClosure*) * core()->builtinPool->cinits.capacity(), MMgc::GC::kZero | MMgc::GC::kContainsPointers);
00067     }
00068 
00069     Toplevel::~Toplevel()
00070     {
00071     }
00072 
00073     ClassClosure* Toplevel::resolveBuiltinClass(int class_id)
00074     {
00075         Traits *traits = core()->builtinPool->cinits[class_id]->declaringTraits->itraits;
00076         Multiname qname(traits->ns, traits->name);
00077         ScriptObject *container = vtable->init->finddef(&qname);
00078 
00079         Atom classAtom = getproperty(container->atom(), &qname, container->vtable);
00080         ClassClosure *cc = (ClassClosure*)AvmCore::atomToScriptObject(classAtom);
00081         //builtinClasses[class_id] = cc;
00082         WBRC(core()->GetGC(), builtinClasses, &builtinClasses[class_id], cc);
00083         return cc;
00084     }
00085 
00086     ScriptObject* Toplevel::toPrototype(Atom atom)
00087     {
00088         if (!AvmCore::isNullOrUndefined(atom))
00089         {
00090             switch (atom&7)
00091             {
00092             default:
00093             
00094             case kNamespaceType:
00095                 return namespaceClass->prototype;
00096 
00097             case kStringType:
00098                 return stringClass->prototype;
00099 
00100             case kObjectType:
00101                 return AvmCore::atomToScriptObject(atom)->getDelegate();
00102 
00103             case kDoubleType:
00104             case kIntegerType:
00105                 // ISSUE what about int?
00106                 return numberClass->prototype;
00107 
00108             case kBooleanType:
00109                 return booleanClass->prototype;
00110             }
00111         }
00112         else
00113         {
00114             // TypeError in ECMA
00115             throwTypeError(
00116                 (atom == undefinedAtom) ? kConvertUndefinedToObjectError :
00117                                             kConvertNullToObjectError);
00118             return NULL;
00119         }
00120     }
00121 
00122     // equivalent to ToObject, obj->traits.  exception if null or undefined.
00123     VTable* Toplevel::toVTable(Atom atom)
00124     {
00125         if (!AvmCore::isNullOrUndefined(atom))
00126         {
00127             switch (atom&7)
00128             {
00129             case kObjectType:
00130                 return AvmCore::atomToScriptObject(atom)->vtable;
00131             case kNamespaceType:
00132                 return namespaceClass->ivtable();
00133             case kStringType:
00134                 return stringClass->ivtable();
00135             case kBooleanType:
00136                 return booleanClass->ivtable();
00137             case kIntegerType:
00138             case kDoubleType:
00139                 // ISSUE what about int?
00140                 return numberClass->ivtable();
00141             }
00142         }
00143         else
00144         {
00145             // TypeError in ECMA
00146             throwTypeError(
00147                     (atom == undefinedAtom) ? kConvertUndefinedToObjectError :
00148                                         kConvertNullToObjectError);
00149         }
00150         return NULL;
00151     }
00152     
00153     // equivalent to ToObject, obj->traits.  exception if null or undefined.
00154     Traits* Toplevel::toTraits(Atom atom)
00155     {
00156         if (!AvmCore::isNullOrUndefined(atom))
00157         {
00158             switch (atom&7)
00159             {
00160             case kObjectType:
00161                 return AvmCore::atomToScriptObject(atom)->traits();
00162             case kNamespaceType:
00163                 return core()->traits.namespace_itraits;
00164             case kStringType:
00165                 return core()->traits.string_itraits;
00166             case kBooleanType:
00167                 return core()->traits.boolean_itraits;
00168             case kIntegerType:
00169             case kDoubleType:
00170                 // ISSUE what about int?
00171                 return core()->traits.number_itraits;
00172             }
00173         }
00174         else
00175         {
00176             // TypeError in ECMA
00177             ErrorClass *error = typeErrorClass();
00178             if( error )
00179                 error->throwError(
00180                     (atom == undefinedAtom) ? kConvertUndefinedToObjectError :
00181                                         kConvertNullToObjectError);
00182             else
00183                 throwVerifyError(kCorruptABCError);
00184         }
00185         return NULL;
00186     }
00187     
00195     Atom Toplevel::op_call(Atom method, int argc, Atom* atomv)
00196     {
00197         if (!AvmCore::isObject(method))
00198         {
00199             Multiname name(core()->publicNamespace, core()->constantString("value"));
00200             throwTypeError(kCallOfNonFunctionError, core()->toErrorString(&name));
00201         }
00202         return AvmCore::atomToScriptObject(method)->call(argc, atomv);
00203     }
00204 
00212     Atom Toplevel::op_construct(Atom ctor, int argc, Atom* atomv)
00213     {
00214         if (!AvmCore::isObject(ctor))
00215         {
00216             throwTypeError(kConstructOfNonFunctionError);
00217         }
00218 
00219         ScriptObject *ct = AvmCore::atomToScriptObject(ctor);
00220         Atom val = ct->construct(argc, atomv);
00221         return val;
00222     }
00223 
00230     Atom Toplevel::op_applytype(Atom factory, int argc, Atom* atomv)
00231     {
00232         if (!AvmCore::isObject(factory))
00233         {
00234             throwTypeError(kTypeAppOfNonParamType);
00235         }
00236         return AvmCore::atomToScriptObject(factory)->applyTypeArgs(argc, atomv);
00237     }
00238     
00239     // E4X 10.5.1, pg 37
00240     QNameObject* Toplevel::ToAttributeName(Atom attributeName)
00241     {
00242         if (!AvmCore::isNullOrUndefined(attributeName))
00243         {
00244             AvmCore* core = this->core();
00245             switch (attributeName&7)
00246             {
00247             case kNamespaceType:
00248                 attributeName = AvmCore::atomToNamespace(attributeName)->getURI()->atom();
00249                 break;
00250             case kObjectType:
00251                 // check for XML, XMLList, Object, AttributeName, AnyName
00252                 // if XML, toString, then do default string case
00253                 // if XMLList, toString, then do default string case
00254                 // if AttributeName, return the input argument
00255                 // if AnyName, return the result of calling "ToAttributeName(*)"
00256                 // if QName, return attributeName
00257                 // otherwise, do toString, then to default case
00258                 if (core->isQName(attributeName))
00259                 {
00260                     QNameObject *q = core->atomToQName (attributeName);
00261                     if (q->isAttr())
00262                         return q;
00263                     else
00264                         return new (core->GetGC(), qnameClass()->ivtable()->getExtraSize()) QNameObject(qnameClass(), attributeName, true);
00265                 }
00266                 else
00267                 {
00268                     attributeName = core->string(attributeName)->atom();
00269                     break;
00270                 }
00271                 break;
00272             case kStringType:
00273                 {
00274                     break;
00275                 }
00276             case kBooleanType:
00277             case kIntegerType:
00278             case kDoubleType:
00279             default: // number
00280                 throwTypeError(kConvertUndefinedToObjectError);
00281             }
00282 
00283             return new (core->GetGC(), qnameClass()->ivtable()->getExtraSize()) QNameObject(qnameClass(), attributeName, true);
00284         }
00285         else
00286         {
00287             throwTypeError(kConvertUndefinedToObjectError);
00288             return NULL;
00289         }
00290     }
00291 
00292     // E4X 10.6.1, page 38
00293     // This returns a Multiname create from a unqualified generic type.
00294     // The multiname returned will have one namespace and will be correctly
00295     // marked as an attribute if input is an attribute
00296     void Toplevel::ToXMLName (const Atom p, Multiname& m) 
00297     {
00298         Stringp s = 0;
00299         AvmCore* core = this->core();
00300 
00301         if (!AvmCore::isNullOrUndefined(p))
00302         {
00303             switch (p & 7)
00304             {
00305             case kNamespaceType:
00306                 s = AvmCore::atomToNamespace(p)->getURI();
00307                 break;
00308             case kObjectType:
00309                 {
00310                     // check for XML, XMLList, Object, AttributeName, AnyName
00311                     // if XML, toString, then do default string case
00312                     // if XMLList, toString, then do default string case
00313                     // if AttributeName, return the input argument
00314                     // if AnyName, return the result of calling "ToAttributeName(*)"
00315                     // if QName, return attributeName
00316                     if (core->isQName(p))
00317                     {
00318                         QNameObject *q = core->atomToQName (p);
00319 
00320                         m.setAttr(q->isAttr() ? true : false);
00321                         m.setNamespace(core->newNamespace (q->getURI()));
00322                         Stringp name = q->getLocalName();
00323                         if (name == core->kAsterisk)
00324                         {
00325                             m.setAnyName(); // marks it as an anyName
00326                         }
00327                         else
00328                         {
00329                             m.setName(name);
00330                         }
00331                         return;
00332                     }
00333                     else // XML, XMLList or generic object - convert to string
00334                     {
00335                         s = core->string(p);
00336                         break;
00337                     }
00338                 }
00339             case kIntegerType:
00340             case kDoubleType:
00341             case kStringType:
00342             case kBooleanType:
00343                 {
00344                     s = core->string(p);
00345                     break;
00346                 }
00347             }
00348         }
00349         else
00350         {
00351             throwTypeError(kConvertUndefinedToObjectError);
00352             return;
00353         }
00354 
00355         // At this point p should be a string atom
00356         AvmAssert (s != 0);
00357 
00358         // if s is integer, throw TypeError
00359         // if first character of s is "@", return __toAttributeName (string - @)
00360         // else, return QName (s)
00361         if ((*s)[0] == '@')
00362         {
00363             // __toAttributeName minus the @
00364             Stringp news = new (core->GetGC()) String(s, 1, s->length() - 1);
00365             m.setName(core->internString(news));
00366             m.setAttr();
00367         }
00368         else
00369         {
00370             m.setName(core->internString(s));
00371         }
00372 
00373         if (m.getName() == core->kAsterisk)
00374         {
00375             m.setAnyName(); // marks it as an anyName
00376         }
00377 
00378         m.setNamespace(core->publicNamespace);
00379     }
00380 
00381     void Toplevel::CoerceE4XMultiname (const Multiname *m, Multiname &out) const
00382     {
00383         // This function is used to convert raw string access into correct
00384         // Multiname types:
00385         // x["*"]
00386         // x["@*"]
00387         // Unqualified anyName types are correct handled in Multiname::matches
00388         // so we do not edit their namespaces here.  (They should have one
00389         // namespace which is null according to the E4X spec.)
00390         //
00391         // Unqualified regular types have the default XML namespace added to their
00392         // namespace count here.
00393 
00394         AvmAssert(!m->isRuntime());
00395 
00396         AvmCore *core = this->core();
00397 
00398         if (m->isQName())
00399         {
00400             AvmAssert(m->namespaceCount() == 1);
00401             out.setNamespace(m);
00402             out.setQName();
00403         }
00404         else
00405         {
00406             // If we're any namespace, no work required.
00407             if (m->isAnyNamespace())
00408             {
00409                 out.setAnyNamespace();
00410             }
00411             else
00412             {
00413                 // search for a match in our nsSet for the defaultNamespace
00414                 Namespace *defaultNs = toplevel()->getDefaultNamespace();
00415                 bool bMatch = false;
00416                 for (int i=0, n=m->namespaceCount(); i < n; i++)
00417                 {
00418                     Namespace *ns = m->getNamespace(i);
00419                     if (ns && ns->getPrefix() == defaultNs->getPrefix() && 
00420                         ns->getURI() == defaultNs->getURI() &&
00421                         ns->getType() == defaultNs->getType())
00422                     {
00423                         bMatch = true;
00424                         break;
00425                     }
00426                 }
00427 
00428                 // For an unqualified reference, we need to add in the default xml namespace
00429                 // since we did not find a match for it in our namespace set
00430                 if (!bMatch)
00431                 {
00432                     int newNameCount = m->namespaceCount() + 1;
00433                     NamespaceSet *nsset = core->newNamespaceSet(newNameCount);
00434                     for (int i=0, n=m->namespaceCount(); i < n; i++)
00435                     {
00436                         nsset->namespaces[i] = m->getNamespace(i);
00437                     }
00438                     //Stringp s1 = string(getDefaultNamespace()->getPrefix());
00439                     //Stringp s2 = string(getDefaultNamespace()->getURI());
00440                     nsset->namespaces[newNameCount-1] = toplevel()->getDefaultNamespace();
00441                     out.setNsset(nsset);
00442                 }
00443                 else
00444                 {   
00445                     if (m->namespaceCount() > 1)
00446                         out.setNsset(m->getNsset());
00447                     else
00448                         out.setNamespace (m->getNamespace());
00449                 }
00450             }
00451         }
00452 
00453         out.setAttr(m->isAttr() ? true : false);
00454 
00455         if (m->isAnyName())
00456         {
00457             out.setAnyName();
00458         }
00459         else
00460         {
00461             Stringp s = m->getName();
00462             if ((s->length() == 1) && ((*s)[0] == '*'))
00463             {
00464                 // Mark is as an "anyName" (name == undefined makes isAnyName true)
00465                 out.setAnyName();
00466             }
00467             else if ((s->length() >= 1) && ((*s)[0] == '@'))
00468             {
00469                 // If we're already marked as an attribute, we don't want to modify 
00470                 // our string in any way.  Degenerative cases where you call:
00471                 // XML.attribute (new QName("@*"))
00472                 if (!out.isAttr())
00473                 {
00474                     // check for "@*"
00475                     if ((s->length() == 2) && ((*s)[1] == '*'))
00476                         out.setAnyName();
00477                     else
00478                         out.setName(core->internString (new (core->GetGC()) String(s, 1, s->length()-1)));
00479                     out.setAttr();
00480                 }
00481                 else
00482                 {
00483                     if (m->isAnyName())
00484                         out.setAnyName();
00485                     else
00486                         out.setName(m->getName());
00487                 }
00488             }
00489             else
00490             {
00491                 if (m->isAnyName())
00492                     out.setAnyName();
00493                 else
00494                     out.setName(m->getName());
00495             }
00496         }
00497     }
00498 
00499     Atom Toplevel::callproperty(Atom base, const Multiname* multiname, int argc, Atom* atomv, VTable* vtable)
00500     {
00501         Binding b = getBinding(vtable->traits, multiname);
00502         switch (b&7)
00503         {
00504         case BIND_METHOD:
00505         {
00506             #ifdef DEBUG_EARLY_BINDING
00507             core()->console << "callproperty method " << vtable->traits << " " << multiname->getName() << "\n";
00508             #endif
00509             // force receiver == base.  if caller used OP_callproplex then receiver was null.
00510             atomv[0] = base;
00511             MethodEnv* method = vtable->methods[AvmCore::bindingToMethodId(b)];
00512             AvmAssert(method != NULL);
00513             return method->coerceEnter(argc, atomv);
00514         }
00515         case BIND_VAR:
00516         case BIND_CONST:
00517         {
00518             #ifdef DEBUG_EARLY_BINDING
00519             core()->console << "callproperty slot " << vtable->traits << " " << multiname->getName() << "\n";
00520             #endif
00521             Atom method = AvmCore::atomToScriptObject(base)->getSlotAtom(AvmCore::bindingToSlotId(b));
00522             return op_call(method, argc, atomv);
00523         }
00524         case BIND_GET:
00525         case BIND_GETSET:
00526         {
00527             #ifdef DEBUG_EARLY_BINDING
00528             core()->console << "callproperty getter " << vtable->traits << " " << multiname->getName() << "\n";
00529             #endif
00530             // Invoke the getter on base
00531             int m = AvmCore::bindingToGetterId(b);
00532             MethodEnv *f = vtable->methods[m];
00533             Atom method = f->coerceEnter(base);
00534             return op_call(method, argc, atomv);
00535         }
00536         case BIND_SET:
00537         {
00538             #ifdef DEBUG_EARLY_BINDING
00539             core()->console << "callproperty setter " << vtable->traits << " " << multiname->getName() << "\n";
00540             #endif
00541             // read on write-only property
00542             throwReferenceError(kWriteOnlyError, multiname, vtable->traits);
00543         }
00544         default:
00545             #ifdef DEBUG_EARLY_BINDING
00546             core()->console << "callproperty dynamic " << vtable->traits << " " << multiname->getName() << "\n";
00547             #endif
00548             if (AvmCore::isObject(base))
00549             {
00550                 return AvmCore::atomToScriptObject(base)->callProperty(multiname, argc, atomv);
00551             }
00552             else
00553             {
00554                 // primitive types are not dynamic, so we can go directly
00555                 // to their __proto__ object
00556                 ScriptObject* proto = toPrototype(base);
00557                 Atom method = proto->getMultinameProperty(multiname);
00558                 return op_call(method, argc, atomv);
00559             }
00560         }
00561     }
00562 
00563     Atom Toplevel::constructprop(const Multiname* multiname, int argc, Atom* atomv, VTable* vtable)
00564     {
00565         Binding b = getBinding(vtable->traits, multiname);
00566         Atom obj = atomv[0];
00567         AvmCore* core = this->core();
00568         switch (b&7)
00569         {
00570         case BIND_METHOD:
00571         {
00572             // can't invoke method as constructor
00573             MethodEnv* env = vtable->methods[AvmCore::bindingToMethodId(b)];
00574             throwTypeError(kCannotCallMethodAsConstructor, core->toErrorString((AbstractFunction*)env->method));
00575         }
00576         case BIND_VAR:
00577         case BIND_CONST:
00578         {
00579             #ifdef DEBUG_EARLY_BINDING
00580             core->console << "constructprop slot " << vtable->traits << " " << multiname->getName() << "\n";
00581             #endif
00582             Atom ctor = AvmCore::atomToScriptObject(obj)->getSlotAtom(AvmCore::bindingToSlotId(b));
00583             if (!core->istype(ctor, CLASS_TYPE) && !core->istype(ctor, FUNCTION_TYPE))
00584                 throwTypeError(kNotConstructorError, core->toErrorString(multiname));
00585             return op_construct(ctor, argc, atomv);
00586         }
00587         case BIND_GET:
00588         case BIND_GETSET:
00589         {
00590             #ifdef DEBUG_EARLY_BINDING
00591             core()->console << "constructprop getter " << vtable->traits << " " << multiname->getName() << "\n";
00592             #endif
00593             // Invoke the getter
00594             int m = AvmCore::bindingToGetterId(b);
00595             MethodEnv *f = vtable->methods[m];
00596             Atom ctor = f->coerceEnter(obj);
00597             return op_construct(ctor, argc, atomv);
00598         }
00599         case BIND_SET:
00600         {
00601             #ifdef DEBUG_EARLY_BINDING
00602             core()->console << "constructprop setter " << vtable->traits << " " << multiname->getName() << "\n";
00603             #endif
00604             // read on write-only property
00605             throwReferenceError(kWriteOnlyError, multiname, vtable->traits);
00606         }
00607         default:
00608             #ifdef DEBUG_EARLY_BINDING
00609             core()->console << "constructprop dynamic " << vtable->traits << " " << multiname->getName() << "\n";
00610             #endif
00611             if ((obj&7)==kObjectType)
00612             {
00613                 return AvmCore::atomToScriptObject(obj)->constructProperty(multiname, argc, atomv);
00614             }
00615             else
00616             {
00617                 // primitive types are not dynamic, so we can go directly
00618                 // to their __proto__ object
00619                 ScriptObject* proto = toPrototype(obj);
00620                 Atom ctor = proto->getMultinameProperty(multiname);
00621                 return op_construct(ctor, argc, atomv);
00622             }
00623         }
00624     }   
00625 
00626     Atom Toplevel::instanceof(Atom atom, Atom ctor)
00627     {
00628         AvmCore* core = this->core();
00629         if ((ctor&7) != kObjectType ||
00630             !core->istype(ctor, core->traits.function_itraits) &&
00631             !core->istype(ctor, core->traits.class_itraits))
00632         {
00633             throwTypeError(kCantUseInstanceofOnNonObjectError);
00634         }
00635         // check for null before tryign to call toPrototype(atom), which will throw an error for null.
00636         if (AvmCore::isNull(atom))
00637             return falseAtom;
00638 
00639         ClassClosure* c = (ClassClosure*)AvmCore::atomToScriptObject(ctor);
00640 
00641         ScriptObject *proto = c->prototype;
00642         ScriptObject *o = toPrototype(atom);
00643 
00644         for (; o != NULL; o = o->getDelegate())
00645         {
00646             if (o == proto)
00647                 return trueAtom;
00648         }
00649 
00650         return falseAtom;
00651     }
00652 
00653     
00658     Atom Toplevel::coerce(Atom atom, Traits* expected) const
00659     {
00660         Traits* actual;
00661         AvmCore* core = this->core();
00662 
00663         // these types always succeed
00664         if (expected == NULL)
00665             return atom;
00666         if (expected == BOOLEAN_TYPE)
00667             return core->booleanAtom(atom);
00668         if (expected == NUMBER_TYPE)
00669             return core->numberAtom(atom);
00670         if ((expected == STRING_TYPE))
00671             return AvmCore::isNullOrUndefined(atom) ? 0|kStringType : core->string(atom)->atom();
00672         if (expected == INT_TYPE)
00673             return core->intAtom(atom);
00674         if (expected == UINT_TYPE)
00675             return core->uintAtom(atom);
00676         if (expected == OBJECT_TYPE)
00677             return atom == undefinedAtom ? nullObjectAtom : atom;
00678 
00679         if (AvmCore::isNullOrUndefined(atom))
00680             return expected == VOID_TYPE ? undefinedAtom : nullObjectAtom;
00681 
00682         switch (atom&7)
00683         {
00684         case kStringType:
00685             actual = STRING_TYPE;
00686             break;
00687 
00688         case kBooleanType:
00689             actual = BOOLEAN_TYPE;
00690             break;
00691 
00692         case kDoubleType:
00693             actual = NUMBER_TYPE;
00694             break;
00695 
00696         case kIntegerType:
00697             actual = INT_TYPE;
00698             break;
00699 
00700         case kNamespaceType:
00701             actual = NAMESPACE_TYPE;
00702             break;
00703 
00704         case kObjectType:
00705             actual = AvmCore::atomToScriptObject(atom)->traits();
00706             break;
00707 
00708         default:
00709             // unexpected atom type
00710             AvmAssert(false);
00711             return false;
00712         }
00713 
00714         if (actual->containsInterface(expected))
00715         {
00716             return atom;
00717         }
00718         else
00719         {
00720             // failed
00721 #ifdef AVMPLUS_VERBOSE
00722             //core->console << "checktype failed " << expected << " <- " << atom << "\n";
00723 #endif
00724             throwTypeError(kCheckTypeFailedError, core->atomToErrorString(atom), core->toErrorString(expected));
00725             return atom;//unreachable
00726         }
00727     }
00728 
00729     void Toplevel::coerceobj(ScriptObject* obj, Traits* expected) const
00730     {
00731         if (obj && !obj->traits()->containsInterface(expected))
00732         {
00733             // failed
00734 #ifdef DEBUGGER
00735             //core->console << "checktype failed " << expected << " <- " << atom << "\n";
00736 #endif
00737             throwTypeError(kCheckTypeFailedError, core()->atomToErrorString(obj->atom()), core()->toErrorString(expected));
00738         }
00739     }
00740     
00741     Atom Toplevel::add2(Atom lhs, Atom rhs)
00742     {
00743         AvmCore* core = this->core();
00744 
00745         // do common cases first/quick:
00746         if (AvmCore::isNumber(lhs) && AvmCore::isNumber(rhs))
00747         {
00748             // C++ porting note. if either side is undefined, null or NaN then result must be NaN.
00749             // Java's + operator ensures this for double operands.
00750             // cn:  null should convert to 0, so I think the above comment is wrong for null.
00751             return core->doubleToAtom(core->number(lhs) + core->number(rhs));
00752         }
00753         else if (AvmCore::isString(lhs) || AvmCore::isString(rhs) || core->isDate(lhs) || core->isDate(rhs))
00754         {
00755             return core->concatStrings(core->string(lhs), core->string(rhs))->atom();
00756         }
00757 
00758 
00759         // then look for the more unlikely cases
00760         
00761         // E4X, section 11.4.1, pg 53
00762         
00763         if (core->isObject (lhs) && core->isObject (rhs) && 
00764                (core->isXML(lhs) || core->isXMLList(lhs)) 
00765             && (core->isXML(rhs) || core->isXMLList (rhs)))
00766         {
00767             XMLListObject *l = new (core->GetGC()) XMLListObject(xmlListClass());
00768             l->_append (lhs);
00769             l->_append (rhs);
00770             return l->atom();
00771         }
00772         
00773         // to catch oddball cases like:
00774         //   function foo() { };
00775         //   foo.prototype.valueOf = function() { return new Object(); }
00776         //   foo.prototype.toString = function() { return 2; }
00777         //   print( new foo() + 33 ); // should be 35
00778         //
00779         // we need to follow the E3 spec:
00780         // 1. call ToPrimitive() on lhs and rhs, then
00781         // if L is String || R is String, concat, else add toNumber(lhs) to toNumber(rhs)
00782 
00783         // ToPrimitive() will call [[DefaultValue]], which calls valueOf().  If the result is
00784         //  a primitive, return that value else call toString() instead.
00785 
00786         // from E3:
00787         // NOTE No hint is provided in the calls to ToPrimitive in steps 5 and 6. All native ECMAScript objects except Date objects handle
00788         // the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the hint String were given.
00789         // Host objects may handle the absence of a hint in some other manner.
00790         
00791         Atom lhs_asPrimVal = core->primitive(lhs); // Date is handled above with the String argument case,  we don't have to check for it here.
00792         Atom rhs_asPrimVal = core->primitive(rhs);
00793 
00794         if (AvmCore::isString(lhs_asPrimVal) || AvmCore::isString(rhs_asPrimVal))
00795         {
00796             return core->concatStrings(core->string(lhs_asPrimVal), core->string(rhs_asPrimVal))->atom();
00797         }
00798         else
00799         {
00800             return core->doubleToAtom(core->number(lhs_asPrimVal) + core->number(rhs_asPrimVal));
00801         }
00802     }
00803 
00804     Atom Toplevel::getproperty(Atom obj, const Multiname* multiname, VTable* vtable)
00805     {
00806         Binding b = getBinding(vtable->traits, multiname);
00807         AvmCore* core = this->core();
00808         switch (b&7)
00809         {
00810         case BIND_METHOD: 
00811         {
00812             #ifdef DEBUG_EARLY_BINDING
00813             core->console << "getproperty method " << vtable->traits << " " << multiname->getName() << "\n";
00814             #endif
00815             if (multiname->contains(core->publicNamespace) && isXmlBase(obj))
00816             {
00817                 // dynamic props should hide declared methods
00818                 ScriptObject* so = AvmCore::atomToScriptObject(obj);
00819                 return so->getMultinameProperty(multiname);
00820             }
00821             // extracting a method
00822             MethodEnv *m = vtable->methods[AvmCore::bindingToMethodId(b)];
00823             return methodClosureClass->create(m, obj)->atom();
00824         }
00825 
00826         case BIND_VAR:
00827         case BIND_CONST:
00828         {
00829             #ifdef DEBUG_EARLY_BINDING
00830             core->console << "getproperty slot " << vtable->traits << " " << multiname->getName() << "\n";
00831             #endif
00832             int slot = AvmCore::bindingToSlotId(b);
00833             return AvmCore::atomToScriptObject(obj)->getSlotAtom(slot);
00834         }
00835 
00836         case BIND_NONE:
00837             #ifdef DEBUG_EARLY_BINDING
00838             core->console << "getproperty dynamic " << vtable->traits << " " << multiname->getName() << "\n";
00839             #endif
00840             if ((obj&7) == kObjectType)
00841             {
00842                 // try dynamic lookup on instance.  even if the traits are sealed,
00843                 // we might need to search the prototype chain
00844                 return AvmCore::atomToScriptObject(obj)->getMultinameProperty(multiname);
00845             }
00846             else
00847             {
00848                 // primitive types are not dynamic, so we can go directly
00849                 // to their __proto__ object.  but they are sealed, so fail if
00850                 // the property is not found on the proto chain.
00851 
00852                 ScriptObject* delegate = toPrototype(obj);
00853                 if (delegate->isValidDynamicName(multiname))
00854                 {
00855                     return delegate->ScriptObject::getStringPropertyFromProtoChain(multiname->getName(), delegate, toTraits(obj));
00856                 }
00857                 else
00858                 {
00859                     throwReferenceError(kReadSealedError, multiname, toTraits(obj));
00860                     return undefinedAtom;
00861                 }
00862             }
00863 
00864         case BIND_GET:
00865         case BIND_GETSET:
00866         {
00867             #ifdef DEBUG_EARLY_BINDING
00868             core->console << "getproperty getter " << vtable->traits << " " << multiname->getName() << "\n";
00869             #endif
00870             // Invoke the getter
00871             int m = AvmCore::bindingToGetterId(b);
00872             MethodEnv *f = vtable->methods[m];
00873             return f->coerceEnter(obj);
00874         }
00875         case BIND_SET:
00876         {
00877             #ifdef DEBUG_EARLY_BINDING
00878             core->console << "getproperty setter " << vtable->traits << " " << multiname->getName() << "\n";
00879             #endif
00880             // read on write-only property
00881             throwReferenceError(kWriteOnlyError, multiname, vtable->traits);
00882         }
00883 
00884         default:
00885             // internal error
00886             AvmAssert(false);
00887             return undefinedAtom;
00888         }
00889     }
00890 
00891     void Toplevel::setproperty(Atom obj, const Multiname* multiname, Atom value, VTable* vtable) const
00892     {
00893         Binding b = getBinding(vtable->traits, multiname);
00894         setproperty_b(obj,multiname,value,vtable,b);
00895     }
00896 
00897     void Toplevel::setproperty_b(Atom obj, const Multiname* multiname, Atom value, VTable* vtable, Binding b) const
00898     {
00899         switch (b&7)
00900         {
00901         case BIND_METHOD: 
00902         {
00903             #ifdef DEBUG_EARLY_BINDING
00904             core()->console << "setproperty method " << vtable->traits << " " << multiname->getName() << "\n";
00905             #endif
00906             if (multiname->contains(core()->publicNamespace) && isXmlBase(obj))
00907             {
00908                 // dynamic props should hide declared methods
00909                 ScriptObject* so = AvmCore::atomToScriptObject(obj);
00910                 so->setMultinameProperty(multiname, value);
00911                 return;
00912             }
00913             // trying to assign to a method.  error.
00914             throwReferenceError(kCannotAssignToMethodError, multiname, vtable->traits);
00915         }
00916 
00917         case BIND_CONST:
00918         {
00919             // OP_setproperty can never set a const.  initproperty must be used
00920             throwReferenceError(kConstWriteError, multiname, vtable->traits);
00921             return;
00922         }
00923         case BIND_VAR:
00924         {
00925             #ifdef DEBUG_EARLY_BINDING
00926             core()->console << "setproperty slot " << vtable->traits << " " << multiname->getName() << "\n";
00927             #endif
00928             int slot = AvmCore::bindingToSlotId(b);
00929             AvmCore::atomToScriptObject(obj)->setSlotAtom(slot, 
00930                 coerce(value, vtable->traits->getSlotTraits(slot)));
00931             return;
00932         }
00933 
00934         case BIND_SET: 
00935         case BIND_GETSET: 
00936         {
00937             #ifdef DEBUG_EARLY_BINDING
00938             core()->console << "setproperty setter " << vtable->traits << " " << multiname->getName() << "\n";
00939             #endif
00940             // Invoke the setter
00941             uint32 m = AvmCore::bindingToSetterId(b);
00942             AvmAssert(m < vtable->traits->methodCount);
00943             MethodEnv* method = vtable->methods[m];
00944             Atom atomv_out[2] = { obj, value };
00945             method->coerceEnter(1, atomv_out);
00946             return;
00947         }
00948         case BIND_GET: 
00949         {
00950             #ifdef DEBUG_EARLY_BINDING
00951             core()->console << "setproperty getter " << vtable->traits << " " << multiname->getName() << "\n";
00952             #endif
00953             throwReferenceError(kConstWriteError, multiname, vtable->traits);
00954             return;
00955         }
00956 
00957         case BIND_NONE:
00958         {
00959             #ifdef DEBUG_EARLY_BINDING
00960             core()->console << "setproperty dynamic " << vtable->traits << " " << multiname->getName() << "\n";
00961             #endif
00962             if (AvmCore::isObject(obj))
00963             {
00964                 AvmCore::atomToScriptObject(obj)->setMultinameProperty(multiname, value);
00965             }
00966             else
00967             {
00968                 // obj represents a primitive Number, Boolean, int, or String, and primitives
00969                 // are sealed and final.  Cannot add dynamic vars to them.
00970 
00971                 // property could not be found and created.
00972                 throwReferenceError(kWriteSealedError, multiname, vtable->traits);
00973             }
00974             return;
00975         }
00976 
00977         default:
00978             // internal error if we get here
00979             AvmAssert(false);
00980         }
00981     }
00982 
00983     // E4X 12.1.1, pg 59
00984     Namespace* Toplevel::getDefaultNamespace()
00985     {
00986         // Walking the scope chain now would require a pointer into the local
00987         // variable space of the currently executing function.  Instead we save/
00988         // restore the defaultNamespace location as we enter/leave methods, so we
00989         // always can get to the current value.
00990         AvmCore* core = this->core();
00991 #ifdef _DEBUG
00992         AvmAssert(!core->dxnsAddr || (uintptr)(*core->dxnsAddr) != 0xcccccccc);
00993 #endif
00994         if (!core->dxnsAddr || !(*core->dxnsAddr))
00995             throwTypeError(kNoDefaultNamespaceError);
00996         return *core->dxnsAddr;
00997     }
00998 
01004     Binding Toplevel::getBinding(Traits* traits, const Multiname* ref) const
01005     {
01006         Binding b = BIND_NONE;
01007         if (traits && ref->isBinding())
01008         {
01009             if (!ref->isNsset())
01010             {
01011                 b = traits->findBinding(ref->getName(), ref->getNamespace());
01012             }
01013             else
01014             {
01015                 b = traits->findBinding(ref->getName(), ref->getNsset());
01016                 if (b == BIND_AMBIGUOUS)
01017                 {
01018                     // ERROR.  more than one binding is available.  throw exception.
01019                     throwTypeError(
01020                                     kAmbiguousBindingError, core()->toErrorString(ref));
01021                 }
01022             }
01023         }
01024         return b;
01025     }
01026 
01027     Stringp Toplevel::decodeURI(Stringp uri)
01028     {
01029         AvmCore* core = this->core();
01030         if (!uri) uri = core->knull;
01031         Stringp out = decode(uri, false);
01032         if (!out) {
01033             toplevel()->uriErrorClass()->throwError(kInvalidURIError, core->toErrorString("decodeURI"));
01034         }
01035         return out;
01036     }
01037 
01038     Stringp Toplevel::decodeURIComponent(Stringp uri)
01039     {
01040         AvmCore* core = this->core();
01041         if (!uri) uri = core->knull;
01042         Stringp out = decode(uri, true);
01043         if (!out) {
01044             toplevel()->uriErrorClass()->throwError(kInvalidURIError, core->toErrorString("decodeURIComponent"));
01045         }
01046         return out;
01047     }
01048 
01049     Stringp Toplevel::encodeURI(Stringp uri)
01050     {
01051         AvmCore* core = this->core();
01052         if (!uri) uri = core->knull;
01053         Stringp out = encode(uri, false);
01054         if (!out) {
01055             toplevel()->uriErrorClass()->throwError(kInvalidURIError, core->toErrorString("encodeURI"));
01056         }
01057         return out;
01058     }
01059 
01060     Stringp Toplevel::encodeURIComponent(Stringp uri)
01061     {
01062         AvmCore* core = this->core();
01063         if (!uri) uri = core->knull;
01064         Stringp out = encode(uri, true);
01065         if (!out) {
01066             toplevel()->uriErrorClass()->throwError(kInvalidURIError, core->toErrorString("encodeURIComponent"));
01067         }
01068         return out;
01069     }
01070     
01071     bool Toplevel::isNaN(double n)
01072     {
01073         return MathUtils::isNaN(n);
01074     }
01075 
01088     bool Toplevel::isFinite(double d)
01089     {
01090         return !(MathUtils::isInfinite(d)||MathUtils::isNaN(d));
01091     }
01092 
01093     double Toplevel::parseInt(Stringp in, int radix)
01094     {
01095         AvmCore* core = this->core();
01096         if (!in) in = core->knull;
01097         const wchar *ptr = in->c_str();
01098         return MathUtils::parseInt(ptr, in->length(), radix, false);
01099     }
01100 
01101     double Toplevel::parseFloat(Stringp in)
01102     {
01103         double result;
01104         
01105         AvmCore* core = this->core();
01106         if (!in) in = core->knull;
01107         if (!MathUtils::convertStringToDouble(in->c_str(), in->length(), &result, false)) {
01108             result = MathUtils::nan();
01109         }
01110         
01111         return result;
01112     }
01113 
01114     Stringp Toplevel::escape(Stringp in)
01115     {
01116         AvmCore* core = this->core();
01117 
01118         if (!in) in = core->knull;
01119 
01120         const wchar *str = in->c_str();
01121         StringBuffer buffer(core);
01122         
01123         for (int i=0, n=in->length(); i<n; i++) {
01124             wchar ch = str[i];
01125             if (contains(unescaped, ch)) {
01126                 buffer << ch;
01127             } else if (ch & 0xff00) {
01128                 buffer << "%u";
01129                 buffer.writeHexWord(ch);
01130             } else {
01131                 buffer << '%';
01132                 buffer.writeHexByte((uint8)ch);
01133             }
01134         }
01135 
01136         return core->newString(buffer.c_str());
01137     }
01138 
01139     Stringp Toplevel::escapeBytes(Stringp input)
01140     {
01141         AvmCore* core = this->core();
01142 
01143         UTF8String* inputUTF8 = input->toUTF8String();
01144         const uint8* src = (const uint8*) inputUTF8->c_str();
01145 
01146         StringBuffer buffer(core);
01147         
01148         for (int i=0, n=inputUTF8->length(); i<n; i++) {
01149             uint8 ch = src[i];
01150             if (contains(unescaped, ch)) {
01151                 buffer << (wchar)ch;
01152             } else {
01153                 buffer << '%';
01154                 buffer.writeHexByte((uint8)ch);
01155             }
01156         }
01157 
01158         return core->newString(buffer.c_str());
01159     }
01160     
01161     // Helper function.
01162     int Toplevel::parseHexChar(wchar c)
01163     {
01164         if ('0' <= c && c <= '9') {
01165             return c-'0';
01166         }
01167         if ('A' <= c && c <= 'F') {
01168             return c-'A'+10;
01169         }
01170         if ('a' <= c && c <= 'f') {
01171             return c-'a'+10;
01172         }
01173         return -1;
01174     }
01175 
01176     wchar Toplevel::extractCharacter(const wchar*& src)
01177     {
01178         if (*src == '%') {
01179             const wchar *ptr = src;
01180             ptr++;
01181             if (*ptr == 0) {
01182                 return *src++;
01183             }
01184             wchar value = 0;
01185             int len = 2;
01186             if (*ptr == 'u') {
01187                 len = 4;
01188                 ptr++;
01189             }
01190             for (int i=0; i<len; i++) {
01191                 int v = parseHexChar(*ptr++);
01192                 if (v < 0) {
01193                     return *src++;
01194                 }
01195                 value = (wchar)((value<<4) | v);
01196             }
01197             src = ptr;
01198             return value;
01199         }
01200         return *src++;
01201     }
01202     
01203     Stringp Toplevel::unescape(Stringp in)
01204     {
01205         AvmCore* core = this->core();
01206 
01207         if (!in) in = core->knull;
01208 
01209         Stringp out = new (core->GetGC()) String(in->length());
01210 
01211         const wchar *src = in->c_str();
01212         wchar *outbuf = out->lockBuffer();
01213         wchar *dst = outbuf;
01214         const wchar *end = src + in->length();
01215         while (src < end) {
01216             *dst++ = extractCharacter(src);
01217         }
01218         *dst = 0;
01219         out->unlockBuffer((int)(dst-outbuf));
01220         
01221         return out;
01222     }
01223     
01224     Stringp Toplevel::encode(Stringp in, bool encodeURIComponentFlag)
01225     {
01226         StringBuffer out(core());
01227 
01228         const wchar *src = in->c_str();
01229         int len = in->length();
01230 
01231         while (len--) {
01232             wchar ch = *src;
01233 
01234             if (contains(uriUnescaped, ch) ||
01235                 (!encodeURIComponentFlag &&
01236                  contains(uriReservedPlusPound, ch)))
01237             {
01238                 out << (char)ch;
01239                 src++;
01240             } else {
01241                 if (ch >= 0xDC00 && ch <= 0xDFFF) {
01242                     return NULL;
01243                 }
01244                 uint32 V;
01245                 if (ch >= 0xD800 && ch < 0xDC00) {
01246                     if (src[1] < 0xDC00 || src[1] > 0xDFFF) {
01247                         return NULL;
01248                     }
01249                     V = (ch - 0xD800) * 0x400 + (src[1] - 0xDC00) * 0x10000;
01250                     src += 2;
01251                 } else {
01252                     V = ch;
01253                     src++;
01254                 }
01255                 uint8 Octets[6];
01256                 int OctetsLen = UnicodeUtils::Ucs4ToUtf8(V, Octets);
01257                 if (!OctetsLen) {
01258                     return NULL;
01259                 }
01260                 for (int i=0; i<OctetsLen; i++) {
01261                     out << '%';
01262                     out.writeHexByte(Octets[i]);
01263                 }
01264             }
01265         }
01266 
01267         return core()->newString(out.c_str());
01268     }
01269     
01270     Stringp Toplevel::decode(Stringp in, bool decodeURIComponentFlag)
01271     {
01272         const wchar *chars = in->c_str();
01273         int length = in->length();
01274         wchar *out = (wchar*) core()->GetGC()->Alloc(length*2+1); // decoded result is at most length wchar chars long
01275         int outLen = 0;
01276 
01277         for (int k = 0; k < length; k++) {
01278             wchar C = chars[k];
01279             if (C == '%') {
01280                 int start = k;
01281                 if ((k + 2) >= length) {
01282                     return NULL;
01283                 }
01284                 int v1 = parseHexChar(chars[k+1]);
01285                 if (v1 == -1) {
01286                     return NULL;
01287                 }
01288                 int v2 = parseHexChar(chars[k+2]);
01289                 if (v2 == -1) {
01290                     return NULL;
01291                 }
01292                 k += 2;
01293                 uint8 B = (uint8)((v1<<4) | v2);
01294                 uint32 V;
01295                 if (!(B & 0x80)) {
01296                     V = (wchar)B;
01297                 } else {
01298                     // 13. Let n be the smallest non-negative number
01299                     //     such that (B << n) & 0x80 is equal to 0.
01300                     int n = 1;
01301                     while (((B<<n) & 0x80) != 0) {
01302                         n++;
01303                     }
01304 
01305                     // 14. If n equals 1 or n is greater than 4,
01306                     //     throw a URIError exception.
01307                     if (n == 1 || n > 4) {
01308                         return NULL;
01309                     }
01310                     uint8 Octets[4];
01311                     Octets[0] = B;
01312                     if (k + 3*(n-1) >= length) {
01313                         return NULL;
01314                     }
01315                     for (int j=1; j<n; j++) {
01316                         k++;
01317                         if (chars[k] != '%') {
01318                             return NULL;
01319                         }
01320                         int v1 = parseHexChar(chars[k+1]);
01321                         if (v1 == -1) {
01322                             return NULL;
01323                         }
01324                         int v2 = parseHexChar(chars[k+2]);
01325                         if (v2 == -1) {
01326                             return NULL;
01327                         }
01328                         B = (uint8)((v1<<4) | v2);
01329                         
01330                         // 23. If the two most significant bits
01331                         //     in B are not 10, throw a URIError exception.
01332                         if ((B&0xC0) != 0x80) {
01333                             return NULL;
01334                         }
01335                         
01336                         k += 2;
01337                         Octets[j] = B;
01338                     }
01339 
01340                     // 29. Let V be the value obtained by applying the UTF-8 transformation
01341                     // to Octets, that is, from an array of octets into a 32-bit value.
01342                     if (!UnicodeUtils::Utf8ToUcs4(Octets, n, &V)) {
01343                         return NULL;
01344                     }
01345                 }
01346 
01347                 if (V < 0x10000) {
01348                     // Check for reserved set
01349                     if (!decodeURIComponentFlag) {
01350                         if (contains(uriReservedPlusPound, V)) {
01351                             while (start <= k) {
01352                                 out[outLen++] = chars[start++];
01353                             }
01354                         } else {
01355                             out[outLen++] = (wchar)V;
01356                         }
01357                     } else {
01358                         out[outLen++] = (wchar)V;
01359                     }
01360                 } else {
01361                     // 31. If V is greater than 0x10FFFF, throw a URIError exception.
01362                     if (V > 0x10FFFF) {
01363                         return NULL;
01364                     }
01365                     // 32. Let L be (((V - 0x10000) & 0x3FF) + 0xDC00).
01366                     // 33. Let H be ((((V - 0x10000) >> 10) & 0x3FF) + 0xD800).                     
01367                     uint32 L = (((V - 0x10000) & 0x3FF) + 0xDC00);
01368                     uint32 H = ((((V - 0x10000) >> 10) & 0x3FF) + 0xD800);
01369                     out[outLen++] = (wchar)H;
01370                     out[outLen++] = (wchar)L;
01371                 }
01372             } else {
01373                 out[outLen++] = C;
01374             }
01375         }
01376         
01377         out[outLen] = 0;
01378         return new (gc()) String(out,outLen);
01379     }
01380 
01381     /*
01382      * uriUnescaped is defined in Section 15.1 of the ECMA-262 specification
01383      */
01384     const uint32 Toplevel::uriUnescaped[] = {
01385         0x00000000,
01386         0x03ff6782,
01387         0x87fffffe,
01388         0x47fffffe
01389     };
01390     
01391     /*
01392      * uriReserved is defined in Section 15.1 of the ECMA-262 specification
01393      * The '#' sign is added in accordance with the definition of
01394      * the encodeURI/decodeURI functions
01395      */
01396     const uint32 Toplevel::uriReservedPlusPound[] = {
01397         0x00000000,
01398         0xac009858,
01399         0x00000001,
01400         0x00000000
01401     };
01402 
01408     const uint32 Toplevel::unescaped[] = {
01409         0x00000000,
01410         0x03ffec00,
01411         0x87ffffff,
01412         0x07fffffe
01413     };
01414 
01415     bool Toplevel::isXMLName(Atom v)
01416     {
01417         return core()->isXMLName(v);
01418     }
01419 
01420     unsigned int Toplevel::readU30(const byte *&p) const
01421     {
01422         unsigned int result = AvmCore::readU30(p);
01423         if (result & 0xc0000000)
01424             throwVerifyError(kCorruptABCError);
01425         return result;
01426     }
01427 
01428     void Toplevel::throwVerifyError(int id) const
01429     {
01430         verifyErrorClass()->throwError(id);
01431     }
01432 
01433 #ifdef DEBUGGER
01434     void Toplevel::throwVerifyError(int id, Stringp arg1) const
01435     {
01436         verifyErrorClass()->throwError(id, arg1);
01437     }
01438 
01439     void Toplevel::throwVerifyError(int id, Stringp arg1, Stringp arg2) const
01440     {
01441         verifyErrorClass()->throwError(id, arg1, arg2);
01442     }
01443 #endif
01444 
01445     void Toplevel::throwTypeError(int id) const
01446     {
01447         typeErrorClass()->throwError(id);
01448     }
01449 
01450     void Toplevel::throwTypeError(int id, Stringp arg1) const
01451     {
01452         typeErrorClass()->throwError(id, arg1);
01453     }
01454 
01455     void Toplevel::throwTypeError(int id, Stringp arg1, Stringp arg2) const
01456     {
01457         typeErrorClass()->throwError(id, arg1, arg2);
01458     }
01459 
01460     void Toplevel::throwError(int id) const
01461     {
01462         errorClass()->throwError(id);
01463     }
01464 
01465     void Toplevel::throwError(int id, Stringp arg1) const
01466     {
01467         errorClass()->throwError(id, arg1);
01468     }
01469 
01470     void Toplevel::throwError(int id, Stringp arg1, Stringp arg2) const
01471     {
01472         errorClass()->throwError(id, arg1, arg2);
01473     }
01474 
01475     void Toplevel::throwArgumentError(int id) const
01476     {
01477         argumentErrorClass()->throwError(id);
01478     }
01479 
01480     void Toplevel::throwArgumentError(int id, Stringp arg1) const
01481     {
01482         argumentErrorClass()->throwError(id, arg1);
01483     }
01484 
01485     void Toplevel::throwArgumentError(int id, const char *s) const
01486     {
01487         argumentErrorClass()->throwError(id, core()->toErrorString(s));
01488     }
01489 
01490     void Toplevel::throwArgumentError(int id, Stringp arg1, Stringp arg2) const
01491     {
01492         argumentErrorClass()->throwError(id, arg1, arg2);
01493     }
01494 
01495     void Toplevel::throwRangeError(int id) const
01496     {
01497         rangeErrorClass()->throwError(id);
01498     }
01499 
01500     void Toplevel::throwRangeError(int id, Stringp arg1) const
01501     {
01502         rangeErrorClass()->throwError(id, arg1);
01503     }
01504 
01505     void Toplevel::throwRangeError(int id, Stringp arg1, Stringp arg2) const
01506     {
01507         rangeErrorClass()->throwError(id, arg1, arg2);
01508     }
01509 
01510     void Toplevel::throwRangeError(int id, Stringp arg1, Stringp arg2, Stringp arg3) const
01511     {
01512         rangeErrorClass()->throwError(id, arg1, arg2, arg3);
01513     }
01514 
01515     void Toplevel::throwReferenceError(int id, const Multiname* multiname, const Traits* traits) const
01516     {
01517         referenceErrorClass()->throwError(id, core()->toErrorString(multiname), core()->toErrorString((Traits*)traits));
01518     }
01519 
01520     void Toplevel::throwReferenceError(int id, const Multiname* multiname) const
01521     {
01522         referenceErrorClass()->throwError(id, core()->toErrorString(multiname));
01523     }
01524 }

Generated on Sun Oct 12 18:50:03 2008 for Tamarin by  doxygen 1.4.6