summaryrefslogtreecommitdiffstats
path: root/kjs/reference.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kjs/reference.cpp')
-rw-r--r--kjs/reference.cpp193
1 files changed, 193 insertions, 0 deletions
diff --git a/kjs/reference.cpp b/kjs/reference.cpp
new file mode 100644
index 000000000..778db8a53
--- /dev/null
+++ b/kjs/reference.cpp
@@ -0,0 +1,193 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2003 Apple Computer, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "reference.h"
+#include "internal.h"
+#include "context.h"
+
+#include <assert.h>
+
+using namespace KJS;
+
+// ------------------------------ Reference ------------------------------------
+
+Reference::Reference(const Object& b, const Identifier& p)
+ : base(b),
+ baseIsValue(false),
+ propertyNameIsNumber(false),
+ prop(p)
+{
+}
+
+Reference::Reference(const Object& b, unsigned p)
+ : base(b),
+ propertyNameAsNumber(p),
+ baseIsValue(false),
+ propertyNameIsNumber(true)
+{
+}
+
+Reference::Reference(ObjectImp *b, const Identifier& p)
+ : base(b),
+ baseIsValue(false),
+ propertyNameIsNumber(false),
+ prop(p)
+{
+}
+
+Reference::Reference(ObjectImp *b, unsigned p)
+ : base(b),
+ propertyNameAsNumber(p),
+ baseIsValue(false),
+ propertyNameIsNumber(true)
+{
+}
+
+Reference::Reference(const Null& b, const Identifier& p)
+ : base(b),
+ baseIsValue(false),
+ propertyNameIsNumber(false),
+ prop(p)
+{
+}
+
+Reference::Reference(const Null& b, unsigned p)
+ : base(b),
+ propertyNameAsNumber(p),
+ baseIsValue(false),
+ propertyNameIsNumber(true)
+{
+}
+
+Reference Reference::makeValueReference(const Value& v)
+{
+ Reference valueRef;
+ valueRef.base = v;
+ valueRef.baseIsValue = true;
+ return valueRef;
+}
+
+Reference::Reference()
+{
+}
+
+Value Reference::getBase(ExecState *exec) const
+{
+ if (baseIsValue) {
+ Object err = Error::create(exec, ReferenceError, I18N_NOOP("Invalid reference base"));
+ exec->setException(err);
+ return err;
+ }
+
+ return base;
+}
+
+Identifier Reference::getPropertyName(ExecState * /*exec*/) const
+{
+ if (baseIsValue) {
+ // the spec wants a runtime error here. But getValue() and putValue()
+ // will catch this case on their own earlier. When returning a Null
+ // string we should be on the safe side.
+ return Identifier();
+ }
+
+ if (propertyNameIsNumber && prop.isNull())
+ prop = Identifier::from(propertyNameAsNumber);
+ return prop;
+}
+
+Value Reference::getValue(ExecState *exec) const
+{
+ if (baseIsValue) {
+ return base;
+ }
+
+ Value o = getBase(exec);
+
+ if (!o.isValid() || o.type() == NullType) {
+ UString m = I18N_NOOP("Can't find variable: ") + getPropertyName(exec).ustring();
+ Object err = Error::create(exec, ReferenceError, m.ascii());
+ exec->setException(err);
+ return err;
+ }
+
+ if (o.type() != ObjectType) {
+ UString m = I18N_NOOP("Base is not an object");
+ Object err = Error::create(exec, ReferenceError, m.ascii());
+ exec->setException(err);
+ return err;
+ }
+
+ ObjectImp *oimp = static_cast<ObjectImp*>(o.imp());
+ if (propertyNameIsNumber)
+ return oimp->getPropertyByIndex(exec, propertyNameAsNumber);
+ return oimp->get(exec, prop);
+}
+
+void Reference::putValue(ExecState *exec, const Value &w)
+{
+ if (baseIsValue) {
+ Object err = Error::create(exec,ReferenceError);
+ exec->setException(err);
+ return;
+ }
+
+#ifdef KJS_VERBOSE
+ printInfo(exec,(UString("setting property ")+getPropertyName(exec).ustring()).cstring().c_str(),w);
+#endif
+ Value o = getBase(exec);
+ if (o.type() == NullType)
+ o = Value(exec->context().imp()->scopeChain().bottom());
+
+ ObjectImp *oimp = static_cast<ObjectImp*>(o.imp());
+ if (propertyNameIsNumber)
+ oimp->putPropertyByIndex(exec, propertyNameAsNumber, w);
+ else
+ oimp->put(exec, prop, w);
+}
+
+bool Reference::deleteValue(ExecState *exec)
+{
+ if (baseIsValue) {
+ Object err = Error::create(exec,ReferenceError);
+ exec->setException(err);
+ return false;
+ }
+
+ Value b = getBase(exec);
+
+ // The spec doesn't mention what to do if the base is null... just return true
+ if (b.type() != ObjectType) {
+ assert(b.type() == NullType);
+ return true;
+ }
+
+ ObjectImp *bimp = static_cast<ObjectImp*>(b.imp());
+ if (propertyNameIsNumber)
+ return bimp->deletePropertyByIndex(exec, propertyNameAsNumber);
+ return bimp->deleteProperty(exec, prop);
+}
+
+bool Reference::isMutable()
+{
+ return !baseIsValue;
+}