--- /dev/null
+Makefile.in
+Makefile
+JavaScriptCore-install-stamp
+libJavaScriptCore.dylib
--- /dev/null
+2002-03-26 Maciej Stachowiak <mjs@apple.com>
+
+ Set up kjs to build by itself into libJavaScriptCore.dylib.
+
+ * .cvsignore: Added.
+ * Makefile.am: Added.
+ * dummy.cpp: Added.
+ * kjs/.cvsignore: Added.
--- /dev/null
+2002-03-26 Maciej Stachowiak <mjs@apple.com>
+
+ Set up kjs to build by itself into libJavaScriptCore.dylib.
+
+ * .cvsignore: Added.
+ * Makefile.am: Added.
+ * dummy.cpp: Added.
+ * kjs/.cvsignore: Added.
--- /dev/null
+2002-03-26 Maciej Stachowiak <mjs@apple.com>
+
+ Set up kjs to build by itself into libJavaScriptCore.dylib.
+
+ * .cvsignore: Added.
+ * Makefile.am: Added.
+ * dummy.cpp: Added.
+ * kjs/.cvsignore: Added.
--- /dev/null
+NULL=
+
+SUBDIRS = kjs
+
+symrootsdir = $(SYMROOTS)
+
+symroots_LIBRARIES = libJavaScriptCore.dylib
+
+libJavaScriptCore_dylib_SOURCES = \
+ dummy.cpp \
+ $(NULL)
+
+libJavaScriptCore_dylib_LIBADD = \
+ ./kjs/libkjs.o \
+ $(NULL)
+
+LIBJAVASCRIPTCORE_INSTALL_PATH = @executable_path/../Frameworks
+
+DYLIB_NAME = libJavaScriptCore.dylib
+EMBED_HOST = $(SYMROOTS)/Alexander.app
+EMBED_DIR = $(EMBED_HOST)/Contents/Frameworks
+
+embed:
+ @if test -f "$(DYLIB_NAME)"; then \
+ INSTALL_PATH=`otool -D "$(DYLIB_NAME)"`; \
+ WILL_EMBED=`echo $$INSTALL_PATH | sed -n -e "s/@executable_path//p"`; \
+ if test -n "$$WILL_EMBED"; then \
+ if [ -d "$(EMBED_HOST)" ]; then \
+ if [ ! -d "$(EMBED_DIR)" ]; then \
+ mkdir -p "$(EMBED_DIR)"; \
+ fi; \
+ echo "embedding $(DYLIB_NAME) into $(EMBED_HOST)..."; \
+ cp -f $(DYLIB_NAME) $(EMBED_DIR); \
+ else \
+ echo "$(EMBED_HOST) not found. Not embedding framework"; \
+ fi; \
+ fi; \
+ else \
+ echo "can't find: $(DYLIB_NAME)"; \
+ exit 1; \
+ fi
+
+LDFLAGS = \
+ -dynamiclib \
+ -twolevel_namespace \
+ -prebind \
+ -undefined error \
+ -all_load \
+ -seg1addr 0x6000000 \
+ -install_name $(LIBJAVASCRIPTCORE_INSTALL_PATH)/libJavaScriptCore.dylib \
+ $(NULL)
+
+libJavaScriptCore_dylib_AR = $(OBJCXXLD) $(AM_OBJCXXFLAGS) $(OBJCXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o
+
+noinst_DATA = JavaScriptCore-install-stamp
+
+JavaScriptCore-install-stamp: libJavaScriptCore.dylib
+ $(MAKE) install-symrootsLIBRARIES
+ touch ./JavaScriptCore-install-stamp
+
+2002-03-26 Maciej Stachowiak <mjs@apple.com>
+
+ Removed kjs from here - it's now been moved to JavaScriptCore at
+ the top level.
+
+ * src/Makefile.am: Don't link libkjs.o.
+ * src/kdelibs/Makefile.am: Remove kjs from subdirs.
+ * src/kdelibs/kjs/.cvsignore: Removed.
+ * src/kdelibs/kjs/Makefile.am: Removed.
+ * src/kdelibs/kjs/array_object.cpp: Removed.
+ * src/kdelibs/kjs/array_object.h: Removed.
+ * src/kdelibs/kjs/bool_object.cpp: Removed.
+ * src/kdelibs/kjs/bool_object.h: Removed.
+ * src/kdelibs/kjs/collector.cpp: Removed.
+ * src/kdelibs/kjs/collector.h: Removed.
+ * src/kdelibs/kjs/create_hash_table: Removed.
+ * src/kdelibs/kjs/date_object.cpp: Removed.
+ * src/kdelibs/kjs/date_object.h: Removed.
+ * src/kdelibs/kjs/debugger.cpp: Removed.
+ * src/kdelibs/kjs/debugger.h: Removed.
+ * src/kdelibs/kjs/error_object.cpp: Removed.
+ * src/kdelibs/kjs/error_object.h: Removed.
+ * src/kdelibs/kjs/function.cpp: Removed.
+ * src/kdelibs/kjs/function.h: Removed.
+ * src/kdelibs/kjs/function_object.cpp: Removed.
+ * src/kdelibs/kjs/function_object.h: Removed.
+ * src/kdelibs/kjs/grammar.y: Removed.
+ * src/kdelibs/kjs/internal.cpp: Removed.
+ * src/kdelibs/kjs/internal.h: Removed.
+ * src/kdelibs/kjs/interpreter.cpp: Removed.
+ * src/kdelibs/kjs/interpreter.h: Removed.
+ * src/kdelibs/kjs/keywords.table: Removed.
+ * src/kdelibs/kjs/kjs-test: Removed.
+ * src/kdelibs/kjs/kjs-test.chk: Removed.
+ * src/kdelibs/kjs/lexer.cpp: Removed.
+ * src/kdelibs/kjs/lexer.h: Removed.
+ * src/kdelibs/kjs/lookup.cpp: Removed.
+ * src/kdelibs/kjs/lookup.h: Removed.
+ * src/kdelibs/kjs/math_object.cpp: Removed.
+ * src/kdelibs/kjs/math_object.h: Removed.
+ * src/kdelibs/kjs/nodes.cpp: Removed.
+ * src/kdelibs/kjs/nodes.h: Removed.
+ * src/kdelibs/kjs/nodes2string.cpp: Removed.
+ * src/kdelibs/kjs/number_object.cpp: Removed.
+ * src/kdelibs/kjs/number_object.h: Removed.
+ * src/kdelibs/kjs/object.cpp: Removed.
+ * src/kdelibs/kjs/object.h: Removed.
+ * src/kdelibs/kjs/object_object.cpp: Removed.
+ * src/kdelibs/kjs/object_object.h: Removed.
+ * src/kdelibs/kjs/operations.cpp: Removed.
+ * src/kdelibs/kjs/operations.h: Removed.
+ * src/kdelibs/kjs/property_map.cpp: Removed.
+ * src/kdelibs/kjs/property_map.h: Removed.
+ * src/kdelibs/kjs/regexp.cpp: Removed.
+ * src/kdelibs/kjs/regexp.h: Removed.
+ * src/kdelibs/kjs/regexp_object.cpp: Removed.
+ * src/kdelibs/kjs/regexp_object.h: Removed.
+ * src/kdelibs/kjs/string_object.cpp: Removed.
+ * src/kdelibs/kjs/string_object.h: Removed.
+ * src/kdelibs/kjs/test.js: Removed.
+ * src/kdelibs/kjs/testkjs.cpp: Removed.
+ * src/kdelibs/kjs/types.cpp: Removed.
+ * src/kdelibs/kjs/types.h: Removed.
+ * src/kdelibs/kjs/ustring.cpp: Removed.
+ * src/kdelibs/kjs/ustring.h: Removed.
+ * src/kdelibs/kjs/value.cpp: Removed.
+ * src/kdelibs/kjs/value.h: Removed.
+
2002-03-26 Maciej Stachowiak <mjs@apple.com>
Removed all the borrowed Qt code.
+2002-03-26 Maciej Stachowiak <mjs@apple.com>
+
+ Removed kjs from here - it's now been moved to JavaScriptCore at
+ the top level.
+
+ * src/Makefile.am: Don't link libkjs.o.
+ * src/kdelibs/Makefile.am: Remove kjs from subdirs.
+ * src/kdelibs/kjs/.cvsignore: Removed.
+ * src/kdelibs/kjs/Makefile.am: Removed.
+ * src/kdelibs/kjs/array_object.cpp: Removed.
+ * src/kdelibs/kjs/array_object.h: Removed.
+ * src/kdelibs/kjs/bool_object.cpp: Removed.
+ * src/kdelibs/kjs/bool_object.h: Removed.
+ * src/kdelibs/kjs/collector.cpp: Removed.
+ * src/kdelibs/kjs/collector.h: Removed.
+ * src/kdelibs/kjs/create_hash_table: Removed.
+ * src/kdelibs/kjs/date_object.cpp: Removed.
+ * src/kdelibs/kjs/date_object.h: Removed.
+ * src/kdelibs/kjs/debugger.cpp: Removed.
+ * src/kdelibs/kjs/debugger.h: Removed.
+ * src/kdelibs/kjs/error_object.cpp: Removed.
+ * src/kdelibs/kjs/error_object.h: Removed.
+ * src/kdelibs/kjs/function.cpp: Removed.
+ * src/kdelibs/kjs/function.h: Removed.
+ * src/kdelibs/kjs/function_object.cpp: Removed.
+ * src/kdelibs/kjs/function_object.h: Removed.
+ * src/kdelibs/kjs/grammar.y: Removed.
+ * src/kdelibs/kjs/internal.cpp: Removed.
+ * src/kdelibs/kjs/internal.h: Removed.
+ * src/kdelibs/kjs/interpreter.cpp: Removed.
+ * src/kdelibs/kjs/interpreter.h: Removed.
+ * src/kdelibs/kjs/keywords.table: Removed.
+ * src/kdelibs/kjs/kjs-test: Removed.
+ * src/kdelibs/kjs/kjs-test.chk: Removed.
+ * src/kdelibs/kjs/lexer.cpp: Removed.
+ * src/kdelibs/kjs/lexer.h: Removed.
+ * src/kdelibs/kjs/lookup.cpp: Removed.
+ * src/kdelibs/kjs/lookup.h: Removed.
+ * src/kdelibs/kjs/math_object.cpp: Removed.
+ * src/kdelibs/kjs/math_object.h: Removed.
+ * src/kdelibs/kjs/nodes.cpp: Removed.
+ * src/kdelibs/kjs/nodes.h: Removed.
+ * src/kdelibs/kjs/nodes2string.cpp: Removed.
+ * src/kdelibs/kjs/number_object.cpp: Removed.
+ * src/kdelibs/kjs/number_object.h: Removed.
+ * src/kdelibs/kjs/object.cpp: Removed.
+ * src/kdelibs/kjs/object.h: Removed.
+ * src/kdelibs/kjs/object_object.cpp: Removed.
+ * src/kdelibs/kjs/object_object.h: Removed.
+ * src/kdelibs/kjs/operations.cpp: Removed.
+ * src/kdelibs/kjs/operations.h: Removed.
+ * src/kdelibs/kjs/property_map.cpp: Removed.
+ * src/kdelibs/kjs/property_map.h: Removed.
+ * src/kdelibs/kjs/regexp.cpp: Removed.
+ * src/kdelibs/kjs/regexp.h: Removed.
+ * src/kdelibs/kjs/regexp_object.cpp: Removed.
+ * src/kdelibs/kjs/regexp_object.h: Removed.
+ * src/kdelibs/kjs/string_object.cpp: Removed.
+ * src/kdelibs/kjs/string_object.h: Removed.
+ * src/kdelibs/kjs/test.js: Removed.
+ * src/kdelibs/kjs/testkjs.cpp: Removed.
+ * src/kdelibs/kjs/types.cpp: Removed.
+ * src/kdelibs/kjs/types.h: Removed.
+ * src/kdelibs/kjs/ustring.cpp: Removed.
+ * src/kdelibs/kjs/ustring.h: Removed.
+ * src/kdelibs/kjs/value.cpp: Removed.
+ * src/kdelibs/kjs/value.h: Removed.
+
2002-03-26 Maciej Stachowiak <mjs@apple.com>
Removed all the borrowed Qt code.
+2002-03-26 Maciej Stachowiak <mjs@apple.com>
+
+ Removed kjs from here - it's now been moved to JavaScriptCore at
+ the top level.
+
+ * src/Makefile.am: Don't link libkjs.o.
+ * src/kdelibs/Makefile.am: Remove kjs from subdirs.
+ * src/kdelibs/kjs/.cvsignore: Removed.
+ * src/kdelibs/kjs/Makefile.am: Removed.
+ * src/kdelibs/kjs/array_object.cpp: Removed.
+ * src/kdelibs/kjs/array_object.h: Removed.
+ * src/kdelibs/kjs/bool_object.cpp: Removed.
+ * src/kdelibs/kjs/bool_object.h: Removed.
+ * src/kdelibs/kjs/collector.cpp: Removed.
+ * src/kdelibs/kjs/collector.h: Removed.
+ * src/kdelibs/kjs/create_hash_table: Removed.
+ * src/kdelibs/kjs/date_object.cpp: Removed.
+ * src/kdelibs/kjs/date_object.h: Removed.
+ * src/kdelibs/kjs/debugger.cpp: Removed.
+ * src/kdelibs/kjs/debugger.h: Removed.
+ * src/kdelibs/kjs/error_object.cpp: Removed.
+ * src/kdelibs/kjs/error_object.h: Removed.
+ * src/kdelibs/kjs/function.cpp: Removed.
+ * src/kdelibs/kjs/function.h: Removed.
+ * src/kdelibs/kjs/function_object.cpp: Removed.
+ * src/kdelibs/kjs/function_object.h: Removed.
+ * src/kdelibs/kjs/grammar.y: Removed.
+ * src/kdelibs/kjs/internal.cpp: Removed.
+ * src/kdelibs/kjs/internal.h: Removed.
+ * src/kdelibs/kjs/interpreter.cpp: Removed.
+ * src/kdelibs/kjs/interpreter.h: Removed.
+ * src/kdelibs/kjs/keywords.table: Removed.
+ * src/kdelibs/kjs/kjs-test: Removed.
+ * src/kdelibs/kjs/kjs-test.chk: Removed.
+ * src/kdelibs/kjs/lexer.cpp: Removed.
+ * src/kdelibs/kjs/lexer.h: Removed.
+ * src/kdelibs/kjs/lookup.cpp: Removed.
+ * src/kdelibs/kjs/lookup.h: Removed.
+ * src/kdelibs/kjs/math_object.cpp: Removed.
+ * src/kdelibs/kjs/math_object.h: Removed.
+ * src/kdelibs/kjs/nodes.cpp: Removed.
+ * src/kdelibs/kjs/nodes.h: Removed.
+ * src/kdelibs/kjs/nodes2string.cpp: Removed.
+ * src/kdelibs/kjs/number_object.cpp: Removed.
+ * src/kdelibs/kjs/number_object.h: Removed.
+ * src/kdelibs/kjs/object.cpp: Removed.
+ * src/kdelibs/kjs/object.h: Removed.
+ * src/kdelibs/kjs/object_object.cpp: Removed.
+ * src/kdelibs/kjs/object_object.h: Removed.
+ * src/kdelibs/kjs/operations.cpp: Removed.
+ * src/kdelibs/kjs/operations.h: Removed.
+ * src/kdelibs/kjs/property_map.cpp: Removed.
+ * src/kdelibs/kjs/property_map.h: Removed.
+ * src/kdelibs/kjs/regexp.cpp: Removed.
+ * src/kdelibs/kjs/regexp.h: Removed.
+ * src/kdelibs/kjs/regexp_object.cpp: Removed.
+ * src/kdelibs/kjs/regexp_object.h: Removed.
+ * src/kdelibs/kjs/string_object.cpp: Removed.
+ * src/kdelibs/kjs/string_object.h: Removed.
+ * src/kdelibs/kjs/test.js: Removed.
+ * src/kdelibs/kjs/testkjs.cpp: Removed.
+ * src/kdelibs/kjs/types.cpp: Removed.
+ * src/kdelibs/kjs/types.h: Removed.
+ * src/kdelibs/kjs/ustring.cpp: Removed.
+ * src/kdelibs/kjs/ustring.h: Removed.
+ * src/kdelibs/kjs/value.cpp: Removed.
+ * src/kdelibs/kjs/value.h: Removed.
+
2002-03-26 Maciej Stachowiak <mjs@apple.com>
Removed all the borrowed Qt code.
$(NULL)
libwebcore_dylib_LIBADD = \
- ./kdelibs/kjs/libkjs.o \
./kdelibs/khtml/libkhtml.o \
./kwq/libkwq.o \
-ljpeg \
+ -L$(symrootsdir) -lJavaScriptCore \
$(NULL)
-
LIBWEBCORE_INSTALL_PATH = @executable_path/../Frameworks
DYLIB_NAME = libwebcore.dylib
NULL=
SUBDIRS = \
- kjs \
kdecore \
khtml \
$(NULL)
+++ /dev/null
-NULL =
-
-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 \
- bool_object.cpp \
- bool_object.h \
- collector.cpp \
- collector.h \
- date_object.cpp \
- date_object.h \
- debugger.cpp \
- debugger.h \
- error_object.cpp \
- error_object.h \
- function.cpp \
- function.h \
- function_object.cpp \
- function_object.h \
- grammar.cpp \
- grammar.h \
- internal.cpp \
- internal.h \
- interpreter.cpp \
- interpreter.h \
- lexer.cpp \
- lexer.h \
- lexer.lut.h \
- lookup.cpp \
- lookup.h \
- math_object.cpp \
- math_object.h \
- math_object.lut.h \
- nodes.cpp \
- nodes.h \
- number_object.cpp \
- number_object.h \
- object.cpp \
- object.h \
- object_object.cpp \
- object_object.h \
- operations.cpp \
- operations.h \
- property_map.cpp \
- property_map.h \
- regexp.cpp \
- regexp.h \
- regexp_object.cpp \
- regexp_object.h \
- string_object.cpp \
- string_object.h \
- types.cpp \
- types.h \
- ustring.cpp \
- ustring.h \
- value.cpp \
- value.h \
- $(NULL)
-
-noinst_PROGRAMS = testkjs
-
-testkjs_SOURCES = testkjs.cpp
-
-testkjs_LDADD = $(srcdir)/libkjs.o
-
-YACCFLAGS = -d --output-file=grammar.cpp --file-prefix=grammar --name-prefix=kjsyy
-
-GRAMMAR_FILES = grammar.h grammar.cpp.h grammar.cpp
-
-$(GRAMMAR_FILES): grammar-stamp
-
-grammar-stamp: grammar.y
- $(YACC) $(YACCFLAGS) $<
- ln -sf grammar.cpp.h grammar.h
- touch ./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)
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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 "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;
-
-// ------------------------------ ArrayInstanceImp -----------------------------
-
-const ClassInfo ArrayInstanceImp::info = {"Array", 0, 0, 0};
-
-ArrayInstanceImp::ArrayInstanceImp(const Object &proto)
- : ObjectImp(proto)
-{
-}
-
-// Special implementation of [[Put]] - see ECMA 15.4.5.1
-void ArrayInstanceImp::put(ExecState *exec, const UString &propertyName, const Value &value, int attr)
-{
- if ((attr == None || attr == DontDelete) && !canPut(exec,propertyName))
- return;
-
- 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);
-
- // array index ?
- unsigned int idx;
- if (!sscanf(propertyName.cstring().c_str(), "%u", &idx)) /* TODO */
- return;
-
- // 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;
- }
-
- ObjectImp::put(exec, "length", Number(idx+1), DontDelete | DontEnum);
-}
-
-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};
-
-/* 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))
-{
- Value protect(this);
- setInternalValue(Null());
-
- // The constructor will be added later, by InterpreterImp, once ArrayObjectImp has been constructed.
- put(exec,"length", Number(0), DontEnum | DontDelete);
-}
-
-Value ArrayPrototypeImp::get(ExecState *exec, const UString &propertyName) const
-{
- //fprintf( stderr, "ArrayPrototypeImp::get(%s)\n", propertyName.ascii() );
- return lookupGetFunction<ArrayProtoFuncImp, ArrayInstanceImp>( exec, propertyName, &arrayTable, this );
-}
-
-// ------------------------------ 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
-Value ArrayProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
-{
- unsigned int length = thisObj.get(exec,"length").toUInt32(exec);
-
- Value result;
- switch (id) {
- case ToLocaleString:
- // TODO - see 15.4.4.3
- // fall through
- case ToString:
-
- if (!thisObj.inherits(&ArrayInstanceImp::info)) {
- Object err = Error::create(exec,TypeError);
- exec->setException(err);
- return err;
- }
-
- // 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;
- 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: {
- Object arr = Object::dynamicCast(exec->interpreter()->builtinArray().construct(exec,List::empty()));
- int n = 0;
- Value curArg = thisObj;
- Object curObj = Object::dynamicCast(thisObj);
- ListIterator it = args.begin();
- for (;;) {
- if (curArg.type() == ObjectType &&
- curObj.inherits(&ArrayInstanceImp::info)) {
- unsigned int k = 0;
- if (n > 0)
- length = curObj.get(exec,"length").toUInt32(exec);
- while (k < length) {
- UString p = UString::from(k);
- if (curObj.hasProperty(exec,p))
- arr.put(exec,UString::from(n), curObj.get(exec,p));
- n++;
- k++;
- }
- } else {
- arr.put(exec,UString::from(n), curArg);
- n++;
- }
- if (it == args.end())
- break;
- curArg = *it;
- curObj = Object::dynamicCast(it++); // may be 0
- }
- arr.put(exec,"length", Number(n), DontEnum | DontDelete);
-
- result = arr;
- break;
- }
- case Pop:{
-
- if (length == 0) {
- thisObj.put(exec, "length", Number(length), DontEnum | DontDelete);
- result = Undefined();
- } else {
- 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: {
- for (int n = 0; n < args.size(); n++)
- thisObj.put(exec,UString::from(length + n), args[n]);
- length += args.size();
- thisObj.put(exec,"length", Number(length), DontEnum | DontDelete);
- result = Number(length);
- break;
- }
- case Reverse: {
-
- unsigned int middle = length / 2;
-
- for (unsigned int k = 0; k < middle; k++) {
- 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(exec, str, obj2);
- thisObj.deleteProperty(exec, str2);
- }
- } else {
- 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(exec, str);
- thisObj.deleteProperty(exec, str2);
- }
- }
- }
- result = thisObj;
- break;
- }
- case Shift: {
- if (length == 0) {
- thisObj.put(exec, "length", Number(length), DontEnum | DontDelete);
- result = Undefined();
- } else {
- result = thisObj.get(exec, "0");
- for(unsigned int k = 1; k < length; k++) {
- 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(exec, str2);
- }
- 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 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].type() != UndefinedType)
- {
- end = args[1].toUInt32(exec);
- if ( end < 0 )
- 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++) {
- 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);
- }
- }
- resObj.put(exec, "length", Number(end - begin), DontEnum | DontDelete);
- break;
- }
- 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].type() != UndefinedType);
- if (useSortFunction)
- {
- sortFunction = args[0].toObject(exec);
- if (!sortFunction.implementsCall())
- useSortFunction = false;
- }
-
- if (length == 0) {
- thisObj.put(exec, "length", Number(0), DontEnum | DontDelete);
- result = Undefined();
- break;
- }
-
- // "Min" sort. Not the fastest, but definitely less code than heapsort
- // or quicksort, and much less swapping than bubblesort/insertionsort.
- for ( unsigned int i = 0 ; i<length-1 ; ++i )
- {
- Value iObj = thisObj.get(exec,UString::from(i));
- unsigned int themin = i;
- Value minObj = iObj;
- for ( unsigned int j = i+1 ; j<length ; ++j )
- {
- Value jObj = thisObj.get(exec,UString::from(j));
- int cmp;
- if ( useSortFunction )
- {
- List l;
- l.append(jObj);
- l.append(minObj);
- Object thisObj = exec->interpreter()->globalObject();
- cmp = sortFunction.call(exec,thisObj, l ).toInt32(exec);
- }
- else
- cmp = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;
- if ( cmp < 0 )
- {
- themin = j;
- minObj = jObj;
- }
- }
- // Swap themin and i
- if ( themin > i )
- {
- //printf("KJS Array::Sort: swapping %d and %d\n", i, themin );
- thisObj.put( exec, UString::from(i), minObj );
- thisObj.put( exec, UString::from(themin), iObj );
- }
- }
-#if 0
- printf("KJS Array::Sort -- Resulting array:\n");
- 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
- result = thisObj;
- break;
- }
- case Splice: {
- // 15.4.4.12 - oh boy this is huge
- 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 );
- unsigned int deleteCount = minInt( maxInt( args[1].toUInt32(exec), 0 ), length - begin );
-
- //printf( "Splicing from %d, deleteCount=%d \n", begin, deleteCount );
- for(unsigned int k = 0; k < deleteCount; k++) {
- 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);
- }
- }
- resObj.put(exec, "length", Number(deleteCount), DontEnum | DontDelete);
-
- unsigned int additionalArgs = maxInt( args.size() - 2, 0 );
- if ( additionalArgs != deleteCount )
- {
- if ( additionalArgs < deleteCount )
- {
- for ( unsigned int k = begin; k < length - deleteCount; ++k )
- {
- UString str = UString::from(k+deleteCount);
- UString str2 = UString::from(k+additionalArgs);
- if (thisObj.hasProperty(exec,str)) {
- Value obj = thisObj.get(exec, str);
- thisObj.put(exec, str2, obj);
- }
- else
- thisObj.deleteProperty(exec, str2);
- }
- for ( unsigned int k = length ; k > length - deleteCount + additionalArgs; --k )
- thisObj.deleteProperty(exec, UString::from(k-1));
- }
- else
- {
- for ( unsigned int k = length - deleteCount; (int)k > begin; --k )
- {
- UString str = UString::from(k+deleteCount-1);
- UString str2 = UString::from(k+additionalArgs-1);
- if (thisObj.hasProperty(exec,str)) {
- Value obj = thisObj.get(exec, str);
- thisObj.put(exec, str2, obj);
- }
- else
- thisObj.deleteProperty(exec, str2);
- }
- }
- }
- for ( unsigned int k = 0; k < additionalArgs; ++k )
- {
- thisObj.put(exec, UString::from(k+begin), args[k+2]);
- }
- thisObj.put(exec, "length", Number(length - deleteCount + additionalArgs), DontEnum | DontDelete);
- break;
- }
- case UnShift: { // 15.4.4.13
- unsigned int nrArgs = args.size();
- for ( unsigned int k = length; k > 0; --k )
- {
- UString str = UString::from(k-1);
- UString str2 = UString::from(k+nrArgs-1);
- if (thisObj.hasProperty(exec,str)) {
- Value obj = thisObj.get(exec, str);
- thisObj.put(exec, str2, obj);
- } else {
- thisObj.deleteProperty(exec, str2);
- }
- }
- for ( unsigned int k = 0; k < nrArgs; ++k )
- thisObj.put(exec, UString::from(k), args[k]);
- result = Number(length + nrArgs);
- thisObj.put(exec, "length", result, DontEnum | DontDelete);
- break;
- }
- default:
- assert(0);
- break;
- }
- return result;
-}
-
-// ------------------------------ ArrayObjectImp -------------------------------
-
-ArrayObjectImp::ArrayObjectImp(ExecState *exec,
- FunctionPrototypeImp *funcProto,
- ArrayPrototypeImp *arrayProto)
- : InternalFunctionImp(funcProto)
-{
- Value protect(this);
- // ECMA 15.4.3.1 Array.prototype
- put(exec,"prototype", Object(arrayProto), DontEnum|DontDelete|ReadOnly);
-
- // no. of arguments for constructor
- put(exec,"length", Number(1), ReadOnly|DontDelete|DontEnum);
-}
-
-bool ArrayObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.4.2
-Object ArrayObjectImp::construct(ExecState *exec, const List &args)
-{
- Object result(new ArrayInstanceImp(exec->interpreter()->builtinArrayPrototype()));
-
- unsigned int len;
- ListIterator it = args.begin();
- // a single argument might denote the array size
- if (args.size() == 1 && it->type() == NumberType)
- len = it->toUInt32(exec);
- else {
- // initialize array
- len = args.size();
- for (unsigned int u = 0; it != args.end(); it++, u++)
- result.put(exec, UString::from(u), *it);
- }
-
- // array size
- result.put(exec, "length", Number(len), DontEnum | DontDelete);
- static_cast<ArrayInstanceImp*>(result.imp())->putDirect(exec, "length", Number(len), DontEnum | DontDelete);
-
- return result;
-}
-
-bool ArrayObjectImp::implementsCall() const
-{
- return true;
-}
-
-// ECMA 15.6.1
-Value ArrayObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
-{
- // equivalent to 'new Array(....)'
- return construct(exec,args);
-}
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _ARRAY_OBJECT_H_
-#define _ARRAY_OBJECT_H_
-
-#include "internal.h"
-#include "function_object.h"
-
-namespace KJS {
-
- class ArrayInstanceImp : public ObjectImp {
- public:
- ArrayInstanceImp(const Object &proto);
-
- virtual void put(ExecState *exec, const UString &propertyName, const Value &value, int attr = None);
- virtual void putDirect(ExecState *exec, const UString &propertyName, const Value &value, int attr = None);
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- class ArrayPrototypeImp : public ArrayInstanceImp {
- public:
- ArrayPrototypeImp(ExecState *exec,
- ObjectPrototypeImp *objProto);
- Value get(ExecState *exec, const UString &p) const;
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- class ArrayProtoFuncImp : public InternalFunctionImp {
- public:
- ArrayProtoFuncImp(ExecState *exec, int i, int len);
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- enum { ToString, ToLocaleString, Concat, Join, Pop, Push,
- Reverse, Shift, Slice, Sort, Splice, UnShift };
- private:
- int id;
- };
-
- class ArrayObjectImp : public InternalFunctionImp {
- public:
- ArrayObjectImp(ExecState *exec,
- FunctionPrototypeImp *funcProto,
- ArrayPrototypeImp *arrayProto);
-
- virtual bool implementsConstruct() const;
- virtual Object construct(ExecState *exec, const List &args);
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- };
-
-}; // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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 "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-#include "operations.h"
-#include "bool_object.h"
-#include "error_object.h"
-
-#include <assert.h>
-
-using namespace KJS;
-
-// ------------------------------ BooleanInstanceImp ---------------------------
-
-const ClassInfo BooleanInstanceImp::info = {"Boolean", 0, 0, 0};
-
-BooleanInstanceImp::BooleanInstanceImp(const Object &proto)
- : ObjectImp(proto)
-{
-}
-
-// ------------------------------ BooleanPrototypeImp --------------------------
-
-// ECMA 15.6.4
-
-BooleanPrototypeImp::BooleanPrototypeImp(ExecState *exec,
- ObjectPrototypeImp *objectProto,
- FunctionPrototypeImp *funcProto)
- : BooleanInstanceImp(Object(objectProto))
-{
- Value protect(this);
- // The constructor will be added later by InterpreterImp::InterpreterImp()
-
- put(exec,"toString", Object(new BooleanProtoFuncImp(exec,funcProto,BooleanProtoFuncImp::ToString,0)), DontEnum);
- put(exec,"valueOf", Object(new BooleanProtoFuncImp(exec,funcProto,BooleanProtoFuncImp::ValueOf,0)), DontEnum);
- setInternalValue(Boolean(false));
-}
-
-
-// ------------------------------ BooleanProtoFuncImp --------------------------
-
-BooleanProtoFuncImp::BooleanProtoFuncImp(ExecState *exec,
- FunctionPrototypeImp *funcProto, int i, int len)
- : InternalFunctionImp(funcProto), id(i)
-{
- Value protect(this);
- put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
-}
-
-
-bool BooleanProtoFuncImp::implementsCall() const
-{
- return true;
-}
-
-
-// ECMA 15.6.4.2 + 15.6.4.3
-Value BooleanProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &/*args*/)
-{
- // no generic function. "this" has to be a Boolean object
- if (!thisObj.inherits(&BooleanInstanceImp::info)) {
- Object err = Error::create(exec,TypeError);
- exec->setException(err);
- return err;
- }
-
- // execute "toString()" or "valueOf()", respectively
-
- Value v = thisObj.internalValue();
- assert(!v.isNull());
-
- if (id == ToString)
- return String(v.toString(exec));
- else
- return Boolean(v.toBoolean(exec)); /* TODO: optimize for bool case */
-}
-
-// ------------------------------ BooleanObjectImp -----------------------------
-
-
-BooleanObjectImp::BooleanObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto,
- BooleanPrototypeImp *booleanProto)
- : InternalFunctionImp(funcProto)
-{
- Value protect(this);
- put(exec,"prototype", Object(booleanProto),DontEnum|DontDelete|ReadOnly);
-
- // no. of arguments for constructor
- put(exec,"length", Number(1), ReadOnly|DontDelete|DontEnum);
-}
-
-
-bool BooleanObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.6.2
-Object BooleanObjectImp::construct(ExecState *exec, const List &args)
-{
- Object proto = exec->interpreter()->builtinBooleanPrototype();
- Object obj(new BooleanInstanceImp(proto));
-
- Boolean b;
- if (args.size() > 0)
- b = args.begin()->toBoolean(exec);
- else
- b = Boolean(false);
-
- obj.setInternalValue(b);
-
- return obj;
-}
-
-bool BooleanObjectImp::implementsCall() const
-{
- return true;
-}
-
-// ECMA 15.6.1
-Value BooleanObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
-{
- if (args.isEmpty())
- return Boolean(false);
- else
- return Boolean(args[0].toBoolean(exec)); /* TODO: optimize for bool case */
-}
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _BOOL_OBJECT_H_
-#define _BOOL_OBJECT_H_
-
-#include "internal.h"
-#include "function_object.h"
-
-namespace KJS {
-
- class BooleanInstanceImp : public ObjectImp {
- public:
- BooleanInstanceImp(const Object &proto);
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- /**
- * @internal
- *
- * The initial value of Boolean.prototype (and thus all objects created
- * with the Boolean constructor
- */
- class BooleanPrototypeImp : public BooleanInstanceImp {
- public:
- BooleanPrototypeImp(ExecState *exec,
- ObjectPrototypeImp *objectProto,
- FunctionPrototypeImp *funcProto);
- };
-
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Boolean.prototype object
- */
- class BooleanProtoFuncImp : public InternalFunctionImp {
- public:
- BooleanProtoFuncImp(ExecState *exec,
- FunctionPrototypeImp *funcProto, int i, int len);
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- enum { ToString, ValueOf };
- private:
- int id;
- };
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Boolean" property
- */
- class BooleanObjectImp : public InternalFunctionImp {
- friend class BooleanProtoFuncImp;
- public:
- BooleanObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto,
- BooleanPrototypeImp *booleanProto);
-
- virtual bool implementsConstruct() const;
- virtual Object construct(ExecState *exec, const List &args);
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
- };
-
-}; // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#include "collector.h"
-#include "internal.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#ifdef KJS_DEBUG_MEM
-#include <typeinfo>
-#endif
-
-namespace KJS {
-
- class CollectorBlock {
- public:
- CollectorBlock(int s);
- ~CollectorBlock();
- int size;
- int filled;
- void** mem;
- CollectorBlock *prev, *next;
- };
-
-}; // namespace
-
-using namespace KJS;
-
-CollectorBlock::CollectorBlock(int s)
- : size(s),
- filled(0),
- prev(0L),
- next(0L)
-{
- mem = new void*[size];
- memset(mem, 0, size * sizeof(void*));
-}
-
-CollectorBlock::~CollectorBlock()
-{
- delete [] mem;
- mem = 0L;
-}
-
-CollectorBlock* Collector::root = 0L;
-CollectorBlock* Collector::currentBlock = 0L;
-unsigned long Collector::filled = 0;
-unsigned long Collector::softLimit = KJS_MEM_INCREMENT;
-
-unsigned long Collector::timesFilled = 0;
-unsigned long Collector::increaseLimitAt = 1;
-
-bool Collector::memLimitReached = false;
-
-#ifdef KJS_DEBUG_MEM
-bool Collector::collecting = false;
-#endif
-
-void* Collector::allocate(size_t s)
-{
- if (s == 0)
- return 0L;
-
- // Try and deal with memory requirements in a scalable way. Simple scripts
- // should only require small amounts of memory, but for complex scripts we don't
- // want to end up running the garbage collector hundreds of times a second.
- if (filled >= softLimit) {
- timesFilled++;
- collect();
-
- if (filled >= softLimit && softLimit < KJS_MEM_LIMIT) {
- // Even after collection we are still using more than the limit, so increase
- // the limit
- softLimit *= 2;
- }
- else if (timesFilled == increaseLimitAt && increaseLimitAt < 128) {
- // The allowed memory limit keeps getting reached (lots of objects created
- // and deleted). Increase it a bit so GC gets run less often.
- timesFilled = 0;
- softLimit *= 2;
- increaseLimitAt *= 2;
- }
- }
-
- void *m = malloc(s);
-#ifdef KJS_DEBUG_MEM
- //fprintf( stderr, "allocate: size=%d valueimp=%p\n",s,m);
-#endif
-
- // VI_CREATED and VI_GCALLOWED being unset ensure that value
- // is protected from GC before any constructors are run
- static_cast<ValueImp*>(m)->_flags = 0;
-
- if (!root) {
- root = new CollectorBlock(BlockSize);
- currentBlock = root;
- }
-
- CollectorBlock *block = currentBlock;
- if (!block)
- block = root;
-
- // search for a block with space left
- while (block->next && block->filled == block->size)
- block = block->next;
-
- if (block->filled >= block->size) {
-#ifdef KJS_DEBUG_MEM
- //fprintf( stderr, "allocating new block of size %d\n", block->size);
-#endif
- CollectorBlock *tmp = new CollectorBlock(BlockSize);
- block->next = tmp;
- tmp->prev = block;
- block = tmp;
- }
- currentBlock = block;
- // look for a free spot in the block
- void **r = block->mem;
- while (*r)
- r++;
- *r = m;
- filled++;
- block->filled++;
-
- if (softLimit >= KJS_MEM_LIMIT) {
- memLimitReached = true;
- fprintf(stderr,"Out of memory");
- }
-
- return m;
-}
-
-/**
- * Mark-sweep garbage collection.
- */
-bool Collector::collect()
-{
-#ifdef KJS_DEBUG_MEM
- fprintf(stderr,"Collector::collect()\n");
-#endif
- bool deleted = false;
- // MARK: first unmark everything
- CollectorBlock *block = root;
- while (block) {
- ValueImp **r = (ValueImp**)block->mem;
- assert(r);
- for (int i = 0; i < block->size; i++, r++)
- if (*r) {
- (*r)->_flags &= ~ValueImp::VI_MARKED;
- }
- block = block->next;
- }
-
- // mark all referenced objects recursively
- // starting out from the set of root objects
- if (InterpreterImp::s_hook) {
- InterpreterImp *scr = InterpreterImp::s_hook;
- do {
- //fprintf( stderr, "Collector marking interpreter %p\n",(void*)scr);
- scr->mark();
- scr = scr->next;
- } while (scr != InterpreterImp::s_hook);
- }
-
- // mark any other objects that we wouldn't delete anyway
- block = root;
- while (block) {
- ValueImp **r = (ValueImp**)block->mem;
- assert(r);
- for (int i = 0; i < block->size; i++, r++)
- {
- ValueImp *imp = (*r);
- // Check for created=true, marked=false and (gcallowed=false or refcount>0)
- if (imp &&
- (imp->_flags & (ValueImp::VI_CREATED|ValueImp::VI_MARKED)) == ValueImp::VI_CREATED &&
- ( (imp->_flags & ValueImp::VI_GCALLOWED) == 0 || imp->refcount ) ) {
- //fprintf( stderr, "Collector marking imp=%p\n",(void*)imp);
- imp->mark();
- }
- }
- block = block->next;
- }
-
- // SWEEP: delete everything with a zero refcount (garbage)
- block = root;
- while (block) {
- ValueImp **r = (ValueImp**)block->mem;
- int del = 0;
- for (int i = 0; i < block->size; i++, r++) {
- ValueImp *imp = (*r);
- // Can delete if refcount==0, created==true, gcAllowed==true, and marked==false
- // Make sure to update the test if you add more bits to _flags.
- if (imp &&
- !imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) {
- // emulate destructing part of 'operator delete()'
- //fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name());
- imp->~ValueImp();
- free(imp);
- *r = 0L;
- del++;
- }
- }
- filled -= del;
- block->filled -= del;
- block = block->next;
- if (del)
- deleted = true;
- }
-
- // delete the empty containers
- block = root;
- while (block) {
- CollectorBlock *next = block->next;
- if (block->filled == 0) {
- if (block->prev)
- block->prev->next = next;
- if (block == root)
- root = next;
- if (next)
- next->prev = block->prev;
- if (block == currentBlock) // we don't want a dangling pointer
- currentBlock = 0L;
- assert(block != root);
- delete block;
- }
- block = next;
- }
-#if 0
- // This is useful to track down memory leaks
- static int s_count = 0;
- fprintf(stderr, "Collector done (was run %d)\n",s_count);
- if (s_count++ % 50 == 2)
- finalCheck();
-#endif
- return deleted;
-}
-
-#ifdef KJS_DEBUG_MEM
-void Collector::finalCheck()
-{
- CollectorBlock *block = root;
- while (block) {
- ValueImp **r = (ValueImp**)block->mem;
- for (int i = 0; i < block->size; i++, r++) {
- if (*r ) {
- fprintf( stderr, "Collector::finalCheck() still having ValueImp %p (%s) [marked:%d gcAllowed:%d created:%d refcount:%d]\n",
- (void*)(*r), typeid( **r ).name(),
- (bool)((*r)->_flags & ValueImp::VI_MARKED),
- (bool)((*r)->_flags & ValueImp::VI_GCALLOWED),
- (bool)((*r)->_flags & ValueImp::VI_CREATED),
- (*r)->refcount);
- }
- }
- block = block->next;
- }
-}
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _KJSCOLLECTOR_H_
-#define _KJSCOLLECTOR_H_
-
-// KJS_MEM_LIMIT and KJS_MEM_INCREMENT can be tweaked to adjust how the
-// garbage collector allocates memory. KJS_MEM_LIMIT is the largest # of objects
-// the collector will allow to be present in memory. Once this limit is reached,
-// a running script will get an "out of memory" exception.
-//
-// KJS_MEM_INCREMENT specifies the amount by which the "soft limit" on memory is
-// increased when the memory gets filled up. The soft limit is the amount after
-// which the GC will run and delete unused objects.
-//
-// If you are debugging seemingly random crashes where an object has been deleted,
-// try setting KJS_MEM_INCREMENT to something small, e.g. 300, to force garbage
-// collection to happen more often, and disable the softLimit increase &
-// out-of-memory testing code in Collector::allocate()
-
-#define KJS_MEM_LIMIT 500000
-#define KJS_MEM_INCREMENT 1000
-
-#include <stdlib.h>
-
-// for DEBUG_*
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-
-namespace KJS {
-
- class CollectorBlock;
-
- /**
- * @short Garbage collector.
- */
- class Collector {
- // disallow direct construction/destruction
- Collector();
- public:
- /**
- * Register an object with the collector. The following assumptions are
- * made:
- * @li the operator new() of the object class is overloaded.
- * @li operator delete() has been overloaded as well and does not free
- * the memory on its own.
- *
- * @param s Size of the memory to be registered.
- * @return A pointer to the allocated memory.
- */
- static void* allocate(size_t s);
- /**
- * Run the garbage collection. This involves calling the delete operator
- * on each object and freeing the used memory.
- */
- static bool collect();
- static int size() { return filled; }
- static bool outOfMemory() { return memLimitReached; }
-
-#ifdef KJS_DEBUG_MEM
- /** Check that nothing is left when the last interpreter gets deleted */
- static void finalCheck();
- /**
- * @internal
- */
- static bool collecting;
-#endif
- private:
- static CollectorBlock* root;
- static CollectorBlock* currentBlock;
- static unsigned long filled;
- static unsigned long softLimit;
- static unsigned long timesFilled;
- static unsigned long increaseLimitAt;
- static bool memLimitReached;
- enum { BlockSize = 100 };
- };
-
-};
-
-#endif
+++ /dev/null
-#! /usr/bin/perl -w
-#
-# Static Hashtable Generator
-#
-# (c) 2000-2002 by Harri Porten <porten@kde.org> and
-# David Faure <faure@kde.org>
-
-$file = $ARGV[0];
-shift;
-my $findSize = 0;
-my $includelookup = 0;
-# Use -s as second argument to make it try many hash sizes
-$findSize = 1 if (defined($ARGV[0]) && $ARGV[0] eq "-s");
-# Use -i as second argument to make it include "lookup.h"
-$includelookup = 1 if (defined($ARGV[0]) && $ARGV[0] eq "-i");
-print STDERR "Creating hashtable for $file\n";
-open(IN, $file) or die "No such file $file";
-
-@keys = ();
-@values = ();
-@attrs = ();
-@params = ();
-
-my $inside = 0;
-my $name;
-my $size;
-my $hashsize;
-my $banner = 0;
-sub calcTable();
-sub output();
-sub hashValue($);
-
-while (<IN>) {
- chop;
- s/^\s*//g;
- if (/^\#|^$/) {
- # comment. do nothing
- } elsif (/^\@begin\s*(\w+)\s*(\d+)\s*$/ && !$inside) {
- $inside = 1;
- $name = $1;
- $hashsize = $2;
- } elsif (/^\@end\s*$/ && $inside) {
-
- if($findSize) {
- my $entriesnum=@keys;
- print STDERR "Table: $name $entriesnum entries\n";
- for( $i=3 ; $i<79 ; ++$i) { $hashsize=$i ; calcTable(); }
- } else {
- calcTable();
- }
-
- output();
- @keys = ();
- @values = ();
- @attrs = ();
- @params = ();
- $inside = 0;
- } elsif (/^([\w\[\=\]]+)\s*([\w\:-]+)\s*([\w\|]*)\s*(\w*)\s*$/ && $inside) {
- my $key = $1;
- my $val = $2;
- my $att = $3;
- my $param = $4;
- push(@keys, $key);
- push(@values, $val);
- printf STDERR "WARNING: Number of arguments missing for $key/$val\n"
- if ( $att =~ m/Function/ && length($param) == 0);
- push(@attrs, length($att) > 0 ? $att : "0");
- push(@params, length($param) > 0 ? $param : "0");
- } elsif ($inside) {
- die "invalid data";
- }
-}
-
-die "missing closing \@end" if ($inside);
-
-sub calcTable() {
- @table = ();
- @links = ();
- $size = $hashsize;
- my $collisions = 0;
- my $maxdepth = 0;
- my $i = 0;
- foreach $key (@keys) {
- my $depth = 0;
- my $h = hashValue($key) % $hashsize;
- while (defined($table[$h])) {
- if (defined($links[$h])) {
- $h = $links[$h];
- $depth++;
- } else {
- $collisions++;
- $links[$h] = $size;
- $h = $size;
- $size++;
- }
- }
- $table[$h] = $i;
- $i++;
- $maxdepth = $depth if ( $depth > $maxdepth);
- }
-
- if ($findSize) {
- my $emptycount = 0;
- foreach $entry (@table) {
- $emptycount++ if (!defined($entry));
- }
- print STDERR "Hashsize: $hashsize Total Size: $size Empty: $emptycount MaxDepth: $maxdepth Collisions: $collisions\n";
- }
-# my $i = 0;
-# foreach $entry (@table) {
-# print "$i " . $entry;
-# print " -> " . $links[$i] if (defined($links[$i]));
-# print "\n";
-# $i++;
-# }
-}
-
-sub hashValue($) {
- @chars = split(/ */, $_[0]);
- my $val = 0;
- foreach $c (@chars) {
- $val += ord($c);
- }
- return $val;
-}
-
-sub output() {
- if (!$banner) {
- $banner = 1;
- print "/* Automatically generated from $file using $0. DO NOT EDIT ! */\n";
- }
-
- print "\n#include \"lookup.h\"\n" if ($includelookup);
- print "\nnamespace KJS {\n";
- print "\nconst struct HashEntry ${name}Entries[] = {\n";
- my $i = 0;
- foreach $entry (@table) {
- if (defined($entry)) {
- my $key = $keys[$entry];
- print " \{ \"" . $key . "\"";
- print ", " . $values[$entry];
- print ", " . $attrs[$entry];
- print ", " . $params[$entry];
- print ", ";
- if (defined($links[$i])) {
- print "&${name}Entries[$links[$i]]" . " \}";
- } else {
- print "0 \}"
- }
- } else {
- print " \{ 0, 0, 0, 0, 0 \}";
- }
- print "," unless ($i == $size - 1);
- print "\n";
- $i++;
- }
- print "};\n";
- print "\nconst struct HashTable $name = ";
- print "\{ 2, $size, ${name}Entries, $hashsize \};\n\n";
- print "}; // namespace\n";
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#ifndef HAVE_SYS_TIMEB_H
-#define HAVE_SYS_TIMEB_H 0
-#endif
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-# include <time.h>
-# endif
-#endif
-#if HAVE_SYS_TIMEB_H
-#include <sys/timeb.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif // HAVE_SYS_PARAM_H
-
-#include <math.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <locale.h>
-#include <ctype.h>
-
-#include "date_object.h"
-#include "error_object.h"
-#include "operations.h"
-
-#include "date_object.lut.h"
-
-using namespace KJS;
-
-// ------------------------------ DateInstanceImp ------------------------------
-
-const ClassInfo DateInstanceImp::info = {"Date", 0, 0, 0};
-
-DateInstanceImp::DateInstanceImp(const Object &proto)
- : ObjectImp(proto)
-{
-}
-
-// ------------------------------ DatePrototypeImp -----------------------------
-
-const ClassInfo DatePrototypeImp::info = {"Date", 0, &dateTable, 0};
-
-/* Source for date_object.lut.h
- We use a negative ID to denote the "UTC" variant.
-@begin dateTable 61
- toString DateProtoFuncImp::ToString DontEnum|Function 0
- toUTCString -DateProtoFuncImp::ToString DontEnum|Function 0
- toDateString DateProtoFuncImp::ToDateString DontEnum|Function 0
- toTimeString DateProtoFuncImp::ToTimeString DontEnum|Function 0
- toLocaleString DateProtoFuncImp::ToLocaleString DontEnum|Function 0
- toLocaleDateString DateProtoFuncImp::ToLocaleDateString DontEnum|Function 0
- toLocaleTimeString DateProtoFuncImp::ToLocaleTimeString DontEnum|Function 0
- valueOf DateProtoFuncImp::ValueOf DontEnum|Function 0
- getTime DateProtoFuncImp::GetTime DontEnum|Function 0
- getFullYear DateProtoFuncImp::GetFullYear DontEnum|Function 0
- getUTCFullYear -DateProtoFuncImp::GetFullYear DontEnum|Function 0
- toGMTString DateProtoFuncImp::ToGMTString DontEnum|Function 0
- getMonth DateProtoFuncImp::GetMonth DontEnum|Function 0
- getUTCMonth -DateProtoFuncImp::GetMonth DontEnum|Function 0
- getDate DateProtoFuncImp::GetDate DontEnum|Function 0
- getUTCDate -DateProtoFuncImp::GetDate DontEnum|Function 0
- getDay DateProtoFuncImp::GetDay DontEnum|Function 0
- getUTCDay -DateProtoFuncImp::GetDay DontEnum|Function 0
- getHours DateProtoFuncImp::GetHours DontEnum|Function 0
- getUTCHours -DateProtoFuncImp::GetHours DontEnum|Function 0
- getMinutes DateProtoFuncImp::GetMinutes DontEnum|Function 0
- getUTCMinutes -DateProtoFuncImp::GetMinutes DontEnum|Function 0
- getSeconds DateProtoFuncImp::GetSeconds DontEnum|Function 0
- getUTCSeconds -DateProtoFuncImp::GetSeconds DontEnum|Function 0
- getMilliseconds DateProtoFuncImp::GetMilliSeconds DontEnum|Function 0
- getUTCMilliseconds -DateProtoFuncImp::GetMilliSeconds DontEnum|Function 0
- getTimezoneOffset DateProtoFuncImp::GetTimezoneOffset DontEnum|Function 0
- setTime DateProtoFuncImp::SetTime DontEnum|Function 1
- setMilliseconds DateProtoFuncImp::SetMilliSeconds DontEnum|Function 1
- setUTCMilliseconds -DateProtoFuncImp::SetMilliSeconds DontEnum|Function 1
- setSeconds DateProtoFuncImp::SetSeconds DontEnum|Function 2
- setUTCSeconds -DateProtoFuncImp::SetSeconds DontEnum|Function 2
- setMinutes DateProtoFuncImp::SetMinutes DontEnum|Function 3
- setUTCMinutes -DateProtoFuncImp::SetMinutes DontEnum|Function 3
- setHours DateProtoFuncImp::SetHours DontEnum|Function 4
- setUTCHours -DateProtoFuncImp::SetHours DontEnum|Function 4
- setDate DateProtoFuncImp::SetDate DontEnum|Function 1
- setUTCDate -DateProtoFuncImp::SetDate DontEnum|Function 1
- setMonth DateProtoFuncImp::SetMonth DontEnum|Function 2
- setUTCMonth -DateProtoFuncImp::SetMonth DontEnum|Function 2
- setFullYear DateProtoFuncImp::SetFullYear DontEnum|Function 3
- setUTCFullYear -DateProtoFuncImp::SetFullYear DontEnum|Function 3
- setYear DateProtoFuncImp::SetYear DontEnum|Function 1
- getYear DateProtoFuncImp::GetYear DontEnum|Function 0
- toGMTString DateProtoFuncImp::ToGMTString DontEnum|Function 0
-@end
-*/
-// ECMA 15.9.4
-
-DatePrototypeImp::DatePrototypeImp(ExecState *,
- ObjectPrototypeImp *objectProto)
- : DateInstanceImp(Object(objectProto))
-{
- Value protect(this);
- setInternalValue(Number(NaN));
- // The constructor will be added later, after DateObjectImp has been built
-}
-
-Value DatePrototypeImp::get(ExecState *exec, const UString &propertyName) const
-{
- return lookupGetFunction<DateProtoFuncImp, ObjectImp>( exec, propertyName, &dateTable, this );
-}
-
-// ------------------------------ DateProtoFuncImp -----------------------------
-
-DateProtoFuncImp::DateProtoFuncImp(ExecState *exec, int i, int len)
- : InternalFunctionImp(
- static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
- ), id(abs(i)), utc(i<0)
- // We use a negative ID to denote the "UTC" variant.
-{
- Value protect(this);
- put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
-}
-
-bool DateProtoFuncImp::implementsCall() const
-{
- return true;
-}
-
-Value DateProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
-{
- if ((id == ToString || id == ValueOf || id == GetTime || id == SetTime) &&
- !thisObj.inherits(&DateInstanceImp::info)) {
- // non-generic function called on non-date object
-
- // ToString and ValueOf are generic according to the spec, but the mozilla
- // tests suggest otherwise...
- Object err = Error::create(exec,TypeError);
- exec->setException(err);
- return err;
- }
-
-
- Value result;
- UString s;
- const int bufsize=100;
- char timebuffer[bufsize];
- char *oldlocale = setlocale(LC_TIME,NULL);
- if (!oldlocale)
- oldlocale = setlocale(LC_ALL, NULL);
- Value v = thisObj.internalValue();
- double milli = v.toNumber(exec);
- time_t tv = (time_t) floor(milli / 1000.0);
- int ms = int(milli - tv * 1000.0);
-
- struct tm *t;
- if (utc)
- t = gmtime(&tv);
- else
- t = localtime(&tv);
-
- switch (id) {
- case ToString:
- s = ctime(&tv);
- result = String(s.substr(0, s.size() - 1));
- break;
- case ToDateString:
- case ToTimeString:
- case ToGMTString:
- setlocale(LC_TIME,"C");
- if (id == DateProtoFuncImp::ToDateString) {
- strftime(timebuffer, bufsize, "%x",t);
- } else if (id == DateProtoFuncImp::ToTimeString) {
- strftime(timebuffer, bufsize, "%X",t);
- } else {
- t = gmtime(&tv);
- strftime(timebuffer, bufsize, "%a, %d-%b-%y %H:%M:%S %Z", t);
- }
- setlocale(LC_TIME,oldlocale);
- result = String(timebuffer);
- break;
- case ToLocaleString:
- strftime(timebuffer, bufsize, "%c", t);
- result = String(timebuffer);
- break;
- case ToLocaleDateString:
- strftime(timebuffer, bufsize, "%x", t);
- result = String(timebuffer);
- break;
- case ToLocaleTimeString:
- strftime(timebuffer, bufsize, "%X", t);
- result = String(timebuffer);
- break;
- case ValueOf:
- result = Number(milli);
- break;
- case GetTime:
- result = Number(milli);
- break;
- case GetYear:
- // IE returns the full year even in getYear.
- if ( exec->interpreter()->compatMode() == Interpreter::IECompat )
- result = Number(1900 + t->tm_year);
- else
- result = Number(t->tm_year);
- break;
- case GetFullYear:
- result = Number(1900 + t->tm_year);
- break;
- case GetMonth:
- result = Number(t->tm_mon);
- break;
- case GetDate:
- result = Number(t->tm_mday);
- break;
- case GetDay:
- result = Number(t->tm_wday);
- break;
- case GetHours:
- result = Number(t->tm_hour);
- break;
- case GetMinutes:
- result = Number(t->tm_min);
- break;
- case GetSeconds:
- result = Number(t->tm_sec);
- break;
- case GetMilliSeconds:
- result = Number(ms);
- break;
- case GetTimezoneOffset:
-#if defined BSD || defined(__APPLE__)
- result = Number(-( t->tm_gmtoff / 60 ) + ( t->tm_isdst ? 60 : 0 ));
-#else
-# if defined(__BORLANDC__)
-#error please add daylight savings offset here!
- result = Number(_timezone / 60 - (_daylight ? 60 : 0));
-# else
- result = Number(( timezone / 60 - ( daylight ? 60 : 0 )));
-# endif
-#endif
- break;
- case SetTime:
- milli = roundValue(exec,args[0]);
- result = Number(milli);
- thisObj.setInternalValue(result);
- break;
- case SetMilliSeconds:
- ms = args[0].toInt32(exec);
- break;
- case SetSeconds:
- t->tm_sec = args[0].toInt32(exec);
- break;
- case SetMinutes:
- t->tm_min = args[0].toInt32(exec);
- break;
- case SetHours:
- t->tm_hour = args[0].toInt32(exec);
- break;
- case SetDate:
- t->tm_mday = args[0].toInt32(exec);
- break;
- case SetMonth:
- t->tm_mon = args[0].toInt32(exec);
- break;
- case SetFullYear:
- t->tm_year = args[0].toInt32(exec) - 1900;
- break;
- case SetYear:
- t->tm_year = args[0].toInt32(exec) >= 1900 ? args[0].toInt32(exec) - 1900 : args[0].toInt32(exec);
- break;
- }
-
- if (id == SetYear || id == SetMilliSeconds || id == SetSeconds ||
- id == SetMinutes || id == SetHours || id == SetDate ||
- id == SetMonth || id == SetFullYear ) {
- result = Number(mktime(t) * 1000.0 + ms);
- thisObj.setInternalValue(result);
- }
-
- return result;
-}
-
-// ------------------------------ DateObjectImp --------------------------------
-
-// TODO: MakeTime (15.9.11.1) etc. ?
-
-DateObjectImp::DateObjectImp(ExecState *exec,
- FunctionPrototypeImp *funcProto,
- DatePrototypeImp *dateProto)
- : InternalFunctionImp(funcProto)
-{
- Value protect(this);
- // ECMA 15.9.4.1 Date.prototype
- put(exec,"prototype", Object(dateProto), DontEnum|DontDelete|ReadOnly);
-
- put(exec,"parse", Object(new DateObjectFuncImp(exec,funcProto,DateObjectFuncImp::Parse, 1)), DontEnum);
- put(exec,"UTC", Object(new DateObjectFuncImp(exec,funcProto,DateObjectFuncImp::UTC, 7)), DontEnum);
-
- // no. of arguments for constructor
- put(exec,"length", Number(7), ReadOnly|DontDelete|DontEnum);
-}
-
-bool DateObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.9.3
-Object DateObjectImp::construct(ExecState *exec, const List &args)
-{
- int numArgs = args.size();
-
-#ifdef KJS_VERBOSE
- fprintf(stderr,"DateObjectImp::construct - %d args\n", numArgs);
-#endif
- Value value;
-
- if (numArgs == 0) { // new Date() ECMA 15.9.3.3
-#if HAVE_SYS_TIMEB_H
-# if defined(__BORLANDC__)
- struct timeb timebuffer;
- ftime(&timebuffer);
-# else
- struct _timeb timebuffer;
- _ftime(&timebuffer);
-# endif
- double utc = floor((double)timebuffer.time * 1000.0 + (double)timebuffer.millitm);
-#else
- struct timeval tv;
- gettimeofday(&tv, 0L);
- double utc = floor((double)tv.tv_sec * 1000.0 + (double)tv.tv_usec / 1000.0);
-#endif
- value = Number(utc);
- } else if (numArgs == 1) {
- UString s = args[0].toString(exec);
- double d = s.toDouble();
- if (isNaN(d))
- value = parseDate(s);
- else
- value = Number(d);
- } else {
- struct tm t;
- memset(&t, 0, sizeof(t));
- Number y = args[0].toNumber(exec);
- // TODO: check for NaN
- int year = y.toInt32(exec);
- t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
- t.tm_mon = args[1].toInt32(exec);
- t.tm_mday = (numArgs >= 3) ? args[2].toInt32(exec) : 1;
- t.tm_hour = (numArgs >= 4) ? args[3].toInt32(exec) : 0;
- t.tm_min = (numArgs >= 5) ? args[4].toInt32(exec) : 0;
- t.tm_sec = (numArgs >= 6) ? args[5].toInt32(exec) : 0;
- t.tm_isdst = -1;
- int ms = (numArgs >= 7) ? args[6].toInt32(exec) : 0;
- value = Number(mktime(&t) * 1000.0 + ms);
- }
-
- Object proto = exec->interpreter()->builtinDatePrototype();
- Object ret(new DateInstanceImp(proto));
- ret.setInternalValue(timeClip(value));
- return ret;
-}
-
-bool DateObjectImp::implementsCall() const
-{
- return true;
-}
-
-// ECMA 15.9.2
-Value DateObjectImp::call(ExecState */*exec*/, Object &/*thisObj*/, const List &/*args*/)
-{
-#ifdef KJS_VERBOSE
- fprintf(stderr,"DateObjectImp::call - current time\n");
-#endif
- time_t t = time(0L);
- UString s(ctime(&t));
-
- // return formatted string minus trailing \n
- return String(s.substr(0, s.size() - 1));
-}
-
-// ------------------------------ DateObjectFuncImp ----------------------------
-
-DateObjectFuncImp::DateObjectFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto,
- int i, int len)
- : InternalFunctionImp(funcProto), id(i)
-{
- Value protect(this);
- put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
-}
-
-bool DateObjectFuncImp::implementsCall() const
-{
- return true;
-}
-
-// ECMA 15.9.4.2 - 3
-Value DateObjectFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
-{
- if (id == Parse) {
- if (args[0].type() == StringType)
- return parseDate(args[0].toString(exec));
- else
- return Undefined();
- }
- else { // UTC
- struct tm t;
- memset(&t, 0, sizeof(t));
- int n = args.size();
- Number y = args[0].toNumber(exec);
- // TODO: check for NaN
- int year = y.toInt32(exec);
- t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
- t.tm_mon = args[1].toInt32(exec);
- t.tm_mday = (n >= 3) ? args[2].toInt32(exec) : 1;
- t.tm_hour = (n >= 4) ? args[3].toInt32(exec) : 0;
- t.tm_min = (n >= 5) ? args[4].toInt32(exec) : 0;
- t.tm_sec = (n >= 6) ? args[5].toInt32(exec) : 0;
- int ms = (n >= 7) ? args[6].toInt32(exec) : 0;
- return Number(mktime(&t) * 1000.0 + ms);
- }
-}
-
-// -----------------------------------------------------------------------------
-
-
-Value KJS::parseDate(const String &s)
-{
- UString u = s.value();
-#ifdef KJS_VERBOSE
- fprintf(stderr,"KJS::parseDate %s\n",u.ascii());
-#endif
- int firstSlash = u.find('/');
- if ( firstSlash == -1 )
- {
- time_t seconds = KRFCDate_parseDate( u );
-#ifdef KJS_VERBOSE
- fprintf(stderr,"KRFCDate_parseDate returned seconds=%d\n",seconds);
-#endif
- if ( seconds == -1 )
- return Undefined();
- else
- return Number(seconds * 1000.0);
- }
- else
- {
- // Found 12/31/2099 on some website -> obviously MM/DD/YYYY
- int month = u.substr(0,firstSlash).toULong();
- int secondSlash = u.find('/',firstSlash+1);
- //fprintf(stdout,"KJS::parseDate firstSlash=%d, secondSlash=%d\n", firstSlash, secondSlash);
- if ( secondSlash == -1 )
- {
- fprintf(stderr,"KJS::parseDate parsing for this format isn't implemented\n%s", u.ascii());
- return Number(0);
- }
- int day = u.substr(firstSlash+1,secondSlash-firstSlash-1).toULong();
- int year = u.substr(secondSlash+1).toULong();
- //fprintf(stdout,"KJS::parseDate day=%d, month=%d, year=%d\n", day, month, year);
- struct tm t;
- memset( &t, 0, sizeof(t) );
- year = (year > 2037) ? 2037 : year; // mktime is limited to 2037 !!!
- t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
- t.tm_mon = month-1; // mktime wants 0-11 for some reason
- t.tm_mday = day;
- time_t seconds = mktime(&t);
- if ( seconds == -1 )
- {
- fprintf(stderr,"KJS::parseDate mktime returned -1.\n%s", u.ascii());
- return Undefined();
- }
- else
- return Number(seconds * 1000.0);
- }
-}
-
-///// Awful duplication from krfcdate.cpp - we don't link to kdecore
-
-static unsigned int ymdhms_to_seconds(int year, int mon, int day, int hour, int minute, int second)
-{
- unsigned int ret = (day - 32075) /* days */
- + 1461L * (year + 4800L + (mon - 14) / 12) / 4
- + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
- - 3 * ((year + 4900L + (mon - 14) / 12) / 100) / 4
- - 2440588;
- ret = 24*ret + hour; /* hours */
- ret = 60*ret + minute; /* minutes */
- ret = 60*ret + second; /* seconds */
-
- return ret;
-}
-
-static const char haystack[37]="janfebmaraprmayjunjulaugsepoctnovdec";
-
-// we follow the recommendation of rfc2822 to consider all
-// obsolete time zones not listed here equivalent to "-0000"
-static const struct {
- const char *tzName;
- int tzOffset;
-} known_zones[] = {
- { "UT", 0 },
- { "GMT", 0 },
- { "EST", -300 },
- { "EDT", -240 },
- { "CST", -360 },
- { "CDT", -300 },
- { "MST", -420 },
- { "MDT", -360 },
- { "PST", -480 },
- { "PDT", -420 },
- { 0, 0 }
-};
-
-time_t KJS::KRFCDate_parseDate(const UString &_date)
-{
- // This parse a date in the form:
- // Wednesday, 09-Nov-99 23:12:40 GMT
- // or
- // Sat, 01-Jan-2000 08:00:00 GMT
- // or
- // Sat, 01 Jan 2000 08:00:00 GMT
- // or
- // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822)
- // ### non RFC format, added for Javascript:
- // [Wednesday] January 09 1999 23:12:40 GMT
- //
- // We ignore the weekday
- //
- time_t result = 0;
- int offset = 0;
- char *newPosStr;
- const char *dateString = _date.ascii();
- int day = 0;
- char monthStr[4];
- int month = -1; // not set yet
- int year = 0;
- int hour = 0;
- int minute = 0;
- int second = 0;
-
- // Skip leading space
- while(*dateString && isspace(*dateString))
- dateString++;
-
- const char *wordStart = dateString;
- // Check contents of first words if not number
- while(*dateString && !isdigit(*dateString))
- {
- if ( isspace(*dateString) && dateString - wordStart >= 3 )
- {
- monthStr[0] = tolower(*wordStart++);
- monthStr[1] = tolower(*wordStart++);
- monthStr[2] = tolower(*wordStart++);
- monthStr[3] = '\0';
- //fprintf(stderr,"KJS::parseDate found word starting with '%s'\n", monthStr);
- const char *str = strstr(haystack, monthStr);
- if (str)
- month = (str-haystack)/3; // Jan=00, Feb=01, Mar=02, ..
- while(*dateString && isspace(*dateString))
- dateString++;
- wordStart = dateString;
- }
- else
- dateString++;
- }
-
- while(*dateString && isspace(*dateString))
- dateString++;
-
- if (!*dateString)
- return result; // Invalid date
-
- // ' 09-Nov-99 23:12:40 GMT'
- day = strtol(dateString, &newPosStr, 10);
- dateString = newPosStr;
-
- if ((day < 1) || (day > 31))
- return result; // Invalid date;
- if (!*dateString)
- return result; // Invalid date
-
- if (*dateString == '-')
- dateString++;
-
- while(*dateString && isspace(*dateString))
- dateString++;
-
- if ( month == -1 ) // not found yet
- {
- for(int i=0; i < 3;i++)
- {
- if (!*dateString || (*dateString == '-') || isspace(*dateString))
- return result; // Invalid date
- monthStr[i] = tolower(*dateString++);
- }
- monthStr[3] = '\0';
-
- newPosStr = (char*)strstr(haystack, monthStr);
-
- if (!newPosStr)
- return result; // Invalid date
-
- month = (newPosStr-haystack)/3; // Jan=00, Feb=01, Mar=02, ..
-
- if ((month < 0) || (month > 11))
- return result; // Invalid date
-
- while(*dateString && (*dateString != '-') && !isspace(*dateString))
- dateString++;
-
- if (!*dateString)
- return result; // Invalid date
-
- // '-99 23:12:40 GMT'
- if ((*dateString != '-') && !isspace(*dateString))
- return result; // Invalid date
- dateString++;
- }
-
- if ((month < 0) || (month > 11))
- return result; // Invalid date
-
- // '99 23:12:40 GMT'
- year = strtol(dateString, &newPosStr, 10);
- dateString = newPosStr;
-
- // Y2K: Solve 2 digit years
- if ((year >= 0) && (year < 50))
- year += 2000;
-
- if ((year >= 50) && (year < 100))
- year += 1900; // Y2K
-
- if ((year < 1900) || (year > 2500))
- return result; // Invalid date
-
- // Don't fail if the time is missing.
- if (*dateString)
- {
- // ' 23:12:40 GMT'
- if (!isspace(*dateString++))
- return result; // Invalid date
-
- hour = strtol(dateString, &newPosStr, 10);
- dateString = newPosStr;
-
- if ((hour < 0) || (hour > 23))
- return result; // Invalid date
-
- if (!*dateString)
- return result; // Invalid date
-
- // ':12:40 GMT'
- if (*dateString++ != ':')
- return result; // Invalid date
-
- minute = strtol(dateString, &newPosStr, 10);
- dateString = newPosStr;
-
- if ((minute < 0) || (minute > 59))
- return result; // Invalid date
-
- if (!*dateString)
- return result; // Invalid date
-
- // ':40 GMT'
- if (*dateString != ':' && !isspace(*dateString))
- return result; // Invalid date
-
- // seconds are optional in rfc822 + rfc2822
- if (*dateString ==':') {
- dateString++;
-
- second = strtol(dateString, &newPosStr, 10);
- dateString = newPosStr;
-
- if ((second < 0) || (second > 59))
- return result; // Invalid date
- } else {
- dateString++;
- }
-
- while(*dateString && isspace(*dateString))
- dateString++;
- }
-
- // don't fail if the time zone is missing, some
- // broken mail-/news-clients omit the time zone
- if (*dateString) {
-
- if ((*dateString == '+') || (*dateString == '-')) {
- offset = strtol(dateString, &newPosStr, 10);
-
- if ((offset < -9959) || (offset > 9959))
- return result; // Invalid date
-
- int sgn = (offset < 0)? -1:1;
- offset = abs(offset);
- offset = ((offset / 100)*60 + (offset % 100))*sgn;
- } else {
- for (int i=0; known_zones[i].tzName != 0; i++) {
- if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
- offset = known_zones[i].tzOffset;
- break;
- }
- }
- }
- }
- if (sizeof(time_t) == 4)
- {
- if ((time_t)-1 < 0)
- {
- if (year >= 2038)
- {
- year = 2038;
- month = 0;
- day = 1;
- hour = 0;
- minute = 0;
- second = 0;
- }
- }
- else
- {
- if (year >= 2115)
- {
- year = 2115;
- month = 0;
- day = 1;
- hour = 0;
- minute = 0;
- second = 0;
- }
- }
- }
-
- result = ymdhms_to_seconds(year, month+1, day, hour, minute, second);
-
- // avoid negative time values
- if ((offset > 0) && (offset > result))
- offset = 0;
-
- result -= offset*60;
-
- // If epoch 0 return epoch +1 which is Thu, 01-Jan-70 00:00:01 GMT
- // This is so that parse error and valid epoch 0 return values won't
- // be the same for sensitive applications...
- if (result < 1) result = 1;
-
- return result;
-}
-
-
-Value KJS::timeClip(const Value &t)
-{
- /* TODO */
- return t;
-}
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _DATE_OBJECT_H_
-#define _DATE_OBJECT_H_
-
-#include "internal.h"
-#include "function_object.h"
-
-namespace KJS {
-
- class DateInstanceImp : public ObjectImp {
- public:
- DateInstanceImp(const Object &proto);
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- /**
- * @internal
- *
- * The initial value of Date.prototype (and thus all objects created
- * with the Date constructor
- */
- class DatePrototypeImp : public DateInstanceImp {
- public:
- DatePrototypeImp(ExecState *exec, ObjectPrototypeImp *objectProto);
- Value get(ExecState *exec, const UString &p) const;
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Date.prototype object
- */
- class DateProtoFuncImp : public InternalFunctionImp {
- public:
- DateProtoFuncImp(ExecState *exec, int i, int len);
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
-
- Completion execute(const List &);
- enum { ToString, ToDateString, ToTimeString, ToLocaleString,
- ToLocaleDateString, ToLocaleTimeString, ValueOf, GetTime,
- GetFullYear, GetMonth, GetDate, GetDay, GetHours, GetMinutes,
- GetSeconds, GetMilliSeconds, GetTimezoneOffset, SetTime,
- SetMilliSeconds, SetSeconds, SetMinutes, SetHours, SetDate,
- SetMonth, SetFullYear, ToUTCString,
- // non-normative properties (Appendix B)
- GetYear, SetYear, ToGMTString };
- private:
- int id;
- bool utc;
- };
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Date" property
- */
- class DateObjectImp : public InternalFunctionImp {
- public:
- DateObjectImp(ExecState *exec,
- FunctionPrototypeImp *funcProto,
- DatePrototypeImp *dateProto);
-
- virtual bool implementsConstruct() const;
- virtual Object construct(ExecState *exec, const List &args);
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- Completion execute(const List &);
- Object construct(const List &);
- };
-
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Date object
- */
- class DateObjectFuncImp : public InternalFunctionImp {
- public:
- DateObjectFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto,
- int i, int len);
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- enum { Parse, UTC };
- private:
- int id;
- };
-
- // helper functions
- Value parseDate(const String &s);
- time_t KRFCDate_parseDate(const UString &_date);
- Value timeClip(const Value &t);
-
-}; // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#include "debugger.h"
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-#include "internal.h"
-#include "ustring.h"
-
-using namespace KJS;
-
-// ------------------------------ Debugger -------------------------------------
-
-namespace KJS {
- struct AttachedInterpreter
- {
- public:
- AttachedInterpreter(Interpreter *i) : interp(i) {}
- Interpreter *interp;
- AttachedInterpreter *next;
- };
-
-}
-
-Debugger::Debugger()
-{
- rep = new DebuggerImp();
-}
-
-Debugger::~Debugger()
-{
- // detach from all interpreters
- while (rep->interps)
- detach(rep->interps->interp);
-
- delete rep;
-}
-
-void Debugger::attach(Interpreter *interp)
-{
- if (interp->imp()->debugger() != this)
- interp->imp()->setDebugger(this);
-
- // add to the list of attached interpreters
- if (!rep->interps)
- rep->interps = new AttachedInterpreter(interp);
- else {
- AttachedInterpreter *ai = rep->interps;
- while (ai->next)
- ai = ai->next;
- ai->next = new AttachedInterpreter(interp);;
- }
-}
-
-void Debugger::detach(Interpreter *interp)
-{
- if (interp->imp()->debugger() == this)
- interp->imp()->setDebugger(this);
-
- // remove from the list of attached interpreters
- if (rep->interps->interp == interp) {
- AttachedInterpreter *old = rep->interps;
- rep->interps = rep->interps->next;
- delete old;
- }
-
- AttachedInterpreter *ai = rep->interps;
- while (ai->next && ai->next->interp != interp)
- ai = ai->next;
- if (ai->next) {
- AttachedInterpreter *old = ai->next;
- ai->next = ai->next->next;
- delete old;
- }
-}
-
-bool Debugger::sourceParsed(ExecState */*exec*/, int /*sourceId*/,
- const UString &/*source*/, int /*errorLine*/)
-{
- return true;
-}
-
-bool Debugger::sourceUnused(ExecState */*exec*/, int /*sourceId*/)
-{
- return true;
-}
-
-bool Debugger::exception(ExecState */*exec*/, int /*sourceId*/, int /*lineno*/,
- Object &/*exceptionObj*/)
-{
- return true;
-}
-
-bool Debugger::atStatement(ExecState */*exec*/, int /*sourceId*/, int /*firstLine*/,
- int /*lastLine*/)
-{
- return true;
-}
-
-bool Debugger::callEvent(ExecState */*exec*/, int /*sourceId*/, int /*lineno*/,
- Object &/*function*/, const List &/*args*/)
-{
- return true;
-}
-
-bool Debugger::returnEvent(ExecState */*exec*/, int /*sourceId*/, int /*lineno*/,
- Object &/*function*/)
-{
- return true;
-}
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _KJSDEBUGGER_H_
-#define _KJSDEBUGGER_H_
-
-namespace KJS {
-
- class DebuggerImp;
- class Interpreter;
- class ExecState;
- class Object;
- class UString;
- class List;
-
- /**
- * @internal
- *
- * Provides an interface which receives notification about various
- * script-execution related events such as statement execution and function
- * calls.
- *
- * WARNING: This interface is still a work in progress and is not yet
- * offically publicly available. It is likely to change in binary incompatible
- * (and possibly source incompatible) ways in future versions. It is
- * anticipated that at some stage the interface will be frozen and made
- * available for general use.
- */
- class Debugger {
- public:
-
- /**
- * Creates a new debugger
- */
- Debugger();
-
- /**
- * Destroys the debugger. If the debugger is attached to any interpreters,
- * it is automatically detached.
- */
- virtual ~Debugger();
-
- DebuggerImp *imp() const { return rep; }
-
- /**
- * Attaches the debugger to specified interpreter. This will cause this
- * object to receive notification of events from the interpreter.
- *
- * If the interpreter is deleted, the debugger will automatically be
- * detached.
- *
- * Note: only one debugger can be attached to an interpreter at a time.
- * Attaching another debugger to the same interpreter will cause the
- * original debugger to be detached from that interpreter.
- *
- * @param interp The interpreter to attach to
- *
- * @see detach()
- */
- void attach(Interpreter *interp);
-
- /**
- * Detach the debugger from an interpreter
- *
- * @param interp The interpreter to detach from. If 0, the debugger will be
- * detached from all interpreters to which it is attached.
- *
- * @see attach()
- */
- void detach(Interpreter *interp);
-
- /**
- * Called to notify the debugger that some javascript source code has
- * been parsed. For calls to Interpreter::evaluate(), this will be called
- * with the supplied source code before any other code is parsed.
- * Other situations in which this may be called include creation of a
- * function using the Function() constructor, or the eval() function.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code (corresponds to the
- * sourceId supplied in other functions such as @ref atStatement()
- * @param source The source code that was parsed
- * @param errorLine The line number at which parsing encountered an
- * error, or -1 if the source code was valid and parsed succesfully
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool sourceParsed(ExecState *exec, int sourceId,
- const UString &source, int errorLine);
-
- /**
- * Called when all functions/programs associated with a particular
- * sourceId have been deleted. After this function has been called for
- * a particular sourceId, that sourceId will not be used again.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code (corresponds to the
- * sourceId supplied in other functions such as atLine()
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool sourceUnused(ExecState *exec, int sourceId);
-
- /**
- * Called when an exception is thrown during script execution.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code being executed
- * @param lineno The line at which the error occurred
- * @param exceptionObj The exception object
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool exception(ExecState *exec, int sourceId, int lineno,
- Object &exceptionObj);
-
- /**
- * Called when a line of the script is reached (before it is executed)
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code being executed
- * @param firstLine The starting line of the statement that is about to be
- * executed
- * @param firstLine The ending line of the statement that is about to be
- * executed (usually the same as firstLine)
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool atStatement(ExecState *exec, int sourceId, int firstLine,
- int lastLine);
- /**
- * Called on each function call. Use together with @ref #returnEvent
- * if you want to keep track of the call stack.
- *
- * Note: This only gets called for functions that are declared in ECMAScript
- * source code or passed to eval(), not for internal KJS or
- * application-supplied functions.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code being executed
- * @param lineno The line that is about to be executed
- * @param function The function being called
- * @param args The arguments that were passed to the function
- * line is being executed
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool callEvent(ExecState *exec, int sourceId, int lineno,
- Object &function, const List &args);
-
- /**
- * Called on each function exit. The function being returned from is that
- * which was supplied in the last callEvent().
- *
- * Note: This only gets called for functions that are declared in ECMAScript
- * source code or passed to eval(), not for internal KJS or
- * application-supplied functions.
- *
- * The default implementation does nothing. Override this method if
- * you want to process this event.
- *
- * @param exec The current execution state
- * @param sourceId The ID of the source code being executed
- * @param lineno The line that is about to be executed
- * @param function The function being called
- * @return true if execution should be continue, false if it should
- * be aborted
- */
- virtual bool returnEvent(ExecState *exec, int sourceId, int lineno,
- Object &function);
-
- private:
- DebuggerImp *rep;
- };
-
-};
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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 "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-#include "operations.h"
-#include "error_object.h"
-//#include "debugger.h"
-
-using namespace KJS;
-
-// ------------------------------ ErrorPrototypeImp ----------------------------
-
-// ECMA 15.9.4
-ErrorPrototypeImp::ErrorPrototypeImp(ExecState *exec,
- ObjectPrototypeImp *objectProto,
- FunctionPrototypeImp *funcProto)
- : ObjectImp(Object(objectProto))
-{
- Value protect(this);
- 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, "toString", Object(new ErrorProtoFuncImp(exec,funcProto)), DontEnum);
-}
-
-// ------------------------------ ErrorProtoFuncImp ----------------------------
-
-ErrorProtoFuncImp::ErrorProtoFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto)
- : InternalFunctionImp(funcProto)
-{
- Value protect(this);
- put(exec,"length",Number(0),DontDelete|ReadOnly|DontEnum);
-}
-
-bool ErrorProtoFuncImp::implementsCall() const
-{
- return true;
-}
-
-Value ErrorProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &/*args*/)
-{
- // toString()
- UString s = "Error";
-
- Value v = thisObj.get(exec,"name");
- if (v.type() != UndefinedType) {
- s = v.toString(exec);
- }
-
- v = thisObj.get(exec,"message");
- if (v.type() != UndefinedType) {
- s += ": "+v.toString(exec);
- }
-
- return String(s);
-}
-
-// ------------------------------ ErrorObjectImp -------------------------------
-
-ErrorObjectImp::ErrorObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto,
- ErrorPrototypeImp *errorProto)
- : InternalFunctionImp(funcProto)
-{
- Value protect(this);
- // ECMA 15.11.3.1 Error.prototype
- put(exec, "prototype", Object(errorProto), DontEnum|DontDelete|ReadOnly);
- //put(exec, "name", String(n));
-}
-
-bool ErrorObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.9.3
-Object ErrorObjectImp::construct(ExecState *exec, const List &args)
-{
- Object proto = Object::dynamicCast(exec->interpreter()->builtinErrorPrototype());
- Object obj(new ObjectImp(proto));
-
- if (!args.isEmpty() && args[0].type() != UndefinedType) {
- obj.put(exec,"message", String(args[0].toString(exec)));
- }
-
- return obj;
-}
-
-bool ErrorObjectImp::implementsCall() const
-{
- return true;
-}
-
-// ECMA 15.9.2
-Value ErrorObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
-{
- // "Error()" gives the sames result as "new Error()"
- return construct(exec,args);
-}
-
-// ------------------------------ NativeErrorPrototypeImp ----------------------
-
-NativeErrorPrototypeImp::NativeErrorPrototypeImp(ExecState *exec, ErrorPrototypeImp *errorProto,
- ErrorType et, UString name, UString message)
- : ObjectImp(Object(errorProto))
-{
- Value protect(this);
- errType = et;
- put(exec,"name",String(name));
- put(exec,"message",String(message));
-}
-
-// ------------------------------ NativeErrorImp -------------------------------
-
-const ClassInfo NativeErrorImp::info = {"Error", &InternalFunctionImp::info, 0, 0};
-
-NativeErrorImp::NativeErrorImp(ExecState *exec, FunctionPrototypeImp *funcProto,
- const Object &prot)
- : InternalFunctionImp(funcProto), proto(0)
-{
- Value protect(this);
- proto = static_cast<ObjectImp*>(prot.imp());
-
- put(exec,"length",Number(1),DontDelete|ReadOnly|DontEnum); // ECMA 15.11.7.5
- put(exec,"prototype",prot);
-}
-
-bool NativeErrorImp::implementsConstruct() const
-{
- return true;
-}
-
-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)));
- return obj;
-}
-
-bool NativeErrorImp::implementsCall() const
-{
- return true;
-}
-
-Value NativeErrorImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
-{
- return construct(exec,args);
-}
-
-void NativeErrorImp::mark()
-{
- ObjectImp::mark();
- if (proto && !proto->marked())
- proto->mark();
-}
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _ERROR_OBJECT_H_
-#define _ERROR_OBJECT_H_
-
-#include "internal.h"
-#include "function_object.h"
-
-namespace KJS {
-
- class ErrorPrototypeImp : public ObjectImp {
- public:
- ErrorPrototypeImp(ExecState *exec,
- ObjectPrototypeImp *objectProto,
- FunctionPrototypeImp *funcProto);
- };
-
- class ErrorProtoFuncImp : public InternalFunctionImp {
- public:
- ErrorProtoFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto);
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
- };
-
- class ErrorObjectImp : public InternalFunctionImp {
- public:
- ErrorObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto,
- ErrorPrototypeImp *errorProto);
-
- virtual bool implementsConstruct() const;
- virtual Object construct(ExecState *exec, const List &args);
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
- };
-
-
-
-
-
- class NativeErrorPrototypeImp : public ObjectImp {
- public:
- NativeErrorPrototypeImp(ExecState *exec, ErrorPrototypeImp *errorProto,
- ErrorType et, UString name, UString message);
- private:
- ErrorType errType;
- };
-
- class NativeErrorImp : public InternalFunctionImp {
- public:
- NativeErrorImp(ExecState *exec, FunctionPrototypeImp *funcProto,
- const Object &prot);
-
- virtual bool implementsConstruct() const;
- virtual Object construct(ExecState *exec, const List &args);
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- virtual void mark();
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- private:
- ObjectImp *proto;
- };
-
-}; // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * 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 "function.h"
-
-#include "internal.h"
-#include "function_object.h"
-#include "lexer.h"
-#include "nodes.h"
-#include "operations.h"
-#include "debugger.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-
-using namespace KJS;
-
-// ------------------------------ FunctionImp ----------------------------------
-
-const ClassInfo FunctionImp::info = {"Function", &InternalFunctionImp::info, 0, 0};
-
-namespace KJS {
- class Parameter {
- public:
- Parameter(const UString &n) : name(n), next(0L) { }
- ~Parameter() { delete next; }
- UString name;
- Parameter *next;
- };
-};
-
-FunctionImp::FunctionImp(ExecState *exec, const UString &n)
- : InternalFunctionImp(
- static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
- ), param(0L), ident(n), argStack(0)
-{
- Value protect(this);
- argStack = new ListImp();
- put(exec,"arguments",Null(),ReadOnly|DontDelete|DontEnum);
-}
-
-FunctionImp::~FunctionImp()
-{
- argStack->setGcAllowed();
- // The function shouldn't be deleted while it is still executed; argStack
- // should be set to 0 by the last call to popArgs()
- assert(argStack->isEmpty());
- delete param;
-}
-
-void FunctionImp::mark()
-{
- InternalFunctionImp::mark();
- if (argStack && !argStack->marked())
- argStack->mark();
-}
-
-bool FunctionImp::implementsCall() const
-{
- return true;
-}
-
-Value FunctionImp::call(ExecState *exec, Object &thisObj, const List &args)
-{
- Object globalObj = exec->interpreter()->globalObject();
-
- Debugger *dbg = exec->interpreter()->imp()->debugger();
- int sid = -1;
- int lineno = -1;
- if (dbg) {
- if (inherits(&DeclaredFunctionImp::info)) {
- sid = static_cast<DeclaredFunctionImp*>(this)->body->sourceId();
- lineno = static_cast<DeclaredFunctionImp*>(this)->body->firstLine();
- }
-
- Object func(this);
- int cont = dbg->callEvent(exec,sid,lineno,func,args);
- if (!cont) {
- dbg->imp()->abort();
- return Undefined();
- }
- }
-
- // enter a new execution context
- ContextImp *ctx = new ContextImp(globalObj, exec, thisObj,
- codeType(), exec->context().imp(), this, args);
- ExecState *newExec = new ExecState(exec->interpreter(),ctx);
- newExec->setException(exec->exception()); // could be null
-
- // In order to maintain our "arguments" property, we maintain a list of arguments
- // properties from earlier in the execution stack. Upon return, we restore the
- // previous arguments object using popArgs().
- // Note: this does not appear to be part of the spec
- if (codeType() == FunctionCode) {
- assert(ctx->activationObject().inherits(&ActivationImp::info));
- Object argsObj = static_cast<ActivationImp*>(ctx->activationObject().imp())->argumentsObject();
- put(newExec,"arguments", argsObj, DontDelete|DontEnum|ReadOnly);
- pushArgs(newExec,argsObj);
- }
-
- // assign user supplied arguments to parameters
- processParameters(newExec,args);
- // add variable declarations (initialized to undefined)
- processVarDecls(newExec);
-
- Completion comp = execute(newExec);
-
- // if an exception occured, propogate it back to the previous execution object
- if (newExec->hadException())
- exec->setException(newExec->exception());
- if (codeType() == FunctionCode)
- popArgs(newExec);
- delete newExec;
- delete ctx;
-
-#ifdef KJS_VERBOSE
- if (comp.complType() == Throw)
- printInfo(exec,"throwing", comp.value());
- else if (comp.complType() == ReturnValue)
- printInfo(exec,"returning", comp.value());
- else
- fprintf(stderr, "returning: undefined\n");
-#endif
-
- if (dbg) {
- Object func(this);
- int cont = dbg->returnEvent(exec,sid,lineno,func);
- if (!cont) {
- dbg->imp()->abort();
- return Undefined();
- }
- }
-
- if (comp.complType() == Throw) {
- exec->setException(comp.value());
- return comp.value();
- }
- else if (comp.complType() == ReturnValue)
- return comp.value();
- else
- return Undefined();
-}
-
-void FunctionImp::addParameter(const UString &n)
-{
- Parameter **p = ¶m;
- while (*p)
- p = &(*p)->next;
-
- *p = new Parameter(n);
-}
-
-
-// ECMA 10.1.3q
-void FunctionImp::processParameters(ExecState *exec, const List &args)
-{
- Object variable = exec->context().imp()->variableObject();
-
-#ifdef KJS_VERBOSE
- fprintf(stderr, "---------------------------------------------------\n"
- "processing parameters for %s call\n",
- name().isEmpty() ? "(internal)" : name().ascii());
-#endif
-
- if (param) {
- ListIterator it = args.begin();
- Parameter **p = ¶m;
- while (*p) {
- if (it != args.end()) {
-#ifdef KJS_VERBOSE
- fprintf(stderr, "setting parameter %s ", (*p)->name.ascii());
- printInfo(exec,"to", *it);
-#endif
- variable.put(exec,(*p)->name, *it);
- it++;
- } else
- variable.put(exec,(*p)->name, Undefined());
- p = &(*p)->next;
- }
- }
-#ifdef KJS_VERBOSE
- else {
- for (int i = 0; i < args.size(); i++)
- printInfo(exec,"setting argument", args[i]);
- }
-#endif
-}
-
-void FunctionImp::processVarDecls(ExecState */*exec*/)
-{
-}
-
-void FunctionImp::pushArgs(ExecState *exec, const Object &args)
-{
- argStack->append(args);
- put(exec,"arguments",args,ReadOnly|DontDelete|DontEnum);
-}
-
-void FunctionImp::popArgs(ExecState *exec)
-{
- argStack->removeLast();
- if (argStack->isEmpty()) {
- put(exec,"arguments",Null(),ReadOnly|DontDelete|DontEnum);
- }
- else
- put(exec,"arguments",argStack->at(argStack->size()-1),ReadOnly|DontDelete|DontEnum);
-}
-
-// ------------------------------ DeclaredFunctionImp --------------------------
-
-// ### is "Function" correct here?
-const ClassInfo DeclaredFunctionImp::info = {"Function", &FunctionImp::info, 0, 0};
-
-DeclaredFunctionImp::DeclaredFunctionImp(ExecState *exec, const UString &n,
- FunctionBodyNode *b, const List &sc)
- : FunctionImp(exec,n), body(b)
-{
- Value protect(this);
- body->ref();
- setScope(sc.copy());
-}
-
-DeclaredFunctionImp::~DeclaredFunctionImp()
-{
- if ( body->deref() )
- delete body;
-}
-
-bool DeclaredFunctionImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 13.2.2 [[Construct]]
-Object DeclaredFunctionImp::construct(ExecState *exec, const List &args)
-{
- Object proto;
- Value p = get(exec,"prototype");
- if (p.type() == ObjectType)
- proto = Object(static_cast<ObjectImp*>(p.imp()));
- else
- proto = exec->interpreter()->builtinObjectPrototype();
-
- Object obj(new ObjectImp(proto));
-
- Value res = call(exec,obj,args);
-
- if (res.type() == ObjectType)
- return Object::dynamicCast(res);
- else
- return obj;
-}
-
-Completion DeclaredFunctionImp::execute(ExecState *exec)
-{
- Completion result = body->execute(exec);
-
- if (result.complType() == Throw || result.complType() == ReturnValue)
- return result;
- return Completion(Normal, Undefined()); // TODO: or ReturnValue ?
-}
-
-void DeclaredFunctionImp::processVarDecls(ExecState *exec)
-{
- body->processVarDecls(exec);
-}
-
-// ------------------------------ ArgumentsImp ---------------------------------
-
-const ClassInfo ArgumentsImp::info = {"Arguments", 0, 0, 0};
-
-// ECMA 10.1.8
-ArgumentsImp::ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args)
- : ObjectImp(exec->interpreter()->builtinObjectPrototype())
-{
- Value protect(this);
- put(exec,"callee", Object(func), DontEnum);
- put(exec,"length", Number(args.size()), DontEnum);
- if (!args.isEmpty()) {
- ListIterator arg = args.begin();
- for (int i = 0; arg != args.end(); arg++, i++) {
- put(exec,UString::from(i), *arg, DontEnum);
- }
- }
-}
-
-// ------------------------------ ActivationImp --------------------------------
-
-const ClassInfo ActivationImp::info = {"Activation", 0, 0, 0};
-
-// ECMA 10.1.6
-ActivationImp::ActivationImp(ExecState *exec, FunctionImp *f, const List &args)
- : ObjectImp()
-{
- Value protect(this);
- arguments = new ArgumentsImp(exec,f, args);
- put(exec, "arguments", Object(arguments), Internal|DontDelete);
-}
-
-ActivationImp::~ActivationImp()
-{
- arguments->setGcAllowed();
-}
-
-// ------------------------------ GlobalFunc -----------------------------------
-
-
-GlobalFuncImp::GlobalFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto, int i, int len)
- : InternalFunctionImp(funcProto), id(i)
-{
- Value protect(this);
- put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
-}
-
-CodeType GlobalFuncImp::codeType() const
-{
- return id == Eval ? EvalCode : codeType();
-}
-
-bool GlobalFuncImp::implementsCall() const
-{
- return true;
-}
-
-Value GlobalFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
-{
- Value res;
-
- static const char non_escape[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789@*_+-./";
-
- if (id == Eval) { // eval()
- Value x = args[0];
- if (x.type() != StringType)
- return x;
- else {
- UString s = x.toString(exec);
-
- int sid;
- int errLine;
- UString errMsg;
- ProgramNode *progNode = Parser::parse(s.data(),s.size(),&sid,&errLine,&errMsg);
-
- // no program node means a syntax occurred
- if (!progNode) {
- Object err = Error::create(exec,SyntaxError,errMsg.ascii(),errLine);
- err.put(exec,"sid",Number(sid));
- exec->setException(err);
- return err;
- }
-
- progNode->ref();
-
- // enter a new execution context
- Object glob(exec->interpreter()->globalObject());
- Object thisVal(Object::dynamicCast(exec->context().thisValue()));
- ContextImp *ctx = new ContextImp(glob,
- exec,
- thisVal,
- EvalCode,
- exec->context().imp());
-
- ExecState *newExec = new ExecState(exec->interpreter(),ctx);
- newExec->setException(exec->exception()); // could be null
-
- // execute the code
- Completion c = progNode->execute(newExec);
-
- // if an exception occured, propogate it back to the previous execution object
- if (newExec->hadException())
- exec->setException(newExec->exception());
- delete newExec;
- delete ctx;
-
- if ( progNode->deref() )
- delete progNode;
- if (c.complType() == ReturnValue)
- return c;
- // ### setException() on throw?
- else if (c.complType() == Normal) {
- if (c.isValueCompletion())
- return c.value();
- else
- return Undefined();
- } else
- return c;
- }
- } else if (id == ParseInt) {
- String str = args[0].toString(exec);
- int radix = args[1].toInt32(exec);
- if (radix == 0)
- radix = 10;
- else if (radix < 2 || radix > 36) {
- res = Number(NaN);
- return res;
- }
- /* TODO: use radix */
- // Can't use toULong(), we want to accept floating point values too
- double value = str.value().toDouble( true /*tolerant*/ );
- if ( isNaN(value) )
- res = Number(NaN);
- else
- res = Number(static_cast<long>(value)); // remove floating-point part
- } else if (id == ParseFloat) {
- String str = args[0].toString(exec);
- res = Number(str.value().toDouble( true /*tolerant*/ ));
- } else if (id == IsNaN) {
- res = Boolean(isNaN(args[0].toNumber(exec)));
- } else if (id == IsFinite) {
- Number n = args[0].toNumber(exec);
- res = Boolean(!n.isNaN() && !n.isInf());
- } else if (id == Escape) {
- UString r = "", s, str = args[0].toString(exec);
- const UChar *c = str.data();
- for (int k = 0; k < str.size(); k++, c++) {
- int u = c->unicode();
- if (u > 255) {
- char tmp[7];
- sprintf(tmp, "%%u%04X", u);
- s = UString(tmp);
- } else if (strchr(non_escape, (char)u)) {
- s = UString(c, 1);
- } else {
- char tmp[4];
- sprintf(tmp, "%%%02X", u);
- s = UString(tmp);
- }
- r += s;
- }
- res = String(r);
- } else if (id == UnEscape) {
- UString s, str = args[0].toString(exec);
- int k = 0, len = str.size();
- while (k < len) {
- const UChar *c = str.data() + k;
- UChar u;
- if (*c == UChar('%') && k <= len - 6 && *(c+1) == UChar('u')) {
- u = Lexer::convertUnicode((c+2)->unicode(), (c+3)->unicode(),
- (c+4)->unicode(), (c+5)->unicode());
- c = &u;
- k += 5;
- } else if (*c == UChar('%') && k <= len - 3) {
- u = UChar(Lexer::convertHex((c+1)->unicode(), (c+2)->unicode()));
- c = &u;
- k += 2;
- }
- k++;
- s += UString(c, 1);
- }
- res = String(s);
- }
-
- return res;
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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.
- *
- * $Id$
- */
-
-#ifndef _KJS_FUNCTION_H_
-#define _KJS_FUNCTION_H_
-
-#include "internal.h"
-
-namespace KJS {
-
- class Parameter;
-
- /**
- * @short Implementation class for internal Functions.
- */
- class FunctionImp : public InternalFunctionImp {
- friend class Function;
- friend class ActivationImp;
- public:
- FunctionImp(ExecState *exec, const UString &n = UString::null);
- virtual ~FunctionImp();
-
- virtual void mark();
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- void addParameter(const UString &n);
- virtual CodeType codeType() const = 0;
-
- virtual Completion execute(ExecState *exec) = 0;
- UString name() const { return ident; }
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- protected:
- Parameter *param;
- UString ident;
-
- private:
- void processParameters(ExecState *exec, const List &);
- virtual void processVarDecls(ExecState *exec);
-
- void pushArgs(ExecState *exec, const Object &args);
- void popArgs(ExecState *exec);
- ListImp *argStack;
- };
-
- class DeclaredFunctionImp : public FunctionImp {
- public:
- DeclaredFunctionImp(ExecState *exec, const UString &n,
- FunctionBodyNode *b, const List &sc);
- ~DeclaredFunctionImp();
-
- bool implementsConstruct() const;
- Object construct(ExecState *exec, const List &args);
-
- virtual Completion execute(ExecState *exec);
- CodeType codeType() const { return FunctionCode; }
- FunctionBodyNode *body;
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- private:
- virtual void processVarDecls(ExecState *exec);
- };
-
-
-
-
- class ArgumentsImp : public ObjectImp {
- public:
- ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args);
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- class ActivationImp : public ObjectImp {
- public:
- ActivationImp(ExecState *exec, FunctionImp *f, const List &args);
- ~ActivationImp();
-
- Object argumentsObject() { return Object(arguments); }
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- private:
- ObjectImp* arguments;
- };
-
- class GlobalFuncImp : public InternalFunctionImp {
- public:
- GlobalFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto, int i, int len);
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
- virtual CodeType codeType() const;
- enum { Eval, ParseInt, ParseFloat, IsNaN, IsFinite, Escape, UnEscape };
- private:
- int id;
- };
-
-
-
-}; // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * 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 "function_object.h"
-#include "internal.h"
-#include "function.h"
-#include "array_object.h"
-#include "nodes.h"
-#include "lexer.h"
-#include "debugger.h"
-#include "object.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-using namespace KJS;
-
-// ------------------------------ FunctionPrototypeImp -------------------------
-
-FunctionPrototypeImp::FunctionPrototypeImp(ExecState *exec)
- : InternalFunctionImp(0)
-{
- Value protect(this);
- put(exec, "toString", Object(new FunctionProtoFuncImp(exec, this, FunctionProtoFuncImp::ToString, 0)), DontEnum);
- put(exec, "apply", Object(new FunctionProtoFuncImp(exec, this, FunctionProtoFuncImp::Apply, 2)), DontEnum);
- put(exec, "call", Object(new FunctionProtoFuncImp(exec, this, FunctionProtoFuncImp::Call, 1)), DontEnum);
-}
-
-FunctionPrototypeImp::~FunctionPrototypeImp()
-{
-}
-
-bool FunctionPrototypeImp::implementsCall() const
-{
- return true;
-}
-
-// ECMA 15.3.4
-Value FunctionPrototypeImp::call(ExecState */*exec*/, Object &/*thisObj*/, const List &/*args*/)
-{
- return Undefined();
-}
-
-// ------------------------------ FunctionProtoFuncImp -------------------------
-
-FunctionProtoFuncImp::FunctionProtoFuncImp(ExecState *exec,
- FunctionPrototypeImp *funcProto, int i, int len)
- : InternalFunctionImp(funcProto), id(i)
-{
- Value protect(this);
- put(exec,"length",Number(len),DontDelete|ReadOnly|DontEnum);
-}
-
-
-bool FunctionProtoFuncImp::implementsCall() const
-{
- return true;
-}
-
-Value FunctionProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
-{
- Value result;
-
- switch (id) {
- case ToString: {
- // ### also make this work for internal functions
- // ### return the text of the function body (see 15.3.4.2)
- if (thisObj.isNull() || !thisObj.inherits(&InternalFunctionImp::info)) {
-#ifndef NDEBUG
- fprintf(stderr,"attempted toString() call on null or non-function object\n");
-#endif
- Object err = Error::create(exec,TypeError);
- exec->setException(err);
- return err;
- }
- if (thisObj.inherits(&FunctionImp::info) &&
- !static_cast<FunctionImp*>(thisObj.imp())->name().isNull()) {
- result = String("function " + static_cast<FunctionImp*>(thisObj.imp())->name() + "()");
- }
- else {
- result = String("(Internal function)");
- }
- }
- break;
- case Apply: {
- Value thisArg = args[0];
- Value argArray = args[1];
- Object func = thisObj;
-
- if (!func.implementsCall()) {
- Object err = Error::create(exec,TypeError);
- exec->setException(err);
- return err;
- }
-
- Object applyThis;
- if (thisArg.isA(NullType) || thisArg.isA(UndefinedType))
- applyThis = exec->interpreter()->globalObject();
- else
- applyThis = thisArg.toObject(exec);
-
- List applyArgs;
- if (!argArray.isA(NullType) && !argArray.isA(UndefinedType)) {
- if ((argArray.isA(ObjectType) &&
- Object::dynamicCast(argArray).inherits(&ArrayInstanceImp::info)) ||
- Object::dynamicCast(argArray).inherits(&ArgumentsImp::info)) {
-
- Object argArrayObj = Object::dynamicCast(argArray);
- unsigned int length = argArrayObj.get(exec,"length").toUInt32(exec);
- for (uint i = 0; i < length; i++)
- applyArgs.append(argArrayObj.get(exec,UString::from(i)));
- }
- else {
- Object err = Error::create(exec,TypeError);
- exec->setException(err);
- return err;
- }
- }
- result = func.call(exec,applyThis,applyArgs);
- }
- break;
- case Call: {
- Value thisArg = args[0];
- Object func = thisObj;
-
- if (!func.implementsCall()) {
- Object err = Error::create(exec,TypeError);
- exec->setException(err);
- return err;
- }
-
- Object callThis;
- if (thisArg.isA(NullType) || thisArg.isA(UndefinedType))
- callThis = exec->interpreter()->globalObject();
- else
- callThis = thisArg.toObject(exec);
-
- List callArgs = args.copy();
- callArgs.removeFirst();
- result = func.call(exec,callThis,callArgs);
- }
- break;
- }
-
- return result;
-}
-
-// ------------------------------ FunctionObjectImp ----------------------------
-
-FunctionObjectImp::FunctionObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto)
- : InternalFunctionImp(funcProto)
-{
- Value protect(this);
- put(exec,"prototype", Object(funcProto), DontEnum|DontDelete|ReadOnly);
-
- // no. of arguments for constructor
- put(exec,"length", Number(1), ReadOnly|DontDelete|DontEnum);
-}
-
-FunctionObjectImp::~FunctionObjectImp()
-{
-}
-
-bool FunctionObjectImp::implementsConstruct() const
-{
- return true;
-}
-
-// ECMA 15.3.2 The Function Constructor
-Object FunctionObjectImp::construct(ExecState *exec, const List &args)
-{
- UString p("");
- UString body;
- int argsSize = args.size();
- if (argsSize == 0) {
- body = "";
- } else if (argsSize == 1) {
- body = args[0].toString(exec);
- } else {
- p = args[0].toString(exec);
- for (int k = 1; k < argsSize - 1; k++)
- p += "," + args[k].toString(exec);
- body = args[argsSize-1].toString(exec);
- }
-
- // parse the source code
- int sid;
- int errLine;
- UString errMsg;
- ProgramNode *progNode = Parser::parse(body.data(),body.size(),&sid,&errLine,&errMsg);
-
- // notify debugger that source has been parsed
- Debugger *dbg = exec->interpreter()->imp()->debugger();
- if (dbg) {
- bool cont = dbg->sourceParsed(exec,sid,body,errLine);
- if (!cont) {
- dbg->imp()->abort();
- return Object(new ObjectImp());
- }
- }
-
- // no program node == syntax error - throw a syntax error
- if (!progNode) {
- Object err = Error::create(exec,SyntaxError,errMsg.ascii(),errLine);
- // we can't return a Completion(Throw) here, so just set the exception
- // and return it
- exec->setException(err);
- return err;
- }
-
- List scopeChain;
- scopeChain.append(exec->interpreter()->globalObject());
- FunctionBodyNode *bodyNode = progNode;
-
- FunctionImp *fimp = new DeclaredFunctionImp(exec, UString::null, bodyNode,
- scopeChain);
- Object ret(fimp); // protect from GC
-
- // parse parameter list. throw syntax error on illegal identifiers
- int len = p.size();
- const UChar *c = p.data();
- int i = 0, params = 0;
- UString param;
- while (i < len) {
- while (*c == ' ' && i < len)
- c++, i++;
- if (Lexer::isIdentLetter(c->unicode())) { // else error
- param = UString(c, 1);
- c++, i++;
- while (i < len && (Lexer::isIdentLetter(c->unicode()) ||
- Lexer::isDecimalDigit(c->unicode()))) {
- param += UString(c, 1);
- c++, i++;
- }
- while (i < len && *c == ' ')
- c++, i++;
- if (i == len) {
- fimp->addParameter(param);
- params++;
- break;
- } else if (*c == ',') {
- fimp->addParameter(param);
- params++;
- c++, i++;
- continue;
- } // else error
- }
- Object err = Error::create(exec,SyntaxError,
- I18N_NOOP("Syntax error in parameter list"),
- -1);
- exec->setException(err);
- return err;
- }
-
- fimp->put(exec,"length", Number(params),ReadOnly|DontDelete|DontEnum);
- List consArgs;
-
- Object objCons = exec->interpreter()->builtinObject();
- Object prototype = objCons.construct(exec,List::empty());
- prototype.put(exec, "constructor",
- Object(fimp), DontEnum|DontDelete|ReadOnly);
- fimp->put(exec,"prototype",prototype,DontEnum|DontDelete|ReadOnly);
- fimp->put(exec,"arguments",Null(),DontEnum|DontDelete|ReadOnly);
- return ret;
-}
-
-bool FunctionObjectImp::implementsCall() const
-{
- return true;
-}
-
-// ECMA 15.3.1 The Function Constructor Called as a Function
-Value FunctionObjectImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
-{
- return construct(exec,args);
-}
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _FUNCTION_OBJECT_H_
-#define _FUNCTION_OBJECT_H_
-
-#include "internal.h"
-#include "object_object.h"
-#include "function.h"
-
-namespace KJS {
-
- /**
- * @internal
- *
- * The initial value of Function.prototype (and thus all objects created
- * with the Function constructor
- */
- class FunctionPrototypeImp : public InternalFunctionImp {
- public:
- FunctionPrototypeImp(ExecState *exec);
- virtual ~FunctionPrototypeImp();
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
- };
-
- /**
- * @internal
- *
- * Class to implement all methods that are properties of the
- * Function.prototype object
- */
- class FunctionProtoFuncImp : public InternalFunctionImp {
- public:
- FunctionProtoFuncImp(ExecState *exec,
- FunctionPrototypeImp *funcProto, int i, int len);
-
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
-
- enum { ToString, Apply, Call };
- private:
- int id;
- };
-
- /**
- * @internal
- *
- * The initial value of the the global variable's "Function" property
- */
- class FunctionObjectImp : public InternalFunctionImp {
- public:
- FunctionObjectImp(ExecState *exec, FunctionPrototypeImp *funcProto);
- virtual ~FunctionObjectImp();
-
- virtual bool implementsConstruct() const;
- virtual Object construct(ExecState *exec, const List &args);
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
- };
-
-}; // namespace
-
-#endif // _FUNCTION_OBJECT_H_
+++ /dev/null
-%{
-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <string.h>
-#include <stdlib.h>
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-#include "nodes.h"
-#include "lexer.h"
-#include "internal.h"
-
-/* default values for bison */
-#define YYDEBUG 0
-#define YYMAXDEPTH 0
-#ifdef APPLE_CHANGES
-#else
-#define YYERROR_VERBOSE
-#endif
-#define DBG(l, s, e) { l->setLoc(s.first_line, e.last_line, Parser::sid); } // location
-
-extern int yylex();
-int yyerror (const char *);
-bool automatic();
-
-using namespace KJS;
-
-%}
-
-%union {
- int ival;
- double dval;
- UString *ustr;
- Node *node;
- StatementNode *stat;
- ParameterNode *param;
- FunctionBodyNode *body;
- FuncDeclNode *func;
- ProgramNode *prog;
- AssignExprNode *init;
- SourceElementNode *src;
- SourceElementsNode *srcs;
- StatListNode *slist;
- ArgumentsNode *args;
- ArgumentListNode *alist;
- VarDeclNode *decl;
- VarDeclListNode *vlist;
- CaseBlockNode *cblk;
- ClauseListNode *clist;
- CaseClauseNode *ccl;
- ElementNode *elm;
- ElisionNode *eli;
- Operator op;
-}
-
-%start Program
-
-/* expect a shift/reduce conflict from the "dangling else" problem
- when using bison the warning can be supressed */
-// %expect 1
-
-/* literals */
-%token NULLTOKEN TRUETOKEN FALSETOKEN
-%token STRING NUMBER
-
-/* keywords */
-%token BREAK CASE DEFAULT FOR NEW VAR CONTINUE
-%token FUNCTION RETURN VOID DELETE
-%token IF THIS DO WHILE ELSE IN INSTANCEOF TYPEOF
-%token SWITCH WITH RESERVED
-%token THROW TRY CATCH FINALLY
-
-/* punctuators */
-%token EQEQ NE /* == and != */
-%token STREQ STRNEQ /* === and !== */
-%token LE GE /* < and > */
-%token OR AND /* || and && */
-%token PLUSPLUS MINUSMINUS /* ++ and -- */
-%token LSHIFT /* << */
-%token RSHIFT URSHIFT /* >> and >>> */
-%token PLUSEQUAL MINUSEQUAL /* += and -= */
-%token MULTEQUAL DIVEQUAL /* *= and /= */
-%token LSHIFTEQUAL /* <<= */
-%token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
-%token ANDEQUAL MODEQUAL /* &= and %= */
-%token XOREQUAL OREQUAL /* ^= and |= */
-
-/* terminal types */
-%token <dval> NUMBER
-%token <ustr> STRING
-%token <ustr> IDENT
-
-/* automatically inserted semicolon */
-%token AUTOPLUSPLUS AUTOMINUSMINUS
-
-/* non-terminal types */
-%type <node> Literal PrimaryExpr Expr MemberExpr FunctionExpr NewExpr CallExpr
-%type <node> ArrayLiteral PropertyName PropertyNameAndValueList
-%type <node> LeftHandSideExpr PostfixExpr UnaryExpr
-%type <node> MultiplicativeExpr AdditiveExpr
-%type <node> ShiftExpr RelationalExpr EqualityExpr
-%type <node> BitwiseANDExpr BitwiseXORExpr BitwiseORExpr
-%type <node> LogicalANDExpr LogicalORExpr
-%type <node> ConditionalExpr AssignmentExpr
-%type <node> ExprOpt
-%type <node> CallExpr
-%type <node> Catch Finally
-
-%type <stat> Statement Block
-%type <stat> VariableStatement EmptyStatement ExprStatement
-%type <stat> IfStatement IterationStatement ContinueStatement
-%type <stat> BreakStatement ReturnStatement WithStatement
-%type <stat> SwitchStatement LabelledStatement
-%type <stat> ThrowStatement TryStatement
-
-%type <slist> StatementList
-%type <init> Initializer
-%type <func> FunctionDeclaration
-%type <body> FunctionBody
-%type <src> SourceElement
-%type <srcs> SourceElements
-%type <param> FormalParameterList
-%type <op> AssignmentOperator
-%type <prog> Program
-%type <args> Arguments
-%type <alist> ArgumentList
-%type <vlist> VariableDeclarationList
-%type <decl> VariableDeclaration
-%type <cblk> CaseBlock
-%type <ccl> CaseClause DefaultClause
-%type <clist> CaseClauses CaseClausesOpt
-%type <eli> Elision ElisionOpt
-%type <elm> ElementList
-
-%%
-
-Literal:
- NULLTOKEN { $$ = new NullNode(); }
- | TRUETOKEN { $$ = new BooleanNode(true); }
- | FALSETOKEN { $$ = new BooleanNode(false); }
- | NUMBER { $$ = new NumberNode($1); }
- | STRING { $$ = new StringNode($1); delete $1; }
- | '/' /* a RegExp ? */ { Lexer *l = Lexer::curr();
- if (!l->scanRegExp()) YYABORT;
- $$ = new RegExpNode(l->pattern,l->flags);}
- | DIVEQUAL /* a RegExp starting with /= ! */
- { Lexer *l = Lexer::curr();
- if (!l->scanRegExp()) YYABORT;
- $$ = new RegExpNode(UString('=')+l->pattern,l->flags);}
-;
-
-PrimaryExpr:
- THIS { $$ = new ThisNode(); }
- | IDENT { $$ = new ResolveNode($1);
- delete $1; }
- | Literal
- | ArrayLiteral
- | '(' Expr ')' { $$ = new GroupNode($2); }
- | '{' '}' { $$ = new ObjectLiteralNode(0L); }
- | '{' PropertyNameAndValueList '}' { $$ = new ObjectLiteralNode($2); }
-;
-
-ArrayLiteral:
- '[' ElisionOpt ']' { $$ = new ArrayNode($2); }
- | '[' ElementList ']' { $$ = new ArrayNode($2); }
- | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2); }
-;
-
-ElementList:
- ElisionOpt AssignmentExpr { $$ = new ElementNode($1, $2); }
- | ElementList ',' ElisionOpt AssignmentExpr
- { $$ = new ElementNode($1, $3, $4); }
-;
-
-ElisionOpt:
- /* nothing */ { $$ = 0L; }
- | Elision
-;
-
-Elision:
- ',' { $$ = new ElisionNode(0L); }
- | Elision ',' { $$ = new ElisionNode($1); }
-;
-
-PropertyNameAndValueList:
- PropertyName ':' AssignmentExpr { $$ = new PropertyValueNode($1, $3); }
- | PropertyNameAndValueList ',' PropertyName ':' AssignmentExpr
- { $$ = new PropertyValueNode($3, $5, $1); }
-;
-
-PropertyName:
- IDENT { $$ = new PropertyNode($1);
- delete $1; }
- | STRING { $$ = new PropertyNode($1); delete $1; }
- | NUMBER { $$ = new PropertyNode($1); }
-;
-
-MemberExpr:
- PrimaryExpr
- | FunctionExpr
- | MemberExpr '[' Expr ']' { $$ = new AccessorNode1($1, $3); }
- | MemberExpr '.' IDENT { $$ = new AccessorNode2($1, $3);
- delete $3; }
- | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); }
-;
-
-NewExpr:
- MemberExpr
- | NEW NewExpr { $$ = new NewExprNode($2); }
-;
-
-CallExpr:
- MemberExpr Arguments { $$ = new FunctionCallNode($1, $2); }
- | CallExpr Arguments { $$ = new FunctionCallNode($1, $2); }
- | CallExpr '[' Expr ']' { $$ = new AccessorNode1($1, $3); }
- | CallExpr '.' IDENT { $$ = new AccessorNode2($1, $3); }
-;
-
-Arguments:
- '(' ')' { $$ = new ArgumentsNode(0L); }
- | '(' ArgumentList ')' { $$ = new ArgumentsNode($2); }
-;
-
-ArgumentList:
- AssignmentExpr { $$ = new ArgumentListNode($1); }
- | ArgumentList ',' AssignmentExpr { $$ = new ArgumentListNode($1, $3); }
-;
-
-LeftHandSideExpr:
- NewExpr
- | CallExpr
-;
-
-PostfixExpr: /* TODO: no line terminator here */
- LeftHandSideExpr
- | LeftHandSideExpr PLUSPLUS { $$ = new PostfixNode($1, OpPlusPlus); }
- | LeftHandSideExpr MINUSMINUS { $$ = new PostfixNode($1, OpMinusMinus); }
-;
-
-UnaryExpr:
- PostfixExpr
- | DELETE UnaryExpr { $$ = new DeleteNode($2); }
- | VOID UnaryExpr { $$ = new VoidNode($2); }
- | TYPEOF UnaryExpr { $$ = new TypeOfNode($2); }
- | PLUSPLUS UnaryExpr { $$ = new PrefixNode(OpPlusPlus, $2); }
- | AUTOPLUSPLUS UnaryExpr { $$ = new PrefixNode(OpPlusPlus, $2); }
- | MINUSMINUS UnaryExpr { $$ = new PrefixNode(OpMinusMinus, $2); }
- | AUTOMINUSMINUS UnaryExpr { $$ = new PrefixNode(OpMinusMinus, $2); }
- | '+' UnaryExpr { $$ = new UnaryPlusNode($2); }
- | '-' UnaryExpr { $$ = new NegateNode($2); }
- | '~' UnaryExpr { $$ = new BitwiseNotNode($2); }
- | '!' UnaryExpr { $$ = new LogicalNotNode($2); }
-;
-
-MultiplicativeExpr:
- UnaryExpr
- | MultiplicativeExpr '*' UnaryExpr { $$ = new MultNode($1, $3, '*'); }
- | MultiplicativeExpr '/' UnaryExpr { $$ = new MultNode($1, $3, '/'); }
- | MultiplicativeExpr '%' UnaryExpr { $$ = new MultNode($1,$3,'%'); }
-;
-
-AdditiveExpr:
- MultiplicativeExpr
- | AdditiveExpr '+' MultiplicativeExpr { $$ = new AddNode($1, $3, '+'); }
- | AdditiveExpr '-' MultiplicativeExpr { $$ = new AddNode($1, $3, '-'); }
-;
-
-ShiftExpr:
- AdditiveExpr
- | ShiftExpr LSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpLShift, $3); }
- | ShiftExpr RSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpRShift, $3); }
- | ShiftExpr URSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpURShift, $3); }
-;
-
-RelationalExpr:
- ShiftExpr
- | RelationalExpr '<' ShiftExpr
- { $$ = new RelationalNode($1, OpLess, $3); }
- | RelationalExpr '>' ShiftExpr
- { $$ = new RelationalNode($1, OpGreater, $3); }
- | RelationalExpr LE ShiftExpr
- { $$ = new RelationalNode($1, OpLessEq, $3); }
- | RelationalExpr GE ShiftExpr
- { $$ = new RelationalNode($1, OpGreaterEq, $3); }
- | RelationalExpr INSTANCEOF ShiftExpr
- { $$ = new RelationalNode($1, OpInstanceOf, $3); }
- | RelationalExpr IN ShiftExpr
- { $$ = new RelationalNode($1, OpIn, $3); }
-;
-
-EqualityExpr:
- RelationalExpr
- | EqualityExpr EQEQ RelationalExpr { $$ = new EqualNode($1, OpEqEq, $3); }
- | EqualityExpr NE RelationalExpr { $$ = new EqualNode($1, OpNotEq, $3); }
- | EqualityExpr STREQ RelationalExpr { $$ = new EqualNode($1, OpStrEq, $3); }
- | EqualityExpr STRNEQ RelationalExpr { $$ = new EqualNode($1, OpStrNEq, $3);}
-;
-
-BitwiseANDExpr:
- EqualityExpr
- | BitwiseANDExpr '&' EqualityExpr { $$ = new BitOperNode($1, OpBitAnd, $3); }
-;
-
-BitwiseXORExpr:
- BitwiseANDExpr
- | BitwiseXORExpr '^' EqualityExpr { $$ = new BitOperNode($1, OpBitXOr, $3); }
-;
-
-BitwiseORExpr:
- BitwiseXORExpr
- | BitwiseORExpr '|' EqualityExpr { $$ = new BitOperNode($1, OpBitOr, $3); }
-;
-
-LogicalANDExpr:
- BitwiseORExpr
- | LogicalANDExpr AND BitwiseORExpr
- { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
-;
-
-LogicalORExpr:
- LogicalANDExpr
- | LogicalORExpr OR LogicalANDExpr
- { $$ = new BinaryLogicalNode($1, OpOr, $3); }
-;
-
-ConditionalExpr:
- LogicalORExpr
- | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
- { $$ = new ConditionalNode($1, $3, $5); }
-;
-
-AssignmentExpr:
- ConditionalExpr
- | LeftHandSideExpr AssignmentOperator AssignmentExpr
- { $$ = new AssignNode($1, $2, $3);}
-;
-
-AssignmentOperator:
- '=' { $$ = OpEqual; }
- | PLUSEQUAL { $$ = OpPlusEq; }
- | MINUSEQUAL { $$ = OpMinusEq; }
- | MULTEQUAL { $$ = OpMultEq; }
- | DIVEQUAL { $$ = OpDivEq; }
- | LSHIFTEQUAL { $$ = OpLShift; }
- | RSHIFTEQUAL { $$ = OpRShift; }
- | URSHIFTEQUAL { $$ = OpURShift; }
- | ANDEQUAL { $$ = OpAndEq; }
- | XOREQUAL { $$ = OpXOrEq; }
- | OREQUAL { $$ = OpOrEq; }
- | MODEQUAL { $$ = OpModEq; }
-;
-
-Expr:
- AssignmentExpr
- | Expr ',' AssignmentExpr { $$ = new CommaNode($1, $3); }
-;
-
-Statement:
- Block
- | VariableStatement
- | EmptyStatement
- | ExprStatement
- | IfStatement
- | IterationStatement
- | ContinueStatement
- | BreakStatement
- | ReturnStatement
- | WithStatement
- | SwitchStatement
- | LabelledStatement
- | ThrowStatement
- | TryStatement
-;
-
-Block:
- '{' '}' { $$ = new BlockNode(0L); DBG($$, @2, @2); }
- | '{' SourceElements '}' { $$ = new BlockNode($2); DBG($$, @3, @3); }
-;
-
-StatementList:
- Statement { $$ = new StatListNode($1); }
- | StatementList Statement { $$ = new StatListNode($1, $2); }
-;
-
-VariableStatement:
- VAR VariableDeclarationList ';' { $$ = new VarStatementNode($2);
- DBG($$, @1, @3); }
- | VAR VariableDeclarationList error { if (automatic()) {
- $$ = new VarStatementNode($2);
- DBG($$, @1, @2);
- } else {
- YYABORT;
- }
- }
-;
-
-VariableDeclarationList:
- VariableDeclaration { $$ = new VarDeclListNode($1); }
- | VariableDeclarationList ',' VariableDeclaration
- { $$ = new VarDeclListNode($1, $3); }
-;
-
-VariableDeclaration:
- IDENT { $$ = new VarDeclNode($1, 0); delete $1; }
- | IDENT Initializer { $$ = new VarDeclNode($1, $2); delete $1; }
-;
-
-Initializer:
- '=' AssignmentExpr { $$ = new AssignExprNode($2); }
-;
-
-EmptyStatement:
- ';' { $$ = new EmptyStatementNode(); }
-;
-
-ExprStatement:
- Expr ';' { $$ = new ExprStatementNode($1);
- DBG($$, @1, @2); }
- | Expr error { if (automatic()) {
- $$ = new ExprStatementNode($1);
- DBG($$, @1, @1);
- } else
- YYABORT; }
-;
-
-IfStatement: /* shift/reduce conflict due to dangling else */
- IF '(' Expr ')' Statement { $$ = new IfNode($3,$5,0L);DBG($$,@1,@4); }
- | IF '(' Expr ')' Statement ELSE Statement
- { $$ = new IfNode($3,$5,$7);DBG($$,@1,@4); }
-;
-
-IterationStatement:
- DO Statement WHILE '(' Expr ')' { $$=new DoWhileNode($2,$5);DBG($$,@1,@3);}
- | WHILE '(' Expr ')' Statement { $$ = new WhileNode($3,$5);DBG($$,@1,@4); }
- | FOR '(' ExprOpt ';' ExprOpt ';' ExprOpt ')'
- Statement { $$ = new ForNode($3,$5,$7,$9);
- DBG($$,@1,@8); }
- | FOR '(' VAR VariableDeclarationList ';' ExprOpt ';' ExprOpt ')'
- Statement { $$ = new ForNode($4,$6,$8,$10);
- DBG($$,@1,@9); }
- | FOR '(' LeftHandSideExpr IN Expr ')'
- Statement { $$ = new ForInNode($3, $5, $7);
- DBG($$,@1,@6); }
- | FOR '(' VAR IDENT IN Expr ')'
- Statement { $$ = new ForInNode($4,0L,$6,$8);
- DBG($$,@1,@7);
- delete $4; }
- | FOR '(' VAR IDENT Initializer IN Expr ')'
- Statement { $$ = new ForInNode($4,$5,$7,$9);
- DBG($$,@1,@8);
- delete $4; }
-;
-
-ExprOpt:
- /* nothing */ { $$ = 0L; }
- | Expr
-;
-
-ContinueStatement:
- CONTINUE ';' { $$ = new ContinueNode(); DBG($$,@1,@2); }
- | CONTINUE error { if (automatic()) {
- $$ = new ContinueNode(); DBG($$,@1,@2);
- } else
- YYABORT; }
- | CONTINUE IDENT ';' { $$ = new ContinueNode($2); DBG($$,@1,@3);
- delete $2; }
- | CONTINUE IDENT error { if (automatic()) {
- $$ = new ContinueNode($2);DBG($$,@1,@2);
- delete $2;
- } else
- YYABORT; }
-;
-
-BreakStatement:
- BREAK ';' { $$ = new BreakNode();DBG($$,@1,@2); }
- | BREAK error { if (automatic()) {
- $$ = new BreakNode(); DBG($$,@1,@1);
- } else
- YYABORT; }
- | BREAK IDENT ';' { $$ = new BreakNode($2); DBG($$,@1,@3);
- delete $2; }
- | BREAK IDENT error { if (automatic()) {
- $$ = new BreakNode($2); DBG($$,@1,@2);
- delete $2;
- } else
- YYABORT;
- }
-;
-
-ReturnStatement:
- RETURN ';' { $$ = new ReturnNode(0L); DBG($$,@1,@2); }
- | RETURN error { if (automatic()) {
- $$ = new ReturnNode(0L); DBG($$,@1,@1);
- } else
- YYABORT; }
- | RETURN Expr ';' { $$ = new ReturnNode($2); }
- | RETURN Expr error { if (automatic())
- $$ = new ReturnNode($2);
- else
- YYABORT; }
-;
-
-WithStatement:
- WITH '(' Expr ')' Statement { $$ = new WithNode($3,$5);
- DBG($$, @1, @4); }
-;
-
-SwitchStatement:
- SWITCH '(' Expr ')' CaseBlock { $$ = new SwitchNode($3, $5);
- DBG($$, @1, @4); }
-;
-
-CaseBlock:
- '{' CaseClausesOpt '}' { $$ = new CaseBlockNode($2, 0L, 0L); }
- | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
- { $$ = new CaseBlockNode($2, $3, $4); }
-;
-
-CaseClausesOpt:
- /* nothing */ { $$ = 0L; }
- | CaseClauses
-;
-
-CaseClauses:
- CaseClause { $$ = new ClauseListNode($1); }
- | CaseClauses CaseClause { $$ = $1->append($2); }
-;
-
-CaseClause:
- CASE Expr ':' { $$ = new CaseClauseNode($2, 0L); }
- | CASE Expr ':' StatementList { $$ = new CaseClauseNode($2, $4); }
-;
-
-DefaultClause:
- DEFAULT ':' { $$ = new CaseClauseNode(0L, 0L);; }
- | DEFAULT ':' StatementList { $$ = new CaseClauseNode(0L, $3); }
-;
-
-LabelledStatement:
- IDENT ':' Statement { $3->pushLabel($1);
- $$ = new LabelNode($1, $3);
- delete $1; }
-;
-
-ThrowStatement:
- THROW Expr ';' { $$ = new ThrowNode($2); }
-;
-
-TryStatement:
- TRY Block Catch { $$ = new TryNode($2, $3); }
- | TRY Block Finally { $$ = new TryNode($2, 0L, $3); }
- | TRY Block Catch Finally { $$ = new TryNode($2, $3, $4); }
-;
-
-Catch:
- CATCH '(' IDENT ')' Block { $$ = new CatchNode($3, $5); delete $3; }
-;
-
-Finally:
- FINALLY Block { $$ = new FinallyNode($2); }
-;
-
-FunctionDeclaration:
- FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncDeclNode($2, 0L, $5);
- delete $2; }
- | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
- { $$ = new FuncDeclNode($2, $4, $6);
- delete $2; }
-
-FunctionExpr:
- FUNCTION '(' ')' FunctionBody { $$ = new FuncExprNode(0L, $4); }
- | FUNCTION '(' FormalParameterList ')' FunctionBody
- { $$ = new FuncExprNode($3, $5); }
-
-;
-
-FormalParameterList:
- IDENT { $$ = new ParameterNode($1); delete $1; }
- | FormalParameterList ',' IDENT { $$ = $1->append($3);
- delete $3; }
-;
-
-FunctionBody:
- '{' '}' /* TODO: spec ??? */ { $$ = new FunctionBodyNode(0L);
- DBG($$, @1, @2);}
- | '{' SourceElements '}' { $$ = new FunctionBodyNode($2);
- DBG($$, @1, @3);}
-;
-
-Program:
- /* nothing, empty script */ { $$ = new ProgramNode(0L);
- Parser::progNode = $$; }
- | SourceElements { $$ = new ProgramNode($1);
- Parser::progNode = $$; }
-;
-
-SourceElements:
- SourceElement { $$ = new SourceElementsNode($1); }
- | SourceElements SourceElement { $$ = new SourceElementsNode($1, $2); }
-;
-
-SourceElement:
- Statement { $$ = new SourceElementNode($1); }
- | FunctionDeclaration { $$ = new SourceElementNode($1); }
-;
-
-%%
-
-int yyerror (const char *) /* Called by yyparse on error */
-{
-// fprintf(stderr, "ERROR: %s at line %d\n",
-// s, KJScript::lexer()->lineNo());
- return 1;
-}
-
-/* may we automatically insert a semicolon ? */
-bool automatic()
-{
- if (yychar == '}' || yychar == 0)
- return true;
- else if (Lexer::curr()->prevTerminator())
- return true;
-
- return false;
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * 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 <stdio.h>
-#include <math.h>
-#include <assert.h>
-#ifndef NDEBUG
-#include <strings.h> // for strdup
-#endif
-
-#include "array_object.h"
-#include "bool_object.h"
-#include "collector.h"
-#include "date_object.h"
-#include "debugger.h"
-#include "error_object.h"
-#include "function_object.h"
-#include "internal.h"
-#include "lexer.h"
-#include "math_object.h"
-#include "nodes.h"
-#include "number_object.h"
-#include "object.h"
-#include "object_object.h"
-#include "operations.h"
-#include "regexp_object.h"
-#include "string_object.h"
-
-#define I18N_NOOP(s) s
-
-extern int kjsyyparse();
-
-using namespace KJS;
-
-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;
-};
-
-// ------------------------------ UndefinedImp ---------------------------------
-
-UndefinedImp *UndefinedImp::staticUndefined = 0;
-
-Value UndefinedImp::toPrimitive(ExecState */*exec*/, Type) const
-{
- return Value((ValueImp*)this);
-}
-
-bool UndefinedImp::toBoolean(ExecState */*exec*/) const
-{
- return false;
-}
-
-double UndefinedImp::toNumber(ExecState */*exec*/) const
-{
- return NaN;
-}
-
-UString UndefinedImp::toString(ExecState */*exec*/) const
-{
- return "undefined";
-}
-
-Object UndefinedImp::toObject(ExecState *exec) const
-{
- Object err = Error::create(exec, TypeError, I18N_NOOP("Undefined value"));
- exec->setException(err);
- return err;
-}
-
-// ------------------------------ NullImp --------------------------------------
-
-NullImp *NullImp::staticNull = 0;
-
-Value NullImp::toPrimitive(ExecState */*exec*/, Type) const
-{
- return Value((ValueImp*)this);
-}
-
-bool NullImp::toBoolean(ExecState */*exec*/) const
-{
- return false;
-}
-
-double NullImp::toNumber(ExecState */*exec*/) const
-{
- return 0.0;
-}
-
-UString NullImp::toString(ExecState */*exec*/) const
-{
- return "null";
-}
-
-Object NullImp::toObject(ExecState *exec) const
-{
- Object err = Error::create(exec, TypeError, I18N_NOOP("Null value"));
- exec->setException(err);
- return err;
-}
-
-// ------------------------------ BooleanImp -----------------------------------
-
-BooleanImp* BooleanImp::staticTrue = 0;
-BooleanImp* BooleanImp::staticFalse = 0;
-
-Value BooleanImp::toPrimitive(ExecState */*exec*/, Type) const
-{
- return Value((ValueImp*)this);
-}
-
-bool BooleanImp::toBoolean(ExecState */*exec*/) const
-{
- return val;
-}
-
-double BooleanImp::toNumber(ExecState */*exec*/) const
-{
- return val ? 1.0 : 0.0;
-}
-
-UString BooleanImp::toString(ExecState */*exec*/) const
-{
- return val ? "true" : "false";
-}
-
-Object BooleanImp::toObject(ExecState *exec) const
-{
- List args;
- args.append(Boolean(const_cast<BooleanImp*>(this)));
- return Object::dynamicCast(exec->interpreter()->builtinBoolean().construct(exec,args));
-}
-
-// ------------------------------ StringImp ------------------------------------
-
-StringImp::StringImp(const UString& v)
- : val(v)
-{
-}
-
-Value StringImp::toPrimitive(ExecState */*exec*/, Type) const
-{
- return Value((ValueImp*)this);
-}
-
-bool StringImp::toBoolean(ExecState */*exec*/) const
-{
- return (val.size() > 0);
-}
-
-double StringImp::toNumber(ExecState */*exec*/) const
-{
- return val.toDouble();
-}
-
-UString StringImp::toString(ExecState */*exec*/) const
-{
- return val;
-}
-
-Object StringImp::toObject(ExecState *exec) const
-{
- List args;
- args.append(String(const_cast<StringImp*>(this)));
- return Object::dynamicCast(exec->interpreter()->builtinString().construct(exec,args));
-}
-
-// ------------------------------ NumberImp ------------------------------------
-
-NumberImp::NumberImp(double v)
- : val(v)
-{
-}
-
-Value NumberImp::toPrimitive(ExecState *, Type) const
-{
- return Number((NumberImp*)this);
-}
-
-bool NumberImp::toBoolean(ExecState *) const
-{
- return !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
-}
-
-double NumberImp::toNumber(ExecState *) const
-{
- return val;
-}
-
-UString NumberImp::toString(ExecState *) const
-{
- return UString::from(val);
-}
-
-Object NumberImp::toObject(ExecState *exec) const
-{
- List args;
- args.append(Number(const_cast<NumberImp*>(this)));
- return Object::dynamicCast(exec->interpreter()->builtinNumber().construct(exec,args));
-}
-
-// ------------------------------ ReferenceImp ---------------------------------
-
-ReferenceImp::ReferenceImp(const Value& v, const UString& p)
- : base(v.imp()), prop(p)
-{
-}
-
-void ReferenceImp::mark()
-{
- ValueImp::mark();
- if (base && !base->marked())
- base->mark();
-}
-
-Value ReferenceImp::toPrimitive(ExecState */*exec*/, Type /*preferredType*/) const
-{
- // invalid for Reference
- assert(false);
- return Value();
-}
-
-bool ReferenceImp::toBoolean(ExecState */*exec*/) const
-{
- // invalid for Reference
- assert(false);
- return false;
-}
-
-double ReferenceImp::toNumber(ExecState */*exec*/) const
-{
- // invalid for Reference
- assert(false);
- return 0;
-}
-
-UString ReferenceImp::toString(ExecState */*exec*/) const
-{
- // invalid for Reference
- assert(false);
- return UString::null;
-}
-
-Object ReferenceImp::toObject(ExecState */*exec*/) const
-{
- // invalid for Reference
- assert(false);
- return Object();
-}
-
-// ------------------------------ LabelStack -----------------------------------
-
-LabelStack::LabelStack(const LabelStack &other)
-{
- tos = 0;
- *this = other;
-}
-
-LabelStack &LabelStack::operator=(const LabelStack &other)
-{
- clear();
- tos = 0;
- StackElem *cur = 0;
- StackElem *se = other.tos;
- while (se) {
- StackElem *newPrev = new StackElem;
- newPrev->prev = 0;
- newPrev->id = se->id;
- if (cur)
- cur->prev = newPrev;
- else
- tos = newPrev;
- cur = newPrev;
- se = se->prev;
- }
- return *this;
-}
-
-bool LabelStack::push(const UString &id)
-{
- if (id.isEmpty() || contains(id))
- return false;
-
- StackElem *newtos = new StackElem;
- newtos->id = id;
- newtos->prev = tos;
- tos = newtos;
- return true;
-}
-
-bool LabelStack::contains(const UString &id) const
-{
- if (id.isEmpty())
- return true;
-
- for (StackElem *curr = tos; curr; curr = curr->prev)
- if (curr->id == id)
- return true;
-
- return false;
-}
-
-void LabelStack::pop()
-{
- if (tos) {
- StackElem *prev = tos->prev;
- delete tos;
- tos = prev;
- }
-}
-
-LabelStack::~LabelStack()
-{
- clear();
-}
-
-void LabelStack::clear()
-{
- StackElem *prev;
-
- while (tos) {
- prev = tos->prev;
- delete tos;
- tos = prev;
- }
-}
-
-// ------------------------------ CompletionImp --------------------------------
-
-CompletionImp::CompletionImp(ComplType c, const Value& v, const UString& t)
- : comp(c), val(v.imp()), tar(t)
-{
-}
-
-CompletionImp::~CompletionImp()
-{
-}
-
-void CompletionImp::mark()
-{
- ValueImp::mark();
-
- if (val && !val->marked())
- val->mark();
-}
-
-Value CompletionImp::toPrimitive(ExecState */*exec*/, Type /*preferredType*/) const
-{
- // invalid for Completion
- assert(false);
- return Value();
-}
-
-bool CompletionImp::toBoolean(ExecState */*exec*/) const
-{
- // invalid for Completion
- assert(false);
- return false;
-}
-
-double CompletionImp::toNumber(ExecState */*exec*/) const
-{
- // invalid for Completion
- assert(false);
- return 0;
-}
-
-UString CompletionImp::toString(ExecState */*exec*/) const
-{
- // invalid for Completion
- assert(false);
- return UString::null;
-}
-
-Object CompletionImp::toObject(ExecState */*exec*/) const
-{
- // invalid for Completion
- assert(false);
- return Object();
-}
-
-// ------------------------------ ListImp --------------------------------------
-
-#ifdef KJS_DEBUG_MEM
-int ListImp::count = 0;
-#endif
-
-Value ListImp::toPrimitive(ExecState */*exec*/, Type /*preferredType*/) const
-{
- // invalid for List
- assert(false);
- return Value();
-}
-
-bool ListImp::toBoolean(ExecState */*exec*/) const
-{
- // invalid for List
- assert(false);
- return false;
-}
-
-double ListImp::toNumber(ExecState */*exec*/) const
-{
- // invalid for List
- assert(false);
- return 0;
-}
-
-UString ListImp::toString(ExecState */*exec*/) const
-{
- // invalid for List
- assert(false);
- return UString::null;
-}
-
-Object ListImp::toObject(ExecState */*exec*/) const
-{
- // invalid for List
- assert(false);
- return Object();
-}
-
-ListImp::ListImp()
-{
-#ifdef KJS_DEBUG_MEM
- count++;
-#endif
-
- hook = new ListNode(Null(), 0L, 0L);
- hook->next = hook;
- hook->prev = hook;
- //fprintf(stderr,"ListImp::ListImp %p hook=%p\n",this,hook);
-}
-
-ListImp::~ListImp()
-{
- //fprintf(stderr,"ListImp::~ListImp %p\n",this);
-#ifdef KJS_DEBUG_MEM
- count--;
-#endif
-
- clear();
- delete hook;
-}
-
-void ListImp::mark()
-{
- ListNode *n = hook->next;
- while (n != hook) {
- if (!n->member->marked())
- n->member->mark();
- n = n->next;
- }
- ValueImp::mark();
-}
-
-void ListImp::append(const Value& obj)
-{
- ListNode *n = new ListNode(obj, hook->prev, hook);
- hook->prev->next = n;
- hook->prev = n;
-}
-
-void ListImp::prepend(const Value& obj)
-{
- ListNode *n = new ListNode(obj, hook, hook->next);
- hook->next->prev = n;
- hook->next = n;
-}
-
-void ListImp::appendList(const List& lst)
-{
- ListIterator it = lst.begin();
- ListIterator e = lst.end();
- while(it != e) {
- append(*it);
- ++it;
- }
-}
-
-void ListImp::prependList(const List& lst)
-{
- ListIterator it = lst.end();
- ListIterator e = lst.begin();
- while(it != e) {
- --it;
- prepend(*it);
- }
-}
-
-void ListImp::removeFirst()
-{
- erase(hook->next);
-}
-
-void ListImp::removeLast()
-{
- erase(hook->prev);
-}
-
-void ListImp::remove(const Value &obj)
-{
- if (obj.isNull())
- return;
- ListNode *n = hook->next;
- while (n != hook) {
- if (n->member == obj.imp()) {
- erase(n);
- return;
- }
- n = n->next;
- }
-}
-
-void ListImp::clear()
-{
- ListNode *n = hook->next;
- while (n != hook) {
- n = n->next;
- delete n->prev;
- }
-
- hook->next = hook;
- hook->prev = hook;
-}
-
-ListImp *ListImp::copy() const
-{
- ListImp* newList = new ListImp;
-
- ListIterator e = end();
- ListIterator it = begin();
-
- while(it != e) {
- newList->append(*it);
- ++it;
- }
-
- //fprintf( stderr, "ListImp::copy returning newList=%p\n", newList );
- return newList;
-}
-
-void ListImp::erase(ListNode *n)
-{
- if (n != hook) {
- n->next->prev = n->prev;
- n->prev->next = n->next;
- delete n;
- }
-}
-
-bool ListImp::isEmpty() const
-{
- return (hook->prev == hook);
-}
-
-int ListImp::size() const
-{
- int s = 0;
- ListNode *node = hook;
- while ((node = node->next) != hook)
- s++;
-
- return s;
-}
-
-Value ListImp::at(int i) const
-{
- if (i < 0 || i >= size())
- return Undefined();
-
- ListIterator it = begin();
- int j = 0;
- while ((j++ < i))
- it++;
-
- return *it;
-}
-
-ListImp *ListImp::emptyList = 0L;
-
-ListImp *ListImp::empty()
-{
- if (!emptyList)
- emptyList = new ListImp();
- return emptyList;
-}
-
-// ------------------------------ ContextImp -----------------------------------
-
-
-// ECMA 10.2
-ContextImp::ContextImp(Object &glob, ExecState *exec, Object &thisV, CodeType type,
- ContextImp *_callingContext, FunctionImp *func, const List &args)
-{
- codeType = type;
- callingCon = _callingContext;
-
- // create and initialize activation object (ECMA 10.1.6)
- if (type == FunctionCode || type == AnonymousCode ) {
- activation = Object(new ActivationImp(exec,func,args));
- variable = activation;
- } else {
- activation = Object();
- variable = glob;
- }
-
- // ECMA 10.2
- switch(type) {
- case EvalCode:
- if (callingCon) {
- scope = callingCon->scopeChain().copy();
- variable = callingCon->variableObject();
- thisVal = callingCon->thisValue();
- break;
- } // else same as GlobalCode
- case GlobalCode:
- scope = List();
- scope.append(glob);
- thisVal = Object(static_cast<ObjectImp*>(glob.imp()));
- break;
- case FunctionCode:
- case AnonymousCode:
- if (type == FunctionCode) {
- scope = func->scope().copy();
- scope.prepend(activation);
- } else {
- scope = List();
- scope.append(activation);
- scope.append(glob);
- }
- variable = activation; // TODO: DontDelete ? (ECMA 10.2.3)
- thisVal = thisV;
- break;
- }
-
-}
-
-ContextImp::~ContextImp()
-{
-}
-
-void ContextImp::pushScope(const Object &s)
-{
- scope.prepend(s);
-}
-
-void ContextImp::popScope()
-{
- scope.removeFirst();
-}
-
-// ------------------------------ Parser ---------------------------------------
-
-ProgramNode *Parser::progNode = 0;
-int Parser::sid = 0;
-
-ProgramNode *Parser::parse(const UChar *code, unsigned int length, int *sourceId,
- int *errLine, UString *errMsg)
-{
- if (errLine)
- *errLine = -1;
- if (errMsg)
- *errMsg = 0;
-
- Lexer::curr()->setCode(code, length);
- progNode = 0;
- sid++;
- if (sourceId)
- *sourceId = sid;
- // Enable this (and the #define YYDEBUG in grammar.y) to debug a parse error
- //extern int kjsyydebug;
- //kjsyydebug=1;
- int parseError = kjsyyparse();
- ProgramNode *prog = progNode;
- progNode = 0;
- sid = -1;
-
- if (parseError) {
- int eline = Lexer::curr()->lineNo();
- if (errLine)
- *errLine = eline;
- if (errMsg)
- *errMsg = "Parse error at line " + UString::from(eline);
-#ifndef NDEBUG
- fprintf(stderr, "KJS: JavaScript parse error at line %d.\n", eline);
-#endif
- delete prog;
- return 0;
- }
-
- return prog;
-}
-
-// ------------------------------ InterpreterImp -------------------------------
-
-InterpreterImp* InterpreterImp::s_hook = 0L;
-
-void InterpreterImp::globalInit()
-{
- //fprintf( stderr, "InterpreterImp::globalInit()\n" );
- UndefinedImp::staticUndefined = new UndefinedImp();
- UndefinedImp::staticUndefined->ref();
- NullImp::staticNull = new NullImp();
- NullImp::staticNull->ref();
- BooleanImp::staticTrue = new BooleanImp(true);
- BooleanImp::staticTrue->ref();
- BooleanImp::staticFalse = new BooleanImp(false);
- BooleanImp::staticFalse->ref();
-}
-
-void InterpreterImp::globalClear()
-{
- //fprintf( stderr, "InterpreterImp::globalClear()\n" );
- UndefinedImp::staticUndefined->deref();
- UndefinedImp::staticUndefined->setGcAllowed();
- UndefinedImp::staticUndefined = 0L;
- NullImp::staticNull->deref();
- NullImp::staticNull->setGcAllowed();
- NullImp::staticNull = 0L;
- BooleanImp::staticTrue->deref();
- BooleanImp::staticTrue->setGcAllowed();
- BooleanImp::staticTrue = 0L;
- BooleanImp::staticFalse->deref();
- BooleanImp::staticFalse->setGcAllowed();
- BooleanImp::staticFalse = 0L;
-}
-
-InterpreterImp::InterpreterImp(Interpreter *interp, const Object &glob)
-{
- // add this interpreter to the global chain
- // as a root set for garbage collection
- if (s_hook) {
- prev = s_hook;
- next = s_hook->next;
- s_hook->next->prev = this;
- s_hook->next = this;
- } else {
- // This is the first interpreter
- s_hook = next = prev = this;
- globalInit();
- }
-
- m_interpreter = interp;
- global = glob;
- globExec = new ExecState(m_interpreter,0);
- dbg = 0;
- m_compatMode = Interpreter::NativeMode;
-
- // initialize properties of the global object
-
- // Contructor prototype objects (Object.prototype, Array.prototype etc)
-
- FunctionPrototypeImp *funcProto = new FunctionPrototypeImp(globExec);
- b_FunctionPrototype = Object(funcProto);
- ObjectPrototypeImp *objProto = new ObjectPrototypeImp(globExec,funcProto);
- b_ObjectPrototype = Object(objProto);
- funcProto->setPrototype(b_ObjectPrototype);
-
- ArrayPrototypeImp *arrayProto = new ArrayPrototypeImp(globExec,objProto);
- b_ArrayPrototype = Object(arrayProto);
- StringPrototypeImp *stringProto = new StringPrototypeImp(globExec,objProto);
- b_StringPrototype = Object(stringProto);
- BooleanPrototypeImp *booleanProto = new BooleanPrototypeImp(globExec,objProto,funcProto);
- b_BooleanPrototype = Object(booleanProto);
- NumberPrototypeImp *numberProto = new NumberPrototypeImp(globExec,objProto,funcProto);
- b_NumberPrototype = Object(numberProto);
- DatePrototypeImp *dateProto = new DatePrototypeImp(globExec,objProto);
- b_DatePrototype = Object(dateProto);
- RegExpPrototypeImp *regexpProto = new RegExpPrototypeImp(globExec,objProto,funcProto);
- b_RegExpPrototype = Object(regexpProto);
- ErrorPrototypeImp *errorProto = new ErrorPrototypeImp(globExec,objProto,funcProto);
- b_ErrorPrototype = Object(errorProto);
-
- static_cast<ObjectImp*>(global.imp())->setPrototype(b_ObjectPrototype);
-
- // Constructors (Object, Array, etc.)
-
- ObjectObjectImp *objectObj = new ObjectObjectImp(globExec,objProto,funcProto);
- b_Object = Object(objectObj);
- FunctionObjectImp *funcObj = new FunctionObjectImp(globExec,funcProto);
- b_Function = Object(funcObj);
- ArrayObjectImp *arrayObj = new ArrayObjectImp(globExec,funcProto,arrayProto);
- b_Array = Object(arrayObj);
- StringObjectImp *stringObj = new StringObjectImp(globExec,funcProto,stringProto);
- b_String = Object(stringObj);
- BooleanObjectImp *booleanObj = new BooleanObjectImp(globExec,funcProto,booleanProto);
- b_Boolean = Object(booleanObj);
- NumberObjectImp *numberObj = new NumberObjectImp(globExec,funcProto,numberProto);
- b_Number = Object(numberObj);
- DateObjectImp *dateObj = new DateObjectImp(globExec,funcProto,dateProto);
- b_Date = Object(dateObj);
- RegExpObjectImp *regexpObj = new RegExpObjectImp(globExec,regexpProto,funcProto);
- b_RegExp = Object(regexpObj);
- ErrorObjectImp *errorObj = new ErrorObjectImp(globExec,funcProto,errorProto);
- b_Error = Object(errorObj);
-
- // Error object prototypes
- b_evalErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,EvalError,
- "EvalError","EvalError"));
- b_rangeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,RangeError,
- "RangeError","RangeError"));
- b_referenceErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,ReferenceError,
- "ReferenceError","ReferenceError"));
- b_syntaxErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,SyntaxError,
- "SyntaxError","SyntaxError"));
- b_typeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,TypeError,
- "TypeError","TypeError"));
- b_uriErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,URIError,
- "URIError","URIError"));
-
- // Error objects
- b_evalError = Object(new NativeErrorImp(globExec,funcProto,b_evalErrorPrototype));
- b_rangeError = Object(new NativeErrorImp(globExec,funcProto,b_rangeErrorPrototype));
- b_referenceError = Object(new NativeErrorImp(globExec,funcProto,b_referenceErrorPrototype));
- b_syntaxError = Object(new NativeErrorImp(globExec,funcProto,b_syntaxErrorPrototype));
- b_typeError = Object(new NativeErrorImp(globExec,funcProto,b_typeErrorPrototype));
- b_uriError = Object(new NativeErrorImp(globExec,funcProto,b_uriErrorPrototype));
-
- // ECMA 15.3.4.1
- funcProto->put(globExec,"constructor", b_Function, DontEnum);
-
- global.put(globExec,"Object", b_Object, DontEnum);
- global.put(globExec,"Function", b_Function, DontEnum);
- global.put(globExec,"Array", b_Array, DontEnum);
- global.put(globExec,"Boolean", b_Boolean, DontEnum);
- global.put(globExec,"String", b_String, DontEnum);
- global.put(globExec,"Number", b_Number, DontEnum);
- global.put(globExec,"Date", b_Date, DontEnum);
- global.put(globExec,"RegExp", b_RegExp, DontEnum);
- global.put(globExec,"Error", b_Error, DontEnum);
- // Using Internal for those to have something != 0
- // (see kjs_window). Maybe DontEnum would be ok too ?
- global.put(globExec,"EvalError",b_evalError, Internal);
- global.put(globExec,"RangeError",b_rangeError, Internal);
- global.put(globExec,"ReferenceError",b_referenceError, Internal);
- global.put(globExec,"SyntaxError",b_syntaxError, Internal);
- global.put(globExec,"TypeError",b_typeError, Internal);
- global.put(globExec,"URIError",b_uriError, Internal);
-
- // Set the "constructor" property of all builtin constructors
- objProto->put(globExec, "constructor", b_Object, DontEnum | DontDelete | ReadOnly);
- funcProto->put(globExec, "constructor", b_Function, DontEnum | DontDelete | ReadOnly);
- arrayProto->put(globExec, "constructor", b_Array, DontEnum | DontDelete | ReadOnly);
- booleanProto->put(globExec, "constructor", b_Boolean, DontEnum | DontDelete | ReadOnly);
- stringProto->put(globExec, "constructor", b_String, DontEnum | DontDelete | ReadOnly);
- numberProto->put(globExec, "constructor", b_Number, DontEnum | DontDelete | ReadOnly);
- dateProto->put(globExec, "constructor", b_Date, DontEnum | DontDelete | ReadOnly);
- regexpProto->put(globExec, "constructor", b_RegExp, DontEnum | DontDelete | ReadOnly);
- errorProto->put(globExec, "constructor", b_Error, DontEnum | DontDelete | ReadOnly);
- b_evalErrorPrototype.put(globExec, "constructor", b_evalError, DontEnum | DontDelete | ReadOnly);
- b_rangeErrorPrototype.put(globExec, "constructor", b_rangeError, DontEnum | DontDelete | ReadOnly);
- b_referenceErrorPrototype.put(globExec, "constructor", b_referenceError, DontEnum | DontDelete | ReadOnly);
- b_syntaxErrorPrototype.put(globExec, "constructor", b_syntaxError, DontEnum | DontDelete | ReadOnly);
- b_typeErrorPrototype.put(globExec, "constructor", b_typeError, DontEnum | DontDelete | ReadOnly);
- b_uriErrorPrototype.put(globExec, "constructor", b_uriError, DontEnum | DontDelete | ReadOnly);
-
- // built-in values
- global.put(globExec,"NaN", Number(NaN), DontEnum);
- global.put(globExec,"Infinity", Number(Inf), DontEnum);
- global.put(globExec,"undefined", Undefined(), DontEnum);
-
- // built-in functions
- global.put(globExec,"eval", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Eval, 1)), DontEnum);
- global.put(globExec,"parseInt", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseInt, 2)), DontEnum);
- global.put(globExec,"parseFloat", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseFloat, 1)), DontEnum);
- global.put(globExec,"isNaN", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsNaN, 1)), DontEnum);
- global.put(globExec,"isFinite", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsFinite, 1)), DontEnum);
- global.put(globExec,"escape", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Escape, 1)), DontEnum);
- global.put(globExec,"unescape", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::UnEscape, 1)), DontEnum);
-
- // built-in objects
- global.put(globExec,"Math", Object(new MathObjectImp(globExec,objProto)), DontEnum);
-
- recursion = 0;
-}
-
-InterpreterImp::~InterpreterImp()
-{
- if (dbg)
- dbg->detach(m_interpreter);
- delete globExec;
- globExec = 0L;
- clear();
-}
-
-void InterpreterImp::clear()
-{
- //fprintf(stderr,"InterpreterImp::clear\n");
- // remove from global chain (see init())
- next->prev = prev;
- prev->next = next;
- s_hook = next;
- if (s_hook == this)
- {
- // This was the last interpreter
- s_hook = 0L;
- globalClear();
- }
-}
-
-void InterpreterImp::mark()
-{
- //if (exVal && !exVal->marked())
- // exVal->mark();
- //if (retVal && !retVal->marked())
- // retVal->mark();
- if (UndefinedImp::staticUndefined && !UndefinedImp::staticUndefined->marked())
- UndefinedImp::staticUndefined->mark();
- if (NullImp::staticNull && !NullImp::staticNull->marked())
- NullImp::staticNull->mark();
- if (BooleanImp::staticTrue && !BooleanImp::staticTrue->marked())
- BooleanImp::staticTrue->mark();
- if (BooleanImp::staticFalse && !BooleanImp::staticFalse->marked())
- BooleanImp::staticFalse->mark();
- if (ListImp::emptyList && !ListImp::emptyList->marked())
- ListImp::emptyList->mark();
- //fprintf( stderr, "InterpreterImp::mark this=%p global.imp()=%p\n", this, global.imp() );
- if (global.imp())
- global.imp()->mark();
- if (m_interpreter)
- m_interpreter->mark();
-}
-
-bool InterpreterImp::checkSyntax(const UString &code)
-{
- // Parser::parse() returns 0 in a syntax error occurs, so we just check for that
- ProgramNode *progNode = Parser::parse(code.data(),code.size(),0,0,0);
- bool ok = (progNode != 0);
- delete progNode;
- return ok;
-}
-
-Completion InterpreterImp::evaluate(const UString &code, const Value &thisV)
-{
- // prevent against infinite recursion
- if (recursion >= 20) {
- return Completion(Throw,Error::create(globExec,GeneralError,"Recursion too deep"));
- }
-
- // parse the source code
- int sid;
- int errLine;
- UString errMsg;
- ProgramNode *progNode = Parser::parse(code.data(),code.size(),&sid,&errLine,&errMsg);
-
- // notify debugger that source has been parsed
- if (dbg) {
- bool cont = dbg->sourceParsed(globExec,sid,code,errLine);
- if (!cont)
- return Completion(Break);
- }
-
- // no program node means a syntax occurred
- if (!progNode) {
- Object err = Error::create(globExec,SyntaxError,errMsg.ascii(),errLine);
- err.put(globExec,"sid",Number(sid));
- return Completion(Throw,err);
- }
-
- globExec->clearException();
-
- recursion++;
- progNode->ref();
-
- Object globalObj = globalObject();
- Object thisObj = globalObject();
-
- if (!thisV.isNull()) {
- // "this" must be an object... use same rules as Function.prototype.apply()
- if (thisV.isA(NullType) || thisV.isA(UndefinedType))
- thisObj = globalObject();
- else {
- thisObj = thisV.toObject(globExec);
- }
- }
-
- Completion res;
- if (globExec->hadException()) {
- // the thisArg.toObject() conversion above might have thrown an exception - if so,
- // propagate it back
- res = Completion(Throw,globExec->exception());
- }
- else {
- // execute the code
- ExecState *exec1 = 0;
- ContextImp *ctx = new ContextImp(globalObj, exec1, thisObj);
- ExecState *newExec = new ExecState(m_interpreter,ctx);
-
- res = progNode->execute(newExec);
-
- delete newExec;
- delete ctx;
- }
-
- if (progNode->deref())
- delete progNode;
- recursion--;
-
- return res;
-}
-
-void InterpreterImp::setDebugger(Debugger *d)
-{
- if (d)
- d->detach(m_interpreter);
- dbg = d;
-}
-
-// ------------------------------ InternalFunctionImp --------------------------
-
-const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
-
-InternalFunctionImp::InternalFunctionImp(FunctionPrototypeImp *funcProto)
- : ObjectImp(Object(funcProto))
-{
-}
-
-bool InternalFunctionImp::implementsHasInstance() const
-{
- return true;
-}
-
-Boolean InternalFunctionImp::hasInstance(ExecState *exec, const Value &value)
-{
- if (value.type() != ObjectType)
- return Boolean(false);
-
- Value prot = get(exec,"prototype");
- if (prot.type() != ObjectType && prot.type() != NullType) {
- Object err = Error::create(exec, TypeError, "Invalid prototype encountered "
- "in instanceof operation.");
- exec->setException(err);
- return Boolean(false);
- }
-
- Object v = Object(static_cast<ObjectImp*>(value.imp()));
- while ((v = Object::dynamicCast(v.prototype())).imp()) {
- if (v.imp() == prot.imp())
- return Boolean(true);
- }
- return Boolean(false);
-}
-
-// ------------------------------ global functions -----------------------------
-
-double KJS::roundValue(ExecState *exec, const Value &v)
-{
- if (v.type() == UndefinedType) /* TODO: see below */
- return 0.0;
- Number n = v.toNumber(exec);
- 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;
-}
-
-#ifndef NDEBUG
-#include <stdio.h>
-void KJS::printInfo(ExecState *exec, const char *s, const Value &o, int lineno)
-{
- if (o.isNull())
- fprintf(stderr, "KJS: %s: (null)", s);
- else {
- Value v = o;
- if (o.isA(ReferenceType))
- v = o.getValue(exec);
-
- UString name;
- switch ( v.type() ) {
- case UnspecifiedType:
- name = "Unspecified";
- break;
- case UndefinedType:
- name = "Undefined";
- break;
- case NullType:
- name = "Null";
- break;
- case BooleanType:
- name = "Boolean";
- break;
- case StringType:
- name = "String";
- break;
- case NumberType:
- name = "Number";
- break;
- case ObjectType:
- name = Object::dynamicCast(v).className();
- if (name.isNull())
- name = "(unknown class)";
- break;
- case ReferenceType:
- name = "Reference";
- break;
- case ListType:
- name = "List";
- break;
- case CompletionType:
- name = "Completion";
- break;
- default:
- break;
- }
- UString vString = v.toString(exec);
- if ( vString.size() > 50 )
- vString = vString.substr( 0, 50 ) + "...";
- // Can't use two UString::ascii() in the same fprintf call
- CString tempString( vString.cstring() );
-
- fprintf(stderr, "KJS: %s: %s : %s (%p)",
- s, tempString.c_str(), name.ascii(), (void*)v.imp());
-
- if (lineno >= 0)
- fprintf(stderr, ", line %d\n",lineno);
- else
- fprintf(stderr, "\n");
- if (!o.isNull())
- if (o.isA(ReferenceType)) {
- fprintf(stderr, "KJS: Was property '%s'\n", o.getPropertyName(exec).ascii());
- printInfo(exec,"of", o.getBase(exec));
- }
- }
-}
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * 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.
- *
- */
-
-#ifndef _INTERNAL_H_
-#define _INTERNAL_H_
-
-#include "ustring.h"
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-
-#define I18N_NOOP(s) s
-
-namespace KJS {
-
- static const double D16 = 65536.0;
- static const double D32 = 4294967296.0;
-
- class ProgramNode;
- class FunctionBodyNode;
- class FunctionPrototypeImp;
- class FunctionImp;
- class Debugger;
-
- // ---------------------------------------------------------------------------
- // Primitive impls
- // ---------------------------------------------------------------------------
-
- class UndefinedImp : public ValueImp {
- public:
- UndefinedImp() {}
- virtual ~UndefinedImp() { }
-
- Type type() const { return UndefinedType; }
-
- Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- UString toString(ExecState *exec) const;
- Object toObject(ExecState *exec) const;
-
- static UndefinedImp *staticUndefined;
- };
-
- class NullImp : public ValueImp {
- public:
- NullImp() {}
- virtual ~NullImp() { }
-
- Type type() const { return NullType; }
-
- Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- UString toString(ExecState *exec) const;
- Object toObject(ExecState *exec) const;
-
- static NullImp *staticNull;
- };
-
- class BooleanImp : public ValueImp {
- public:
- virtual ~BooleanImp() { }
- BooleanImp(bool v = false) : val(v) { }
- bool value() const { return val; }
-
- Type type() const { return BooleanType; }
-
- Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- UString toString(ExecState *exec) const;
- Object toObject(ExecState *exec) const;
-
- static BooleanImp *staticTrue;
- static BooleanImp *staticFalse;
- private:
- bool val;
- };
-
- class StringImp : public ValueImp {
- public:
- StringImp(const UString& v);
- virtual ~StringImp() { }
- UString value() const { return val; }
-
- Type type() const { return StringType; }
-
- Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- UString toString(ExecState *exec) const;
- Object toObject(ExecState *exec) const;
-
- private:
- UString val;
- };
-
- class NumberImp : public ValueImp {
- public:
- NumberImp(double v);
- virtual ~NumberImp() { }
- double value() const { return val; }
-
- Type type() const { return NumberType; }
-
- Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- UString toString(ExecState *exec) const;
- Object toObject(ExecState *exec) const;
-
- private:
- double val;
- };
-
- // ---------------------------------------------------------------------------
- // Internal type impls
- // ---------------------------------------------------------------------------
-
- class ReferenceImp : public ValueImp {
- public:
-
- ReferenceImp(const Value& v, const UString& p);
- virtual ~ReferenceImp() { }
- virtual void mark();
-
- Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- UString toString(ExecState *exec) const;
- Object toObject(ExecState *exec) const;
-
- Value getBase() const { return Value(base); }
- UString getPropertyName() const { return prop; }
-
- Type type() const { return ReferenceType; }
-
- private:
- ValueImp *base;
- UString prop;
- };
-
- class CompletionImp : public ValueImp {
- public:
- Type type() const { return CompletionType; }
-
- CompletionImp(ComplType c, const Value& v, const UString& t);
- virtual ~CompletionImp();
- virtual void mark();
-
- Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- UString toString(ExecState *exec) const;
- Object toObject(ExecState *exec) const;
-
- ComplType complType() const { return comp; }
- Value value() const { return Value(val); }
- UString target() const { return tar; }
-
- private:
- ComplType comp;
- ValueImp * val;
- UString tar;
- };
-
- /**
- * @internal
- */
- class ListNode {
- friend class List;
- friend class ListImp;
- friend class ListIterator;
- ListNode(Value val, ListNode *p, ListNode *n)
- : member(val.imp()), prev(p), next(n) {};
- ValueImp *member;
- ListNode *prev, *next;
- };
-
- class ListImp : public ValueImp {
- friend class ListIterator;
- friend class List;
- friend class InterpreterImp;
- public:
- ListImp();
- ~ListImp();
-
- Type type() const { return ListType; }
-
- virtual void mark();
-
- Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
- bool toBoolean(ExecState *exec) const;
- double toNumber(ExecState *exec) const;
- UString toString(ExecState *exec) const;
- Object toObject(ExecState *exec) const;
-
- void append(const Value& val);
- void prepend(const Value& val);
- void appendList(const List& lst);
- void prependList(const List& lst);
- void removeFirst();
- void removeLast();
- void remove(const Value &val);
- void clear();
- ListImp *copy() const;
- ListIterator begin() const { return ListIterator(hook->next); }
- ListIterator end() const { return ListIterator(hook); }
- // bool isEmpty() const { return (hook->prev == hook); }
- bool isEmpty() const;
- int size() const;
- Value at(int i) const;
- Value operator[](int i) const { return at(i); }
- static ListImp* empty();
-
-#ifdef KJS_DEBUG_MEM
- static int count;
-#endif
- private:
- void erase(ListNode *n);
- ListNode *hook;
- static ListImp *emptyList;
- };
-
- /**
- * @short The "label set" in Ecma-262 spec
- */
- class LabelStack {
- public:
- LabelStack(): tos(0L) {}
- ~LabelStack();
-
- LabelStack(const LabelStack &other);
- LabelStack &operator=(const LabelStack &other);
-
- /**
- * If id is not empty and is not in the stack already, puts it on top of
- * the stack and returns true, otherwise returns false
- */
- bool push(const UString &id);
- /**
- * Is the id in the stack?
- */
- bool contains(const UString &id) const;
- /**
- * Removes from the stack the last pushed id (what else?)
- */
- void pop();
- private:
- struct StackElem {
- UString id;
- StackElem *prev;
- };
-
- StackElem *tos;
- void clear();
- };
-
-
- // ---------------------------------------------------------------------------
- // Parsing & evaluateion
- // ---------------------------------------------------------------------------
-
- enum CodeType { GlobalCode,
- EvalCode,
- FunctionCode,
- AnonymousCode };
-
- /**
- * @short Execution context.
- */
- class ContextImp {
- public:
- ContextImp(Object &glob, ExecState *exec, Object &thisV, CodeType type = GlobalCode,
- ContextImp *_callingContext = 0L, FunctionImp *func = 0L, const List &args = List());
- virtual ~ContextImp();
-
- const List scopeChain() const { return scope; }
- Object variableObject() const { return variable; }
- void setVariableObject(const Object &v) { variable = v; }
- Object thisValue() const { return thisVal; }
- ContextImp *callingContext() { return callingCon; }
- Object activationObject() { return activation; }
-
- void pushScope(const Object &s);
- void popScope();
- LabelStack *seenLabels() { return &ls; }
-
- private:
-
- List scope;
- Object variable;
- Object thisVal;
- ContextImp *callingCon;
- Object activation;
-
-
- LabelStack ls;
- CodeType codeType;
- };
-
- /**
- * @internal
- *
- * Parses ECMAScript source code and converts into ProgramNode objects, which
- * represent the root of a parse tree. This class provides a conveniant workaround
- * for the problem of the bison parser working in a static context.
- */
- class Parser {
- public:
- static ProgramNode *parse(const UChar *code, unsigned int length, int *sourceId = 0,
- int *errLine = 0, UString *errMsg = 0);
-
- static ProgramNode *progNode;
- static int sid;
- };
-
- class InterpreterImp {
- friend class Collector;
- public:
- static void globalInit();
- static void globalClear();
-
- InterpreterImp(Interpreter *interp, const Object &glob);
- ~InterpreterImp();
-
- Object globalObject() const { return global; }
- Interpreter* interpreter() const { return m_interpreter; }
-
- void mark();
-
- ExecState *globalExec() { return globExec; }
- bool checkSyntax(const UString &code);
- Completion evaluate(const UString &code, const Value &thisV);
- Debugger *debugger() const { return dbg; }
- void setDebugger(Debugger *d);
-
- Object builtinObject() const { return b_Object; }
- Object builtinFunction() const { return b_Function; }
- Object builtinArray() const { return b_Array; }
- Object builtinBoolean() const { return b_Boolean; }
- Object builtinString() const { return b_String; }
- Object builtinNumber() const { return b_Number; }
- Object builtinDate() const { return b_Date; }
- Object builtinRegExp() const { return b_RegExp; }
- Object builtinError() const { return b_Error; }
-
- Object builtinObjectPrototype() const { return b_ObjectPrototype; }
- Object builtinFunctionPrototype() const { return b_FunctionPrototype; }
- Object builtinArrayPrototype() const { return b_ArrayPrototype; }
- Object builtinBooleanPrototype() const { return b_BooleanPrototype; }
- Object builtinStringPrototype() const { return b_StringPrototype; }
- Object builtinNumberPrototype() const { return b_NumberPrototype; }
- Object builtinDatePrototype() const { return b_DatePrototype; }
- Object builtinRegExpPrototype() const { return b_RegExpPrototype; }
- Object builtinErrorPrototype() const { return b_ErrorPrototype; }
-
- Object builtinEvalError() const { return b_evalError; }
- Object builtinRangeError() const { return b_rangeError; }
- Object builtinReferenceError() const { return b_referenceError; }
- Object builtinSyntaxError() const { return b_syntaxError; }
- Object builtinTypeError() const { return b_typeError; }
- Object builtinURIError() const { return b_uriError; }
-
- Object builtinEvalErrorPrototype() const { return b_evalErrorPrototype; }
- Object builtinRangeErrorPrototype() const { return b_rangeErrorPrototype; }
- Object builtinReferenceErrorPrototype() const { return b_referenceErrorPrototype; }
- Object builtinSyntaxErrorPrototype() const { return b_syntaxErrorPrototype; }
- Object builtinTypeErrorPrototype() const { return b_typeErrorPrototype; }
- Object builtinURIErrorPrototype() const { return b_uriErrorPrototype; }
-
- void setCompatMode(Interpreter::CompatMode mode) { m_compatMode = mode; }
- Interpreter::CompatMode compatMode() const { return m_compatMode; }
-
- // Chained list of interpreters (ring)
- static InterpreterImp* firstInterpreter() { return s_hook; }
- InterpreterImp *nextInterpreter() const { return next; }
- InterpreterImp *prevInterpreter() const { return prev; }
-
- private:
- void clear();
- Interpreter *m_interpreter;
- Object global;
- Debugger *dbg;
-
- // Built-in properties of the object prototype. These are accessible
- // from here even if they are replaced by js code (e.g. assigning to
- // Array.prototype)
-
- Object b_Object;
- Object b_Function;
- Object b_Array;
- Object b_Boolean;
- Object b_String;
- Object b_Number;
- Object b_Date;
- Object b_RegExp;
- Object b_Error;
-
- Object b_ObjectPrototype;
- Object b_FunctionPrototype;
- Object b_ArrayPrototype;
- Object b_BooleanPrototype;
- Object b_StringPrototype;
- Object b_NumberPrototype;
- Object b_DatePrototype;
- Object b_RegExpPrototype;
- Object b_ErrorPrototype;
-
- Object b_evalError;
- Object b_rangeError;
- Object b_referenceError;
- Object b_syntaxError;
- Object b_typeError;
- Object b_uriError;
-
- Object b_evalErrorPrototype;
- Object b_rangeErrorPrototype;
- Object b_referenceErrorPrototype;
- Object b_syntaxErrorPrototype;
- Object b_typeErrorPrototype;
- Object b_uriErrorPrototype;
-
- ExecState *globExec;
- Interpreter::CompatMode m_compatMode;
-
- // Chained list of interpreters (ring) - for collector
- static InterpreterImp* s_hook;
- InterpreterImp *next, *prev;
-
- int recursion;
- };
-
- class AttachedInterpreter;
- class DebuggerImp {
- public:
-
- DebuggerImp() {
- interps = 0;
- isAborted = false;
- }
-
- void abort() { isAborted = true; }
- bool aborted() const { return isAborted; }
-
- AttachedInterpreter *interps;
- bool isAborted;
- };
-
-
-
- class InternalFunctionImp : public ObjectImp {
- public:
- InternalFunctionImp(FunctionPrototypeImp *funcProto);
- bool implementsHasInstance() const;
- Boolean hasInstance(ExecState *exec, const Value &value);
-
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- };
-
- // helper function for toInteger, toInt32, toUInt32 and toUInt16
- double roundValue(ExecState *exec, const Value &v);
-
-#ifndef NDEBUG
- void printInfo(ExecState *exec, const char *s, const Value &o, int lineno = -1);
-#endif
-
-}; // namespace
-
-
-#endif // _INTERNAL_H_
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * 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.
- *
- * $Id$
- */
-
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
-
-#include "internal.h"
-#include "collector.h"
-#include "operations.h"
-#include "error_object.h"
-#include "nodes.h"
-
-using namespace KJS;
-
-// ------------------------------ Context --------------------------------------
-
-Context::Context(ContextImp *c)
-{
- rep = c;
-}
-
-Context::Context(const Context &c)
-{
- rep = c.rep;
-}
-
-Context& Context::operator=(const Context &c)
-{
- rep = c.rep;
- return *this;
-}
-
-Context::~Context()
-{
-}
-
-bool Context::isNull() const
-{
- return (rep == 0);
-}
-
-ContextImp *Context::imp() const
-{
- return rep;
-}
-
-const List Context::scopeChain() const
-{
- return rep->scopeChain();
-}
-
-Object Context::variableObject() const
-{
- return rep->variableObject();
-}
-
-Object Context::thisValue() const
-{
- return rep->thisValue();
-}
-
-const Context Context::callingContext() const
-{
- return rep->callingContext();
-}
-
-// ------------------------------ Interpreter ----------------------------------
-
-Interpreter::Interpreter(const Object &global) : rep(0)
-{
- rep = new InterpreterImp(this,global);
-}
-
-Interpreter::Interpreter()
-{
- Object global(new ObjectImp());
- rep = new InterpreterImp(this,global);
-}
-
-Interpreter::~Interpreter()
-{
- delete rep;
-}
-
-Object Interpreter::globalObject() const
-{
- return rep->globalObject();
-}
-
-ExecState *Interpreter::globalExec()
-{
- return rep->globalExec();
-}
-
-bool Interpreter::checkSyntax(const UString &code)
-{
- return rep->checkSyntax(code);
-}
-
-Completion Interpreter::evaluate(const UString &code, const Value &thisV)
-{
- return rep->evaluate(code,thisV);
-}
-
-InterpreterImp *Interpreter::imp()
-{
- return rep;
-}
-
-Object Interpreter::builtinObject() const
-{
- return rep->builtinObject();
-}
-
-Object Interpreter::builtinFunction() const
-{
- return rep->builtinFunction();
-}
-
-Object Interpreter::builtinArray() const
-{
- return rep->builtinArray();
-}
-
-Object Interpreter::builtinBoolean() const
-{
- return rep->builtinBoolean();
-}
-
-Object Interpreter::builtinString() const
-{
- return rep->builtinString();
-}
-
-Object Interpreter::builtinNumber() const
-{
- return rep->builtinNumber();
-}
-
-Object Interpreter::builtinDate() const
-{
- return rep->builtinDate();
-}
-
-Object Interpreter::builtinRegExp() const
-{
- return rep->builtinRegExp();
-}
-
-Object Interpreter::builtinError() const
-{
- return rep->builtinError();
-}
-
-Object Interpreter::builtinObjectPrototype() const
-{
- return rep->builtinObjectPrototype();
-}
-
-Object Interpreter::builtinFunctionPrototype() const
-{
- return rep->builtinFunctionPrototype();
-}
-
-Object Interpreter::builtinArrayPrototype() const
-{
- return rep->builtinArrayPrototype();
-}
-
-Object Interpreter::builtinBooleanPrototype() const
-{
- return rep->builtinBooleanPrototype();
-}
-
-Object Interpreter::builtinStringPrototype() const
-{
- return rep->builtinStringPrototype();
-}
-
-Object Interpreter::builtinNumberPrototype() const
-{
- return rep->builtinNumberPrototype();
-}
-
-Object Interpreter::builtinDatePrototype() const
-{
- return rep->builtinDatePrototype();
-}
-
-Object Interpreter::builtinRegExpPrototype() const
-{
- return rep->builtinRegExpPrototype();
-}
-
-Object Interpreter::builtinErrorPrototype() const
-{
- return rep->builtinErrorPrototype();
-}
-
-Object Interpreter::builtinEvalError() const
-{
- return rep->builtinEvalError();
-}
-
-Object Interpreter::builtinRangeError() const
-{
- return rep->builtinRangeError();
-}
-
-Object Interpreter::builtinReferenceError() const
-{
- return rep->builtinReferenceError();
-}
-
-Object Interpreter::builtinSyntaxError() const
-{
- return rep->builtinSyntaxError();
-}
-
-Object Interpreter::builtinTypeError() const
-{
- return rep->builtinTypeError();
-}
-
-Object Interpreter::builtinURIError() const
-{
- return rep->builtinURIError();
-}
-
-Object Interpreter::builtinEvalErrorPrototype() const
-{
- return rep->builtinEvalErrorPrototype();
-}
-
-Object Interpreter::builtinRangeErrorPrototype() const
-{
- return rep->builtinRangeErrorPrototype();
-}
-
-Object Interpreter::builtinReferenceErrorPrototype() const
-{
- return rep->builtinReferenceErrorPrototype();
-}
-
-Object Interpreter::builtinSyntaxErrorPrototype() const
-{
- return rep->builtinSyntaxErrorPrototype();
-}
-
-Object Interpreter::builtinTypeErrorPrototype() const
-{
- return rep->builtinTypeErrorPrototype();
-}
-
-Object Interpreter::builtinURIErrorPrototype() const
-{
- return rep->builtinURIErrorPrototype();
-}
-
-void Interpreter::setCompatMode(CompatMode mode)
-{
- rep->setCompatMode(mode);
-}
-
-Interpreter::CompatMode Interpreter::compatMode() const
-{
- return rep->compatMode();
-}
-
-#ifdef KJS_DEBUG_MEM
-void Interpreter::finalCheck()
-{
- fprintf(stderr,"Interpreter::finalCheck()\n");
- // Garbage collect - as many times as necessary
- // (we could delete an object which was holding another object, so
- // the deref() will happen too late for deleting the impl of the 2nd object).
- while( Collector::collect() )
- ;
-
- fprintf(stderr,"ListImp::count = %d\n", KJS::ListImp::count);
- Node::finalCheck();
- Collector::finalCheck();
-}
-#endif
-
-// ------------------------------ ExecState --------------------------------------
-
-namespace KJS {
- class ExecStateImp
- {
- public:
- ExecStateImp(Interpreter *interp, ContextImp *con)
- : interpreter(interp), context(con) {};
- Interpreter *interpreter;
- ContextImp *context;
- Value exception;
- };
-};
-
-ExecState::~ExecState()
-{
- delete rep;
-}
-
-Interpreter *ExecState::interpreter() const
-{
- return rep->interpreter;
-}
-
-const Context ExecState::context() const
-{
- return rep->context;
-}
-
-void ExecState::setException(const Value &e)
-{
- rep->exception = e;
-}
-
-void ExecState::clearException()
-{
- rep->exception = Value();
-}
-
-Value ExecState::exception() const
-{
- return rep->exception;
-}
-
-bool ExecState::hadException() const
-{
- return !rep->exception.isNull();
-}
-
-ExecState::ExecState(Interpreter *interp, ContextImp *con)
-{
- rep = new ExecStateImp(interp,con);
-}
-
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * 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.
- *
- * $Id$
- */
-
-#ifndef _KJS_INTERPRETER_H_
-#define _KJS_INTERPRETER_H_
-
-#include "value.h"
-#include "object.h"
-#include "types.h"
-
-namespace KJS {
-
- class ContextImp;
- class ExecStateImp;
- class InterpreterImp;
-
- /**
- * Represents an execution context, as specified by section 10 of the ECMA
- * spec.
- *
- * An execution context contains information about the current state of the
- * script - the scope for variable lookup, the value of "this", etc. A new
- * execution context is entered whenever global code is executed (e.g. with
- * @ref Interpreter::evaluate()), a function is called (see @ref
- * Object::call()), or the builtin "eval" function is executed.
- *
- * Most inheritable functions in the KJS api take a @ref ExecState pointer as
- * their first parameter. This can be used to obtain a handle to the current
- * execution context.
- *
- * Note: Context objects are wrapper classes/smart pointers for the internal
- * KJS ContextImp type. When one context variable is assigned to another, it
- * is still referencing the same internal object.
- */
- class Context {
- public:
- Context(ContextImp *);
- Context(const Context &c);
- Context& operator=(const Context &c);
- virtual ~Context();
-
- bool isNull() const;
- ContextImp *imp() const;
-
- /**
- * Returns the scope chain for this execution context. This is used for
- * variable lookup, with the list being searched from start to end until a
- * variable is found.
- *
- * @return The execution context's scope chain
- */
- const List scopeChain() const;
-
- /**
- * Returns the variable object for the execution context. This contains a
- * property for each variable declared in the execution context.
- *
- * @return The execution context's variable object
- */
- Object variableObject() const;
-
- /**
- * Returns the "this" value for the execution context. This is the value
- * returned when a script references the special variable "this". It should
- * always be an Object, unless application-specific code has passed in a
- * different type.
- *
- * The object that is used as the "this" value depends on the type of
- * execution context - for global contexts, the global object is used. For
- * function objewcts, the value is given by the caller (e.g. in the case of
- * obj.func(), obj would be the "this" value). For code executed by the
- * built-in "eval" function, the this value is the same as the calling
- * context.
- *
- * @return The execution context's "this" value
- */
- Object thisValue() const;
-
- /**
- * Returns the context from which the current context was invoked. For
- * global code this will be a null context (i.e. one for which @ref
- * isNull() returns true). You should check @ref isNull() on the returned
- * value before calling any of it's methods.
- *
- * @return The calling execution context
- */
- const Context callingContext() const;
- private:
- ContextImp *rep;
- };
-
- /**
- * Interpreter objects can be used to evaluate ECMAScript code. Each
- * interpreter has a global object which is used for the purposes of code
- * evaluation, and also provides access to built-in properties such as
- " Object" and "Number".
- */
- class Interpreter {
- public:
- /**
- * Creates a new interpreter. The supplied object will be used as the global
- * object for all scripts executed with this interpreter. During
- * constuction, all the standard properties such as "Object" and "Number"
- * will be added to the global object.
- *
- * Note: You should not use the same global object for multiple
- * interpreters.
- *
- * This is due do the fact that the built-in properties are set in the
- * constructor, and if these objects have been modified from another
- * interpreter (e.g. a script modifying String.prototype), the changes will
- * be overridden.
- *
- * @param global The object to use as the global object for this interpreter
- */
- Interpreter(const Object &global);
- /**
- * Creates a new interpreter. A global object will be created and
- * initialized with the standard global properties.
- */
- Interpreter();
- virtual ~Interpreter();
-
- /**
- * Returns the object that is used as the global object during all script
- * execution performed by this interpreter
- */
- Object globalObject() const;
-
- /**
- * Returns the execution state object which can be used to execute
- * scripts using this interpreter at a the "global" level, i.e. one
- * with a execution context that has the global object as the "this"
- * value, and who's scope chain contains only the global object.
- *
- * Note: this pointer remains constant for the life of the interpreter
- * and should not be manually deleted.
- *
- * @return The interpreter global execution state object
- */
- ExecState *globalExec();
-
- /**
- * Parses the supplied ECMAScript code and checks for syntax errors.
- *
- * @param code The code to check
- * @return true if there were no syntax errors in the code, otherwise false
- */
- bool checkSyntax(const UString &code);
-
- /**
- * Evaluates the supplied ECMAScript code.
- *
- * Since this method returns a Completion, you should check the type of
- * completion to detect an error or before attempting to access the returned
- * value. For example, if an error occurs during script execution and is not
- * caught by the script, the completion type will be Throw.
- *
- * If the supplied code is invalid, a SyntaxError will be thrown.
- *
- * @param code The code to evaluate
- * @param thisV The value to pass in as the "this" value for the script
- * execution. This should either be Null() or an Object.
- * @return A completion object representing the result of the execution.
- */
- Completion evaluate(const UString &code, const Value &thisV = Value());
-
- /**
- * @internal
- *
- * Returns the implementation object associated with this interpreter.
- * Only useful for internal KJS operations.
- */
- InterpreterImp *imp();
-
- /**
- * Returns the builtin "Object" object. This is the object that was set
- * as a property of the global object during construction; if the property
- * is replaced by script code, this method will still return the original
- * object.
- *
- * @return The builtin "Object" object
- */
- Object builtinObject() const;
-
- /** Returns the builtin "Function" object. */
- Object builtinFunction() const;
-
- /** Returns the builtin "Array" object. */
- Object builtinArray() const;
-
-
- /** Returns the builtin "Boolean" object. */
- Object builtinBoolean() const;
-
- /** Returns the builtin "String" object. */
- Object builtinString() const;
-
- /** Returns the builtin "Number" object. */
- Object builtinNumber() const;
-
- /** Returns the builtin "Date" object. */
- Object builtinDate() const;
-
- /** Returns the builtin "RegExp" object. */
- Object builtinRegExp() const;
-
- /** Returns the builtin "Error" object. */
- Object builtinError() const;
-
- /** Returns the builtin "Object.prototype" object. */
- Object builtinObjectPrototype() const;
-
- /** Returns the builtin "Function.prototype" object. */
- Object builtinFunctionPrototype() const;
-
- /** Returns the builtin "Array.prototype" object. */
- Object builtinArrayPrototype() const;
-
- /** Returns the builtin "Boolean.prototype" object. */
- Object builtinBooleanPrototype() const;
-
- /** Returns the builtin "String.prototype" object. */
- Object builtinStringPrototype() const;
-
- /** Returns the builtin "Number.prototype" object. */
- Object builtinNumberPrototype() const;
-
- /** Returns the builtin "Date.prototype" object. */
- Object builtinDatePrototype() const;
-
- /** Returns the builtin "RegExp.prototype" object. */
- Object builtinRegExpPrototype() const;
-
- /** Returns the builtin "Error.prototype" object. */
- Object builtinErrorPrototype() const;
-
- /** The initial value of "Error" global property */
- Object builtinEvalError() const;
- Object builtinRangeError() const;
- Object builtinReferenceError() const;
- Object builtinSyntaxError() const;
- Object builtinTypeError() const;
- Object builtinURIError() const;
-
- Object builtinEvalErrorPrototype() const;
- Object builtinRangeErrorPrototype() const;
- Object builtinReferenceErrorPrototype() const;
- Object builtinSyntaxErrorPrototype() const;
- Object builtinTypeErrorPrototype() const;
- Object builtinURIErrorPrototype() const;
-
- enum CompatMode { NativeMode, IECompat, NetscapeCompat };
- /**
- * Call this to enable a compatibility mode with another browser.
- * (by default konqueror is in "native mode").
- * Currently, in KJS, this only changes the behaviour of Date::getYear()
- * which returns the full year under IE.
- */
- void setCompatMode(CompatMode mode);
- CompatMode compatMode() const;
-
- /**
- * Called by InterpreterImp during the mark phase of the garbage collector
- * Default implementation does nothing, this exist for classes that reimplement Interpreter.
- */
- virtual void mark() {}
-
- /**
- * Provides a way to distinguish derived classes.
- * Only useful if you reimplement Interpreter and if different kind of
- * interpreters are created in the same process.
- * The base class returns 0, the ECMA-bindings interpreter returns 1.
- */
- virtual int rtti() { return 0; }
-
-#ifdef KJS_DEBUG_MEM
- /**
- * @internal
- */
- static void finalCheck();
-#endif
- private:
- InterpreterImp *rep;
-
- /**
- * This constructor is not implemented, in order to prevent
- * copy-construction of Interpreter objects. You should always pass around
- * pointers to an interpreter instance instead.
- */
- Interpreter(const Interpreter&);
-
- /**
- * This constructor is not implemented, in order to prevent assignment of
- * Interpreter objects. You should always pass around pointers to an
- * interpreter instance instead.
- */
- Interpreter operator=(const Interpreter&);
- };
-
- /**
- * Represents the current state of script execution. This object allows you
- * obtain a handle the interpreter that is currently executing the script,
- * and also the current execution state context.
- */
- class ExecState {
- friend class InterpreterImp;
- friend class FunctionImp;
- friend class GlobalFuncImp;
- public:
- virtual ~ExecState();
-
- /**
- * Returns the interpreter associated with this execution state
- *
- * @return The interpreter executing the script
- */
- Interpreter *interpreter() const;
-
- /**
- * Returns the execution context associated with this execution state
- *
- * @return The current execution state context
- */
- const Context context() const;
-
- void setException(const Value &e);
- void clearException();
- Value exception() const;
- bool hadException() const;
-
- private:
- ExecState(Interpreter *interp, ContextImp *con);
- ExecStateImp *rep;
- };
-
-}; // namespace
-
-#endif // _KJS_INTERPRETER_H_
+++ /dev/null
-# main keywords
-@begin mainTable 41
-# types
-null NULLTOKEN
-true TRUETOKEN
-false FALSETOKEN
-# keywords
-break BREAK
-case CASE
-catch CATCH
-default DEFAULT
-finally FINALLY
-for FOR
-instanceof INSTANCEOF
-new NEW
-var VAR
-continue CONTINUE
-function FUNCTION
-return RETURN
-void VOID
-delete DELETE
-if IF
-this THIS
-do DO
-while WHILE
-else ELSE
-in IN
-switch SWITCH
-throw THROW
-try TRY
-typeof TYPEOF
-with WITH
-# reserved for future use
-abstract RESERVED
-boolean RESERVED
-byte RESERVED
-char RESERVED
-class RESERVED
-const RESERVED
-debugger RESERVED
-double RESERVED
-enum RESERVED
-export RESERVED
-extends RESERVED
-final RESERVED
-float RESERVED
-goto RESERVED
-implements RESERVED
-import RESERVED
-int RESERVED
-interface RESERVED
-long RESERVED
-native RESERVED
-package RESERVED
-private RESERVED
-protected RESERVED
-public RESERVED
-short RESERVED
-static RESERVED
-super RESERVED
-synchronized RESERVED
-throws RESERVED
-transient RESERVED
-volatile RESERVED
-@end
-
+++ /dev/null
-#!/bin/sh
-
-unset MallocStackLogging
-export MallocStackLogging
-unset MallocScribble
-export MallocScribble
-unset MallocGuardEdges
-export MallocGuardEdges
-unset DYLD_IMAGE_SUFFIX
-export DYLD_IMAGE_SUFFIX
-
-`dirname $0`/testkjs `dirname $0`/test.js 2>&1
-
-if [ $? -eq 1 ]; then
- exit 0;
-fi
\ No newline at end of file
+++ /dev/null
----> inside test()
----> 20
----> 30
----> inside test()
----> 10
----> 50
----> s = 60
----> i = 2
----> a[0] = 11
----> a[1] = 22
----> a[2] = undefined
----> a[3] = undefined
----> a[4] = apple
----> b = [object Boolean]
----> bbbc
-OK.
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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.
- *
- * $Id$
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-#include "nodes.h"
-#include "lexer.h"
-#include "ustring.h"
-#include "lookup.h"
-#include "internal.h"
-
-// we can't specify the namespace in yacc's C output, so do it here
-using namespace KJS;
-
-static Lexer *currLexer = 0;
-
-#ifndef KDE_USE_FINAL
-#include "grammar.h"
-#endif
-
-#include "lexer.lut.h"
-
-extern YYLTYPE yylloc; // global bison variable holding token info
-
-// a bridge for yacc from the C world to C++
-int kjsyylex()
-{
- return Lexer::curr()->lex();
-}
-
-Lexer::Lexer()
- : yylineno(0),
- size8(128), size16(128), restrKeyword(false),
- eatNextIdentifier(false), stackToken(-1), lastToken(-1), pos(0),
- code(0), length(0),
-#ifndef KJS_PURE_ECMA
- bol(true),
-#endif
- current(0), next1(0), next2(0), next3(0)
-{
- // allocate space for read buffers
- buffer8 = new char[size8];
- buffer16 = new UChar[size16];
- currLexer = this;
-
-}
-
-Lexer::~Lexer()
-{
- delete [] buffer8;
- delete [] buffer16;
-}
-
-Lexer *Lexer::curr()
-{
- if (!currLexer) {
- // create singleton instance
- currLexer = new Lexer();
- }
- return currLexer;
-}
-
-void Lexer::setCode(const UChar *c, unsigned int len)
-{
- yylineno = 0;
- restrKeyword = false;
- delimited = false;
- eatNextIdentifier = false;
- stackToken = -1;
- lastToken = -1;
- pos = 0;
- code = c;
- length = len;
- skipLF = false;
- skipCR = false;
-#ifndef KJS_PURE_ECMA
- bol = true;
-#endif
-
- // read first characters
- current = (length > 0) ? code[0].unicode() : 0;
- next1 = (length > 1) ? code[1].unicode() : 0;
- next2 = (length > 2) ? code[2].unicode() : 0;
- next3 = (length > 3) ? code[3].unicode() : 0;
-}
-
-void Lexer::shift(unsigned int p)
-{
- while (p--) {
- pos++;
- current = next1;
- next1 = next2;
- next2 = next3;
- next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
- }
-}
-
-void Lexer::setDone(State s)
-{
- state = s;
- done = true;
-}
-
-int Lexer::lex()
-{
- int token = 0;
- state = Start;
- unsigned short stringType = 0; // either single or double quotes
- pos8 = pos16 = 0;
- done = false;
- terminator = false;
- skipLF = false;
- skipCR = false;
-
- // did we push a token on the stack previously ?
- // (after an automatic semicolon insertion)
- if (stackToken >= 0) {
- setDone(Other);
- token = stackToken;
- stackToken = 0;
- }
-
- while (!done) {
- if (skipLF && current != '\n') // found \r but not \n afterwards
- skipLF = false;
- if (skipCR && current != '\r') // found \n but not \r afterwards
- skipCR = false;
- if (skipLF || skipCR) // found \r\n or \n\r -> eat the second one
- {
- skipLF = false;
- skipCR = false;
- shift(1);
- }
- switch (state) {
- case Start:
- if (isWhiteSpace()) {
- // do nothing
- } else if (current == '/' && next1 == '/') {
- shift(1);
- state = InSingleLineComment;
- } else if (current == '/' && next1 == '*') {
- shift(1);
- state = InMultiLineComment;
- } else if (current == 0) {
- if (!terminator && !delimited) {
- // automatic semicolon insertion if program incomplete
- token = ';';
- stackToken = 0;
- setDone(Other);
- } else
- setDone(Eof);
- } else if (isLineTerminator()) {
- yylineno++;
-#ifndef KJS_PURE_ECMA
- bol = true;
-#endif
- terminator = true;
- if (restrKeyword) {
- token = ';';
- setDone(Other);
- }
- } else if (current == '"' || current == '\'') {
- state = InString;
- stringType = current;
- } else if (isIdentLetter(current)) {
- record16(current);
- state = InIdentifier;
- } else if (current == '0') {
- record8(current);
- state = InNum0;
- } else if (isDecimalDigit(current)) {
- record8(current);
- state = InNum;
- } else if (current == '.' && isDecimalDigit(next1)) {
- record8(current);
- state = InDecimal;
-#ifndef KJS_PURE_ECMA
- // <!-- marks the beginning of a line comment (for www usage)
- } else if (bol && current == '<' && next1 == '!' &&
- next2 == '-' && next3 == '-') {
- shift(3);
- state = InSingleLineComment;
- // same of -->
- } else if (bol && current == '-' && next1 == '-' && next2 == '>') {
- shift(2);
- state = InSingleLineComment;
-#endif
- } else {
- token = matchPunctuator(current, next1, next2, next3);
- if (token != -1) {
- setDone(Other);
- } else {
- // cerr << "encountered unknown character" << endl;
- setDone(Bad);
- }
- }
- break;
- case InString:
- if (current == stringType) {
- shift(1);
- setDone(String);
- } else if (current == 0 || isLineTerminator()) {
- setDone(Bad);
- } else if (current == '\\') {
- state = InEscapeSequence;
- } else {
- record16(current);
- }
- break;
- // Escape Sequences inside of strings
- case InEscapeSequence:
- if (isOctalDigit(current)) {
- if (current >= '0' && current <= '3' &&
- isOctalDigit(next1) && isOctalDigit(next2)) {
- record16(convertOctal(current, next1, next2));
- shift(2);
- state = InString;
- } else if (isOctalDigit(current) && isOctalDigit(next1)) {
- record16(convertOctal('0', current, next1));
- shift(1);
- state = InString;
- } else if (isOctalDigit(current)) {
- record16(convertOctal('0', '0', current));
- state = InString;
- } else {
- setDone(Bad);
- }
- } else if (current == 'x')
- state = InHexEscape;
- else if (current == 'u')
- state = InUnicodeEscape;
- else {
- record16(singleEscape(current));
- state = InString;
- }
- break;
- case InHexEscape:
- if (isHexDigit(current) && isHexDigit(next1)) {
- state = InString;
- record16(convertHex(current, next1));
- shift(1);
- } else if (current == stringType) {
- record16('x');
- shift(1);
- setDone(String);
- } else {
- record16('x');
- record16(current);
- state = InString;
- }
- break;
- case InUnicodeEscape:
- if (isHexDigit(current) && isHexDigit(next1) &&
- isHexDigit(next2) && isHexDigit(next3)) {
- record16(convertUnicode(current, next1, next2, next3));
- shift(3);
- state = InString;
- } else if (current == stringType) {
- record16('u');
- shift(1);
- setDone(String);
- } else {
- setDone(Bad);
- }
- break;
- case InSingleLineComment:
- if (isLineTerminator()) {
- yylineno++;
- terminator = true;
-#ifndef KJS_PURE_ECMA
- bol = true;
-#endif
- if (restrKeyword) {
- token = ';';
- setDone(Other);
- } else
- state = Start;
- } else if (current == 0) {
- setDone(Eof);
- }
- break;
- case InMultiLineComment:
- if (current == 0) {
- setDone(Bad);
- } else if (isLineTerminator()) {
- yylineno++;
- } else if (current == '*' && next1 == '/') {
- state = Start;
- shift(1);
- }
- break;
- case InIdentifier:
- if (isIdentLetter(current) || isDecimalDigit(current)) {
- record16(current);
- break;
- }
- setDone(Identifier);
- break;
- case InNum0:
- if (current == 'x' || current == 'X') {
- record8(current);
- state = InHex;
- } else if (current == '.') {
- record8(current);
- state = InDecimal;
- } else if (current == 'e' || current == 'E') {
- record8(current);
- state = InExponentIndicator;
- } else if (isOctalDigit(current)) {
- record8(current);
- state = InOctal;
- } else if (isDecimalDigit(current)) {
- record8(current);
- state = InDecimal;
- } else {
- setDone(Number);
- }
- break;
- case InHex:
- if (isHexDigit(current)) {
- record8(current);
- } else {
- setDone(Hex);
- }
- break;
- case InOctal:
- if (isOctalDigit(current)) {
- record8(current);
- }
- else if (isDecimalDigit(current)) {
- record8(current);
- state = InDecimal;
- } else
- setDone(Octal);
- break;
- case InNum:
- if (isDecimalDigit(current)) {
- record8(current);
- } else if (current == '.') {
- record8(current);
- state = InDecimal;
- } else if (current == 'e' || current == 'E') {
- record8(current);
- state = InExponentIndicator;
- } else
- setDone(Number);
- break;
- case InDecimal:
- if (isDecimalDigit(current)) {
- record8(current);
- } else if (current == 'e' || current == 'E') {
- record8(current);
- state = InExponentIndicator;
- } else
- setDone(Number);
- break;
- case InExponentIndicator:
- if (current == '+' || current == '-') {
- record8(current);
- } else if (isDecimalDigit(current)) {
- record8(current);
- state = InExponent;
- } else
- setDone(Bad);
- break;
- case InExponent:
- if (isDecimalDigit(current)) {
- record8(current);
- } else
- setDone(Number);
- break;
- default:
- assert(!"Unhandled state in switch statement");
- }
-
- // move on to the next character
- if (!done)
- shift(1);
-#ifndef KJS_PURE_ECMA
- if (state != Start && state != InSingleLineComment)
- bol = false;
-#endif
- }
-
- // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
- if ((state == Number || state == Octal || state == Hex)
- && isIdentLetter(current))
- state = Bad;
-
- // terminate string
- buffer8[pos8] = '\0';
-
-#ifdef KJS_DEBUG_LEX
- fprintf(stderr, "line: %d ", lineNo());
- fprintf(stderr, "yytext (%x): ", buffer8[0]);
- fprintf(stderr, "%s ", buffer8);
-#endif
-
- double dval = 0;
- if (state == Number) {
- dval = strtod(buffer8, 0L);
- } else if (state == Hex) { // scan hex numbers
- // TODO: support long unsigned int
- unsigned int i;
- sscanf(buffer8, "%x", &i);
- dval = i;
- state = Number;
- } else if (state == Octal) { // scan octal number
- unsigned int ui;
- sscanf(buffer8, "%o", &ui);
- dval = ui;
- state = Number;
- }
-
-#ifdef KJS_DEBUG_LEX
- switch (state) {
- case Eof:
- printf("(EOF)\n");
- break;
- case Other:
- printf("(Other)\n");
- break;
- case Identifier:
- printf("(Identifier)/(Keyword)\n");
- break;
- case String:
- printf("(String)\n");
- break;
- case Number:
- printf("(Number)\n");
- break;
- default:
- printf("(unknown)");
- }
-#endif
-
- if (state != Identifier && eatNextIdentifier)
- eatNextIdentifier = false;
-
- restrKeyword = false;
- delimited = false;
- yylloc.first_line = yylineno; // ???
- yylloc.last_line = yylineno;
-
- switch (state) {
- case Eof:
- token = 0;
- break;
- case Other:
- if(token == '}' || token == ';') {
- delimited = true;
- }
- break;
- case Identifier:
- if ((token = Lookup::find(&mainTable, buffer16, pos16)) < 0) {
- // Lookup for keyword failed, means this is an identifier
- // Apply anonymous-function hack below (eat the identifier)
- if (eatNextIdentifier) {
- eatNextIdentifier = false;
- UString debugstr(buffer16, pos16); fprintf(stderr,"Anonymous function hack: eating identifier %s\n",debugstr.ascii());
- token = lex();
- break;
- }
- /* TODO: close leak on parse error. same holds true for String */
- kjsyylval.ustr = new UString(buffer16, pos16);
- token = IDENT;
- break;
- }
-
- eatNextIdentifier = false;
- // Hack for "f = function somename() { ... }", too hard to get into the grammar
- if (token == FUNCTION && lastToken == '=' )
- eatNextIdentifier = true;
-
- if (token == CONTINUE || token == BREAK ||
- token == RETURN || token == THROW)
- restrKeyword = true;
- break;
- case String:
- kjsyylval.ustr = new UString(buffer16, pos16);
- token = STRING;
- break;
- case Number:
- kjsyylval.dval = dval;
- token = NUMBER;
- break;
- case Bad:
- fprintf(stderr, "yylex: ERROR.\n");
- return -1;
- default:
- assert(!"unhandled numeration value in switch");
- return -1;
- }
- lastToken = token;
- return token;
-}
-
-bool Lexer::isWhiteSpace() const
-{
- return (current == ' ' || current == '\t' ||
- current == 0x0b || current == 0x0c);
-}
-
-bool Lexer::isLineTerminator()
-{
- bool cr = (current == '\r');
- bool lf = (current == '\n');
- if (cr)
- skipLF = true;
- else if (lf)
- skipCR = true;
- return cr || lf;
-}
-
-bool Lexer::isIdentLetter(unsigned short c)
-{
- /* TODO: allow other legitimate unicode chars */
- return (c >= 'a' && c <= 'z' ||
- c >= 'A' && c <= 'Z' ||
- c == '$' || c == '_');
-}
-
-bool Lexer::isDecimalDigit(unsigned short c)
-{
- return (c >= '0' && c <= '9');
-}
-
-bool Lexer::isHexDigit(unsigned short c) const
-{
- return (c >= '0' && c <= '9' ||
- c >= 'a' && c <= 'f' ||
- c >= 'A' && c <= 'F');
-}
-
-bool Lexer::isOctalDigit(unsigned short c) const
-{
- return (c >= '0' && c <= '7');
-}
-
-int Lexer::matchPunctuator(unsigned short c1, unsigned short c2,
- unsigned short c3, unsigned short c4)
-{
- if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
- shift(4);
- return URSHIFTEQUAL;
- } else if (c1 == '=' && c2 == '=' && c3 == '=') {
- shift(3);
- return STREQ;
- } else if (c1 == '!' && c2 == '=' && c3 == '=') {
- shift(3);
- return STRNEQ;
- } else if (c1 == '>' && c2 == '>' && c3 == '>') {
- shift(3);
- return URSHIFT;
- } else if (c1 == '<' && c2 == '<' && c3 == '=') {
- shift(3);
- return LSHIFTEQUAL;
- } else if (c1 == '>' && c2 == '>' && c3 == '=') {
- shift(3);
- return RSHIFTEQUAL;
- } else if (c1 == '<' && c2 == '=') {
- shift(2);
- return LE;
- } else if (c1 == '>' && c2 == '=') {
- shift(2);
- return GE;
- } else if (c1 == '!' && c2 == '=') {
- shift(2);
- return NE;
- } else if (c1 == '+' && c2 == '+') {
- shift(2);
- if (terminator)
- return AUTOPLUSPLUS;
- else
- return PLUSPLUS;
- } else if (c1 == '-' && c2 == '-') {
- shift(2);
- if (terminator)
- return AUTOMINUSMINUS;
- else
- return MINUSMINUS;
- } else if (c1 == '=' && c2 == '=') {
- shift(2);
- return EQEQ;
- } else if (c1 == '+' && c2 == '=') {
- shift(2);
- return PLUSEQUAL;
- } else if (c1 == '-' && c2 == '=') {
- shift(2);
- return MINUSEQUAL;
- } else if (c1 == '*' && c2 == '=') {
- shift(2);
- return MULTEQUAL;
- } else if (c1 == '/' && c2 == '=') {
- shift(2);
- return DIVEQUAL;
- } else if (c1 == '&' && c2 == '=') {
- shift(2);
- return ANDEQUAL;
- } else if (c1 == '^' && c2 == '=') {
- shift(2);
- return XOREQUAL;
- } else if (c1 == '%' && c2 == '=') {
- shift(2);
- return MODEQUAL;
- } else if (c1 == '|' && c2 == '=') {
- shift(2);
- return OREQUAL;
- } else if (c1 == '<' && c2 == '<') {
- shift(2);
- return LSHIFT;
- } else if (c1 == '>' && c2 == '>') {
- shift(2);
- return RSHIFT;
- } else if (c1 == '&' && c2 == '&') {
- shift(2);
- return AND;
- } else if (c1 == '|' && c2 == '|') {
- shift(2);
- return OR;
- }
-
- switch(c1) {
- case '=':
- case '>':
- case '<':
- case ',':
- case '!':
- case '~':
- case '?':
- case ':':
- case '.':
- case '+':
- case '-':
- case '*':
- case '/':
- case '&':
- case '|':
- case '^':
- case '%':
- case '(':
- case ')':
- case '{':
- case '}':
- case '[':
- case ']':
- case ';':
- shift(1);
- return static_cast<int>(c1);
- default:
- return -1;
- }
-}
-
-unsigned short Lexer::singleEscape(unsigned short c) const
-{
- switch(c) {
- case 'b':
- return 0x08;
- case 't':
- return 0x09;
- case 'n':
- return 0x0A;
- case 'v':
- return 0x0B;
- case 'f':
- return 0x0C;
- case 'r':
- return 0x0D;
- case '"':
- return 0x22;
- case '\'':
- return 0x27;
- case '\\':
- return 0x5C;
- default:
- return c;
- }
-}
-
-unsigned short Lexer::convertOctal(unsigned short c1, unsigned short c2,
- unsigned short c3) const
-{
- return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
-}
-
-unsigned char Lexer::convertHex(unsigned short c)
-{
- if (c >= '0' && c <= '9')
- return (c - '0');
- else if (c >= 'a' && c <= 'f')
- return (c - 'a' + 10);
- else
- return (c - 'A' + 10);
-}
-
-unsigned char Lexer::convertHex(unsigned short c1, unsigned short c2)
-{
- return ((convertHex(c1) << 4) + convertHex(c2));
-}
-
-UChar Lexer::convertUnicode(unsigned short c1, unsigned short c2,
- unsigned short c3, unsigned short c4)
-{
- return UChar((convertHex(c1) << 4) + convertHex(c2),
- (convertHex(c3) << 4) + convertHex(c4));
-}
-
-void Lexer::record8(unsigned short c)
-{
- assert(c <= 0xff);
-
- // enlarge buffer if full
- if (pos8 >= size8 - 1) {
- char *tmp = new char[2 * size8];
- memcpy(tmp, buffer8, size8 * sizeof(char));
- delete [] buffer8;
- buffer8 = tmp;
- size8 *= 2;
- }
-
- buffer8[pos8++] = (char) c;
-}
-
-void Lexer::record16(UChar c)
-{
- // enlarge buffer if full
- if (pos16 >= size16 - 1) {
- UChar *tmp = new UChar[2 * size16];
- memcpy(tmp, buffer16, size16 * sizeof(UChar));
- delete [] buffer16;
- buffer16 = tmp;
- size16 *= 2;
- }
-
- buffer16[pos16++] = c;
-}
-
-bool Lexer::scanRegExp()
-{
- pos16 = 0;
- bool lastWasEscape = false;
- bool inBrackets = false;
-
- while (1) {
- if (isLineTerminator() || current == 0)
- return false;
- else if (current != '/' || lastWasEscape == true || inBrackets == true)
- {
- // keep track of '[' and ']'
- if ( !lastWasEscape ) {
- if ( current == '[' && !inBrackets )
- inBrackets = true;
- if ( current == ']' && inBrackets )
- inBrackets = false;
- }
- record16(current);
- lastWasEscape =
- !lastWasEscape && (current == '\\');
- }
- else { // end of regexp
- pattern = UString(buffer16, pos16);
- pos16 = 0;
- shift(1);
- break;
- }
- shift(1);
- }
-
- while (isIdentLetter(current)) {
- record16(current);
- shift(1);
- }
- flags = UString(buffer16, pos16);
-
- return true;
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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.
- *
- * $Id$
- */
-
-#ifndef _KJSLEXER_H_
-#define _KJSLEXER_H_
-
-#include "ustring.h"
-
-namespace KJS {
-
- class RegExp;
-
- class Lexer {
- public:
- Lexer();
- ~Lexer();
- static Lexer *curr();
-
- void setCode(const UChar *c, unsigned int len);
- int lex();
-
- int lineNo() const { return yylineno + 1; }
-
- bool prevTerminator() const { return terminator; }
-
- enum State { Start,
- Identifier,
- InIdentifier,
- InSingleLineComment,
- InMultiLineComment,
- InNum,
- InNum0,
- InHex,
- InOctal,
- InDecimal,
- InExponentIndicator,
- InExponent,
- Hex,
- Octal,
- Number,
- String,
- Eof,
- InString,
- InEscapeSequence,
- InHexEscape,
- InUnicodeEscape,
- Other,
- Bad };
-
- bool scanRegExp();
- UString pattern, flags;
-
- private:
- int yylineno;
- bool done;
- char *buffer8;
- UChar *buffer16;
- unsigned int size8, size16;
- unsigned int pos8, pos16;
- bool terminator;
- bool restrKeyword;
- // encountered delimiter like "'" and "}" on last run
- bool delimited;
- bool skipLF;
- bool skipCR;
- bool eatNextIdentifier;
- int stackToken;
- int lastToken;
-
- State state;
- void setDone(State s);
- unsigned int pos;
- void shift(unsigned int p);
- int lookupKeyword(const char *);
-
- bool isWhiteSpace() const;
- bool isLineTerminator();
- bool isHexDigit(unsigned short c) const;
- bool isOctalDigit(unsigned short c) const;
-
- int matchPunctuator(unsigned short c1, unsigned short c2,
- unsigned short c3, unsigned short c4);
- unsigned short singleEscape(unsigned short c) const;
- unsigned short convertOctal(unsigned short c1, unsigned short c2,
- unsigned short c3) const;
- public:
- static unsigned char convertHex(unsigned short c1);
- static unsigned char convertHex(unsigned short c1, unsigned short c2);
- static UChar convertUnicode(unsigned short c1, unsigned short c2,
- unsigned short c3, unsigned short c4);
- static bool isIdentLetter(unsigned short c);
- static bool isDecimalDigit(unsigned short c);
-
- private:
-
- void record8(unsigned short c);
- void record16(UChar c);
-
- const UChar *code;
- unsigned int length;
- int yycolumn;
-#ifndef KJS_PURE_ECMA
- int bol; // begin of line
-#endif
-
- // current and following unicode characters
- unsigned short current, next1, next2, next3;
-
- // for future extensions
- class LexerPrivate;
- LexerPrivate *priv;
- };
-
-}; // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "lookup.h"
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-using namespace KJS;
-
-const HashEntry* Lookup::findEntry( const struct HashTable *table,
- const UChar *c, unsigned int len )
-{
- if (table->type != 2) {
- fprintf(stderr, "KJS: Unknown hash table version.\n");
- return 0;
- }
- char *ascii = new char[len+1];
- unsigned int i;
- for(i = 0; i < len; i++, c++) {
- if (!c->high())
- ascii[i] = c->low();
- else
- break;
- }
- ascii[i] = '\0';
-
- int h = hash(ascii) % table->hashSize;
- const HashEntry *e = &table->entries[h];
-
- // empty bucket ?
- if (!e->s) {
- delete [] ascii;
- return 0;
- }
-
- do {
- // compare strings
- if (strcmp(ascii, e->s) == 0) {
- delete [] ascii;
- return e;
- }
- // try next bucket
- e = e->next;
- } while (e);
-
- delete [] ascii;
- return 0;
-}
-
-const HashEntry* Lookup::findEntry( const struct HashTable *table,
- const UString &s )
-{
- return findEntry( table, s.data(), s.size() );
-}
-
-int Lookup::find(const struct HashTable *table,
- const UChar *c, unsigned int len)
-{
- const HashEntry *entry = findEntry( table, c, len );
- if (entry)
- return entry->value;
- return -1;
-}
-
-int Lookup::find(const struct HashTable *table, const UString &s)
-{
- return find(table, s.data(), s.size());
-}
-
-unsigned int Lookup::hash(const UChar *c, unsigned int len)
-{
- unsigned int val = 0;
- // ignoring higher byte
- for (unsigned int i = 0; i < len; i++, c++)
- val += c->low();
-
- return val;
-}
-
-unsigned int Lookup::hash(const UString &key)
-{
- return hash(key.data(), key.size());
-}
-
-unsigned int Lookup::hash(const char *s)
-{
- unsigned int val = 0;
- while (*s)
- val += *s++;
-
- return val;
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _KJSLOOKUP_H_
-#define _KJSLOOKUP_H_
-
-#include "ustring.h"
-#include "value.h"
-#include <stdio.h>
-
-namespace KJS {
-
- /**
- * An entry in a hash table.
- */
- struct HashEntry {
- /** s is the key (e.g. a property name) */
- const char *s;
- /** value is the result value (usually an enum value) */
- int value;
- /** attr is a set for flags (e.g. the property flags, see object.h) */
- short int attr;
- /** params is another number. For property hashtables, it is used to
- denote the number of argument of the function */
- short int params;
- /** next is the pointer to the next entry for the same hash value */
- const HashEntry *next;
- };
-
- /**
- * A hash table
- * Usually the hashtable is generated by the create_hash_table script, from a .table file.
- *
- * The implementation uses an array of entries, "size" is the total size of that array.
- * The entries between 0 and hashSize-1 are the entry points
- * for each hash value, and the entries between hashSize and size-1
- * are the overflow entries for the hash values that need one.
- * The "next" pointer of the entry links entry points to overflow entries,
- * and links overflow entries between them.
- */
- struct HashTable {
- /** type is a version number. Currently always 2 */
- int type;
- /** size is the total number of entries in the hashtable, including the null entries,
- * i.e. the size of the "entries" array.
- * Used to iterate over all entries in the table */
- int size;
- /** pointer to the array of entries
- * Mind that some entries in the array are null (0,0,0,0). */
- const HashEntry *entries;
- /** the maximum value for the hash. Always smaller than size. */
- int hashSize;
- };
-
- /**
- * @short Fast keyword lookup.
- */
- class Lookup {
- public:
- /** Find an entry in the table, and return its value (i.e. the value field of HashEntry) */
- static int find(const struct HashTable *table, const UString &s);
- static int find(const struct HashTable *table,
- const UChar *c, unsigned int len);
-
- /**
- * Find an entry in the table, and return the entry
- * This variant gives access to the other attributes of the entry,
- * especially the attr field.
- */
- static const HashEntry* findEntry(const struct HashTable *table,
- const UString &s);
- static const HashEntry* findEntry(const struct HashTable *table,
- const UChar *c, unsigned int len);
-
- /** Calculate the hash value for a given key */
- static unsigned int hash(const UString &key);
- static unsigned int hash(const UChar *c, unsigned int len);
- static unsigned int hash(const char *s);
- };
-
- class ExecState;
- class UString;
- /** @internal
- * Helper for lookupFunction and lookupValueOrFunction */
- template <class FuncImp>
- inline Value lookupOrCreateFunction(ExecState *exec, const UString &propertyName,
- const ObjectImp *thisObj, int token, int params, int attr)
- {
- // Look for cached value in dynamic map of properties (in ObjectImp)
- ValueImp * cachedVal = thisObj->ObjectImp::getDirect(propertyName);
- /*if (cachedVal)
- fprintf(stderr, "lookupOrCreateFunction: Function -> looked up in ObjectImp, found type=%d\n", cachedVal->type());*/
- if (cachedVal)
- return Value(cachedVal);
-
- Value val = Value(new FuncImp(exec,token, params));
- ObjectImp *thatObj = const_cast<ObjectImp *>(thisObj);
- thatObj->ObjectImp::put(exec, propertyName, val, attr);
- return val;
- }
-
- /**
- * Helper method for property lookups
- *
- * This method does it all (looking in the hashtable, checking for function
- * overrides, creating the function or retrieving from cache, calling
- * getValueProperty in case of a non-function property, forwarding to parent if
- * unknown property).
- *
- * Template arguments:
- * @param FuncImp the class which implements this object's functions
- * @param ThisImp the class of "this". It must implement the getValueProperty(exec,token) method,
- * for non-function properties.
- * @param ParentImp the class of the parent, to propagate the lookup.
- *
- * Method arguments:
- * @param exec execution state, as usual
- * @param propertyName the property we're looking for
- * @param table the static hashtable for this class
- * @param thisObj "this"
- */
- template <class FuncImp, class ThisImp, class ParentImp>
- inline Value lookupGet(ExecState *exec, const UString &propertyName,
- const HashTable* table, const ThisImp* thisObj)
- {
- const HashEntry* entry = Lookup::findEntry(table, propertyName);
-
- if (!entry) // not found, forward to parent
- return thisObj->ParentImp::get(exec, propertyName);
-
- //fprintf(stderr, "lookupGet: found value=%d attr=%d\n", entry->value, entry->attr);
- if (entry->attr & Function)
- return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
- return thisObj->getValueProperty(exec, entry->value);
- }
-
- /**
- * Simplified version of lookupGet in case there are only functions.
- * Using this instead of lookupGet prevents 'this' from implementing a dummy getValueProperty.
- */
- template <class FuncImp, class ParentImp>
- inline Value lookupGetFunction(ExecState *exec, const UString &propertyName,
- const HashTable* table, const ObjectImp* thisObj)
- {
- const HashEntry* entry = Lookup::findEntry(table, propertyName);
-
- if (!entry) // not found, forward to parent
- return static_cast<const ParentImp *>(thisObj)->ParentImp::get(exec, propertyName);
-
- if (entry->attr & Function)
- return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
-
- fprintf(stderr, "Function bit not set! Shouldn't happen in lookupGetFunction!\n" );
- return Undefined();
- };
-
- /**
- * Simplified version of lookupGet in case there are no functions, only "values".
- * Using this instead of lookupGet removes the need for a FuncImp class.
- */
- template <class ThisImp, class ParentImp>
- inline Value lookupGetValue(ExecState *exec, const UString &propertyName,
- const HashTable* table, const ThisImp* thisObj)
- {
- const HashEntry* entry = Lookup::findEntry(table, propertyName);
-
- if (!entry) // not found, forward to parent
- return thisObj->ParentImp::get(exec, propertyName);
-
- if (entry->attr & Function)
- fprintf(stderr, "Function bit set! Shouldn't happen in lookupGetValue! propertyName was %s\n", propertyName.ascii() );
- return thisObj->getValueProperty(exec, entry->value);
- }
-
- /**
- * This one is for "put".
- * Lookup hash entry for property to be set, and set the value.
- */
- template <class ThisImp, class ParentImp>
- inline void lookupPut(ExecState *exec, const UString &propertyName,
- const Value& value, int attr,
- const HashTable* table, const ThisImp* thisObj)
- {
- const HashEntry* entry = Lookup::findEntry(table, propertyName);
-
- if (!entry) // not found: forward to parent
- thisObj->ParentImp::put(exec, propertyName, value, attr);
- else if (entry->attr & Function) // function: put as override property
- thisObj->ObjectImp::put(exec, propertyName, value, attr);
- else if (entry->attr & ReadOnly) // readonly! Can't put!
-#ifdef KJS_VERBOSE
- fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii());
-#else
- ; // do nothing
-#endif
- else
- thisObj->putValueProperty(exec, entry->value, value, attr);
- }
-
- /*
- * List of things to do when porting an objectimp to the 'static hashtable' mechanism:
- * - write the hashtable source, between @begin and @end
- * - add a rule to build the .lut.h
- * - include the .lut.h
- * - mention the table in the classinfo (add a classinfo if necessary)
- * - write/update the class enum (for the tokens)
- * - turn get() into getValueProperty(), put() into putValueProperty(), using a switch and removing funcs
- * - write get() and/or put() using a template method
- * - cleanup old stuff (e.g. hasProperty)
- * - compile, test, commit ;)
- */
-}; // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#include <math.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-#include "operations.h"
-#include "math_object.h"
-
-#include "math_object.lut.h"
-
-using namespace KJS;
-
-// ------------------------------ MathObjectImp --------------------------------
-
-const ClassInfo MathObjectImp::info = { "Math", 0, &mathTable, 0 };
-
-/* Source for math_object.lut.h
-@begin mathTable 21
- E MathObjectImp::Euler DontEnum
- LN2 MathObjectImp::Ln2 DontEnum
- LN10 MathObjectImp::Ln10 DontEnum
- LOG2E MathObjectImp::Log2E DontEnum
- LOG10E MathObjectImp::Log10E DontEnum
- PI MathObjectImp::Pi DontEnum
- SQRT1_2 MathObjectImp::Sqrt1_2 DontEnum
- SQRT2 MathObjectImp::Sqrt2 DontEnum
- abs MathObjectImp::Abs DontEnum|Function 1
- acos MathObjectImp::ACos DontEnum|Function 1
- asin MathObjectImp::ASin DontEnum|Function 1
- atan MathObjectImp::ATan DontEnum|Function 1
- atan2 MathObjectImp::ATan2 DontEnum|Function 2
- ceil MathObjectImp::Ceil DontEnum|Function 1
- cos MathObjectImp::Cos DontEnum|Function 1
- exp MathObjectImp::Exp DontEnum|Function 1
- floor MathObjectImp::Floor DontEnum|Function 1
- log MathObjectImp::Log DontEnum|Function 1
- max MathObjectImp::Max DontEnum|Function 2
- min MathObjectImp::Min DontEnum|Function 2
- pow MathObjectImp::Pow DontEnum|Function 2
- random MathObjectImp::Random DontEnum|Function 0
- round MathObjectImp::Round DontEnum|Function 1
- sin MathObjectImp::Sin DontEnum|Function 1
- sqrt MathObjectImp::Sqrt DontEnum|Function 1
- tan MathObjectImp::Tan DontEnum|Function 1
-@end
-*/
-
-MathObjectImp::MathObjectImp(ExecState * /*exec*/,
- ObjectPrototypeImp *objProto)
- : ObjectImp(Object(objProto))
-{
-}
-
-// ECMA 15.8
-Value MathObjectImp::get(ExecState *exec, const UString &propertyName) const
-{
- return lookupGet<MathFuncImp, MathObjectImp, ObjectImp>( exec, propertyName, &mathTable, this );
-}
-
-Value MathObjectImp::getValueProperty(ExecState *, int token) const
-{
- double d = -42; // ;)
- switch (token) {
- case Euler:
- d = exp(1.0);
- break;
- case Ln2:
- d = log(2.0);
- break;
- case Ln10:
- d = log(10.0);
- break;
- case Log2E:
- d = 1.0/log(2.0);
- break;
- case Log10E:
- d = 1.0/log(10.0);
- break;
- case Pi:
- d = 2.0 * asin(1.0);
- break;
- case Sqrt1_2:
- d = sqrt(0.5);
- break;
- case Sqrt2:
- d = sqrt(2.0);
- break;
- default:
- fprintf( stderr, "Internal error in MathObjectImp: unhandled token %d\n", token );
- break;
- }
-
- return Number(d);
-}
-
-// ------------------------------ MathObjectImp --------------------------------
-
-MathFuncImp::MathFuncImp(ExecState *exec, int i, int l)
- : InternalFunctionImp(
- static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
- ), id(i)
-{
- Value protect(this);
- put(exec,"length",Number(l),DontDelete|ReadOnly|DontEnum);
-}
-
-bool MathFuncImp::implementsCall() const
-{
- return true;
-}
-
-Value MathFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
-{
- Value v = args[0];
- Number n = v.toNumber(exec);
- double arg = n.value();
-
- Value v2 = args[1];
- Number n2 = v2.toNumber(exec);
- double arg2 = n2.value();
- double result;
-
- switch (id) {
- case MathObjectImp::Abs:
- result = ( arg < 0 || arg == -0) ? (-arg) : arg;
- break;
- case MathObjectImp::ACos:
- result = ::acos(arg);
- break;
- case MathObjectImp::ASin:
- result = ::asin(arg);
- break;
- case MathObjectImp::ATan:
- result = ::atan(arg);
- break;
- case MathObjectImp::ATan2:
- result = ::atan2(arg, arg2);
- break;
- case MathObjectImp::Ceil:
- result = ::ceil(arg);
- break;
- case MathObjectImp::Cos:
- result = ::cos(arg);
- break;
- case MathObjectImp::Exp:
- result = ::exp(arg);
- break;
- case MathObjectImp::Floor:
- result = ::floor(arg);
- break;
- case MathObjectImp::Log:
- result = ::log(arg);
- break;
- case MathObjectImp::Max: {
- unsigned int argsCount = args.size();
- result = -Inf;
- for ( unsigned int k = 0 ; k < argsCount ; ++k ) {
- double val = args[k].toNumber(exec);
- if ( isNaN( val ) )
- {
- result = NaN;
- break;
- }
- if ( val > result )
- result = val;
- }
- break;
- }
- case MathObjectImp::Min: {
- unsigned int argsCount = args.size();
- result = +Inf;
- for ( unsigned int k = 0 ; k < argsCount ; ++k ) {
- double val = args[k].toNumber(exec);
- if ( isNaN( val ) )
- {
- result = NaN;
- break;
- }
- if ( val < result )
- result = val;
- }
- break;
- }
- case MathObjectImp::Pow:
- // ECMA 15.8.2.1.13 (::pow takes care of most of the critera)
- if (KJS::isNaN(arg2))
- result = NaN;
- else if (arg2 == 0)
- result = 1;
- else if (KJS::isNaN(arg) && arg2 != 0)
- result = NaN;
- else if (::fabs(arg) > 1 && KJS::isPosInf(arg2))
- result = Inf;
- else if (::fabs(arg) > 1 && KJS::isNegInf(arg2))
- result = +0;
- else if (::fabs(arg) == 1 && KJS::isPosInf(arg2))
- result = NaN;
- else if (::fabs(arg) == 1 && KJS::isNegInf(arg2))
- result = NaN;
- else if (::fabs(arg) < 1 && KJS::isPosInf(arg2))
- result = +0;
- else if (::fabs(arg) < 1 && KJS::isNegInf(arg2))
- result = Inf;
- else
- result = ::pow(arg, arg2);
- break;
- case MathObjectImp::Random:
- result = ::rand();
- result = result / RAND_MAX;
- break;
- case MathObjectImp::Round:
- if (isNaN(arg))
- result = arg;
- if (isInf(arg) || isInf(-arg))
- result = arg;
- else if (arg == -0.5)
- result = 0;
- else
- result = (double)(arg >= 0.0 ? int(arg + 0.5) : int(arg - 0.5));
- break;
- case MathObjectImp::Sin:
- result = ::sin(arg);
- break;
- case MathObjectImp::Sqrt:
- result = ::sqrt(arg);
- break;
- case MathObjectImp::Tan:
- result = ::tan(arg);
- break;
-
- default:
- result = 0.0;
- assert(0);
- }
-
- return Number(result);
-}
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * 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 Lesser 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
- * Lesser General Public License for more details.
- *
- * 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
- *
- * $Id$
- */
-
-#ifndef _MATH_OBJECT_H_
-#define _MATH_OBJECT_H_
-
-#include "internal.h"
-#include "function_object.h"
-
-namespace KJS {
-
- class MathObjectImp : public ObjectImp {
- public:
- MathObjectImp(ExecState *exec,
- ObjectPrototypeImp *objProto);
- Value get(ExecState *exec, const UString &p) const;
- Value getValueProperty(ExecState *exec, int token) const;
- virtual const ClassInfo *classInfo() const { return &info; }
- static const ClassInfo info;
- enum { Euler, Ln2, Ln10, Log2E, Log10E, Pi, Sqrt1_2, Sqrt2,
- Abs, ACos, ASin, ATan, ATan2, Ceil, Cos, Pow,
- Exp, Floor, Log, Max, Min, Random, Round, Sin, Sqrt, Tan };
- };
-
- class MathFuncImp : public InternalFunctionImp {
- public:
- MathFuncImp(ExecState *exec, int i, int l);
- virtual bool implementsCall() const;
- virtual Value call(ExecState *exec, Object &thisObj, const List &args);
- private:
- int id;
- };
-
-}; // namespace
-
-#endif
+++ /dev/null
-// -*- c-basic-offset: 2 -*-
-/*
- * This file is part of the KDE libraries
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *
- * 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 "nodes.h"
-
-#include <assert.h>
-#include <iostream.h>
-#include <math.h>
-#include <stdio.h>
-#ifdef KJS_DEBUG_MEM
-#include <typeinfo>
-#endif
-
-#include "collector.h"
-#include "debugger.h"
-#include "function_object.h"
-#include "internal.h"
-#include "value.h"
-#include "object.h"
-#include "types.h"
-#include "interpreter.h"
-#include "lexer.h"
-#include "operations.h"
-#include "ustring.h"
-
-using namespace KJS;
-
-#define KJS_BREAKPOINT \
- if (!hitStatement(exec)) \
- return Completion(Normal);
-
-#define KJS_ABORTPOINT \
- if (exec->interpreter()->imp()->debugger() && \
- exec->interpreter()->imp()->debugger()->imp()->aborted()) \
- return Completion(Normal);
-
-#define KJS_CHECKEXCEPTION \
- if (exec->hadException()) \
- return Completion(Throw, exec->exception()); \
- if (Collector::outOfMemory()) \
- return Completion(Throw, Error::create(exec,GeneralError,"Out of memory"));
-
-#define KJS_CHECKEXCEPTIONVALUE \
- if (exec->hadException()) \
- return exec->exception(); \
- if (Collector::outOfMemory()) \
- return Undefined(); // will be picked up by KJS_CHECKEXCEPTION
-
-#define KJS_CHECKEXCEPTIONLIST \
- if (exec->hadException()) \
- return List(); \
- if (Collector::outOfMemory()) \
- return List(); // will be picked up by KJS_CHECKEXCEPTION
-
-#ifdef KJS_DEBUG_MEM
-std::list<Node *> Node::s_nodes;
-#endif
-// ------------------------------ Node -----------------------------------------
-
-Node::Node()
-{
- line = Lexer::curr()->lineNo();
- refcount = 0;
-#ifdef KJS_DEBUG_MEM
- s_nodes.push_back( this );
-#endif
-}
-
-Node::~Node()
-{
-#ifdef KJS_DEBUG_MEM
- s_nodes.remove( this );
-#endif
-}
-
-#ifdef KJS_DEBUG_MEM
-void Node::finalCheck()
-{
- fprintf( stderr, "Node::finalCheck(): list count : %d\n", s_nodes.size() );
- std::list<Node *>::iterator it = s_nodes.begin();
- for ( uint i = 0; it != s_nodes.end() ; ++it, ++i )
- fprintf( stderr, "[%d] Still having node %p (%s) (refcount %d)\n", i, (void*)*it, typeid( **it ).name(), (*it)->refcount );
-}
-#endif
-
-Value Node::throwError(ExecState *exec, ErrorType e, const char *msg)
-{
- Object err = Error::create(exec, e, msg, lineNo(), sourceId());
- exec->setException(err);
- return err;
-}
-
-// ------------------------------ StatementNode --------------------------------
-StatementNode::StatementNode() : l0(-1), l1(-1), sid(-1), breakPoint(false)
-{
-}
-
-StatementNode::~StatementNode()
-{
-}
-
-void StatementNode::setLoc(int line0, int line1, int sourceId)
-{
- l0 = line0;
- l1 = line1;
- sid = sourceId;
-}
-
-// return true if the debugger wants us to stop at this point
-bool StatementNode::hitStatement(ExecState *exec)
-{
- Debugger *dbg = exec->interpreter()->imp()->debugger();
- if (dbg)
- return dbg->atStatement(exec,sid,l0,l1);
- else
- return true; // continue
-}
-
-// return true if the debugger wants us to stop at this point
-bool StatementNode::abortStatement(ExecState *exec)
-{
- Debugger *dbg = exec->interpreter()->imp()->debugger();
- if (dbg)
- return dbg->imp()->aborted();
- else
- return false;
-}
-
-// ------------------------------ NullNode -------------------------------------
-
-Value NullNode::evaluate(ExecState */*exec*/)
-{
- return Null();
-}
-
-// ------------------------------ BooleanNode ----------------------------------
-
-Value BooleanNode::evaluate(ExecState */*exec*/)
-{
- return Boolean(value);
-}
-
-// ------------------------------ NumberNode -----------------------------------
-
-Value NumberNode::evaluate(ExecState */*exec*/)
-{
- return Number(value);
-}
-
-// ------------------------------ StringNode -----------------------------------
-
-Value StringNode::evaluate(ExecState */*exec*/)
-{
- return String(value);
-}
-
-// ------------------------------ RegExpNode -----------------------------------
-
-Value RegExpNode::evaluate(ExecState *exec)
-{
- List list;
- String p(pattern);
- String f(flags);
- list.append(p);
- list.append(f);
-
- Object reg = exec->interpreter()->imp()->builtinRegExp();
- return reg.construct(exec,list);
-}
-
-// ------------------------------ ThisNode -------------------------------------
-
-// ECMA 11.1.1
-Value ThisNode::evaluate(ExecState *exec)
-{
- return exec->context().thisValue();
-}
-
-// ------------------------------ ResolveNode ----------------------------------
-
-// ECMA 11.1.2 & 10.1.4
-Value ResolveNode::evaluate(ExecState *exec)
-{
- const List chain = exec->context().scopeChain();
- ListIterator scope = chain.begin();
-
- while (scope != chain.end()) {
- ObjectImp *o = static_cast<ObjectImp*>((*scope).imp());
-
- //cout << "Resolve: looking at '" << ident.ascii() << "'"
- // << " in " << (void*)o << " " << o->classInfo()->className << endl;
- if (o->hasProperty(exec,ident)) {
- //cout << "Resolve: FOUND '" << ident.ascii() << "'"
- // << " in " << (void*)o << " " << o->classInfo()->className << endl;
- return Reference(Object(o), ident);
- }
- scope++;
- }
-
- // identifier not found
- //cout << "Resolve: didn't find '" << ident.ascii() << "'" << endl;
- return Reference(Null(), ident);
-}
-
-// ------------------------------ GroupNode ------------------------------------
-
-GroupNode::~GroupNode()
-{
-}
-
-void GroupNode::ref()
-{
- Node::ref();
- if ( group )
- group->ref();
-}
-
-bool GroupNode::deref()
-{
- if ( group && group->deref() )
- delete group;
- return Node::deref();
-}
-
-// ECMA 11.1.6
-Value GroupNode::evaluate(ExecState *exec)
-{
- return group->evaluate(exec);
-}
-
-// ------------------------------ ElisionNode ----------------------------------
-
-ElisionNode::~ElisionNode()
-{
-}
-
-void ElisionNode::ref()
-{
- Node::ref();
- if ( elision )
- elision->ref();
-}
-
-bool ElisionNode::deref()
-{
- if ( elision && elision->deref() )
- delete elision;
- return Node::deref();
-}
-
-// ECMA 11.1.4
-Value ElisionNode::evaluate(ExecState *exec)
-{
- if (elision)
- return Number(elision->evaluate(exec).toNumber(exec) + 1);
- else
- return Number(1);
-}
-
-// ------------------------------ ElementNode ----------------------------------
-
-ElementNode::~ElementNode()
-{
-}
-
-void ElementNode::ref()
-{
- Node::ref();
- if ( list )
- list->ref();
- if ( elision )
- elision->ref();
- if ( node )
- node->ref();
-}
-
-bool ElementNode::deref()
-{
- if ( list && list->deref() )
- delete list;
- if ( elision && elision->deref() )
- delete elision;
- if ( node && node->deref() )
- delete node;
- return Node::deref();
-}
-
-// ECMA 11.1.4
-Value ElementNode::evaluate(ExecState *exec)
-{
- Object array;
- Value val;
- int length = 0;
- int elisionLen = elision ? elision->evaluate(exec).toInt32(exec) : 0;
- KJS_CHECKEXCEPTIONVALUE
-
- if (list) {
- array = Object(static_cast<ObjectImp*>(list->evaluate(exec).imp()));
- KJS_CHECKEXCEPTIONVALUE
- val = node->evaluate(exec).getValue(exec);
- length = array.get(exec,"length").toInt32(exec);
- } else {
- Value newArr = exec->interpreter()->builtinArray().construct(exec,List::empty());
- array = Object(static_cast<ObjectImp*>(newArr.imp()));
- val = node->evaluate(exec).getValue(exec);
- KJS_CHECKEXCEPTIONVALUE
- }
-
- array.put(exec, UString::from(elisionLen + length), val);
-
- return array;
-}
-
-// ------------------------------ ArrayNode ------------------------------------
-
-ArrayNode::~ArrayNode()
-{
-}
-
-void ArrayNode::ref()
-{
- Node::ref();
- if ( element )
- element->ref();
- if ( elision )
- elision->ref();
-}
-
-bool ArrayNode::deref()
-{
- if ( element && element->deref() )
- delete element;
- if ( elision && elision->deref() )
- delete elision;
- return Node::deref();
-}
-
-// ECMA 11.1.4
-Value ArrayNode::evaluate(ExecState *exec)
-{
- Object array;
- int length;
- int elisionLen = elision ? elision->evaluate(exec).toInt32(exec) : 0;
- KJS_CHECKEXCEPTIONVALUE
-
- if (element) {
- array = Object(static_cast<ObjectImp*>(element->evaluate(exec).imp()));
- KJS_CHECKEXCEPTIONVALUE
- length = opt ? array.get(exec,"length").toInt32(exec) : 0;
- } else {
- Value newArr = exec->interpreter()->builtinArray().construct(exec,List::empty());
- array = Object(static_cast<ObjectImp*>(newArr.imp()));
- length = 0;
- }
-
- if (opt)
- array.put(exec,"length", Number(elisionLen + length), DontEnum | DontDelete);
-
- return array;
-}
-
-// ------------------------------ ObjectLiteralNode ----------------------------
-
-ObjectLiteralNode::~ObjectLiteralNode()
-{
-}
-
-void ObjectLiteralNode::ref()
-{
- Node::ref();
- if ( list )
- list->ref();
-}
-
-bool ObjectLiteralNode::deref()
-{
- if ( list && list->deref() )
- delete list;
- return Node::deref();
-}
-
-// ECMA 11.1.5
-Value ObjectLiteralNode::evaluate(ExecState *exec)
-{
- if (list)
- return list->evaluate(exec);
-
- return exec->interpreter()->builtinObject().construct(exec,List::empty());
-}
-
-// ------------------------------ PropertyValueNode ----------------------------
-
-PropertyValueNode::~PropertyValueNode()
-{
-}
-
-void PropertyValueNode::ref()
-{
- Node::ref();
- if ( name )
- name->ref();
- if ( assign )
- assign->ref();
- if ( list )
- list->ref();
-}
-
-bool PropertyValueNode::deref()
-{
- if ( name && name->deref() )
- delete name;
- if ( assign && assign->deref() )
- delete assign;
- if ( list && list->deref() )
- delete list;
- return Node::deref();
-}
-
-// ECMA 11.1.5
-Value PropertyValueNode::evaluate(ExecState *exec)
-{
- Object obj;
- if (list) {
- obj = Object(static_cast<ObjectImp*>(list->evaluate(exec).imp()));
- KJS_CHECKEXCEPTIONVALUE
- }
- else {
- Value newObj = exec->interpreter()->builtinObject().construct(exec,List::empty());
- obj = Object(static_cast<ObjectImp*>(newObj.imp()));
- }
- Value n = name->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value a = assign->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = a.getValue(exec);
-
- obj.put(exec,n.toString(exec), v);
-
- return obj;
-}
-
-// ------------------------------ PropertyNode ---------------------------------
-
-// ECMA 11.1.5
-Value PropertyNode::evaluate(ExecState */*exec*/)
-{
- Value s;
-
- if (str.isNull()) {
- s = String(UString::from(numeric));
- } else
- s = String(str);
-
- return s;
-}
-
-// ------------------------------ AccessorNode1 --------------------------------
-
-AccessorNode1::~AccessorNode1()
-{
-}
-
-void AccessorNode1::ref()
-{
- Node::ref();
- if ( expr1 )
- expr1->ref();
- if ( expr2 )
- expr2->ref();
-}
-
-bool AccessorNode1::deref()
-{
- if ( expr1 && expr1->deref() )
- delete expr1;
- if ( expr2 && expr2->deref() )
- delete expr2;
- return Node::deref();
-}
-
-// ECMA 11.2.1a
-Value AccessorNode1::evaluate(ExecState *exec)
-{
- Value e1 = expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = e1.getValue(exec);
- Value e2 = expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v2 = e2.getValue(exec);
- Object o = v1.toObject(exec);
- String s = v2.toString(exec);
- return Reference(o, s.value());
-}
-
-// ------------------------------ AccessorNode2 --------------------------------
-
-AccessorNode2::~AccessorNode2()
-{
-}
-
-void AccessorNode2::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool AccessorNode2::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.2.1b
-Value AccessorNode2::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
- Object o = v.toObject(exec);
- return Reference(o, ident);
-}
-
-// ------------------------------ ArgumentListNode -----------------------------
-
-ArgumentListNode::ArgumentListNode(Node *e) : list(0L), expr(e)
-{
-}
-
-ArgumentListNode::ArgumentListNode(ArgumentListNode *l, Node *e)
- : list(l), expr(e)
-{
-}
-
-ArgumentListNode::~ArgumentListNode()
-{
-}
-
-void ArgumentListNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
- if ( list )
- list->ref();
-}
-
-bool ArgumentListNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- if ( list && list->deref() )
- delete list;
- return Node::deref();
-}
-
-Value ArgumentListNode::evaluate(ExecState */*exec*/)
-{
- assert(0);
- return Value(); // dummy, see evaluateList()
-}
-
-// ECMA 11.2.4
-List ArgumentListNode::evaluateList(ExecState *exec)
-{
- List l;
- if (list) {
- l = list->evaluateList(exec);
- KJS_CHECKEXCEPTIONLIST
- }
-
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONLIST
- Value v = e.getValue(exec);
-
- l.append(v);
-
- return l;
-}
-
-// ------------------------------ ArgumentsNode --------------------------------
-
-ArgumentsNode::ArgumentsNode(ArgumentListNode *l) : list(l)
-{
-}
-
-ArgumentsNode::~ArgumentsNode()
-{
-}
-
-void ArgumentsNode::ref()
-{
- Node::ref();
- if ( list )
- list->ref();
-}
-
-bool ArgumentsNode::deref()
-{
- if ( list && list->deref() )
- delete list;
- return Node::deref();
-}
-
-Value ArgumentsNode::evaluate(ExecState */*exec*/)
-{
- assert(0);
- return Value(); // dummy, see evaluateList()
-}
-
-// ECMA 11.2.4
-List ArgumentsNode::evaluateList(ExecState *exec)
-{
- if (!list)
- return List();
-
- return list->evaluateList(exec);
-}
-
-// ------------------------------ NewExprNode ----------------------------------
-
-// ECMA 11.2.2
-
-NewExprNode::~NewExprNode()
-{
-}
-
-void NewExprNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
- if ( args )
- args->ref();
-}
-
-bool NewExprNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- if ( args && args->deref() )
- delete args;
- return Node::deref();
-}
-
-Value NewExprNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
-
- List argList;
- if (args) {
- argList = args->evaluateList(exec);
- KJS_CHECKEXCEPTIONVALUE
- }
-
- if (v.type() != ObjectType) {
- return throwError(exec, TypeError, "Expression is no object. Cannot be new'ed");
- }
-
- Object constr = Object(static_cast<ObjectImp*>(v.imp()));
- if (!constr.implementsConstruct()) {
- return throwError(exec, TypeError, "Expression is no constructor.");
- }
-
- Value res = constr.construct(exec,argList);
-
- return res;
-}
-
-// ------------------------------ FunctionCallNode -----------------------------
-
-FunctionCallNode::~FunctionCallNode()
-{
-}
-
-void FunctionCallNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
- if ( args )
- args->ref();
-}
-
-bool FunctionCallNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- if ( args && args->deref() )
- delete args;
- return Node::deref();
-}
-
-// ECMA 11.2.3
-Value FunctionCallNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- List argList = args->evaluateList(exec);
-
- KJS_CHECKEXCEPTIONVALUE
-
- Value v = e.getValue(exec);
-
- if (v.type() != ObjectType) {
-#ifndef NDEBUG
- printInfo(exec, "WARNING: Failed function call attempt on", e, line);
-#endif
- return throwError(exec, TypeError, "Expression is no object. Cannot be called.");
- }
-
- Object func = Object(static_cast<ObjectImp*>(v.imp()));
-
- if (!func.implementsCall()) {
-#ifndef NDEBUG
- printInfo(exec, "Failed function call attempt on", e, line);
-#endif
- return throwError(exec, TypeError, "Expression does not allow calls.");
- }
-
- Value thisVal;
- if (e.type() == ReferenceType)
- thisVal = e.getBase(exec);
- else
- thisVal = Null();
-
- if (thisVal.type() == ObjectType &&
- Object::dynamicCast(thisVal).inherits(&ActivationImp::info))
- thisVal = Null();
-
- if (thisVal.type() != ObjectType) {
- // ECMA 11.2.3 says that in this situation the this value should be null.
- // However, section 10.2.3 says that in the case where the value provided
- // by the caller is null, the global object should be used. It also says
- // that the section does not apply to interal functions, but for simplicity
- // of implementation we use the global object anyway here. This guarantees
- // that in host objects you always get a valid object for this.
- // thisVal = Null();
- thisVal = exec->interpreter()->globalObject();
- }
-
- Object thisObj = Object::dynamicCast(thisVal);
- Value result = func.call(exec,thisObj, argList);
-
- return result;
-}
-
-// ------------------------------ PostfixNode ----------------------------------
-
-PostfixNode::~PostfixNode()
-{
-}
-
-void PostfixNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool PostfixNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.3
-Value PostfixNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
- Number n = v.toNumber(exec);
-
- double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
- Value n2 = Number(newValue);
-
- e.putValue(exec,n2);
-
- return n;
-}
-
-// ------------------------------ DeleteNode -----------------------------------
-
-DeleteNode::~DeleteNode()
-{
-}
-
-void DeleteNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool DeleteNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.4.1
-Value DeleteNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- if (e.type() != ReferenceType)
- return Boolean(true);
- Value b = e.getBase(exec);
- UString n = e.getPropertyName(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 Boolean(true);
- }
-
- Object o = Object(static_cast<ObjectImp*>(b.imp()));
-
- bool ret = o.deleteProperty(exec,n);
-
- return Boolean(ret);
-}
-
-// ------------------------------ VoidNode -------------------------------------
-
-VoidNode::~VoidNode()
-{
-}
-
-void VoidNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool VoidNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.4.2
-Value VoidNode::evaluate(ExecState *exec)
-{
- Value dummy1 = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value dummy2 = dummy1.getValue(exec);
-
- return Undefined();
-}
-
-// ------------------------------ TypeOfNode -----------------------------------
-
-TypeOfNode::~TypeOfNode()
-{
-}
-
-void TypeOfNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool TypeOfNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.4.3
-Value TypeOfNode::evaluate(ExecState *exec)
-{
- const char *s = 0L;
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- if (e.type() == ReferenceType) {
- Value b = e.getBase(exec);
- if (b.type() == NullType)
- return String("undefined");
- }
- Value v = e.getValue(exec);
- switch (v.type())
- {
- case UndefinedType:
- s = "undefined";
- break;
- case NullType:
- s = "object";
- break;
- case BooleanType:
- s = "boolean";
- break;
- case NumberType:
- s = "number";
- break;
- case StringType:
- s = "string";
- break;
- default:
- if (v.type() == ObjectType && static_cast<ObjectImp*>(v.imp())->implementsCall())
- s = "function";
- else
- s = "object";
- break;
- }
-
- return String(s);
-}
-
-// ------------------------------ PrefixNode -----------------------------------
-
-PrefixNode::~PrefixNode()
-{
-}
-
-void PrefixNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool PrefixNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.4.4 and 11.4.5
-Value PrefixNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
- Number n = v.toNumber(exec);
-
- double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
- Value n2 = Number(newValue);
-
- e.putValue(exec,n2);
-
- return n2;
-}
-
-// ------------------------------ UnaryPlusNode --------------------------------
-
-UnaryPlusNode::~UnaryPlusNode()
-{
-}
-
-void UnaryPlusNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool UnaryPlusNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.4.6
-Value UnaryPlusNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
-
- return Number(v.toNumber(exec)); /* TODO: optimize */
-}
-
-// ------------------------------ NegateNode -----------------------------------
-
-NegateNode::~NegateNode()
-{
-}
-
-void NegateNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool NegateNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.4.7
-Value NegateNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
- Number n = v.toNumber(exec);
-
- double d = -n.value();
-
- return Number(d);
-}
-
-// ------------------------------ BitwiseNotNode -------------------------------
-
-BitwiseNotNode::~BitwiseNotNode()
-{
-}
-
-void BitwiseNotNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool BitwiseNotNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.4.8
-Value BitwiseNotNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
- int i32 = v.toInt32(exec);
-
- return Number(~i32);
-}
-
-// ------------------------------ LogicalNotNode -------------------------------
-
-LogicalNotNode::~LogicalNotNode()
-{
-}
-
-void LogicalNotNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool LogicalNotNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.4.9
-Value LogicalNotNode::evaluate(ExecState *exec)
-{
- Value e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
- bool b = v.toBoolean(exec);
-
- return Boolean(!b);
-}
-
-// ------------------------------ MultNode -------------------------------------
-
-MultNode::~MultNode()
-{
-}
-
-void MultNode::ref()
-{
- Node::ref();
- if ( term1 )
- term1->ref();
- if ( term2 )
- term2->ref();
-}
-
-bool MultNode::deref()
-{
- if ( term1 && term1->deref() )
- delete term1;
- if ( term2 && term2->deref() )
- delete term2;
- return Node::deref();
-}
-
-// ECMA 11.5
-Value MultNode::evaluate(ExecState *exec)
-{
- Value t1 = term1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = t1.getValue(exec);
-
- Value t2 = term2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v2 = t2.getValue(exec);
-
- return mult(exec,v1, v2, oper);
-}
-
-// ------------------------------ AddNode --------------------------------------
-
-AddNode::~AddNode()
-{
-}
-
-void AddNode::ref()
-{
- Node::ref();
- if ( term1 )
- term1->ref();
- if ( term2 )
- term2->ref();
-}
-
-bool AddNode::deref()
-{
- if ( term1 && term1->deref() )
- delete term1;
- if ( term2 && term2->deref() )
- delete term2;
- return Node::deref();
-}
-
-// ECMA 11.6
-Value AddNode::evaluate(ExecState *exec)
-{
- Value t1 = term1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = t1.getValue(exec);
-
- Value t2 = term2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v2 = t2.getValue(exec);
-
- return add(exec,v1, v2, oper);
-}
-
-// ------------------------------ ShiftNode ------------------------------------
-
-ShiftNode::~ShiftNode()
-{
-}
-
-void ShiftNode::ref()
-{
- Node::ref();
- if ( term1 )
- term1->ref();
- if ( term2 )
- term2->ref();
-}
-
-bool ShiftNode::deref()
-{
- if ( term1 && term1->deref() )
- delete term1;
- if ( term2 && term2->deref() )
- delete term2;
- return Node::deref();
-}
-
-// ECMA 11.7
-Value ShiftNode::evaluate(ExecState *exec)
-{
- Value t1 = term1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = t1.getValue(exec);
- Value t2 = term2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v2 = t2.getValue(exec);
- unsigned int i2 = v2.toUInt32(exec);
- i2 &= 0x1f;
-
- long result;
- switch (oper) {
- case OpLShift:
- result = v1.toInt32(exec) << i2;
- break;
- case OpRShift:
- result = v1.toInt32(exec) >> i2;
- break;
- case OpURShift:
- result = v1.toUInt32(exec) >> i2;
- break;
- default:
- assert(!"ShiftNode: unhandled switch case");
- result = 0L;
- }
-
- return Number(static_cast<double>(result));
-}
-
-// ------------------------------ RelationalNode -------------------------------
-
-RelationalNode::~RelationalNode()
-{
-}
-
-void RelationalNode::ref()
-{
- Node::ref();
- if ( expr1 )
- expr1->ref();
- if ( expr2 )
- expr2->ref();
-}
-
-bool RelationalNode::deref()
-{
- if ( expr1 && expr1->deref() )
- delete expr1;
- if ( expr2 && expr2->deref() )
- delete expr2;
- return Node::deref();
-}
-
-// ECMA 11.8
-Value RelationalNode::evaluate(ExecState *exec)
-{
- Value e1 = expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = e1.getValue(exec);
- Value e2 = expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v2 = e2.getValue(exec);
-
- bool b;
- if (oper == OpLess || oper == OpGreaterEq) {
- int r = relation(exec, v1, v2);
- if (r < 0)
- b = false;
- else
- b = (oper == OpLess) ? (r == 1) : (r == 0);
- } else if (oper == OpGreater || oper == OpLessEq) {
- int r = relation(exec, v2, v1);
- if (r < 0)
- b = false;
- else
- b = (oper == OpGreater) ? (r == 1) : (r == 0);
- } else if (oper == OpIn) {
- // Is all of this OK for host objects?
- if (v2.type() != ObjectType)
- 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));
- } else {
- if (v2.type() != ObjectType)
- return throwError(exec, TypeError,
- "Called instanceof operator on non-object." );
-
- Object o2(static_cast<ObjectImp*>(v2.imp()));
- if (!o2.implementsHasInstance()) {
- // According to the spec, only some types of objects "imlement" the [[HasInstance]] property.
- // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
- // property. It seems that all object have the property, but not all implement it, so in this
- // case we return false (consistent with mozilla)
- return Boolean(false);
- // return throwError(exec, TypeError,
- // "Object does not implement the [[HasInstance]] method." );
- }
- return o2.hasInstance(exec, v1);
- }
-
- return Boolean(b);
-}
-
-// ------------------------------ EqualNode ------------------------------------
-
-EqualNode::~EqualNode()
-{
-}
-
-void EqualNode::ref()
-{
- Node::ref();
- if ( expr1 )
- expr1->ref();
- if ( expr2 )
- expr2->ref();
-}
-
-bool EqualNode::deref()
-{
- if ( expr1 && expr1->deref() )
- delete expr1;
- if ( expr2 && expr2->deref() )
- delete expr2;
- return Node::deref();
-}
-
-// ECMA 11.9
-Value EqualNode::evaluate(ExecState *exec)
-{
- Value e1 = expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value e2 = expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = e1.getValue(exec);
- Value v2 = e2.getValue(exec);
-
- bool result;
- if (oper == OpEqEq || oper == OpNotEq) {
- // == and !=
- bool eq = equal(exec,v1, v2);
- result = oper == OpEqEq ? eq : !eq;
- } else {
- // === and !==
- bool eq = strictEqual(exec,v1, v2);
- result = oper == OpStrEq ? eq : !eq;
- }
- return Boolean(result);
-}
-
-// ------------------------------ BitOperNode ----------------------------------
-
-BitOperNode::~BitOperNode()
-{
-}
-
-void BitOperNode::ref()
-{
- Node::ref();
- if ( expr1 )
- expr1->ref();
- if ( expr2 )
- expr2->ref();
-}
-
-bool BitOperNode::deref()
-{
- if ( expr1 && expr1->deref() )
- delete expr1;
- if ( expr2 && expr2->deref() )
- delete expr2;
- return Node::deref();
-}
-
-// ECMA 11.10
-Value BitOperNode::evaluate(ExecState *exec)
-{
- Value e1 = expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = e1.getValue(exec);
- Value e2 = expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v2 = e2.getValue(exec);
- int i1 = v1.toInt32(exec);
- int i2 = v2.toInt32(exec);
- int result;
- if (oper == OpBitAnd)
- result = i1 & i2;
- else if (oper == OpBitXOr)
- result = i1 ^ i2;
- else
- result = i1 | i2;
-
- return Number(result);
-}
-
-// ------------------------------ BinaryLogicalNode ----------------------------
-
-BinaryLogicalNode::~BinaryLogicalNode()
-{
-}
-
-void BinaryLogicalNode::ref()
-{
- Node::ref();
- if ( expr1 )
- expr1->ref();
- if ( expr2 )
- expr2->ref();
-}
-
-bool BinaryLogicalNode::deref()
-{
- if ( expr1 && expr1->deref() )
- delete expr1;
- if ( expr2 && expr2->deref() )
- delete expr2;
- return Node::deref();
-}
-
-// ECMA 11.11
-Value BinaryLogicalNode::evaluate(ExecState *exec)
-{
- Value e1 = expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = e1.getValue(exec);
- bool b1 = v1.toBoolean(exec);
- if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
- return v1;
-
- Value e2 = expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v2 = e2.getValue(exec);
-
- return v2;
-}
-
-// ------------------------------ ConditionalNode ------------------------------
-
-ConditionalNode::~ConditionalNode()
-{
-}
-
-void ConditionalNode::ref()
-{
- Node::ref();
- if ( expr1 )
- expr1->ref();
- if ( expr2 )
- expr2->ref();
- if ( logical )
- logical->ref();
-}
-
-bool ConditionalNode::deref()
-{
- if ( expr1 && expr1->deref() )
- delete expr1;
- if ( expr2 && expr2->deref() )
- delete expr2;
- if ( logical && logical->deref() )
- delete logical;
- return Node::deref();
-}
-
-// ECMA 11.12
-Value ConditionalNode::evaluate(ExecState *exec)
-{
- Value e = logical->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v = e.getValue(exec);
- bool b = v.toBoolean(exec);
-
- if (b)
- e = expr1->evaluate(exec);
- else
- e = expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return e.getValue(exec);
-}
-
-// ------------------------------ AssignNode -----------------------------------
-
-AssignNode::~AssignNode()
-{
-}
-
-void AssignNode::ref()
-{
- Node::ref();
- if ( left )
- left->ref();
- if ( expr )
- expr->ref();
-}
-
-bool AssignNode::deref()
-{
- if ( left && left->deref() )
- delete left;
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 11.13
-Value AssignNode::evaluate(ExecState *exec)
-{
-
- Value l, e, v;
- if (oper == OpEqual) {
- l = left->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- v = e.getValue(exec);
- } else {
- l = left->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v1 = l.getValue(exec);
- e = expr->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value v2 = e.getValue(exec);
- int i1 = v1.toInt32(exec);
- int i2 = v2.toInt32(exec);
- unsigned int ui;
- switch (oper) {
- case OpMultEq:
- v = mult(exec, v1, v2, '*');
- break;
- case OpDivEq:
- v = mult(exec, v1, v2, '/');
- break;
- case OpPlusEq:
- v = add(exec, v1, v2, '+');
- break;
- case OpMinusEq:
- v = add(exec, v1, v2, '-');
- break;
- case OpLShift:
- v = Number(i1 <<= i2);
- break;
- case OpRShift:
- v = Number(i1 >>= i2);
- break;
- case OpURShift:
- ui = v1.toUInt32(exec);
- v = Number(ui >>= i2);
- break;
- case OpAndEq:
- v = Number(i1 &= i2);
- break;
- case OpXOrEq:
- v = Number(i1 ^= i2);
- break;
- case OpOrEq:
- v = Number(i1 |= i2);
- break;
- case OpModEq: {
- double d1 = v1.toNumber(exec);
- double d2 = v2.toNumber(exec);
- v = Number(fmod(d1,d2));
- }
- break;
- default:
- v = Undefined();
- }
- };
- l.putValue(exec,v);
-
- KJS_CHECKEXCEPTIONVALUE
-
- return v;
-}
-
-// ------------------------------ CommaNode ------------------------------------
-
-CommaNode::~CommaNode()
-{
-}
-
-void CommaNode::ref()
-{
- Node::ref();
- if ( expr1 )
- expr1->ref();
- if ( expr2 )
- expr2->ref();
-}
-
-bool CommaNode::deref()
-{
- if ( expr1 && expr1->deref() )
- delete expr1;
- if ( expr2 && expr2->deref() )
- delete expr2;
- return Node::deref();
-}
-
-// ECMA 11.14
-Value CommaNode::evaluate(ExecState *exec)
-{
- Value e = expr1->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
- Value dummy = e.getValue(exec); // ignore return value
- e = expr2->evaluate(exec);
- KJS_CHECKEXCEPTIONVALUE
-
- return e.getValue(exec);
-}
-
-// ------------------------------ StatListNode ---------------------------------
-
-StatListNode::~StatListNode()
-{
-}
-
-void StatListNode::ref()
-{
- Node::ref();
- if ( statement )
- statement->ref();
- if ( list )
- list->ref();
-}
-
-bool StatListNode::deref()
-{
- if ( statement && statement->deref() )
- delete statement;
- if ( list && list->deref() )
- delete list;
- return Node::deref();
-}
-
-// ECMA 12.1
-Completion StatListNode::execute(ExecState *exec)
-{
- if (!list) {
- Completion c = statement->execute(exec);
- KJS_ABORTPOINT
- if (exec->hadException()) {
- Value ex = exec->exception();
- exec->clearException();
- return Completion(Throw, ex);
- }
- else
- return c;
- }
-
- Completion l = list->execute(exec);
- KJS_ABORTPOINT
- if (l.complType() != Normal)
- return l;
- Completion e = statement->execute(exec);
- KJS_ABORTPOINT;
-
- if (exec->hadException()) {
- Value ex = exec->exception();
- exec->clearException();
- return Completion(Throw, ex);
- }
-
- Value v = e.isValueCompletion() ? e.value() : l.value();
-
- return Completion(e.complType(), v, e.target() );
-}
-
-void StatListNode::processVarDecls(ExecState *exec)
-{
- statement->processVarDecls(exec);
-
- if (list)
- list->processVarDecls(exec);
-}
-
-// ------------------------------ AssignExprNode -------------------------------
-
-AssignExprNode::~AssignExprNode()
-{
-}
-
-void AssignExprNode::ref()
-{
- Node::ref();
- if ( expr )
- expr->ref();
-}
-
-bool AssignExprNode::deref()
-{
- if ( expr && expr->deref() )
- delete expr;
- return Node::deref();
-}
-
-// ECMA 12.2
-Value AssignExprNode::evaluate(ExecState *exec)
-{
- return expr->evaluate(exec);
-}
-
-// ------------------------------ VarDeclNode ----------------------------------
-
-VarDeclNode::VarDeclNode(const UString *id, AssignExprNode *in)
- : ident(*id), init(in)
-