Commit 55be9897 authored by darin's avatar darin

- a few more globals for often-used property names

	- conversion to Identifier from UString must now be explicit

        * kjs/error_object.cpp:
        * kjs/function.cpp:
        * kjs/function_object.cpp:
        * kjs/identifier.cpp:
        * kjs/identifier.h:
        * kjs/lexer.cpp:
        * kjs/nodes.cpp:
        * kjs/number_object.cpp:
        * kjs/object.cpp:
        * kjs/object.h:
        * kjs/string_object.cpp:
        * kjs/testkjs.cpp:
        * kjs/ustring.cpp:
        * kjs/ustring.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2772 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent dd4cc915
2002-11-19 Darin Adler <darin@apple.com>
- a few more globals for often-used property names
- conversion to Identifier from UString must now be explicit
* kjs/error_object.cpp:
* kjs/function.cpp:
* kjs/function_object.cpp:
* kjs/identifier.cpp:
* kjs/identifier.h:
* kjs/lexer.cpp:
* kjs/nodes.cpp:
* kjs/number_object.cpp:
* kjs/object.cpp:
* kjs/object.h:
* kjs/string_object.cpp:
* kjs/testkjs.cpp:
* kjs/ustring.cpp:
* kjs/ustring.h:
2002-11-19 Darin Adler <darin@apple.com>
- another step towards atomic identifiers; storing hash in the string rep. gives about
......
2002-11-19 Darin Adler <darin@apple.com>
- a few more globals for often-used property names
- conversion to Identifier from UString must now be explicit
* kjs/error_object.cpp:
* kjs/function.cpp:
* kjs/function_object.cpp:
* kjs/identifier.cpp:
* kjs/identifier.h:
* kjs/lexer.cpp:
* kjs/nodes.cpp:
* kjs/number_object.cpp:
* kjs/object.cpp:
* kjs/object.h:
* kjs/string_object.cpp:
* kjs/testkjs.cpp:
* kjs/ustring.cpp:
* kjs/ustring.h:
2002-11-19 Darin Adler <darin@apple.com>
- another step towards atomic identifiers; storing hash in the string rep. gives about
......
2002-11-19 Darin Adler <darin@apple.com>
- a few more globals for often-used property names
- conversion to Identifier from UString must now be explicit
* kjs/error_object.cpp:
* kjs/function.cpp:
* kjs/function_object.cpp:
* kjs/identifier.cpp:
* kjs/identifier.h:
* kjs/lexer.cpp:
* kjs/nodes.cpp:
* kjs/number_object.cpp:
* kjs/object.cpp:
* kjs/object.h:
* kjs/string_object.cpp:
* kjs/testkjs.cpp:
* kjs/ustring.cpp:
* kjs/ustring.h:
2002-11-19 Darin Adler <darin@apple.com>
- another step towards atomic identifiers; storing hash in the string rep. gives about
......
......@@ -41,8 +41,8 @@ ErrorPrototypeImp::ErrorPrototypeImp(ExecState *exec,
setInternalValue(Undefined());
// The constructor will be added later in ErrorObjectImp's constructor
put(exec, "name", String("Error"), DontEnum);
put(exec, "message", String("Unknown error"), DontEnum);
put(exec, namePropertyName, String("Error"), DontEnum);
put(exec, messagePropertyName, String("Unknown error"), DontEnum);
put(exec, toStringPropertyName, Object(new ErrorProtoFuncImp(exec,funcProto)), DontEnum);
}
......@@ -65,12 +65,12 @@ Value ErrorProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &/*ar
// toString()
UString s = "Error";
Value v = thisObj.get(exec,"name");
Value v = thisObj.get(exec, namePropertyName);
if (v.type() != UndefinedType) {
s = v.toString(exec);
}
v = thisObj.get(exec,"message");
v = thisObj.get(exec, messagePropertyName);
if (v.type() != UndefinedType) {
s += ": "+v.toString(exec);
}
......@@ -87,7 +87,7 @@ ErrorObjectImp::ErrorObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto,
Value protect(this);
// ECMA 15.11.3.1 Error.prototype
put(exec, prototypePropertyName, Object(errorProto), DontEnum|DontDelete|ReadOnly);
//put(exec, "name", String(n));
//put(exec, namePropertyName, String(n));
}
bool ErrorObjectImp::implementsConstruct() const
......@@ -102,7 +102,7 @@ Object ErrorObjectImp::construct(ExecState *exec, const List &args)
Object obj(new ObjectImp(proto));
if (!args.isEmpty() && args[0].type() != UndefinedType) {
obj.put(exec,"message", String(args[0].toString(exec)));
obj.put(exec, messagePropertyName, String(args[0].toString(exec)));
}
return obj;
......@@ -128,8 +128,8 @@ NativeErrorPrototypeImp::NativeErrorPrototypeImp(ExecState *exec, ErrorPrototype
{
Value protect(this);
errType = et;
put(exec,"name",String(name));
put(exec,"message",String(message));
put(exec, namePropertyName, String(name));
put(exec, messagePropertyName, String(message));
}
// ------------------------------ NativeErrorImp -------------------------------
......@@ -156,7 +156,7 @@ Object NativeErrorImp::construct(ExecState *exec, const List &args)
{
Object obj(new ObjectImp(Object(proto)));
if (args[0].type() != UndefinedType)
obj.put(exec, "message", String(args[0].toString(exec)));
obj.put(exec, messagePropertyName, String(args[0].toString(exec)));
return obj;
}
......
......@@ -288,7 +288,7 @@ ArgumentsImp::ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args)
: ObjectImp(exec->interpreter()->builtinObjectPrototype())
{
Value protect(this);
put(exec,"callee", Object(func), DontEnum);
put(exec,calleePropertyName, Object(func), DontEnum);
put(exec,lengthPropertyName, Number(args.size()), DontEnum);
if (!args.isEmpty()) {
ListIterator arg = args.begin();
......
......@@ -258,11 +258,11 @@ Object FunctionObjectImp::construct(ExecState *exec, const List &args)
while (i < len && *c == ' ')
c++, i++;
if (i == len) {
fimp->addParameter(param);
fimp->addParameter(Identifier(param));
params++;
break;
} else if (*c == ',') {
fimp->addParameter(param);
fimp->addParameter(Identifier(param));
params++;
c++, i++;
continue;
......@@ -280,7 +280,7 @@ Object FunctionObjectImp::construct(ExecState *exec, const List &args)
Object objCons = exec->interpreter()->builtinObject();
Object prototype = objCons.construct(exec,List::empty());
prototype.put(exec, "constructor",
prototype.put(exec, constructorPropertyName,
Object(fimp), DontEnum|DontDelete|ReadOnly);
fimp->put(exec,prototypePropertyName,prototype,DontEnum|DontDelete|ReadOnly);
fimp->put(exec,argumentsPropertyName,Null(),DontEnum|DontDelete|ReadOnly);
......
......@@ -25,13 +25,73 @@ namespace KJS {
Identifier Identifier::null;
extern const Identifier argumentsPropertyName("arguments");
extern const Identifier calleePropertyName("callee");
extern const Identifier constructorPropertyName("constructor");
extern const Identifier lengthPropertyName("length");
extern const Identifier messagePropertyName("message");
extern const Identifier namePropertyName("name");
extern const Identifier prototypePropertyName("prototype");
extern const Identifier specialPrototypePropertyName("__proto__");
extern const Identifier toLocaleStringPropertyName("toLocaleString");
extern const Identifier toStringPropertyName("toString");
extern const Identifier valueOfPropertyName("valueOf");
bool operator==(const Identifier &a, const char *b)
{
return a._ustring == b;
}
void Identifier::aboutToDestroyUStringRep(UString::Rep *)
UString::Rep *Identifier::add(const char *c)
{
if (!c)
return &UString::Rep::null;
int length = strlen(c);
if (length == 0)
return &UString::Rep::empty;
// Here's where we compute a hash and find it or put it in the hash table.
UChar *d = new UChar[length];
for (int i = 0; i < length; i++)
d[i] = c[i];
UString::Rep *r = new UString::Rep;
r->dat = d;
r->len = length;
r->capacity = length;
r->rc = 0;
r->_hash = 0;
return r;
}
UString::Rep *Identifier::add(const UChar *s, int length)
{
// Here's where we compute a hash and find it or put it in the hash table.
UChar *d = new UChar[length];
for (int i = 0; i < length; i++)
d[i] = s[i];
UString::Rep *r = new UString::Rep;
r->dat = d;
r->len = length;
r->capacity = length;
r->rc = 0;
r->_hash = 0;
return r;
}
UString::Rep *Identifier::add(const UString &s)
{
// Here's where we compute a hash and find it or put it in the hash table.
// Don't forget to check for the case of a string that's already in the table by looking at capacity.
return s.rep;
}
void Identifier::remove(UString::Rep *)
{
// Here's where we find the string already in the hash table, and remove it.
}
} // namespace KJS
......@@ -30,8 +30,9 @@ namespace KJS {
friend class PropertyMap;
public:
Identifier() { }
Identifier(const char *s) : _ustring(s) { }
Identifier(const UString &s) : _ustring(s) { }
Identifier(const char *s) : _ustring(add(s)) { }
Identifier(const UChar *s, int length) : _ustring(add(s, length)) { }
explicit Identifier(const UString &s) : _ustring(add(s)) { }
const UString &ustring() const { return _ustring; }
DOM::DOMString string() const;
......@@ -42,7 +43,7 @@ namespace KJS {
const char *ascii() const { return _ustring.ascii(); }
static Identifier from(unsigned y) { return UString::from(y); }
static Identifier from(unsigned y) { return Identifier(UString::from(y)); }
bool isNull() const { return _ustring.isNull(); }
bool isEmpty() const { return _ustring.isEmpty(); }
......@@ -57,9 +58,13 @@ namespace KJS {
friend bool operator==(const Identifier &, const char *);
static void aboutToDestroyUStringRep(UString::Rep *);
static void remove(UString::Rep *);
private:
static UString::Rep *add(const char *);
static UString::Rep *add(const UChar *, int length);
static UString::Rep *add(const UString &);
UString _ustring;
};
......@@ -73,6 +78,18 @@ namespace KJS {
return a._ustring != b._ustring;
}
extern const Identifier argumentsPropertyName;
extern const Identifier calleePropertyName;
extern const Identifier constructorPropertyName;
extern const Identifier lengthPropertyName;
extern const Identifier messagePropertyName;
extern const Identifier namePropertyName;
extern const Identifier prototypePropertyName;
extern const Identifier specialPrototypePropertyName;
extern const Identifier toLocaleStringPropertyName;
extern const Identifier toStringPropertyName;
extern const Identifier valueOfPropertyName;
}
#endif
......@@ -504,7 +504,7 @@ int Lexer::lex()
break;
}
/* TODO: close leak on parse error. same holds true for String */
kjsyylval.ustr = new UString(buffer16, pos16);
kjsyylval.ident = new KJS::Identifier(buffer16, pos16);
token = IDENT;
break;
}
......
......@@ -446,7 +446,7 @@ Value PropertyValueNode::evaluate(ExecState *exec)
Value v = assign->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
obj.put(exec,n.toString(exec), v);
obj.put(exec, Identifier(n.toString(exec)), v);
return obj;
}
......@@ -504,7 +504,7 @@ Reference AccessorNode1::evaluateReference(ExecState *exec)
if (v2.toUInt32(i))
return Reference(o, i);
String s = v2.toString(exec);
return Reference(o, s.value());
return Reference(o, Identifier(s.value()));
}
......@@ -1217,7 +1217,7 @@ Value RelationalNode::evaluate(ExecState *exec)
return throwError(exec, TypeError,
"Shift expression not an object into IN expression." );
Object o2(static_cast<ObjectImp*>(v2.imp()));
b = o2.hasProperty(exec,v1.toString(exec));
b = o2.hasProperty(exec, Identifier(v1.toString(exec)));
} else {
if (v2.type() != ObjectType)
return throwError(exec, TypeError,
......
......@@ -55,7 +55,7 @@ NumberPrototypeImp::NumberPrototypeImp(ExecState *exec,
// The constructor will be added later, after NumberObjectImp has been constructed
put(exec,toStringPropertyName, Object(new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToString, 1)), DontEnum);
put(exec,"toLocaleString", Object(new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToLocaleString, 0)), DontEnum);
put(exec,toLocaleStringPropertyName, Object(new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ToLocaleString, 0)), DontEnum);
put(exec,valueOfPropertyName, Object(new NumberProtoFuncImp(exec,funcProto,NumberProtoFuncImp::ValueOf, 0)), DontEnum);
}
......
......@@ -40,13 +40,6 @@
namespace KJS {
extern const Identifier argumentsPropertyName("arguments");
extern const Identifier lengthPropertyName("length");
extern const Identifier prototypePropertyName("prototype");
extern const Identifier specialPrototypePropertyName("__proto__");
extern const Identifier toStringPropertyName("toString");
extern const Identifier valueOfPropertyName("valueOf");
// ------------------------------ Object ---------------------------------------
Object Object::dynamicCast(const Value &v)
......
......@@ -703,13 +703,6 @@ namespace KJS {
inline void Object::setInternalValue(const Value &v)
{ imp()->setInternalValue(v); }
extern const Identifier argumentsPropertyName;
extern const Identifier lengthPropertyName;
extern const Identifier prototypePropertyName;
extern const Identifier specialPrototypePropertyName;
extern const Identifier toStringPropertyName;
extern const Identifier valueOfPropertyName;
}; // namespace
#endif // _KJS_OBJECT_H_
......@@ -533,7 +533,7 @@ StringObjectImp::StringObjectImp(ExecState *exec,
// ECMA 15.5.3.1 String.prototype
put(exec,prototypePropertyName, Object(stringProto), DontEnum|DontDelete|ReadOnly);
static UString fromCharCode("fromCharCode");
static Identifier fromCharCode("fromCharCode");
put(exec,fromCharCode, Object(new StringObjectFuncImp(exec,funcProto)), DontEnum);
// no. of arguments for constructor
......
......@@ -62,9 +62,9 @@ int main(int argc, char **argv)
// create interpreter
Interpreter interp(global);
// add debug() function
global.put(interp.globalExec(),"debug", Object(new TestFunctionImp()));
global.put(interp.globalExec(), Identifier("debug"), Object(new TestFunctionImp()));
// add "print" for compatibility with the mozilla js shell
global.put(interp.globalExec(),"print", Object(new TestFunctionImp()));
global.put(interp.globalExec(), Identifier("print"), Object(new TestFunctionImp()));
const int BufferSize = 200000;
char code[BufferSize];
......@@ -92,7 +92,7 @@ int main(int argc, char **argv)
char *msg = exVal.toString(exec).ascii();
int lineno = -1;
if (exVal.type() == ObjectType) {
Value lineVal = Object::dynamicCast(exVal).get(exec,"line");
Value lineVal = Object::dynamicCast(exVal).get(exec,Identifier("line"));
if (lineVal.type() == NumberType)
lineno = int(lineVal.toNumber(exec));
}
......
......@@ -164,32 +164,46 @@ UString::Rep *UString::Rep::create(UChar *d, int l)
r->capacity = l;
r->rc = 1;
r->_hash = 0;
return r;
}
void UString::Rep::destroy()
{
if (capacity == capacityForIdentifier)
Identifier::aboutToDestroyUStringRep(this);
Identifier::remove(this);
delete [] dat;
delete this;
}
void UString::Rep::computeHash() const
unsigned UString::Rep::computeHash(const UChar *s, int length)
{
int length = len;
int prefixLength = length < 8 ? length : 8;
int suffixPosition = length < 16 ? 8 : length - 8;
unsigned h = length;
for (int i = 0; i < prefixLength; i++)
h = 127 * h + dat[i].unicode();
h = 127 * h + s[i].unicode();
for (int i = suffixPosition; i < length; i++)
h = 127 * h + dat[i].unicode();
h = 127 * h + s[i].unicode();
if (h == 0)
h = 0x80000000;
_hash = h;
return h;
}
unsigned UString::Rep::computeHash(const char *s)
{
int length = strlen(s);
int prefixLength = length < 8 ? length : 8;
int suffixPosition = length < 16 ? 8 : length - 8;
unsigned h = length;
for (int i = 0; i < prefixLength; i++)
h = 127 * h + (unsigned char)s[i];
for (int i = suffixPosition; i < length; i++)
h = 127 * h + (unsigned char)s[i];
if (h == 0)
h = 0x80000000;
return h;
}
UString::UString()
......@@ -248,11 +262,6 @@ UString::UString(UChar *c, int length, bool copy)
rep = Rep::create(d, length);
}
UString::UString(const UString &b)
{
attach(b.rep);
}
UString::UString(const UString &a, const UString &b)
{
int aSize = a.size();
......
......@@ -216,8 +216,9 @@ namespace KJS {
UChar *data() const { return dat; }
int size() const { return len; }
int hash() const { if (_hash == 0) computeHash(); return _hash; }
void computeHash() const;
int hash() const { if (_hash == 0) _hash = computeHash(dat, len); return _hash; }
static unsigned computeHash(const UChar *, int length);
static unsigned computeHash(const char *);
void ref() { ++rc; }
void deref() { if (--rc == 0) destroy(); }
......@@ -262,7 +263,7 @@ namespace KJS {
/**
* Copy constructor. Makes a shallow copy only.
*/
UString(const UString &);
UString(const UString &s) { attach(s.rep); }
/**
* Convenience declaration only ! You'll be on your own to write the
* implementation for a construction from QString.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment