Commit 6f821c8d authored by mjs's avatar mjs

Merged changes from LABYRINTH_KDE_3_MERGE branch.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@798 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f54a76f3

Too many changes to show.

To preserve performance only 153 of 153+ files are displayed.

......@@ -4,6 +4,8 @@ noinst_LIBRARIES = libkjs.o
libkjs_o_LDFLAGS = -Wl,-r -nostdlib
libkjs_o_AR = $(OBJCXXLD) $(AM_OBJCXXFLAGS) $(OBJCXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) $(libkjs_o_LDFLAGS) -o
INCLUDES = $(KWQ_INCLUDES)
libkjs_o_SOURCES = \
array_object.cpp \
array_object.h \
......@@ -21,13 +23,12 @@ libkjs_o_SOURCES = \
function.h \
function_object.cpp \
function_object.h \
global_object.cpp \
grammar.cpp \
grammar.h \
internal.cpp \
internal.h \
kjs.cpp \
kjs.h \
interpreter.cpp \
interpreter.h \
lexer.cpp \
lexer.h \
lexer.lut.h \
......@@ -46,6 +47,8 @@ libkjs_o_SOURCES = \
object_object.h \
operations.cpp \
operations.h \
property_map.cpp \
property_map.h \
regexp.cpp \
regexp.h \
regexp_object.cpp \
......@@ -56,6 +59,8 @@ libkjs_o_SOURCES = \
types.h \
ustring.cpp \
ustring.h \
value.cpp \
value.h \
$(NULL)
noinst_PROGRAMS = testkjs
......@@ -75,7 +80,29 @@ grammar-stamp: grammar.y
ln -sf grammar.cpp.h grammar.h
touch ./grammar-stamp
BUILT_SOURCES = $(GRAMMAR_FILES) grammar-stamp
LUT_FILES = math_object.lut.h lexer.lut.h array_object.lut.h date_object.lut.h string_object.lut.h number_object.lut.h
lexer.lut.h: keywords.table
./create_hash_table keywords.table -i > lexer.lut.h;
array_object.lut.h: array_object.cpp
./create_hash_table array_object.cpp -i > array_object.lut.h
math_object.lut.h: math_object.cpp
./create_hash_table math_object.cpp -i > math_object.lut.h
date_object.lut.h: date_object.cpp
./create_hash_table date_object.cpp -i > date_object.lut.h
number_object.lut.h: number_object.cpp
./create_hash_table number_object.cpp -i > number_object.lut.h
string_object.lut.h: string_object.cpp
./create_hash_table string_object.cpp -i > string_object.lut.h
BUILT_SOURCES = $(GRAMMAR_FILES) $(LUT_FILES) grammar-stamp
CLEANFILES = $(BUILT_SOURCES)
<
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
......@@ -15,276 +16,323 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "kjs.h"
#include "operations.h"
#include "value.h"
#include "object.h"
#include "types.h"
#include "interpreter.h"
#include "operations.h"
#include "array_object.h"
#include "internal.h"
#include "error_object.h"
#include "array_object.lut.h"
#include <stdio.h>
#include <assert.h>
using namespace KJS;
ArrayObject::ArrayObject(const Object &funcProto,
const Object &arrayProto)
: ConstructorImp(funcProto, 1)
// ------------------------------ ArrayInstanceImp -----------------------------
const ClassInfo ArrayInstanceImp::info = {"Array", 0, 0, 0};
ArrayInstanceImp::ArrayInstanceImp(const Object &proto)
: ObjectImp(proto)
{
// ECMA 15.4.3.1 Array.prototype
setPrototypeProperty(arrayProto);
}
// ECMA 15.6.1
Completion ArrayObject::execute(const List &args)
// Special implementation of [[Put]] - see ECMA 15.4.5.1
void ArrayInstanceImp::put(ExecState *exec, const UString &propertyName, const Value &value, int attr)
{
// equivalent to 'new Array(....)'
KJSO result = construct(args);
if ((attr == None || attr == DontDelete) && !canPut(exec,propertyName))
return;
return Completion(ReturnValue, result);
}
if (hasProperty(exec,propertyName)) {
if (propertyName == "length") {
Value len = get(exec,"length");
unsigned int oldLen = len.toUInt32(exec);
unsigned int newLen = value.toUInt32(exec);
// shrink array
for (unsigned int u = newLen; u < oldLen; u++) {
UString p = UString::from(u);
if (hasProperty(exec, p, false))
deleteProperty(exec, p);
}
ObjectImp::put(exec, "length", Number(newLen), DontEnum | DontDelete);
return;
}
// put(p, v);
} // } else
ObjectImp::put(exec, propertyName, value, attr);
// ECMA 15.6.2
Object ArrayObject::construct(const List &args)
{
Object result = Object::create(ArrayClass);
// array index ?
unsigned int idx;
if (!sscanf(propertyName.cstring().c_str(), "%u", &idx)) /* TODO */
return;
unsigned int len;
ListIterator it = args.begin();
// a single argument might denote the array size
if (args.size() == 1 && it->isA(NumberType))
len = it->toUInt32();
else {
// initialize array
len = args.size();
for (unsigned int u = 0; it != args.end(); it++, u++)
result.put(UString::from(u), *it);
// do we need to update/create the length property ?
if (hasProperty(exec, "length", false)) {
Value len = get(exec, "length");
if (idx < len.toUInt32(exec))
return;
}
// array size
result.put("length", len, DontEnum | DontDelete);
ObjectImp::put(exec, "length", Number(idx+1), DontDelete | DontEnum);
}
return result;
void ArrayInstanceImp::putDirect(ExecState *exec, const UString &propertyName, const Value &value, int attr)
{
ObjectImp::put(exec,propertyName,value,attr);
}
// ------------------------------ ArrayPrototypeImp ----------------------------
const ClassInfo ArrayPrototypeImp::info = {"Array", &ArrayInstanceImp::info, &arrayTable, 0};
// ECMA 15.6.4
ArrayPrototype::ArrayPrototype(const Object& proto)
: ObjectImp(ArrayClass, Null(), proto)
/* Source for array_object.lut.h
@begin arrayTable 13
toString ArrayProtoFuncImp::ToString DontEnum|Function 0
toLocaleString ArrayProtoFuncImp::ToLocaleString DontEnum|Function 0
concat ArrayProtoFuncImp::Concat DontEnum|Function 1
join ArrayProtoFuncImp::Join DontEnum|Function 1
pop ArrayProtoFuncImp::Pop DontEnum|Function 0
push ArrayProtoFuncImp::Push DontEnum|Function 1
reverse ArrayProtoFuncImp::Reverse DontEnum|Function 0
shift ArrayProtoFuncImp::Shift DontEnum|Function 0
slice ArrayProtoFuncImp::Slice DontEnum|Function 2
sort ArrayProtoFuncImp::Sort DontEnum|Function 1
splice ArrayProtoFuncImp::Splice DontEnum|Function 2
unshift ArrayProtoFuncImp::UnShift DontEnum|Function 1
@end
*/
// ECMA 15.4.4
ArrayPrototypeImp::ArrayPrototypeImp(ExecState *exec,
ObjectPrototypeImp *objProto)
: ArrayInstanceImp(Object(objProto))
{
// The constructor will be added later in ArrayObject's constructor
Value protect(this);
setInternalValue(Null());
put("length", 0u, DontEnum | DontDelete);
// The constructor will be added later, by InterpreterImp, once ArrayObjectImp has been constructed.
put(exec,"length", Number(0), DontEnum | DontDelete);
}
KJSO ArrayPrototype::get(const UString &p) const
Value ArrayPrototypeImp::get(ExecState *exec, const UString &propertyName) const
{
int id;
if(p == "toString")
id = ArrayProtoFunc::ToString;
else if(p == "toLocaleString")
id = ArrayProtoFunc::ToLocaleString;
else if(p == "concat")
id = ArrayProtoFunc::Concat;
else if (p == "join")
id = ArrayProtoFunc::Join;
else if(p == "pop")
id = ArrayProtoFunc::Pop;
else if(p == "push")
id = ArrayProtoFunc::Push;
else if(p == "reverse")
id = ArrayProtoFunc::Reverse;
else if(p == "shift")
id = ArrayProtoFunc::Shift;
else if(p == "slice")
id = ArrayProtoFunc::Slice;
else if(p == "sort")
id = ArrayProtoFunc::Sort;
else if(p == "splice")
id = ArrayProtoFunc::Splice;
else if(p == "unshift")
id = ArrayProtoFunc::UnShift;
else
return Imp::get(p);
//fprintf( stderr, "ArrayPrototypeImp::get(%s)\n", propertyName.ascii() );
return lookupGetFunction<ArrayProtoFuncImp, ArrayInstanceImp>( exec, propertyName, &arrayTable, this );
}
return Function(new ArrayProtoFunc(id));
// ------------------------------ ArrayProtoFuncImp ----------------------------
ArrayProtoFuncImp::ArrayProtoFuncImp(ExecState *exec, int i, int len)
: InternalFunctionImp(
static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
), id(i)
{
Value protect(this);
put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
}
bool ArrayProtoFuncImp::implementsCall() const
{
return true;
}
// ECMA 15.4.4
Completion ArrayProtoFunc::execute(const List &args)
Value ArrayProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
{
KJSO result, obj, obj2;
Object thisObj = Object::dynamicCast(thisValue());
unsigned int length = thisObj.get("length").toUInt32();
unsigned int middle;
UString str = "", str2;
UString separator = ",";
unsigned int length = thisObj.get(exec,"length").toUInt32(exec);
Value result;
switch (id) {
case ToLocaleString:
/* TODO */
// fall trough
// TODO - see 15.4.4.3
// fall through
case ToString:
if (!thisObj.getClass() == ArrayClass) {
result = Error::create(TypeError);
break;
if (!thisObj.inherits(&ArrayInstanceImp::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
// fall trough
case Join:
{
if (!args[0].isA(UndefinedType))
separator = args[0].toString().value();
// fall through
case Join: {
UString separator = ",";
UString str = "";
if (args.size() > 0)
separator = args[0].toString(exec);
for (unsigned int k = 0; k < length; k++) {
if (k >= 1)
str += separator;
obj = thisObj.get(UString::from(k));
if (!obj.isA(UndefinedType) && !obj.isA(NullType))
str += obj.toString().value();
}
Value element = thisObj.get(exec,UString::from(k));
if (element.type() != UndefinedType && element.type() != NullType)
str += element.toString(exec);
}
result = String(str);
break;
}
case Concat: {
result = Object::create(ArrayClass);
Object arr = Object::dynamicCast(exec->interpreter()->builtinArray().construct(exec,List::empty()));
int n = 0;
obj = thisObj;
Value curArg = thisObj;
Object curObj = Object::dynamicCast(thisObj);
ListIterator it = args.begin();
for (;;) {
if (obj.isA(ObjectType) &&
static_cast<Object&>(obj).getClass() == ArrayClass) {
if (curArg.type() == ObjectType &&
curObj.inherits(&ArrayInstanceImp::info)) {
unsigned int k = 0;
if (n > 0)
length = obj.get("length").toUInt32();
length = curObj.get(exec,"length").toUInt32(exec);
while (k < length) {
UString p = UString::from(k);
if (obj.hasProperty(p))
result.put(UString::from(n), obj.get(p));
if (curObj.hasProperty(exec,p))
arr.put(exec,UString::from(n), curObj.get(exec,p));
n++;
k++;
}
} else {
result.put(UString::from(n), obj);
arr.put(exec,UString::from(n), curArg);
n++;
}
if (it == args.end())
break;
obj = it++;
}
result.put("length", Number(n), DontEnum | DontDelete);
curArg = *it;
curObj = Object::dynamicCast(it++); // may be 0
}
arr.put(exec,"length", Number(n), DontEnum | DontDelete);
result = arr;
break;
case Pop:
}
case Pop:{
if (length == 0) {
thisObj.put("length", Number(length), DontEnum | DontDelete);
thisObj.put(exec, "length", Number(length), DontEnum | DontDelete);
result = Undefined();
} else {
str = UString::from(length - 1);
result = thisObj.get(str);
thisObj.deleteProperty(str);
thisObj.put("length", length - 1, DontEnum | DontDelete);
UString str = UString::from(length - 1);
result = thisObj.get(exec,str);
thisObj.deleteProperty(exec, str);
thisObj.put(exec, "length", Number(length - 1), DontEnum | DontDelete);
}
break;
case Push:
{
}
case Push: {
for (int n = 0; n < args.size(); n++)
thisObj.put(UString::from(length + n), args[n]);
thisObj.put(exec,UString::from(length + n), args[n]);
length += args.size();
thisObj.put("length", length, DontEnum | DontDelete);
thisObj.put(exec,"length", Number(length), DontEnum | DontDelete);
result = Number(length);
}
break;
case Reverse:
{
middle = length / 2;
}
case Reverse: {
unsigned int middle = length / 2;
for (unsigned int k = 0; k < middle; k++) {
str = UString::from(k);
str2 = UString::from(length - k - 1);
obj = thisObj.get(str);
obj2 = thisObj.get(str2);
if (thisObj.hasProperty(str2)) {
if (thisObj.hasProperty(str)) {
thisObj.put(str, obj2);
thisObj.put(str2, obj);
UString str = UString::from(k);
UString str2 = UString::from(length - k - 1);
Value obj = thisObj.get(exec,str);
Value obj2 = thisObj.get(exec,str2);
if (thisObj.hasProperty(exec,str2)) {
if (thisObj.hasProperty(exec,str)) {
thisObj.put(exec, str, obj2);
thisObj.put(exec, str2, obj);
} else {
thisObj.put(str, obj2);
thisObj.deleteProperty(str2);
thisObj.put(exec, str, obj2);
thisObj.deleteProperty(exec, str2);
}
} else {
if (thisObj.hasProperty(str)) {
thisObj.deleteProperty(str);
thisObj.put(str2, obj);
if (thisObj.hasProperty(exec, str)) {
thisObj.deleteProperty(exec, str);
thisObj.put(exec, str2, obj);
} else {
// why delete something that's not there ? Strange.
thisObj.deleteProperty(str);
thisObj.deleteProperty(str2);
}
thisObj.deleteProperty(exec, str);
thisObj.deleteProperty(exec, str2);
}
}
}
result = thisObj;
break;
case Shift:
}
case Shift: {
if (length == 0) {
thisObj.put("length", Number(length), DontEnum | DontDelete);
thisObj.put(exec, "length", Number(length), DontEnum | DontDelete);
result = Undefined();
} else {
result = thisObj.get("0");
result = thisObj.get(exec, "0");
for(unsigned int k = 1; k < length; k++) {
str = UString::from(k);
str2 = UString::from(k-1);
if (thisObj.hasProperty(str)) {
obj = thisObj.get(str);
thisObj.put(str2, obj);
UString str = UString::from(k);
UString str2 = UString::from(k-1);
if (thisObj.hasProperty(exec, str)) {
Value obj = thisObj.get(exec, str);
thisObj.put(exec, str2, obj);
} else
thisObj.deleteProperty(str2);
thisObj.deleteProperty(exec, str2);
}
thisObj.deleteProperty(UString::from(length - 1));
thisObj.put("length", length - 1, DontEnum | DontDelete);
thisObj.deleteProperty(exec, UString::from(length - 1));
thisObj.put(exec, "length", Number(length - 1), DontEnum | DontDelete);
}
break;
case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713
{
result = Object::create(ArrayClass); // We return a new array
int begin = args[0].toUInt32();
}
case Slice: {
// http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
// We return a new array
Object resObj = Object::dynamicCast(exec->interpreter()->builtinArray().construct(exec,List::empty()));
result = resObj;
int begin = args[0].toUInt32(exec);
if ( begin < 0 )
begin = maxInt( begin + length, 0 );
else
begin = minInt( begin, length );
int end = length;
if (!args[1].isA(UndefinedType))
if (args[1].type() != UndefinedType)
{
end = args[1].toUInt32();
end = args[1].toUInt32(exec);
if ( end < 0 )
end += length;
}
// safety tests
if ( begin < 0 || end < 0 || begin >= end ) {
result.put("length", Number(0), DontEnum | DontDelete);
break;
end = maxInt( end + length, 0 );
else
end = minInt( end, length );
}
//printf( "Slicing from %d to %d \n", begin, end );
for(unsigned int k = 0; k < (unsigned int) end-begin; k++) {
str = UString::from(k+begin);
str2 = UString::from(k);
if (thisObj.hasProperty(str)) {
obj = thisObj.get(str);
result.put(str2, obj);
UString str = UString::from(k+begin);
if (thisObj.hasProperty(exec,str)) {
UString str2 = UString::from(k);
Value obj = thisObj.get(exec, str);
resObj.put(exec, str2, obj);
}
}
result.put("length", end - begin, DontEnum | DontDelete);
resObj.put(exec, "length", Number(end - begin), DontEnum | DontDelete);
break;
}
case Sort:
{
case Sort:{
#if 0
printf("KJS Array::Sort length=%d\n", length);
for ( unsigned int i = 0 ; i<length ; ++i )
printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(UString::from(i)).toString().value().ascii() );
#endif
Object sortFunction;
bool useSortFunction = !args[0].isA(UndefinedType);
bool useSortFunction = (args[0].type() != UndefinedType);
if (useSortFunction)
{