reference.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2003 Apple Computer, Inc
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Library General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Library General Public License
00017  *  along with this library; see the file COPYING.LIB.  If not, write to
00018  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  *  Boston, MA 02110-1301, USA.
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 // ------------------------------ Reference ------------------------------------
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 * /*exec*/) const
00105 {
00106   if (baseIsValue) {
00107     // the spec wants a runtime error here. But getValue() and putValue()
00108     // will catch this case on their own earlier. When returning a Null
00109     // string we should be on the safe side.
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   // The spec doesn't mention what to do if the base is null... just return true
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 }
KDE Home | KDE Accessibility Home | Description of Access Keys