00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "reference.h"
00024 #include "internal.h"
00025 #include "context.h"
00026
00027 #include <assert.h>
00028
00029 using namespace KJS;
00030
00031
00032
00033 Reference::Reference(const Object& b, const Identifier& p)
00034 : base(b),
00035 baseIsValue(false),
00036 propertyNameIsNumber(false),
00037 prop(p)
00038 {
00039 }
00040
00041 Reference::Reference(const Object& b, unsigned p)
00042 : base(b),
00043 propertyNameAsNumber(p),
00044 baseIsValue(false),
00045 propertyNameIsNumber(true)
00046 {
00047 }
00048
00049 Reference::Reference(ObjectImp *b, const Identifier& p)
00050 : base(b),
00051 baseIsValue(false),
00052 propertyNameIsNumber(false),
00053 prop(p)
00054 {
00055 }
00056
00057 Reference::Reference(ObjectImp *b, unsigned p)
00058 : base(b),
00059 propertyNameAsNumber(p),
00060 baseIsValue(false),
00061 propertyNameIsNumber(true)
00062 {
00063 }
00064
00065 Reference::Reference(const Null& b, const Identifier& p)
00066 : base(b),
00067 baseIsValue(false),
00068 propertyNameIsNumber(false),
00069 prop(p)
00070 {
00071 }
00072
00073 Reference::Reference(const Null& b, unsigned p)
00074 : base(b),
00075 propertyNameAsNumber(p),
00076 baseIsValue(false),
00077 propertyNameIsNumber(true)
00078 {
00079 }
00080
00081 Reference Reference::makeValueReference(const Value& v)
00082 {
00083 Reference valueRef;
00084 valueRef.base = v;
00085 valueRef.baseIsValue = true;
00086 return valueRef;
00087 }
00088
00089 Reference::Reference()
00090 {
00091 }
00092
00093 Value Reference::getBase(ExecState *exec) const
00094 {
00095 if (baseIsValue) {
00096 Object err = Error::create(exec, ReferenceError, I18N_NOOP("Invalid reference base"));
00097 exec->setException(err);
00098 return err;
00099 }
00100
00101 return base;
00102 }
00103
00104 Identifier Reference::getPropertyName(ExecState * ) const
00105 {
00106 if (baseIsValue) {
00107
00108
00109
00110 return Identifier();
00111 }
00112
00113 if (propertyNameIsNumber && prop.isNull())
00114 prop = Identifier::from(propertyNameAsNumber);
00115 return prop;
00116 }
00117
00118 Value Reference::getValue(ExecState *exec) const
00119 {
00120 if (baseIsValue) {
00121 return base;
00122 }
00123
00124 Value o = getBase(exec);
00125
00126 if (!o.isValid() || o.type() == NullType) {
00127 UString m = I18N_NOOP("Can't find variable: ") + getPropertyName(exec).ustring();
00128 Object err = Error::create(exec, ReferenceError, m.ascii());
00129 exec->setException(err);
00130 return err;
00131 }
00132
00133 if (o.type() != ObjectType) {
00134 UString m = I18N_NOOP("Base is not an object");
00135 Object err = Error::create(exec, ReferenceError, m.ascii());
00136 exec->setException(err);
00137 return err;
00138 }
00139
00140 ObjectImp *oimp = static_cast<ObjectImp*>(o.imp());
00141 if (propertyNameIsNumber)
00142 return oimp->getPropertyByIndex(exec, propertyNameAsNumber);
00143 return oimp->get(exec, prop);
00144 }
00145
00146 void Reference::putValue(ExecState *exec, const Value &w)
00147 {
00148 if (baseIsValue) {
00149 Object err = Error::create(exec,ReferenceError);
00150 exec->setException(err);
00151 return;
00152 }
00153
00154 #ifdef KJS_VERBOSE
00155 printInfo(exec,(UString("setting property ")+getPropertyName(exec).ustring()).cstring().c_str(),w);
00156 #endif
00157 Value o = getBase(exec);
00158 if (o.type() == NullType)
00159 o = Value(exec->context().imp()->scopeChain().bottom());
00160
00161 ObjectImp *oimp = static_cast<ObjectImp*>(o.imp());
00162 if (propertyNameIsNumber)
00163 oimp->putPropertyByIndex(exec, propertyNameAsNumber, w);
00164 else
00165 oimp->put(exec, prop, w);
00166 }
00167
00168 bool Reference::deleteValue(ExecState *exec)
00169 {
00170 if (baseIsValue) {
00171 Object err = Error::create(exec,ReferenceError);
00172 exec->setException(err);
00173 return false;
00174 }
00175
00176 Value b = getBase(exec);
00177
00178
00179 if (b.type() != ObjectType) {
00180 assert(b.type() == NullType);
00181 return true;
00182 }
00183
00184 ObjectImp *bimp = static_cast<ObjectImp*>(b.imp());
00185 if (propertyNameIsNumber)
00186 return bimp->deletePropertyByIndex(exec, propertyNameAsNumber);
00187 return bimp->deleteProperty(exec, prop);
00188 }
00189
00190 bool Reference::isMutable()
00191 {
00192 return !baseIsValue;
00193 }