📄 object.cpp
字号:
/* * This file is part of the KDE libraries * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * * 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include "object.h"#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <string.h>#include <math.h>#include "kjs.h"#include "types.h"#include "internal.h"#include "operations.h"#include "collector.h"#include "error_object.h"namespace KJS {#ifdef WORDS_BIGENDIAN unsigned char NaN_Bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 }; unsigned char Inf_Bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 };#elif defined(arm) unsigned char NaN_Bytes[] = { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 }; unsigned char Inf_Bytes[] = { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 };#else unsigned char NaN_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f }; unsigned char Inf_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };#endif const double NaN = *(const double*) NaN_Bytes; const double Inf = *(const double*) Inf_Bytes; const double D16 = 65536.0; const double D31 = 2147483648.0; /* TODO: remove in next version */ const double D32 = 4294967296.0; // TODO: -0};using namespace KJS;const TypeInfo Imp::info = { "Imp", AbstractType, 0, 0, 0 };namespace KJS { struct Property { UString name; Imp *object; int attribute; Property *next; };}KJSO::KJSO() : rep(0){#ifdef KJS_DEBUG_MEM count++;#endif}KJSO::KJSO(Imp *d) : rep(d){#ifdef KJS_DEBUG_MEM count++;#endif if (rep) { rep->ref(); rep->setGcAllowed(true); }}KJSO::KJSO(const KJSO &o){#ifdef KJS_DEBUG_MEM count++;#endif rep = o.rep; if (rep) { rep->ref(); rep->setGcAllowed(true); }}KJSO& KJSO::operator=(const KJSO &o){ if (rep) rep->deref(); rep = o.rep; if (rep) { rep->ref(); rep->setGcAllowed(true); } return *this;}KJSO::~KJSO(){#ifdef KJS_DEBUG_MEM count--;#endif if (rep) rep->deref();}bool KJSO::isDefined() const{ return !isA(UndefinedType);}bool KJSO::isNull() const{ return !rep;}Type KJSO::type() const{#ifdef KJS_VERBOSE if (!rep) fprintf(stderr, "requesting type of null object\n");#endif return rep ? rep->typeInfo()->type : UndefinedType;}bool KJSO::isObject() const{ return (type() >= ObjectType);}bool KJSO::isA(const char *s) const{ assert(rep); const TypeInfo *info = rep->typeInfo(); if (!s || !info || !info->name) return false; if (info->type == HostType && strcmp(s, "HostObject") == 0) return true; return (strcmp(s, info->name) == 0);}bool KJSO::derivedFrom(const char *s) const{ if (!s) return false; assert(rep); const TypeInfo *info = rep->typeInfo(); while (info) { if (info->name && strcmp(s, info->name) == 0) return true; info = info->base; } return false;}KJSO KJSO::toPrimitive(Type preferred) const{ assert(rep); return rep->toPrimitive(preferred);}Boolean KJSO::toBoolean() const{ assert(rep); return rep->toBoolean();}Number KJSO::toNumber() const{ assert(rep); return rep->toNumber();}// helper function for toInteger, toInt32, toUInt32 and toUInt16double KJSO::round() const{ if (isA(UndefinedType)) /* TODO: see below */ return 0.0; Number n = toNumber(); if (n.value() == 0.0) /* TODO: -0, NaN, Inf */ return 0.0; double d = floor(fabs(n.value())); if (n.value() < 0) d *= -1; return d;}// ECMA 9.4Number KJSO::toInteger() const{ return Number(round());}// ECMA 9.5int KJSO::toInt32() const{ double d = round(); double d32 = fmod(d, D32); if (d32 >= D32 / 2.0) d32 -= D32; return static_cast<int>(d32);}// ECMA 9.6unsigned int KJSO::toUInt32() const{ double d = round(); double d32 = fmod(d, D32); return static_cast<unsigned int>(d32);}// ECMA 9.7unsigned short KJSO::toUInt16() const{ double d = round(); double d16 = fmod(d, D16); return static_cast<unsigned short>(d16);}String KJSO::toString() const{ assert(rep); return rep->toString();}Object KJSO::toObject() const{ assert(rep); if (isObject()) return Object(rep); return rep->toObject();}bool KJSO::implementsCall() const{ return (type() == FunctionType || type() == InternalFunctionType || type() == ConstructorType || type() == DeclaredFunctionType || type() == AnonymousFunctionType);}// [[call]]KJSO KJSO::executeCall(const KJSO &thisV, const List *args){ assert(rep); assert(implementsCall()); return (static_cast<FunctionImp*>(rep))->executeCall(thisV.imp(), args);}KJSO KJSO::executeCall(const KJSO &thisV, const List *args, const List *extraScope) const{ assert(rep); assert(implementsCall()); return (static_cast<FunctionImp*>(rep))->executeCall(thisV.imp(), args, extraScope);}void KJSO::setConstructor(KJSO c){ put("constructor", c, DontEnum | DontDelete | ReadOnly);}// ECMA 8.7.1KJSO KJSO::getBase() const{ if (!isA(ReferenceType)) return Error::create(ReferenceError, I18N_NOOP("Invalid reference base")); return ((ReferenceImp*)rep)->getBase();}// ECMA 8.7.2UString KJSO::getPropertyName() const{ if (!isA(ReferenceType)) // 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 UString(); return ((ReferenceImp*)rep)->getPropertyName();}// ECMA 8.7.1KJSO KJSO::getValue() const{ if (!isA(ReferenceType)) { return *this; } KJSO o = getBase(); if (o.isNull() || o.isA(NullType)) { UString m = I18N_NOOP("Can't find variable: ") + getPropertyName(); return Error::create(ReferenceError, m.ascii()); } return o.get(getPropertyName());}/* TODO: remove in next version */KJSO KJSO::getValue(){ return const_cast<const KJSO*>(this)->getValue();}// ECMA 8.7.2ErrorType KJSO::putValue(const KJSO& v){ if (!isA(ReferenceType)) return ReferenceError; KJSO o = getBase(); if (o.isA(NullType)) Global::current().put(getPropertyName(), v); else { // are we writing into an array ? if (o.isA(ObjectType) && (o.toObject().getClass() == ArrayClass)) o.putArrayElement(getPropertyName(), v); else o.put(getPropertyName(), v); } return NoError;}void KJSO::setPrototype(const KJSO& p){ assert(rep); rep->setPrototype(p);}void KJSO::setPrototypeProperty(const KJSO& p){ assert(rep); put("prototype", p, DontEnum | DontDelete | ReadOnly);}KJSO KJSO::prototype() const{ if (rep) return KJSO(rep->proto); else return KJSO();}// ECMA 8.6.2.1KJSO KJSO::get(const UString &p) const{ assert(rep); return rep->get(p);}// ECMA 8.6.2.2void KJSO::put(const UString &p, const KJSO& v){ assert(rep); rep->put(p, v);}// ECMA 8.6.2.2void KJSO::put(const UString &p, const KJSO& v, int attr){ static_cast<Imp*>(rep)->put(p, v, attr);}// provided for convenience.void KJSO::put(const UString &p, double d, int attr){ put(p, Number(d), attr);}// provided for convenience.void KJSO::put(const UString &p, int i, int attr){ put(p, Number(i), attr);}// provided for convenience.void KJSO::put(const UString &p, unsigned int u, int attr){ put(p, Number(u), attr);}// ECMA 15.4.5.1void KJSO::putArrayElement(const UString &p, const KJSO& v){ assert(rep); rep->putArrayElement(p, v);}// ECMA 8.6.2.3bool KJSO::canPut(const UString &p) const{ assert(rep); return rep->canPut(p);}// ECMA 8.6.2.4bool KJSO::hasProperty(const UString &p, bool recursive) const{ assert(rep); return rep->hasProperty(p, recursive);}// ECMA 8.6.2.5bool KJSO::deleteProperty(const UString &p){ assert(rep); return rep->deleteProperty(p);}Object::Object(Imp *d) : KJSO(d) { }Object::Object(Class c) : KJSO(new ObjectImp(c)) { }Object::Object(Class c, const KJSO& v) : KJSO(new ObjectImp(c, v)) { }Object::Object(Class c, const KJSO& v, const Object& p) : KJSO(new ObjectImp(c, v)){ setPrototype(p);}Object::~Object() { }void Object::setClass(Class c){ static_cast<ObjectImp*>(rep)->cl = c;}Class Object::getClass() const{ assert(rep); return static_cast<ObjectImp*>(rep)->cl;}void Object::setInternalValue(const KJSO& v){ assert(rep); static_cast<ObjectImp*>(rep)->val = v.imp();}KJSO Object::internalValue(){ assert(rep); return KJSO(static_cast<ObjectImp*>(rep)->val);}Object Object::create(Class c){ return Object::create(c, KJSO());}// factoryObject Object::create(Class c, const KJSO& val){ Global global(Global::current()); Object obj = Object(); obj.setClass(c); obj.setInternalValue(val); UString p = "[["; switch (c) { case UndefClass: case ObjectClass: p += "Object"; break; case FunctionClass: p += "Function"; break; case ArrayClass: p += "Array"; obj.put("length", Number(0), DontEnum | DontDelete); break; case StringClass: p += "String"; obj.put("length", val.toString().value().size()); break; case BooleanClass: p += "Boolean"; break; case NumberClass: p += "Number"; break; case DateClass: p += "Date"; break; case RegExpClass: p += "RegExp"; break; case ErrorClass: p += "Error"; break; } p += ".prototype]]"; // KJSO prot = global.get(p).get("prototype"); KJSO prot = global.get(p); assert(prot.isDefined());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -