summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /JavaScriptCore/runtime
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r--JavaScriptCore/runtime/ArgList.cpp84
-rw-r--r--JavaScriptCore/runtime/ArgList.h161
-rw-r--r--JavaScriptCore/runtime/Arguments.cpp232
-rw-r--r--JavaScriptCore/runtime/Arguments.h227
-rw-r--r--JavaScriptCore/runtime/ArrayConstructor.cpp84
-rw-r--r--JavaScriptCore/runtime/ArrayConstructor.h40
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.cpp794
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.h41
-rw-r--r--JavaScriptCore/runtime/BatchedTransitionOptimizer.h55
-rw-r--r--JavaScriptCore/runtime/BooleanConstructor.cpp78
-rw-r--r--JavaScriptCore/runtime/BooleanConstructor.h44
-rw-r--r--JavaScriptCore/runtime/BooleanObject.cpp35
-rw-r--r--JavaScriptCore/runtime/BooleanObject.h46
-rw-r--r--JavaScriptCore/runtime/BooleanPrototype.cpp82
-rw-r--r--JavaScriptCore/runtime/BooleanPrototype.h35
-rw-r--r--JavaScriptCore/runtime/CallData.cpp42
-rw-r--r--JavaScriptCore/runtime/CallData.h64
-rw-r--r--JavaScriptCore/runtime/ClassInfo.h62
-rw-r--r--JavaScriptCore/runtime/CollectorHeapIterator.h85
-rw-r--r--JavaScriptCore/runtime/CommonIdentifiers.cpp38
-rw-r--r--JavaScriptCore/runtime/CommonIdentifiers.h87
-rw-r--r--JavaScriptCore/runtime/ConstructData.cpp42
-rw-r--r--JavaScriptCore/runtime/ConstructData.h64
-rw-r--r--JavaScriptCore/runtime/DateConstructor.cpp175
-rw-r--r--JavaScriptCore/runtime/DateConstructor.h43
-rw-r--r--JavaScriptCore/runtime/DateInstance.cpp116
-rw-r--r--JavaScriptCore/runtime/DateInstance.h65
-rw-r--r--JavaScriptCore/runtime/DateMath.cpp1046
-rw-r--r--JavaScriptCore/runtime/DateMath.h191
-rw-r--r--JavaScriptCore/runtime/DatePrototype.cpp1056
-rw-r--r--JavaScriptCore/runtime/DatePrototype.h47
-rw-r--r--JavaScriptCore/runtime/Error.cpp127
-rw-r--r--JavaScriptCore/runtime/Error.h65
-rw-r--r--JavaScriptCore/runtime/ErrorConstructor.cpp73
-rw-r--r--JavaScriptCore/runtime/ErrorConstructor.h44
-rw-r--r--JavaScriptCore/runtime/ErrorInstance.cpp33
-rw-r--r--JavaScriptCore/runtime/ErrorInstance.h38
-rw-r--r--JavaScriptCore/runtime/ErrorPrototype.cpp67
-rw-r--r--JavaScriptCore/runtime/ErrorPrototype.h37
-rw-r--r--JavaScriptCore/runtime/ExecState.cpp38
-rw-r--r--JavaScriptCore/runtime/ExecState.h148
-rw-r--r--JavaScriptCore/runtime/FunctionConstructor.cpp146
-rw-r--r--JavaScriptCore/runtime/FunctionConstructor.h44
-rw-r--r--JavaScriptCore/runtime/FunctionPrototype.cpp136
-rw-r--r--JavaScriptCore/runtime/FunctionPrototype.h44
-rw-r--r--JavaScriptCore/runtime/GetterSetter.cpp84
-rw-r--r--JavaScriptCore/runtime/GetterSetter.h75
-rw-r--r--JavaScriptCore/runtime/GlobalEvalFunction.cpp49
-rw-r--r--JavaScriptCore/runtime/GlobalEvalFunction.h46
-rw-r--r--JavaScriptCore/runtime/InitializeThreading.cpp69
-rw-r--r--JavaScriptCore/runtime/InitializeThreading.h40
-rw-r--r--JavaScriptCore/runtime/InternalFunction.cpp51
-rw-r--r--JavaScriptCore/runtime/InternalFunction.h64
-rw-r--r--JavaScriptCore/runtime/JSActivation.cpp184
-rw-r--r--JavaScriptCore/runtime/JSActivation.h96
-rw-r--r--JavaScriptCore/runtime/JSArray.cpp1002
-rw-r--r--JavaScriptCore/runtime/JSArray.h126
-rw-r--r--JavaScriptCore/runtime/JSCell.cpp223
-rw-r--r--JavaScriptCore/runtime/JSCell.h311
-rw-r--r--JavaScriptCore/runtime/JSFunction.cpp200
-rw-r--r--JavaScriptCore/runtime/JSFunction.h99
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.cpp183
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.h126
-rw-r--r--JavaScriptCore/runtime/JSGlobalObject.cpp469
-rw-r--r--JavaScriptCore/runtime/JSGlobalObject.h363
-rw-r--r--JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp433
-rw-r--r--JavaScriptCore/runtime/JSGlobalObjectFunctions.h58
-rw-r--r--JavaScriptCore/runtime/JSImmediate.cpp81
-rw-r--r--JavaScriptCore/runtime/JSImmediate.h468
-rw-r--r--JavaScriptCore/runtime/JSLock.cpp200
-rw-r--r--JavaScriptCore/runtime/JSLock.h102
-rw-r--r--JavaScriptCore/runtime/JSNotAnObject.cpp137
-rw-r--r--JavaScriptCore/runtime/JSNotAnObject.h97
-rw-r--r--JavaScriptCore/runtime/JSNumberCell.cpp124
-rw-r--r--JavaScriptCore/runtime/JSNumberCell.h267
-rw-r--r--JavaScriptCore/runtime/JSObject.cpp516
-rw-r--r--JavaScriptCore/runtime/JSObject.h541
-rw-r--r--JavaScriptCore/runtime/JSPropertyNameIterator.cpp90
-rw-r--r--JavaScriptCore/runtime/JSPropertyNameIterator.h116
-rw-r--r--JavaScriptCore/runtime/JSStaticScopeObject.cpp84
-rw-r--r--JavaScriptCore/runtime/JSStaticScopeObject.h69
-rw-r--r--JavaScriptCore/runtime/JSString.cpp152
-rw-r--r--JavaScriptCore/runtime/JSString.h214
-rw-r--r--JavaScriptCore/runtime/JSType.h43
-rw-r--r--JavaScriptCore/runtime/JSValue.cpp104
-rw-r--r--JavaScriptCore/runtime/JSValue.h243
-rw-r--r--JavaScriptCore/runtime/JSVariableObject.cpp70
-rw-r--r--JavaScriptCore/runtime/JSVariableObject.h178
-rw-r--r--JavaScriptCore/runtime/JSWrapperObject.cpp36
-rw-r--r--JavaScriptCore/runtime/JSWrapperObject.h60
-rw-r--r--JavaScriptCore/runtime/MathObject.cpp247
-rw-r--r--JavaScriptCore/runtime/MathObject.h45
-rw-r--r--JavaScriptCore/runtime/NativeErrorConstructor.cpp72
-rw-r--r--JavaScriptCore/runtime/NativeErrorConstructor.h51
-rw-r--r--JavaScriptCore/runtime/NativeErrorPrototype.cpp39
-rw-r--r--JavaScriptCore/runtime/NativeErrorPrototype.h35
-rw-r--r--JavaScriptCore/runtime/NumberConstructor.cpp123
-rw-r--r--JavaScriptCore/runtime/NumberConstructor.h55
-rw-r--r--JavaScriptCore/runtime/NumberObject.cpp58
-rw-r--r--JavaScriptCore/runtime/NumberObject.h47
-rw-r--r--JavaScriptCore/runtime/NumberPrototype.cpp441
-rw-r--r--JavaScriptCore/runtime/NumberPrototype.h35
-rw-r--r--JavaScriptCore/runtime/ObjectConstructor.cpp72
-rw-r--r--JavaScriptCore/runtime/ObjectConstructor.h41
-rw-r--r--JavaScriptCore/runtime/ObjectPrototype.cpp134
-rw-r--r--JavaScriptCore/runtime/ObjectPrototype.h37
-rw-r--r--JavaScriptCore/runtime/PropertyMapHashTable.h77
-rw-r--r--JavaScriptCore/runtime/PropertyNameArray.cpp50
-rw-r--r--JavaScriptCore/runtime/PropertyNameArray.h112
-rw-r--r--JavaScriptCore/runtime/PropertySlot.cpp45
-rw-r--r--JavaScriptCore/runtime/PropertySlot.h212
-rw-r--r--JavaScriptCore/runtime/PrototypeFunction.cpp57
-rw-r--r--JavaScriptCore/runtime/PrototypeFunction.h45
-rw-r--r--JavaScriptCore/runtime/PutPropertySlot.h81
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.cpp385
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.h82
-rw-r--r--JavaScriptCore/runtime/RegExpMatchesArray.h87
-rw-r--r--JavaScriptCore/runtime/RegExpObject.cpp169
-rw-r--r--JavaScriptCore/runtime/RegExpObject.h83
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.cpp118
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.h38
-rw-r--r--JavaScriptCore/runtime/ScopeChain.cpp53
-rw-r--r--JavaScriptCore/runtime/ScopeChain.h218
-rw-r--r--JavaScriptCore/runtime/ScopeChainMark.h39
-rw-r--r--JavaScriptCore/runtime/SmallStrings.cpp112
-rw-r--r--JavaScriptCore/runtime/SmallStrings.h72
-rw-r--r--JavaScriptCore/runtime/StringConstructor.cpp90
-rw-r--r--JavaScriptCore/runtime/StringConstructor.h40
-rw-r--r--JavaScriptCore/runtime/StringObject.cpp101
-rw-r--r--JavaScriptCore/runtime/StringObject.h72
-rw-r--r--JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h55
-rw-r--r--JavaScriptCore/runtime/StringPrototype.cpp774
-rw-r--r--JavaScriptCore/runtime/StringPrototype.h42
-rw-r--r--JavaScriptCore/runtime/StructureID.cpp902
-rw-r--r--JavaScriptCore/runtime/StructureID.h216
-rw-r--r--JavaScriptCore/runtime/StructureIDChain.cpp73
-rw-r--r--JavaScriptCore/runtime/StructureIDChain.h54
-rw-r--r--JavaScriptCore/runtime/StructureIDTransitionTable.h72
-rw-r--r--JavaScriptCore/runtime/SymbolTable.h126
-rw-r--r--JavaScriptCore/runtime/Tracing.d40
-rw-r--r--JavaScriptCore/runtime/Tracing.h50
141 files changed, 21018 insertions, 0 deletions
diff --git a/JavaScriptCore/runtime/ArgList.cpp b/JavaScriptCore/runtime/ArgList.cpp
new file mode 100644
index 0000000..7675b20
--- /dev/null
+++ b/JavaScriptCore/runtime/ArgList.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ArgList.h"
+
+#include "JSValue.h"
+#include "JSCell.h"
+
+using std::min;
+
+namespace JSC {
+
+void ArgList::getSlice(int startIndex, ArgList& result) const
+{
+ ASSERT(!result.m_isReadOnly);
+
+ const_iterator start = min(begin() + startIndex, end());
+ result.m_vector.appendRange(start, end());
+ result.m_size = result.m_vector.size();
+ result.m_buffer = result.m_vector.data();
+}
+
+void ArgList::markLists(ListSet& markSet)
+{
+ ListSet::iterator end = markSet.end();
+ for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
+ ArgList* list = *it;
+
+ iterator end2 = list->end();
+ for (iterator it2 = list->begin(); it2 != end2; ++it2)
+ if (!(*it2).marked())
+ (*it2).mark();
+ }
+}
+
+void ArgList::slowAppend(JSValue* v)
+{
+ // As long as our size stays within our Vector's inline
+ // capacity, all our values are allocated on the stack, and
+ // therefore don't need explicit marking. Once our size exceeds
+ // our Vector's inline capacity, though, our values move to the
+ // heap, where they do need explicit marking.
+ if (!m_markSet) {
+ // We can only register for explicit marking once we know which heap
+ // is the current one, i.e., when a non-immediate value is appended.
+ if (Heap* heap = Heap::heap(v)) {
+ ListSet& markSet = heap->markListSet();
+ markSet.add(this);
+ m_markSet = &markSet;
+ }
+ }
+
+ if (m_vector.size() < m_vector.capacity()) {
+ m_vector.uncheckedAppend(v);
+ return;
+ }
+
+ // 4x growth would be excessive for a normal vector, but it's OK for Lists
+ // because they're short-lived.
+ m_vector.reserveCapacity(m_vector.capacity() * 4);
+
+ m_vector.uncheckedAppend(v);
+ m_buffer = m_vector.data();
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ArgList.h b/JavaScriptCore/runtime/ArgList.h
new file mode 100644
index 0000000..44446aa
--- /dev/null
+++ b/JavaScriptCore/runtime/ArgList.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ArgList_h
+#define ArgList_h
+
+#include "JSImmediate.h"
+#include "Register.h"
+
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class ArgList : Noncopyable {
+ private:
+ static const unsigned inlineCapacity = 8;
+ typedef Vector<Register, inlineCapacity> VectorType;
+ typedef HashSet<ArgList*> ListSet;
+
+ public:
+ typedef VectorType::iterator iterator;
+ typedef VectorType::const_iterator const_iterator;
+
+ // Constructor for a read-write list, to which you may append values.
+ // FIXME: Remove all clients of this API, then remove this API.
+ ArgList()
+ : m_markSet(0)
+#ifndef NDEBUG
+ , m_isReadOnly(false)
+#endif
+ {
+ m_buffer = m_vector.data();
+ m_size = 0;
+ }
+
+ // Constructor for a read-only list whose data has already been allocated elsewhere.
+ ArgList(Register* buffer, size_t size)
+ : m_buffer(buffer)
+ , m_size(size)
+ , m_markSet(0)
+#ifndef NDEBUG
+ , m_isReadOnly(true)
+#endif
+ {
+ }
+
+ void initialize(Register* buffer, size_t size)
+ {
+ ASSERT(!m_markSet);
+ ASSERT(isEmpty());
+
+ m_buffer = buffer;
+ m_size = size;
+#ifndef NDEBUG
+ m_isReadOnly = true;
+#endif
+ }
+
+ ~ArgList()
+ {
+ if (m_markSet)
+ m_markSet->remove(this);
+ }
+
+ size_t size() const { return m_size; }
+ bool isEmpty() const { return !m_size; }
+
+ JSValue* at(ExecState* exec, size_t i) const
+ {
+ if (i < m_size)
+ return m_buffer[i].jsValue(exec);
+ return jsUndefined();
+ }
+
+ void clear()
+ {
+ m_vector.clear();
+ m_buffer = 0;
+ m_size = 0;
+ }
+
+ void append(JSValue* v)
+ {
+ ASSERT(!m_isReadOnly);
+
+ if (m_size < inlineCapacity) {
+ m_vector.uncheckedAppend(v);
+ ++m_size;
+ } else {
+ // Putting this case all in one function measurably improves
+ // the performance of the fast "just append to inline buffer" case.
+ slowAppend(v);
+ ++m_size;
+ }
+ }
+
+ void getSlice(int startIndex, ArgList& result) const;
+
+ iterator begin() { return m_buffer; }
+ iterator end() { return m_buffer + m_size; }
+
+ const_iterator begin() const { return m_buffer; }
+ const_iterator end() const { return m_buffer + m_size; }
+
+ static void markLists(ListSet&);
+
+ private:
+ void slowAppend(JSValue*);
+
+ Register* m_buffer;
+ size_t m_size;
+
+ VectorType m_vector;
+ ListSet* m_markSet;
+#ifndef NDEBUG
+ bool m_isReadOnly;
+#endif
+
+ private:
+ // Prohibits new / delete, which would break GC.
+ friend class JSGlobalData;
+
+ void* operator new(size_t size)
+ {
+ return fastMalloc(size);
+ }
+ void operator delete(void* p)
+ {
+ fastFree(p);
+ }
+
+ void* operator new[](size_t);
+ void operator delete[](void*);
+
+ void* operator new(size_t, void*);
+ void operator delete(void*, size_t);
+ };
+
+} // namespace JSC
+
+#endif // ArgList_h
diff --git a/JavaScriptCore/runtime/Arguments.cpp b/JavaScriptCore/runtime/Arguments.cpp
new file mode 100644
index 0000000..fe1de62
--- /dev/null
+++ b/JavaScriptCore/runtime/Arguments.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Arguments.h"
+
+#include "JSActivation.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+
+using namespace std;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(Arguments);
+
+const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
+
+Arguments::~Arguments()
+{
+ if (d->extraArguments != d->extraArgumentsFixedBuffer)
+ delete [] d->extraArguments;
+}
+
+void Arguments::mark()
+{
+ JSObject::mark();
+
+ if (d->registerArray) {
+ for (unsigned i = 0; i < d->numParameters; ++i) {
+ if (!d->registerArray[i].marked())
+ d->registerArray[i].mark();
+ }
+ }
+
+ if (d->extraArguments) {
+ unsigned numExtraArguments = d->numArguments - d->numParameters;
+ for (unsigned i = 0; i < numExtraArguments; ++i) {
+ if (!d->extraArguments[i].marked())
+ d->extraArguments[i].mark();
+ }
+ }
+
+ if (!d->callee->marked())
+ d->callee->mark();
+
+ if (d->activation && !d->activation->marked())
+ d->activation->mark();
+}
+
+void Arguments::fillArgList(ExecState* exec, ArgList& args)
+{
+ if (LIKELY(!d->deletedArguments)) {
+ if (LIKELY(!d->numParameters)) {
+ args.initialize(d->extraArguments, d->numArguments);
+ return;
+ }
+
+ if (d->numParameters == d->numArguments) {
+ args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
+ return;
+ }
+
+ unsigned parametersLength = min(d->numParameters, d->numArguments);
+ unsigned i = 0;
+ for (; i < parametersLength; ++i)
+ args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
+ for (; i < d->numArguments; ++i)
+ args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
+ return;
+ }
+
+ unsigned parametersLength = min(d->numParameters, d->numArguments);
+ unsigned i = 0;
+ for (; i < parametersLength; ++i) {
+ if (!d->deletedArguments[i])
+ args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
+ else
+ args.append(get(exec, i));
+ }
+ for (; i < d->numArguments; ++i) {
+ if (!d->deletedArguments[i])
+ args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
+ else
+ args.append(get(exec, i));
+ }
+}
+
+bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
+{
+ if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters) {
+ slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
+ } else
+ slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
+ return true;
+ }
+
+ return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot);
+}
+
+bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters) {
+ slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
+ } else
+ slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
+ slot.setValue(jsNumber(exec, d->numArguments));
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
+ slot.setValue(d->callee);
+ return true;
+ }
+
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+void Arguments::put(ExecState* exec, unsigned i, JSValue* value, PutPropertySlot& slot)
+{
+ if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters)
+ d->registers[d->firstParameterIndex + i] = value;
+ else
+ d->extraArguments[i - d->numParameters] = value;
+ return;
+ }
+
+ JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
+}
+
+void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters)
+ d->registers[d->firstParameterIndex + i] = value;
+ else
+ d->extraArguments[i - d->numParameters] = value;
+ return;
+ }
+
+ if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
+ d->overrodeLength = true;
+ putDirect(propertyName, value, DontEnum);
+ return;
+ }
+
+ if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
+ d->overrodeCallee = true;
+ putDirect(propertyName, value, DontEnum);
+ return;
+ }
+
+ JSObject::put(exec, propertyName, value, slot);
+}
+
+bool Arguments::deleteProperty(ExecState* exec, unsigned i)
+{
+ if (i < d->numArguments) {
+ if (!d->deletedArguments) {
+ d->deletedArguments.set(new bool[d->numArguments]);
+ memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
+ }
+ if (!d->deletedArguments[i]) {
+ d->deletedArguments[i] = true;
+ return true;
+ }
+ }
+
+ return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)));
+}
+
+bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex && i < d->numArguments) {
+ if (!d->deletedArguments) {
+ d->deletedArguments.set(new bool[d->numArguments]);
+ memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
+ }
+ if (!d->deletedArguments[i]) {
+ d->deletedArguments[i] = true;
+ return true;
+ }
+ }
+
+ if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
+ d->overrodeLength = true;
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
+ d->overrodeCallee = true;
+ return true;
+ }
+
+ return JSObject::deleteProperty(exec, propertyName);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h
new file mode 100644
index 0000000..93cc64f
--- /dev/null
+++ b/JavaScriptCore/runtime/Arguments.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Arguments_h
+#define Arguments_h
+
+#include "JSActivation.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "Machine.h"
+
+namespace JSC {
+
+ struct ArgumentsData : Noncopyable {
+ JSActivation* activation;
+
+ unsigned numParameters;
+ ptrdiff_t firstParameterIndex;
+ unsigned numArguments;
+
+ Register* registers;
+ OwnArrayPtr<Register> registerArray;
+
+ Register* extraArguments;
+ OwnArrayPtr<bool> deletedArguments;
+ Register extraArgumentsFixedBuffer[4];
+
+ JSFunction* callee;
+ bool overrodeLength : 1;
+ bool overrodeCallee : 1;
+ };
+
+
+ class Arguments : public JSObject {
+ public:
+ enum NoParametersType { NoParameters };
+
+ Arguments(CallFrame*);
+ Arguments(CallFrame*, NoParametersType);
+ virtual ~Arguments();
+
+ static const ClassInfo info;
+
+ virtual void mark();
+
+ void fillArgList(ExecState*, ArgList&);
+
+ void copyRegisters();
+ bool isTornOff() const { return d->registerArray; }
+ void setActivation(JSActivation* activation)
+ {
+ d->activation = activation;
+ d->registers = &activation->registerAt(0);
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+ private:
+ void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue*, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ void init(CallFrame*);
+
+ OwnPtr<ArgumentsData> d;
+ };
+
+ Arguments* asArguments(JSValue*);
+
+ inline Arguments* asArguments(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&Arguments::info));
+ return static_cast<Arguments*>(asObject(value));
+ }
+
+ ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
+ {
+ function = callFrame->callee();
+
+ CodeBlock* codeBlock = &function->m_body->generatedByteCode();
+ int numParameters = codeBlock->numParameters;
+ argc = callFrame->argumentCount();
+
+ if (argc <= numParameters)
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ else
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this"
+
+ argc -= 1; // - 1 to skip "this"
+ firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ }
+
+ inline Arguments::Arguments(CallFrame* callFrame)
+ : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
+ , d(new ArgumentsData)
+ {
+ JSFunction* callee;
+ ptrdiff_t firstParameterIndex;
+ Register* argv;
+ int numArguments;
+ getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
+
+ d->numParameters = callee->m_body->parameterCount();
+ d->firstParameterIndex = firstParameterIndex;
+ d->numArguments = numArguments;
+
+ d->activation = 0;
+ d->registers = callFrame->registers();
+
+ Register* extraArguments;
+ if (d->numArguments <= d->numParameters)
+ extraArguments = 0;
+ else {
+ unsigned numExtraArguments = d->numArguments - d->numParameters;
+ if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
+ extraArguments = new Register[numExtraArguments];
+ else
+ extraArguments = d->extraArgumentsFixedBuffer;
+ for (unsigned i = 0; i < numExtraArguments; ++i)
+ extraArguments[i] = argv[d->numParameters + i];
+ }
+
+ d->extraArguments = extraArguments;
+
+ d->callee = callee;
+ d->overrodeLength = false;
+ d->overrodeCallee = false;
+ }
+
+ inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
+ : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
+ , d(new ArgumentsData)
+ {
+ ASSERT(!callFrame->callee()->m_body->parameterCount());
+
+ unsigned numArguments = callFrame->argumentCount() - 1;
+
+ d->numParameters = 0;
+ d->numArguments = numArguments;
+ d->activation = 0;
+
+ Register* extraArguments;
+ if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
+ extraArguments = new Register[numArguments];
+ else
+ extraArguments = d->extraArgumentsFixedBuffer;
+
+ Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
+ for (unsigned i = 0; i < numArguments; ++i)
+ extraArguments[i] = argv[i];
+
+ d->extraArguments = extraArguments;
+
+ d->callee = callFrame->callee();
+ d->overrodeLength = false;
+ d->overrodeCallee = false;
+ }
+
+ inline void Arguments::copyRegisters()
+ {
+ ASSERT(!isTornOff());
+
+ if (!d->numParameters)
+ return;
+
+ int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
+ size_t registerArraySize = d->numParameters;
+
+ Register* registerArray = new Register[registerArraySize];
+ memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register));
+ d->registerArray.set(registerArray);
+ d->registers = registerArray + registerOffset;
+ }
+
+ // This JSActivation function is defined here so it can get at Arguments::setRegisters.
+ inline void JSActivation::copyRegisters(Arguments* arguments)
+ {
+ ASSERT(!d()->registerArray);
+
+ size_t numParametersMinusThis = d()->functionBody->generatedByteCode().numParameters - 1;
+ size_t numVars = d()->functionBody->generatedByteCode().numVars;
+ size_t numLocals = numVars + numParametersMinusThis;
+
+ if (!numLocals)
+ return;
+
+ int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
+ size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
+
+ Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
+ setRegisters(registerArray + registerOffset, registerArray);
+ if (arguments && !arguments->isTornOff())
+ static_cast<Arguments*>(arguments)->setActivation(this);
+ }
+
+} // namespace JSC
+
+#endif // Arguments_h
diff --git a/JavaScriptCore/runtime/ArrayConstructor.cpp b/JavaScriptCore/runtime/ArrayConstructor.cpp
new file mode 100644
index 0000000..5784af0
--- /dev/null
+++ b/JavaScriptCore/runtime/ArrayConstructor.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "ArrayConstructor.h"
+
+#include "ArrayPrototype.h"
+#include "JSArray.h"
+#include "lookup.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
+
+ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<StructureID> structure, ArrayPrototype* arrayPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className))
+{
+ // ECMA 15.4.3.1 Array.prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+}
+
+static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
+{
+ // a single numeric argument denotes the array size (!)
+ if (args.size() == 1 && args.at(exec, 0)->isNumber()) {
+ uint32_t n = args.at(exec, 0)->toUInt32(exec);
+ if (n != args.at(exec, 0)->toNumber(exec))
+ return throwError(exec, RangeError, "Array size is not a small enough positive integer.");
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n);
+ }
+
+ // otherwise the array is constructed with the arguments in it
+ return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), args);
+}
+
+static JSObject* constructWithArrayConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructArrayWithSizeQuirk(exec, args);
+}
+
+// ECMA 15.4.2
+ConstructType ArrayConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithArrayConstructor;
+ return ConstructTypeHost;
+}
+
+static JSValue* callArrayConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return constructArrayWithSizeQuirk(exec, args);
+}
+
+// ECMA 15.6.1
+CallType ArrayConstructor::getCallData(CallData& callData)
+{
+ // equivalent to 'new Array(....)'
+ callData.native.function = callArrayConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ArrayConstructor.h b/JavaScriptCore/runtime/ArrayConstructor.h
new file mode 100644
index 0000000..6f0f866
--- /dev/null
+++ b/JavaScriptCore/runtime/ArrayConstructor.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ArrayConstructor_h
+#define ArrayConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class ArrayPrototype;
+
+ class ArrayConstructor : public InternalFunction {
+ public:
+ ArrayConstructor(ExecState*, PassRefPtr<StructureID>, ArrayPrototype*);
+
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+} // namespace JSC
+
+#endif // ArrayConstructor_h
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp
new file mode 100644
index 0000000..5280784
--- /dev/null
+++ b/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "ArrayPrototype.h"
+
+#include "Machine.h"
+#include "ObjectPrototype.h"
+#include "lookup.h"
+#include "operations.h"
+#include <algorithm>
+#include <wtf/Assertions.h>
+#include <wtf/HashSet.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype);
+
+static JSValue* arrayProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncConcat(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncJoin(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncPop(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncPush(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncReverse(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncShift(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncSlice(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncSort(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncSplice(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncUnShift(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncEvery(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncForEach(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncSome(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncFilter(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncMap(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+}
+
+#include "ArrayPrototype.lut.h"
+
+namespace JSC {
+
+// ------------------------------ ArrayPrototype ----------------------------
+
+const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable};
+
+/* Source for ArrayPrototype.lut.h
+@begin arrayTable 16
+ toString arrayProtoFuncToString DontEnum|Function 0
+ toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0
+ concat arrayProtoFuncConcat DontEnum|Function 1
+ join arrayProtoFuncJoin DontEnum|Function 1
+ pop arrayProtoFuncPop DontEnum|Function 0
+ push arrayProtoFuncPush DontEnum|Function 1
+ reverse arrayProtoFuncReverse DontEnum|Function 0
+ shift arrayProtoFuncShift DontEnum|Function 0
+ slice arrayProtoFuncSlice DontEnum|Function 2
+ sort arrayProtoFuncSort DontEnum|Function 1
+ splice arrayProtoFuncSplice DontEnum|Function 2
+ unshift arrayProtoFuncUnShift DontEnum|Function 1
+ every arrayProtoFuncEvery DontEnum|Function 1
+ forEach arrayProtoFuncForEach DontEnum|Function 1
+ some arrayProtoFuncSome DontEnum|Function 1
+ indexOf arrayProtoFuncIndexOf DontEnum|Function 1
+ lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 1
+ filter arrayProtoFuncFilter DontEnum|Function 1
+ map arrayProtoFuncMap DontEnum|Function 1
+@end
+*/
+
+// ECMA 15.4.4
+ArrayPrototype::ArrayPrototype(PassRefPtr<StructureID> structure)
+ : JSArray(structure)
+{
+}
+
+bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);
+}
+
+// ------------------------------ Array Functions ----------------------------
+
+// Helper function
+static JSValue* getProperty(ExecState* exec, JSObject* obj, unsigned index)
+{
+ PropertySlot slot(obj);
+ if (!obj->getPropertySlot(exec, index, slot))
+ return noValue();
+ return slot.getValue(exec, index);
+}
+
+static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValue* value)
+{
+ PutPropertySlot slot;
+ obj->put(exec, propertyName, value, slot);
+}
+
+JSValue* arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&JSArray::info))
+ return throwError(exec, TypeError);
+ JSObject* thisObj = asArray(thisValue);
+
+ HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
+ if (arrayVisitedElements.size() > MaxReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+
+ bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
+ if (alreadyVisited)
+ return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.
+
+ Vector<UChar, 256> strBuffer;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned k = 0; k < length; k++) {
+ if (k >= 1)
+ strBuffer.append(',');
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ break;
+ }
+
+ JSValue* element = thisObj->get(exec, k);
+ if (element->isUndefinedOrNull())
+ continue;
+
+ UString str = element->toString(exec);
+ strBuffer.append(str.data(), str.size());
+
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ }
+
+ if (exec->hadException())
+ break;
+ }
+ arrayVisitedElements.remove(thisObj);
+ return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+}
+
+JSValue* arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&JSArray::info))
+ return throwError(exec, TypeError);
+ JSObject* thisObj = asArray(thisValue);
+
+ HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
+ if (arrayVisitedElements.size() > MaxReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+
+ bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
+ if (alreadyVisited)
+ return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
+
+ Vector<UChar, 256> strBuffer;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned k = 0; k < length; k++) {
+ if (k >= 1)
+ strBuffer.append(',');
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ break;
+ }
+
+ JSValue* element = thisObj->get(exec, k);
+ if (element->isUndefinedOrNull())
+ continue;
+
+ JSObject* o = element->toObject(exec);
+ JSValue* conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
+ UString str;
+ CallData callData;
+ CallType callType = conversionFunction->getCallData(callData);
+ if (callType != CallTypeNone)
+ str = call(exec, conversionFunction, callType, callData, element, exec->emptyList())->toString(exec);
+ else
+ str = element->toString(exec);
+ strBuffer.append(str.data(), str.size());
+
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ }
+
+ if (exec->hadException())
+ break;
+ }
+ arrayVisitedElements.remove(thisObj);
+ return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+}
+
+JSValue* arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
+ if (arrayVisitedElements.size() > MaxReentryDepth)
+ return throwError(exec, RangeError, "Maximum call stack size exceeded.");
+
+ bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
+ if (alreadyVisited)
+ return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
+
+ Vector<UChar, 256> strBuffer;
+
+ UChar comma = ',';
+ UString separator = args.at(exec, 0)->isUndefined() ? UString(&comma, 1) : args.at(exec, 0)->toString(exec);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned k = 0; k < length; k++) {
+ if (k >= 1)
+ strBuffer.append(separator.data(), separator.size());
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ break;
+ }
+
+ JSValue* element = thisObj->get(exec, k);
+ if (element->isUndefinedOrNull())
+ continue;
+
+ UString str = element->toString(exec);
+ strBuffer.append(str.data(), str.size());
+
+ if (!strBuffer.data()) {
+ JSObject* error = Error::create(exec, GeneralError, "Out of memory");
+ exec->setException(error);
+ }
+
+ if (exec->hadException())
+ break;
+ }
+ arrayVisitedElements.remove(thisObj);
+ return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+}
+
+JSValue* arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSArray* arr = constructEmptyArray(exec);
+ int n = 0;
+ JSValue* curArg = thisValue->toThisObject(exec);
+ ArgList::const_iterator it = args.begin();
+ ArgList::const_iterator end = args.end();
+ while (1) {
+ if (curArg->isObject(&JSArray::info)) {
+ JSArray* curArray = asArray(curArg);
+ unsigned length = curArray->length();
+ for (unsigned k = 0; k < length; ++k) {
+ if (JSValue* v = getProperty(exec, curArray, k))
+ arr->put(exec, n, v);
+ n++;
+ }
+ } else {
+ arr->put(exec, n, curArg);
+ n++;
+ }
+ if (it == end)
+ break;
+ curArg = (*it).jsValue(exec);
+ ++it;
+ }
+ arr->setLength(n);
+ return arr;
+}
+
+JSValue* arrayProtoFuncPop(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (exec->machine()->isJSArray(thisValue))
+ return asArray(thisValue)->pop();
+
+ JSObject* thisObj = thisValue->toThisObject(exec);
+ JSValue* result;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ if (length == 0) {
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
+ result = jsUndefined();
+ } else {
+ result = thisObj->get(exec, length - 1);
+ thisObj->deleteProperty(exec, length - 1);
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
+ }
+ return result;
+}
+
+JSValue* arrayProtoFuncPush(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (exec->machine()->isJSArray(thisValue) && args.size() == 1) {
+ JSArray* array = asArray(thisValue);
+ array->push(exec, args.begin()->jsValue(exec));
+ return jsNumber(exec, array->length());
+ }
+
+ JSObject* thisObj = thisValue->toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned n = 0; n < args.size(); n++)
+ thisObj->put(exec, length + n, args.at(exec, n));
+ length += args.size();
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
+ return jsNumber(exec, length);
+}
+
+JSValue* arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ unsigned middle = length / 2;
+
+ for (unsigned k = 0; k < middle; k++) {
+ unsigned lk1 = length - k - 1;
+ JSValue* obj2 = getProperty(exec, thisObj, lk1);
+ JSValue* obj = getProperty(exec, thisObj, k);
+
+ if (obj2)
+ thisObj->put(exec, k, obj2);
+ else
+ thisObj->deleteProperty(exec, k);
+
+ if (obj)
+ thisObj->put(exec, lk1, obj);
+ else
+ thisObj->deleteProperty(exec, lk1);
+ }
+ return thisObj;
+}
+
+JSValue* arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+ JSValue* result;
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ if (length == 0) {
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
+ result = jsUndefined();
+ } else {
+ result = thisObj->get(exec, 0);
+ for (unsigned k = 1; k < length; k++) {
+ if (JSValue* obj = getProperty(exec, thisObj, k))
+ thisObj->put(exec, k - 1, obj);
+ else
+ thisObj->deleteProperty(exec, k - 1);
+ }
+ thisObj->deleteProperty(exec, length - 1);
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
+ }
+ return result;
+}
+
+JSValue* arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
+
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ // We return a new array
+ JSArray* resObj = constructEmptyArray(exec);
+ JSValue* result = resObj;
+ double begin = args.at(exec, 0)->toInteger(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ if (begin >= 0) {
+ if (begin > length)
+ begin = length;
+ } else {
+ begin += length;
+ if (begin < 0)
+ begin = 0;
+ }
+ double end;
+ if (args.at(exec, 1)->isUndefined())
+ end = length;
+ else {
+ end = args.at(exec, 1)->toInteger(exec);
+ if (end < 0) {
+ end += length;
+ if (end < 0)
+ end = 0;
+ } else {
+ if (end > length)
+ end = length;
+ }
+ }
+
+ int n = 0;
+ int b = static_cast<int>(begin);
+ int e = static_cast<int>(end);
+ for (int k = b; k < e; k++, n++) {
+ if (JSValue* v = getProperty(exec, thisObj, k))
+ resObj->put(exec, n, v);
+ }
+ resObj->setLength(n);
+ return result;
+}
+
+JSValue* arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ JSValue* function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+
+ if (thisObj->classInfo() == &JSArray::info) {
+ if (callType != CallTypeNone)
+ asArray(thisObj)->sort(exec, function, callType, callData);
+ else
+ asArray(thisObj)->sort(exec);
+ return thisObj;
+ }
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+
+ if (!length)
+ return thisObj;
+
+ // "Min" sort. Not the fastest, but definitely less code than heapsort
+ // or quicksort, and much less swapping than bubblesort/insertionsort.
+ for (unsigned i = 0; i < length - 1; ++i) {
+ JSValue* iObj = thisObj->get(exec, i);
+ unsigned themin = i;
+ JSValue* minObj = iObj;
+ for (unsigned j = i + 1; j < length; ++j) {
+ JSValue* jObj = thisObj->get(exec, j);
+ double compareResult;
+ if (jObj->isUndefined())
+ compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
+ else if (minObj->isUndefined())
+ compareResult = -1;
+ else if (callType != CallTypeNone) {
+ ArgList l;
+ l.append(jObj);
+ l.append(minObj);
+ compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l)->toNumber(exec);
+ } else
+ compareResult = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1;
+
+ if (compareResult < 0) {
+ themin = j;
+ minObj = jObj;
+ }
+ }
+ // Swap themin and i
+ if (themin > i) {
+ thisObj->put(exec, i, minObj);
+ thisObj->put(exec, themin, iObj);
+ }
+ }
+ return thisObj;
+}
+
+JSValue* arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ // 15.4.4.12
+ JSArray* resObj = constructEmptyArray(exec);
+ JSValue* result = resObj;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ if (!args.size())
+ return jsUndefined();
+ int begin = args.at(exec, 0)->toUInt32(exec);
+ if (begin < 0)
+ begin = std::max<int>(begin + length, 0);
+ else
+ begin = std::min<int>(begin, length);
+
+ unsigned deleteCount;
+ if (args.size() > 1)
+ deleteCount = std::min<int>(std::max<int>(args.at(exec, 1)->toUInt32(exec), 0), length - begin);
+ else
+ deleteCount = length - begin;
+
+ for (unsigned k = 0; k < deleteCount; k++) {
+ if (JSValue* v = getProperty(exec, thisObj, k + begin))
+ resObj->put(exec, k, v);
+ }
+ resObj->setLength(deleteCount);
+
+ unsigned additionalArgs = std::max<int>(args.size() - 2, 0);
+ if (additionalArgs != deleteCount) {
+ if (additionalArgs < deleteCount) {
+ for (unsigned k = begin; k < length - deleteCount; ++k) {
+ if (JSValue* v = getProperty(exec, thisObj, k + deleteCount))
+ thisObj->put(exec, k + additionalArgs, v);
+ else
+ thisObj->deleteProperty(exec, k + additionalArgs);
+ }
+ for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
+ thisObj->deleteProperty(exec, k - 1);
+ } else {
+ for (unsigned k = length - deleteCount; (int)k > begin; --k) {
+ if (JSValue* obj = getProperty(exec, thisObj, k + deleteCount - 1))
+ thisObj->put(exec, k + additionalArgs - 1, obj);
+ else
+ thisObj->deleteProperty(exec, k + additionalArgs - 1);
+ }
+ }
+ }
+ for (unsigned k = 0; k < additionalArgs; ++k)
+ thisObj->put(exec, k + begin, args.at(exec, k + 2));
+
+ putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - deleteCount + additionalArgs));
+ return result;
+}
+
+JSValue* arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ // 15.4.4.13
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ unsigned nrArgs = args.size();
+ if (nrArgs) {
+ for (unsigned k = length; k > 0; --k) {
+ if (JSValue* v = getProperty(exec, thisObj, k - 1))
+ thisObj->put(exec, k + nrArgs - 1, v);
+ else
+ thisObj->deleteProperty(exec, k + nrArgs - 1);
+ }
+ }
+ for (unsigned k = 0; k < nrArgs; ++k)
+ thisObj->put(exec, k, args.at(exec, k));
+ JSValue* result = jsNumber(exec, length + nrArgs);
+ putProperty(exec, thisObj, exec->propertyNames().length, result);
+ return result;
+}
+
+JSValue* arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ JSValue* function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
+ JSArray* resultArray = constructEmptyArray(exec);
+
+ unsigned filterIndex = 0;
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ JSValue* v = slot.getValue(exec, k);
+
+ ArgList eachArguments;
+
+ eachArguments.append(v);
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments);
+
+ if (result->toBoolean(exec))
+ resultArray->put(exec, filterIndex++, v);
+ }
+ return resultArray;
+}
+
+JSValue* arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ JSValue* function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+
+ JSArray* resultArray = constructEmptyArray(exec, length);
+
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ JSValue* v = slot.getValue(exec, k);
+
+ ArgList eachArguments;
+
+ eachArguments.append(v);
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments);
+ resultArray->put(exec, k, result);
+ }
+
+ return resultArray;
+}
+
+// Documentation for these three is available at:
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
+// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
+
+JSValue* arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ JSValue* function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
+
+ JSValue* result = jsBoolean(true);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ ArgList eachArguments;
+
+ eachArguments.append(slot.getValue(exec, k));
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec);
+
+ if (!predicateResult) {
+ result = jsBoolean(false);
+ break;
+ }
+ }
+
+ return result;
+}
+
+JSValue* arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ JSValue* function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ ArgList eachArguments;
+ eachArguments.append(slot.getValue(exec, k));
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ call(exec, function, callType, callData, applyThis, eachArguments);
+ }
+ return jsUndefined();
+}
+
+JSValue* arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ JSValue* function = args.at(exec, 0);
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSObject* applyThis = args.at(exec, 1)->isUndefinedOrNull() ? exec->globalThisValue() : args.at(exec, 1)->toObject(exec);
+
+ JSValue* result = jsBoolean(false);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
+ PropertySlot slot(thisObj);
+ if (!thisObj->getPropertySlot(exec, k, slot))
+ continue;
+
+ ArgList eachArguments;
+ eachArguments.append(slot.getValue(exec, k));
+ eachArguments.append(jsNumber(exec, k));
+ eachArguments.append(thisObj);
+
+ bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec);
+
+ if (predicateResult) {
+ result = jsBoolean(true);
+ break;
+ }
+ }
+ return result;
+}
+
+JSValue* arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ // JavaScript 1.5 Extension by Mozilla
+ // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
+
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ unsigned index = 0;
+ double d = args.at(exec, 1)->toInteger(exec);
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ if (d < 0)
+ d += length;
+ if (d > 0) {
+ if (d > length)
+ index = length;
+ else
+ index = static_cast<unsigned>(d);
+ }
+
+ JSValue* searchElement = args.at(exec, 0);
+ for (; index < length; ++index) {
+ JSValue* e = getProperty(exec, thisObj, index);
+ if (!e)
+ continue;
+ if (strictEqual(searchElement, e))
+ return jsNumber(exec, index);
+ }
+
+ return jsNumber(exec, -1);
+}
+
+JSValue* arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ // JavaScript 1.6 Extension by Mozilla
+ // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
+
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ int index = length - 1;
+ double d = args.at(exec, 1)->toIntegerPreserveNaN(exec);
+
+ if (d < 0) {
+ d += length;
+ if (d < 0)
+ return jsNumber(exec, -1);
+ }
+ if (d < length)
+ index = static_cast<int>(d);
+
+ JSValue* searchElement = args.at(exec, 0);
+ for (; index >= 0; --index) {
+ JSValue* e = getProperty(exec, thisObj, index);
+ if (!e)
+ continue;
+ if (strictEqual(searchElement, e))
+ return jsNumber(exec, index);
+ }
+
+ return jsNumber(exec, -1);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ArrayPrototype.h b/JavaScriptCore/runtime/ArrayPrototype.h
new file mode 100644
index 0000000..33ce30b
--- /dev/null
+++ b/JavaScriptCore/runtime/ArrayPrototype.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ArrayPrototype_h
+#define ArrayPrototype_h
+
+#include "JSArray.h"
+#include "lookup.h"
+
+namespace JSC {
+
+ class ArrayPrototype : public JSArray {
+ public:
+ explicit ArrayPrototype(PassRefPtr<StructureID>);
+
+ bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // ArrayPrototype_h
diff --git a/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
new file mode 100644
index 0000000..536d09c
--- /dev/null
+++ b/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
@@ -0,0 +1,55 @@
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BatchedTransitionOptimizer_h
+#define BatchedTransitionOptimizer_h
+
+#include <wtf/Noncopyable.h>
+#include "JSObject.h"
+
+namespace JSC {
+
+ class BatchedTransitionOptimizer : Noncopyable {
+ public:
+ BatchedTransitionOptimizer(JSObject* object)
+ : m_object(object)
+ {
+ if (!m_object->structureID()->isDictionary())
+ m_object->setStructureID(StructureID::toDictionaryTransition(m_object->structureID()));
+ }
+
+ ~BatchedTransitionOptimizer()
+ {
+ m_object->setStructureID(StructureID::fromDictionaryTransition(m_object->structureID()));
+ }
+
+ private:
+ JSObject* m_object;
+ };
+
+} // namespace JSC
+
+#endif // BatchedTransitionOptimizer_h
diff --git a/JavaScriptCore/runtime/BooleanConstructor.cpp b/JavaScriptCore/runtime/BooleanConstructor.cpp
new file mode 100644
index 0000000..46a6018
--- /dev/null
+++ b/JavaScriptCore/runtime/BooleanConstructor.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "BooleanConstructor.h"
+
+#include "BooleanPrototype.h"
+#include "JSGlobalObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
+
+BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<StructureID> structure, BooleanPrototype* booleanPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, booleanPrototype->classInfo()->className))
+{
+ putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum);
+}
+
+// ECMA 15.6.2
+JSObject* constructBoolean(ExecState* exec, const ArgList& args)
+{
+ BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
+ obj->setInternalValue(jsBoolean(args.at(exec, 0)->toBoolean(exec)));
+ return obj;
+}
+
+static JSObject* constructWithBooleanConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructBoolean(exec, args);
+}
+
+ConstructType BooleanConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithBooleanConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.6.1
+static JSValue* callBooleanConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsBoolean(args.at(exec, 0)->toBoolean(exec));
+}
+
+CallType BooleanConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callBooleanConstructor;
+ return CallTypeHost;
+}
+
+JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue* immediateBooleanValue)
+{
+ BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
+ obj->setInternalValue(immediateBooleanValue);
+ return obj;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/BooleanConstructor.h b/JavaScriptCore/runtime/BooleanConstructor.h
new file mode 100644
index 0000000..3b1f1a0
--- /dev/null
+++ b/JavaScriptCore/runtime/BooleanConstructor.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BooleanConstructor_h
+#define BooleanConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class BooleanPrototype;
+
+ class BooleanConstructor : public InternalFunction {
+ public:
+ BooleanConstructor(ExecState*, PassRefPtr<StructureID>, BooleanPrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+ JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValue*);
+ JSObject* constructBoolean(ExecState*, const ArgList&);
+
+} // namespace JSC
+
+#endif // BooleanConstructor_h
diff --git a/JavaScriptCore/runtime/BooleanObject.cpp b/JavaScriptCore/runtime/BooleanObject.cpp
new file mode 100644
index 0000000..2ebfb1b
--- /dev/null
+++ b/JavaScriptCore/runtime/BooleanObject.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "BooleanObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
+
+const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 };
+
+BooleanObject::BooleanObject(PassRefPtr<StructureID> structure)
+ : JSWrapperObject(structure)
+{
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/BooleanObject.h b/JavaScriptCore/runtime/BooleanObject.h
new file mode 100644
index 0000000..5963b28
--- /dev/null
+++ b/JavaScriptCore/runtime/BooleanObject.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BooleanObject_h
+#define BooleanObject_h
+
+#include "JSWrapperObject.h"
+
+namespace JSC {
+
+ class BooleanObject : public JSWrapperObject {
+ public:
+ explicit BooleanObject(PassRefPtr<StructureID>);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ BooleanObject* asBooleanObject(JSValue*);
+
+ inline BooleanObject* asBooleanObject(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&BooleanObject::info));
+ return static_cast<BooleanObject*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // BooleanObject_h
diff --git a/JavaScriptCore/runtime/BooleanPrototype.cpp b/JavaScriptCore/runtime/BooleanPrototype.cpp
new file mode 100644
index 0000000..b47aeac
--- /dev/null
+++ b/JavaScriptCore/runtime/BooleanPrototype.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "BooleanPrototype.h"
+
+#include "Error.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
+
+// Functions
+static JSValue* booleanProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* booleanProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+// ECMA 15.6.4
+
+BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure)
+ : BooleanObject(structure)
+{
+ setInternalValue(jsBoolean(false));
+
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum);
+}
+
+
+// ------------------------------ Functions --------------------------
+
+// ECMA 15.6.4.2 + 15.6.4.3
+
+JSValue* booleanProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (thisValue == jsBoolean(false))
+ return jsNontrivialString(exec, "false");
+
+ if (thisValue == jsBoolean(true))
+ return jsNontrivialString(exec, "true");
+
+ if (!thisValue->isObject(&BooleanObject::info))
+ return throwError(exec, TypeError);
+
+ if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
+ return jsNontrivialString(exec, "false");
+
+ ASSERT(asBooleanObject(thisValue)->internalValue() == jsBoolean(true));
+ return jsNontrivialString(exec, "true");
+}
+
+JSValue* booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (JSImmediate::isBoolean(thisValue))
+ return thisValue;
+
+ if (!thisValue->isObject(&BooleanObject::info))
+ return throwError(exec, TypeError);
+
+ return asBooleanObject(thisValue)->internalValue();
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/BooleanPrototype.h b/JavaScriptCore/runtime/BooleanPrototype.h
new file mode 100644
index 0000000..484bb7d
--- /dev/null
+++ b/JavaScriptCore/runtime/BooleanPrototype.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef BooleanPrototype_h
+#define BooleanPrototype_h
+
+#include "BooleanObject.h"
+
+namespace JSC {
+
+ class BooleanPrototype : public BooleanObject {
+ public:
+ BooleanPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure);
+ };
+
+} // namespace JSC
+
+#endif // BooleanPrototype_h
diff --git a/JavaScriptCore/runtime/CallData.cpp b/JavaScriptCore/runtime/CallData.cpp
new file mode 100644
index 0000000..572c495
--- /dev/null
+++ b/JavaScriptCore/runtime/CallData.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CallData.h"
+
+#include "JSFunction.h"
+
+namespace JSC {
+
+JSValue* call(ExecState* exec, JSValue* functionObject, CallType callType, const CallData& callData, JSValue* thisValue, const ArgList& args)
+{
+ if (callType == CallTypeHost)
+ return callData.native.function(exec, asObject(functionObject), thisValue, args);
+ ASSERT(callType == CallTypeJS);
+ // FIXME: Can this be done more efficiently using the callData?
+ return asFunction(functionObject)->call(exec, thisValue, args);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/CallData.h b/JavaScriptCore/runtime/CallData.h
new file mode 100644
index 0000000..5be011a
--- /dev/null
+++ b/JavaScriptCore/runtime/CallData.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CallData_h
+#define CallData_h
+
+#include "JSImmediate.h"
+
+namespace JSC {
+
+ class ArgList;
+ class ExecState;
+ class FunctionBodyNode;
+ class JSObject;
+ class ScopeChainNode;
+
+ enum CallType {
+ CallTypeNone,
+ CallTypeHost,
+ CallTypeJS
+ };
+
+ typedef JSValue* (*NativeFunction)(ExecState*, JSObject*, JSValue* thisValue, const ArgList&);
+
+ union CallData {
+ struct {
+ NativeFunction function;
+ } native;
+ struct {
+ FunctionBodyNode* functionBody;
+ ScopeChainNode* scopeChain;
+ } js;
+ };
+
+ JSValue* call(ExecState*, JSValue* functionObject, CallType, const CallData&, JSValue* thisValue, const ArgList&);
+
+} // namespace JSC
+
+#endif // CallData_h
diff --git a/JavaScriptCore/runtime/ClassInfo.h b/JavaScriptCore/runtime/ClassInfo.h
new file mode 100644
index 0000000..979145e
--- /dev/null
+++ b/JavaScriptCore/runtime/ClassInfo.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ClassInfo_h
+#define ClassInfo_h
+
+#include "ExecState.h"
+
+namespace JSC {
+
+ struct HashEntry;
+ struct HashTable;
+
+ struct ClassInfo {
+ /**
+ * A string denoting the class name. Example: "Window".
+ */
+ const char* className;
+
+ /**
+ * Pointer to the class information of the base class.
+ * 0L if there is none.
+ */
+ const ClassInfo* parentClass;
+ /**
+ * Static hash-table of properties.
+ * For classes that can be used from multiple threads, it is accessed via a getter function that would typically return a pointer to thread-specific value.
+ */
+ const HashTable* propHashTable(ExecState* exec) const
+ {
+ if (classPropHashTableGetterFunction)
+ return classPropHashTableGetterFunction(exec);
+ return staticPropHashTable;
+ }
+
+ const HashTable* staticPropHashTable;
+ typedef const HashTable* (*ClassPropHashTableGetterFunction)(ExecState*);
+ const ClassPropHashTableGetterFunction classPropHashTableGetterFunction;
+ };
+
+} // namespace JSC
+
+#endif // ClassInfo_h
diff --git a/JavaScriptCore/runtime/CollectorHeapIterator.h b/JavaScriptCore/runtime/CollectorHeapIterator.h
new file mode 100644
index 0000000..c5e1d78
--- /dev/null
+++ b/JavaScriptCore/runtime/CollectorHeapIterator.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "collector.h"
+
+namespace JSC {
+
+ template <HeapType heapType> class CollectorHeapIterator {
+ public:
+ CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock);
+
+ bool operator!=(const CollectorHeapIterator<heapType>& other) { return m_block != other.m_block || m_cell != other.m_cell; }
+ CollectorHeapIterator<heapType>& operator++();
+ JSCell* operator*() const;
+
+ private:
+ typedef typename HeapConstants<heapType>::Block Block;
+ typedef typename HeapConstants<heapType>::Cell Cell;
+
+ Block** m_block;
+ Block** m_endBlock;
+ Cell* m_cell;
+ Cell* m_endCell;
+ };
+
+ template <HeapType heapType>
+ CollectorHeapIterator<heapType>::CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock)
+ : m_block(reinterpret_cast<Block**>(block))
+ , m_endBlock(reinterpret_cast<Block**>(endBlock))
+ , m_cell(m_block == m_endBlock ? 0 : (*m_block)->cells)
+ , m_endCell(m_block == m_endBlock ? 0 : (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock)
+ {
+ if (m_cell && m_cell->u.freeCell.zeroIfFree == 0)
+ ++*this;
+ }
+
+ template <HeapType heapType>
+ CollectorHeapIterator<heapType>& CollectorHeapIterator<heapType>::operator++()
+ {
+ do {
+ for (++m_cell; m_cell != m_endCell; ++m_cell)
+ if (m_cell->u.freeCell.zeroIfFree != 0) {
+ return *this;
+ }
+
+ if (++m_block != m_endBlock) {
+ m_cell = (*m_block)->cells;
+ m_endCell = (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock;
+ }
+ } while(m_block != m_endBlock);
+
+ m_cell = 0;
+ return *this;
+ }
+
+ template <HeapType heapType>
+ JSCell* CollectorHeapIterator<heapType>::operator*() const
+ {
+ return reinterpret_cast<JSCell*>(m_cell);
+ }
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/CommonIdentifiers.cpp b/JavaScriptCore/runtime/CommonIdentifiers.cpp
new file mode 100644
index 0000000..fe0a830
--- /dev/null
+++ b/JavaScriptCore/runtime/CommonIdentifiers.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "CommonIdentifiers.h"
+
+namespace JSC {
+
+const char* const nullCString = 0;
+
+#define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name)
+
+CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData)
+ : nullIdentifier(globalData, nullCString)
+ , underscoreProto(globalData, "__proto__")
+ , thisIdentifier(globalData, "this")
+ JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
+{
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h
new file mode 100644
index 0000000..1788c77
--- /dev/null
+++ b/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2003,2007 Apple Computer, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CommonIdentifiers_h
+#define CommonIdentifiers_h
+
+#include "identifier.h"
+#include <wtf/Noncopyable.h>
+
+// ArgList of property names, passed to a macro so we can do set them up various
+// ways without repeating the list.
+#define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
+ macro(__defineGetter__) \
+ macro(__defineSetter__) \
+ macro(__lookupGetter__) \
+ macro(__lookupSetter__) \
+ macro(apply) \
+ macro(arguments) \
+ macro(call) \
+ macro(callee) \
+ macro(caller) \
+ macro(compile) \
+ macro(constructor) \
+ macro(eval) \
+ macro(exec) \
+ macro(fromCharCode) \
+ macro(global) \
+ macro(hasOwnProperty) \
+ macro(ignoreCase) \
+ macro(index) \
+ macro(input) \
+ macro(isPrototypeOf) \
+ macro(length) \
+ macro(message) \
+ macro(multiline) \
+ macro(name) \
+ macro(now) \
+ macro(parse) \
+ macro(propertyIsEnumerable) \
+ macro(prototype) \
+ macro(source) \
+ macro(test) \
+ macro(toExponential) \
+ macro(toFixed) \
+ macro(toLocaleString) \
+ macro(toPrecision) \
+ macro(toString) \
+ macro(UTC) \
+ macro(valueOf)
+
+namespace JSC {
+
+ class CommonIdentifiers : Noncopyable {
+ private:
+ CommonIdentifiers(JSGlobalData*);
+ friend class JSGlobalData;
+
+ public:
+ const Identifier nullIdentifier;
+ const Identifier underscoreProto;
+ const Identifier thisIdentifier;
+
+#define JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name;
+ JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL)
+#undef JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL
+ };
+
+} // namespace JSC
+
+#endif // CommonIdentifiers_h
diff --git a/JavaScriptCore/runtime/ConstructData.cpp b/JavaScriptCore/runtime/ConstructData.cpp
new file mode 100644
index 0000000..88a8ef6
--- /dev/null
+++ b/JavaScriptCore/runtime/ConstructData.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ConstructData.h"
+
+#include "JSFunction.h"
+
+namespace JSC {
+
+JSObject* construct(ExecState* exec, JSValue* object, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
+{
+ if (constructType == ConstructTypeHost)
+ return constructData.native.function(exec, asObject(object), args);
+ ASSERT(constructType == ConstructTypeJS);
+ // FIXME: Can this be done more efficiently using the constructData?
+ return asFunction(object)->construct(exec, args);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ConstructData.h b/JavaScriptCore/runtime/ConstructData.h
new file mode 100644
index 0000000..3cc52a0
--- /dev/null
+++ b/JavaScriptCore/runtime/ConstructData.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ConstructData_h
+#define ConstructData_h
+
+#include "JSImmediate.h" // temporary until JSValue* becomes a class we can forward-declare
+
+namespace JSC {
+
+ class ArgList;
+ class ExecState;
+ class FunctionBodyNode;
+ class JSObject;
+ class ScopeChainNode;
+
+ enum ConstructType {
+ ConstructTypeNone,
+ ConstructTypeHost,
+ ConstructTypeJS
+ };
+
+ typedef JSObject* (*NativeConstructor)(ExecState*, JSObject*, const ArgList&);
+
+ union ConstructData {
+ struct {
+ NativeConstructor function;
+ } native;
+ struct {
+ FunctionBodyNode* functionBody;
+ ScopeChainNode* scopeChain;
+ } js;
+ };
+
+ JSObject* construct(ExecState*, JSValue* constructor, ConstructType, const ConstructData&, const ArgList&);
+
+} // namespace JSC
+
+#endif // ConstructData_h
diff --git a/JavaScriptCore/runtime/DateConstructor.cpp b/JavaScriptCore/runtime/DateConstructor.cpp
new file mode 100644
index 0000000..8339ff3
--- /dev/null
+++ b/JavaScriptCore/runtime/DateConstructor.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "DateConstructor.h"
+
+#include "DateInstance.h"
+#include "DateMath.h"
+#include "DatePrototype.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "PrototypeFunction.h"
+#include <math.h>
+#include <time.h>
+#include <wtf/MathExtras.h>
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if HAVE(SYS_TIMEB_H)
+#include <sys/timeb.h>
+#endif
+
+namespace JSC {
+
+// TODO: MakeTime (15.9.11.1) etc. ?
+
+ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
+
+static JSValue* dateParse(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateNow(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateUTC(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+DateConstructor::DateConstructor(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure, DatePrototype* datePrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className))
+{
+ putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly);
+
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), DontEnum);
+
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 7), ReadOnly | DontEnum | DontDelete);
+}
+
+// ECMA 15.9.3
+JSObject* constructDate(ExecState* exec, const ArgList& args)
+{
+ int numArgs = args.size();
+
+ double value;
+
+ if (numArgs == 0) // new Date() ECMA 15.9.3.3
+ value = getCurrentUTCTime();
+ else if (numArgs == 1) {
+ if (args.at(exec, 0)->isObject(&DateInstance::info))
+ value = asDateInstance(args.at(exec, 0))->internalNumber();
+ else {
+ JSValue* primitive = args.at(exec, 0)->toPrimitive(exec);
+ if (primitive->isString())
+ value = parseDate(primitive->getString());
+ else
+ value = primitive->toNumber(exec);
+ }
+ } else {
+ if (isnan(args.at(exec, 0)->toNumber(exec))
+ || isnan(args.at(exec, 1)->toNumber(exec))
+ || (numArgs >= 3 && isnan(args.at(exec, 2)->toNumber(exec)))
+ || (numArgs >= 4 && isnan(args.at(exec, 3)->toNumber(exec)))
+ || (numArgs >= 5 && isnan(args.at(exec, 4)->toNumber(exec)))
+ || (numArgs >= 6 && isnan(args.at(exec, 5)->toNumber(exec)))
+ || (numArgs >= 7 && isnan(args.at(exec, 6)->toNumber(exec))))
+ value = NaN;
+ else {
+ GregorianDateTime t;
+ int year = args.at(exec, 0)->toInt32(exec);
+ t.year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.month = args.at(exec, 1)->toInt32(exec);
+ t.monthDay = (numArgs >= 3) ? args.at(exec, 2)->toInt32(exec) : 1;
+ t.hour = args.at(exec, 3)->toInt32(exec);
+ t.minute = args.at(exec, 4)->toInt32(exec);
+ t.second = args.at(exec, 5)->toInt32(exec);
+ t.isDST = -1;
+ double ms = (numArgs >= 7) ? args.at(exec, 6)->toNumber(exec) : 0;
+ value = gregorianDateTimeToMS(t, ms, false);
+ }
+ }
+
+ DateInstance* result = new (exec) DateInstance(exec->lexicalGlobalObject()->dateStructure());
+ result->setInternalValue(jsNumber(exec, timeClip(value)));
+ return result;
+}
+
+static JSObject* constructWithDateConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructDate(exec, args);
+}
+
+ConstructType DateConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithDateConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.9.2
+static JSValue* callDate(ExecState* exec, JSObject*, JSValue*, const ArgList&)
+{
+ time_t localTime = time(0);
+ tm localTM;
+ getLocalTime(&localTime, &localTM);
+ GregorianDateTime ts(localTM);
+ return jsNontrivialString(exec, formatDate(ts) + " " + formatTime(ts, false));
+}
+
+CallType DateConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callDate;
+ return CallTypeHost;
+}
+
+static JSValue* dateParse(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, parseDate(args.at(exec, 0)->toString(exec)));
+}
+
+static JSValue* dateNow(ExecState* exec, JSObject*, JSValue*, const ArgList&)
+{
+ return jsNumber(exec, getCurrentUTCTime());
+}
+
+static JSValue* dateUTC(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ int n = args.size();
+ if (isnan(args.at(exec, 0)->toNumber(exec))
+ || isnan(args.at(exec, 1)->toNumber(exec))
+ || (n >= 3 && isnan(args.at(exec, 2)->toNumber(exec)))
+ || (n >= 4 && isnan(args.at(exec, 3)->toNumber(exec)))
+ || (n >= 5 && isnan(args.at(exec, 4)->toNumber(exec)))
+ || (n >= 6 && isnan(args.at(exec, 5)->toNumber(exec)))
+ || (n >= 7 && isnan(args.at(exec, 6)->toNumber(exec))))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ int year = args.at(exec, 0)->toInt32(exec);
+ t.year = (year >= 0 && year <= 99) ? year : year - 1900;
+ t.month = args.at(exec, 1)->toInt32(exec);
+ t.monthDay = (n >= 3) ? args.at(exec, 2)->toInt32(exec) : 1;
+ t.hour = args.at(exec, 3)->toInt32(exec);
+ t.minute = args.at(exec, 4)->toInt32(exec);
+ t.second = args.at(exec, 5)->toInt32(exec);
+ double ms = (n >= 7) ? args.at(exec, 6)->toNumber(exec) : 0;
+ return jsNumber(exec, gregorianDateTimeToMS(t, ms, true));
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/DateConstructor.h b/JavaScriptCore/runtime/DateConstructor.h
new file mode 100644
index 0000000..1279f82
--- /dev/null
+++ b/JavaScriptCore/runtime/DateConstructor.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef DateConstructor_h
+#define DateConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class DatePrototype;
+
+ class DateConstructor : public InternalFunction {
+ public:
+ DateConstructor(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure, DatePrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+ JSObject* constructDate(ExecState*, const ArgList&);
+
+} // namespace JSC
+
+#endif // DateConstructor_h
diff --git a/JavaScriptCore/runtime/DateInstance.cpp b/JavaScriptCore/runtime/DateInstance.cpp
new file mode 100644
index 0000000..b38c6ef
--- /dev/null
+++ b/JavaScriptCore/runtime/DateInstance.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "DateInstance.h"
+
+#include "DateMath.h"
+#include <math.h>
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+struct DateInstance::Cache {
+ double m_gregorianDateTimeCachedForMS;
+ GregorianDateTime m_cachedGregorianDateTime;
+ double m_gregorianDateTimeUTCCachedForMS;
+ GregorianDateTime m_cachedGregorianDateTimeUTC;
+};
+
+const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
+
+DateInstance::DateInstance(PassRefPtr<StructureID> structure)
+ : JSWrapperObject(structure)
+ , m_cache(0)
+{
+}
+
+DateInstance::~DateInstance()
+{
+ delete m_cache;
+}
+
+void DateInstance::msToGregorianDateTime(double milli, bool outputIsUTC, GregorianDateTime& t) const
+{
+ if (!m_cache) {
+ m_cache = new Cache;
+ m_cache->m_gregorianDateTimeCachedForMS = NaN;
+ m_cache->m_gregorianDateTimeUTCCachedForMS = NaN;
+ }
+
+ if (outputIsUTC) {
+ if (m_cache->m_gregorianDateTimeUTCCachedForMS != milli) {
+ JSC::msToGregorianDateTime(milli, true, m_cache->m_cachedGregorianDateTimeUTC);
+ m_cache->m_gregorianDateTimeUTCCachedForMS = milli;
+ }
+ t.copyFrom(m_cache->m_cachedGregorianDateTimeUTC);
+ } else {
+ if (m_cache->m_gregorianDateTimeCachedForMS != milli) {
+ JSC::msToGregorianDateTime(milli, false, m_cache->m_cachedGregorianDateTime);
+ m_cache->m_gregorianDateTimeCachedForMS = milli;
+ }
+ t.copyFrom(m_cache->m_cachedGregorianDateTime);
+ }
+}
+
+bool DateInstance::getTime(GregorianDateTime& t, int& offset) const
+{
+ double milli = internalNumber();
+ if (isnan(milli))
+ return false;
+
+ msToGregorianDateTime(milli, false, t);
+ offset = gmtoffset(t);
+ return true;
+}
+
+bool DateInstance::getUTCTime(GregorianDateTime& t) const
+{
+ double milli = internalNumber();
+ if (isnan(milli))
+ return false;
+
+ msToGregorianDateTime(milli, true, t);
+ return true;
+}
+
+bool DateInstance::getTime(double& milli, int& offset) const
+{
+ milli = internalNumber();
+ if (isnan(milli))
+ return false;
+
+ GregorianDateTime t;
+ msToGregorianDateTime(milli, false, t);
+ offset = gmtoffset(t);
+ return true;
+}
+
+bool DateInstance::getUTCTime(double& milli) const
+{
+ milli = internalNumber();
+ if (isnan(milli))
+ return false;
+
+ return true;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/DateInstance.h b/JavaScriptCore/runtime/DateInstance.h
new file mode 100644
index 0000000..98f4b64
--- /dev/null
+++ b/JavaScriptCore/runtime/DateInstance.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef DateInstance_h
+#define DateInstance_h
+
+#include "JSWrapperObject.h"
+
+namespace JSC {
+
+ struct GregorianDateTime;
+
+ class DateInstance : public JSWrapperObject {
+ public:
+ explicit DateInstance(PassRefPtr<StructureID>);
+ virtual ~DateInstance();
+
+ double internalNumber() const { return internalValue()->uncheckedGetNumber(); }
+
+ bool getTime(GregorianDateTime&, int& offset) const;
+ bool getUTCTime(GregorianDateTime&) const;
+ bool getTime(double& milliseconds, int& offset) const;
+ bool getUTCTime(double& milliseconds) const;
+
+ static const ClassInfo info;
+
+ void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&) const;
+
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ using JSWrapperObject::internalValue;
+
+ struct Cache;
+ mutable Cache* m_cache;
+ };
+
+ DateInstance* asDateInstance(JSValue*);
+
+ inline DateInstance* asDateInstance(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&DateInstance::info));
+ return static_cast<DateInstance*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // DateInstance_h
diff --git a/JavaScriptCore/runtime/DateMath.cpp b/JavaScriptCore/runtime/DateMath.cpp
new file mode 100644
index 0000000..ec2a3f6
--- /dev/null
+++ b/JavaScriptCore/runtime/DateMath.cpp
@@ -0,0 +1,1046 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "DateMath.h"
+
+#include "JSNumberCell.h"
+#include <math.h>
+#include <stdint.h>
+#include <time.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
+
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#endif
+
+#if PLATFORM(DARWIN)
+#include <notify.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if HAVE(SYS_TIMEB_H)
+#include <sys/timeb.h>
+#endif
+
+using namespace WTF;
+
+namespace JSC {
+
+/* Constants */
+
+static const double minutesPerDay = 24.0 * 60.0;
+static const double secondsPerDay = 24.0 * 60.0 * 60.0;
+static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0;
+
+static const double usecPerSec = 1000000.0;
+
+static const double maxUnixTime = 2145859200.0; // 12/31/2037
+
+// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
+// First for non-leap years, then for leap years.
+static const int firstDayOfMonth[2][12] = {
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
+};
+
+static inline bool isLeapYear(int year)
+{
+ if (year % 4 != 0)
+ return false;
+ if (year % 400 == 0)
+ return true;
+ if (year % 100 == 0)
+ return false;
+ return true;
+}
+
+static inline int daysInYear(int year)
+{
+ return 365 + isLeapYear(year);
+}
+
+static inline double daysFrom1970ToYear(int year)
+{
+ // The Gregorian Calendar rules for leap years:
+ // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years.
+ // However, every hundredth year is not a leap year. 1900 and 2100 are not leap years.
+ // Every four hundred years, there's a leap year after all. 2000 and 2400 are leap years.
+
+ static const int leapDaysBefore1971By4Rule = 1970 / 4;
+ static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100;
+ static const int leapDaysBefore1971By400Rule = 1970 / 400;
+
+ const double yearMinusOne = year - 1;
+ const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule;
+ const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule;
+ const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule;
+
+ return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule;
+}
+
+static inline double msToDays(double ms)
+{
+ return floor(ms / msPerDay);
+}
+
+static inline int msToYear(double ms)
+{
+ int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
+ double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
+ if (msFromApproxYearTo1970 > ms)
+ return approxYear - 1;
+ if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms)
+ return approxYear + 1;
+ return approxYear;
+}
+
+static inline int dayInYear(double ms, int year)
+{
+ return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year));
+}
+
+static inline double msToMilliseconds(double ms)
+{
+ double result = fmod(ms, msPerDay);
+ if (result < 0)
+ result += msPerDay;
+ return result;
+}
+
+// 0: Sunday, 1: Monday, etc.
+static inline int msToWeekDay(double ms)
+{
+ int wd = (static_cast<int>(msToDays(ms)) + 4) % 7;
+ if (wd < 0)
+ wd += 7;
+ return wd;
+}
+
+static inline int msToSeconds(double ms)
+{
+ double result = fmod(floor(ms / msPerSecond), secondsPerMinute);
+ if (result < 0)
+ result += secondsPerMinute;
+ return static_cast<int>(result);
+}
+
+static inline int msToMinutes(double ms)
+{
+ double result = fmod(floor(ms / msPerMinute), minutesPerHour);
+ if (result < 0)
+ result += minutesPerHour;
+ return static_cast<int>(result);
+}
+
+static inline int msToHours(double ms)
+{
+ double result = fmod(floor(ms/msPerHour), hoursPerDay);
+ if (result < 0)
+ result += hoursPerDay;
+ return static_cast<int>(result);
+}
+
+static inline int monthFromDayInYear(int dayInYear, bool leapYear)
+{
+ const int d = dayInYear;
+ int step;
+
+ if (d < (step = 31))
+ return 0;
+ step += (leapYear ? 29 : 28);
+ if (d < step)
+ return 1;
+ if (d < (step += 31))
+ return 2;
+ if (d < (step += 30))
+ return 3;
+ if (d < (step += 31))
+ return 4;
+ if (d < (step += 30))
+ return 5;
+ if (d < (step += 31))
+ return 6;
+ if (d < (step += 31))
+ return 7;
+ if (d < (step += 30))
+ return 8;
+ if (d < (step += 31))
+ return 9;
+ if (d < (step += 30))
+ return 10;
+ return 11;
+}
+
+static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth)
+{
+ startDayOfThisMonth = startDayOfNextMonth;
+ startDayOfNextMonth += daysInThisMonth;
+ return (dayInYear <= startDayOfNextMonth);
+}
+
+static inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
+{
+ const int d = dayInYear;
+ int step;
+ int next = 30;
+
+ if (d <= next)
+ return d + 1;
+ const int daysInFeb = (leapYear ? 29 : 28);
+ if (checkMonth(d, step, next, daysInFeb))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ if (checkMonth(d, step, next, 31))
+ return d - step;
+ if (checkMonth(d, step, next, 30))
+ return d - step;
+ step = next;
+ return d - step;
+}
+
+static inline int monthToDayInYear(int month, bool isLeapYear)
+{
+ return firstDayOfMonth[isLeapYear][month];
+}
+
+static inline double timeToMS(double hour, double min, double sec, double ms)
+{
+ return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
+}
+
+static int dateToDayInYear(int year, int month, int day)
+{
+ year += month / 12;
+
+ month %= 12;
+ if (month < 0) {
+ month += 12;
+ --year;
+ }
+
+ int yearday = static_cast<int>(floor(daysFrom1970ToYear(year)));
+ int monthday = monthToDayInYear(month, isLeapYear(year));
+
+ return yearday + monthday + day - 1;
+}
+
+double getCurrentUTCTime()
+{
+ return floor(getCurrentUTCTimeWithMicroseconds());
+}
+
+#if PLATFORM(WIN_OS)
+
+static LARGE_INTEGER qpcFrequency;
+static bool syncedTime;
+
+static double highResUpTime()
+{
+ // We use QPC, but only after sanity checking its result, due to bugs:
+ // http://support.microsoft.com/kb/274323
+ // http://support.microsoft.com/kb/895980
+ // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("...you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL)."
+
+ static LARGE_INTEGER qpcLast;
+ static DWORD tickCountLast;
+ static bool inited;
+
+ LARGE_INTEGER qpc;
+ QueryPerformanceCounter(&qpc);
+ DWORD tickCount = GetTickCount();
+
+ if (inited) {
+ __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart;
+ __int64 tickCountElapsed;
+ if (tickCount >= tickCountLast)
+ tickCountElapsed = (tickCount - tickCountLast);
+ else {
+#if COMPILER(MINGW)
+ __int64 tickCountLarge = tickCount + 0x100000000ULL;
+#else
+ __int64 tickCountLarge = tickCount + 0x100000000I64;
+#endif
+ tickCountElapsed = tickCountLarge - tickCountLast;
+ }
+
+ // force a re-sync if QueryPerformanceCounter differs from GetTickCount by more than 500ms.
+ // (500ms value is from http://support.microsoft.com/kb/274323)
+ __int64 diff = tickCountElapsed - qpcElapsed;
+ if (diff > 500 || diff < -500)
+ syncedTime = false;
+ } else
+ inited = true;
+
+ qpcLast = qpc;
+ tickCountLast = tickCount;
+
+ return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart);;
+}
+
+static double lowResUTCTime()
+{
+ struct _timeb timebuffer;
+ _ftime(&timebuffer);
+ return timebuffer.time * msPerSecond + timebuffer.millitm;
+}
+
+static bool qpcAvailable()
+{
+ static bool available;
+ static bool checked;
+
+ if (checked)
+ return available;
+
+ available = QueryPerformanceFrequency(&qpcFrequency);
+ checked = true;
+ return available;
+}
+
+#endif
+
+double getCurrentUTCTimeWithMicroseconds()
+{
+#if PLATFORM(WIN_OS)
+ // Use a combination of ftime and QueryPerformanceCounter.
+ // ftime returns the information we want, but doesn't have sufficient resolution.
+ // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals.
+ // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will use QueryPerformanceCounter
+ // by itself, adding the delta to the saved ftime. We periodically re-sync to correct for drift.
+ static bool started;
+ static double syncLowResUTCTime;
+ static double syncHighResUpTime;
+ static double lastUTCTime;
+
+ double lowResTime = lowResUTCTime();
+
+ if (!qpcAvailable())
+ return lowResTime;
+
+ double highResTime = highResUpTime();
+
+ if (!syncedTime) {
+ timeBeginPeriod(1); // increase time resolution around low-res time getter
+ syncLowResUTCTime = lowResTime = lowResUTCTime();
+ timeEndPeriod(1); // restore time resolution
+ syncHighResUpTime = highResTime;
+ syncedTime = true;
+ }
+
+ double highResElapsed = highResTime - syncHighResUpTime;
+ double utc = syncLowResUTCTime + highResElapsed;
+
+ // force a clock re-sync if we've drifted
+ double lowResElapsed = lowResTime - syncLowResUTCTime;
+ const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy
+ if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec)
+ syncedTime = false;
+
+ // make sure time doesn't run backwards (only correct if difference is < 2 seconds, since DST or clock changes could occur)
+ const double backwardTimeLimit = 2000.0;
+ if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit)
+ return lastUTCTime;
+ lastUTCTime = utc;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ double utc = tv.tv_sec * msPerSecond + tv.tv_usec / 1000.0;
+#endif
+ return utc;
+}
+
+void getLocalTime(const time_t* localTime, struct tm* localTM)
+{
+#if COMPILER(MSVC7) || COMPILER(MINGW)
+ *localTM = *localtime(localTime);
+#elif COMPILER(MSVC)
+ localtime_s(localTM, localTime);
+#else
+ localtime_r(localTime, localTM);
+#endif
+}
+
+// There is a hard limit at 2038 that we currently do not have a workaround
+// for (rdar://problem/5052975).
+static inline int maximumYearForDST()
+{
+ return 2037;
+}
+
+static inline int minimumYearForDST()
+{
+ // Because of the 2038 issue (see maximumYearForDST) if the current year is
+ // greater than the max year minus 27 (2010), we want to use the max year
+ // minus 27 instead, to ensure there is a range of 28 years that all years
+ // can map to.
+ return std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ;
+}
+
+/*
+ * Find an equivalent year for the one given, where equivalence is deterined by
+ * the two years having the same leapness and the first day of the year, falling
+ * on the same day of the week.
+ *
+ * This function returns a year between this current year and 2037, however this
+ * function will potentially return incorrect results if the current year is after
+ * 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after
+ * 2100, (rdar://problem/5055038).
+ */
+int equivalentYearForDST(int year)
+{
+ // It is ok if the cached year is not the current year as long as the rules
+ // for DST did not change between the two years; if they did the app would need
+ // to be restarted.
+ static int minYear = minimumYearForDST();
+ int maxYear = maximumYearForDST();
+
+ int difference;
+ if (year > maxYear)
+ difference = minYear - year;
+ else if (year < minYear)
+ difference = maxYear - year;
+ else
+ return year;
+
+ int quotient = difference / 28;
+ int product = (quotient) * 28;
+
+ year += product;
+ ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(NaN)));
+ return year;
+}
+
+static int32_t calculateUTCOffset()
+{
+ tm localt;
+ memset(&localt, 0, sizeof(localt));
+
+ // get the difference between this time zone and UTC on Jan 01, 2000 12:00:00 AM
+ localt.tm_mday = 1;
+ localt.tm_year = 100;
+ time_t utcOffset = 946684800 - mktime(&localt);
+
+ return static_cast<int32_t>(utcOffset * 1000);
+}
+
+#if PLATFORM(DARWIN)
+static int32_t s_cachedUTCOffset; // In milliseconds. An assumption here is that access to an int32_t variable is atomic on platforms that take this code path.
+static bool s_haveCachedUTCOffset;
+static int s_notificationToken;
+#endif
+
+/*
+ * Get the difference in milliseconds between this time zone and UTC (GMT)
+ * NOT including DST.
+ */
+double getUTCOffset()
+{
+#if PLATFORM(DARWIN)
+ if (s_haveCachedUTCOffset) {
+ int notified;
+ uint32_t status = notify_check(s_notificationToken, &notified);
+ if (status == NOTIFY_STATUS_OK && !notified)
+ return s_cachedUTCOffset;
+ }
+#endif
+
+ int32_t utcOffset = calculateUTCOffset();
+
+#if PLATFORM(DARWIN)
+ // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition,
+ // and a newer value may be overwritten. In practice, time zones don't change that often.
+ s_cachedUTCOffset = utcOffset;
+#endif
+
+ return utcOffset;
+}
+
+/*
+ * Get the DST offset for the time passed in. Takes
+ * seconds (not milliseconds) and cannot handle dates before 1970
+ * on some OS'
+ */
+static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset)
+{
+ if (localTimeSeconds > maxUnixTime)
+ localTimeSeconds = maxUnixTime;
+ else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0)
+ localTimeSeconds += secondsPerDay;
+
+ //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset()
+ double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset;
+
+ // Offset from UTC but doesn't include DST obviously
+ int offsetHour = msToHours(offsetTime);
+ int offsetMinute = msToMinutes(offsetTime);
+
+ // FIXME: time_t has a potential problem in 2038
+ time_t localTime = static_cast<time_t>(localTimeSeconds);
+
+ tm localTM;
+ getLocalTime(&localTime, &localTM);
+
+ double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.tm_min - offsetMinute) * 60);
+
+ if (diff < 0)
+ diff += secondsPerDay;
+
+ return (diff * msPerSecond);
+}
+
+// Get the DST offset, given a time in UTC
+static double getDSTOffset(double ms, double utcOffset)
+{
+ // On Mac OS X, the call to localtime (see getDSTOffsetSimple) will return historically accurate
+ // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript
+ // standard explicitly dictates that historical information should not be considered when
+ // determining DST. For this reason we shift away from years that localtime can handle but would
+ // return historically accurate information.
+ int year = msToYear(ms);
+ int equivalentYear = equivalentYearForDST(year);
+ if (year != equivalentYear) {
+ bool leapYear = isLeapYear(year);
+ int dayInYearLocal = dayInYear(ms, year);
+ int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear);
+ int month = monthFromDayInYear(dayInYearLocal, leapYear);
+ int day = dateToDayInYear(equivalentYear, month, dayInMonth);
+ ms = (day * msPerDay) + msToMilliseconds(ms);
+ }
+
+ return getDSTOffsetSimple(ms / msPerSecond, utcOffset);
+}
+
+double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
+{
+ int day = dateToDayInYear(t.year + 1900, t.month, t.monthDay);
+ double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
+ double result = (day * msPerDay) + ms;
+
+ if (!inputIsUTC) { // convert to UTC
+ double utcOffset = getUTCOffset();
+ result -= utcOffset;
+ result -= getDSTOffset(result, utcOffset);
+ }
+
+ return result;
+}
+
+void msToGregorianDateTime(double ms, bool outputIsUTC, GregorianDateTime& tm)
+{
+ // input is UTC
+ double dstOff = 0.0;
+ const double utcOff = getUTCOffset();
+
+ if (!outputIsUTC) { // convert to local time
+ dstOff = getDSTOffset(ms, utcOff);
+ ms += dstOff + utcOff;
+ }
+
+ const int year = msToYear(ms);
+ tm.second = msToSeconds(ms);
+ tm.minute = msToMinutes(ms);
+ tm.hour = msToHours(ms);
+ tm.weekDay = msToWeekDay(ms);
+ tm.yearDay = dayInYear(ms, year);
+ tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
+ tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year));
+ tm.year = year - 1900;
+ tm.isDST = dstOff != 0.0;
+
+ tm.utcOffset = static_cast<long>((dstOff + utcOff) / msPerSecond);
+ tm.timeZone = NULL;
+}
+
+void initDateMath()
+{
+#ifndef NDEBUG
+ static bool alreadyInitialized;
+ ASSERT(!alreadyInitialized++);
+#endif
+
+ equivalentYearForDST(2000); // Need to call once to initialize a static used in this function.
+#if PLATFORM(DARWIN)
+ // Register for a notification whenever the time zone changes.
+ uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken);
+ if (status == NOTIFY_STATUS_OK) {
+ s_cachedUTCOffset = calculateUTCOffset();
+ s_haveCachedUTCOffset = true;
+ }
+#endif
+}
+
+static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
+{
+ double days = (day - 32075)
+ + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
+ + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
+ - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
+ - 2440588;
+ return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
+}
+
+// We follow the recommendation of RFC 2822 to consider all
+// obsolete time zones not listed here equivalent to "-0000".
+static const struct KnownZone {
+#if !PLATFORM(WIN_OS)
+ const
+#endif
+ char tzName[4];
+ int tzOffset;
+} known_zones[] = {
+ { "UT", 0 },
+ { "GMT", 0 },
+ { "EST", -300 },
+ { "EDT", -240 },
+ { "CST", -360 },
+ { "CDT", -300 },
+ { "MST", -420 },
+ { "MDT", -360 },
+ { "PST", -480 },
+ { "PDT", -420 }
+};
+
+inline static void skipSpacesAndComments(const char*& s)
+{
+ int nesting = 0;
+ char ch;
+ while ((ch = *s)) {
+ if (!isASCIISpace(ch)) {
+ if (ch == '(')
+ nesting++;
+ else if (ch == ')' && nesting > 0)
+ nesting--;
+ else if (nesting == 0)
+ break;
+ }
+ s++;
+ }
+}
+
+// returns 0-11 (Jan-Dec); -1 on failure
+static int findMonth(const char* monthStr)
+{
+ ASSERT(monthStr);
+ char needle[4];
+ for (int i = 0; i < 3; ++i) {
+ if (!*monthStr)
+ return -1;
+ needle[i] = static_cast<char>(toASCIILower(*monthStr++));
+ }
+ needle[3] = '\0';
+ const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec";
+ const char *str = strstr(haystack, needle);
+ if (str) {
+ int position = static_cast<int>(str - haystack);
+ if (position % 3 == 0)
+ return position / 3;
+ }
+ return -1;
+}
+
+double parseDate(const UString &date)
+{
+ // This parses a date in the form:
+ // Tuesday, 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 formats, added for Javascript:
+ // [Wednesday] January 09 1999 23:12:40 GMT
+ // [Wednesday] January 09 23:12:40 GMT 1999
+ //
+ // We ignore the weekday.
+
+ CString dateCString = date.UTF8String();
+ const char *dateString = dateCString.c_str();
+
+ // Skip leading space
+ skipSpacesAndComments(dateString);
+
+ long month = -1;
+ const char *wordStart = dateString;
+ // Check contents of first words if not number
+ while (*dateString && !isASCIIDigit(*dateString)) {
+ if (isASCIISpace(*dateString) || *dateString == '(') {
+ if (dateString - wordStart >= 3)
+ month = findMonth(wordStart);
+ skipSpacesAndComments(dateString);
+ wordStart = dateString;
+ } else
+ dateString++;
+ }
+
+ // Missing delimiter between month and day (like "January29")?
+ if (month == -1 && wordStart != dateString)
+ month = findMonth(wordStart);
+
+ skipSpacesAndComments(dateString);
+
+ if (!*dateString)
+ return NaN;
+
+ // ' 09-Nov-99 23:12:40 GMT'
+ char *newPosStr;
+ errno = 0;
+ long day = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ dateString = newPosStr;
+
+ if (!*dateString)
+ return NaN;
+
+ if (day < 0)
+ return NaN;
+
+ long year = 0;
+ if (day > 31) {
+ // ### where is the boundary and what happens below?
+ if (*dateString != '/')
+ return NaN;
+ // looks like a YYYY/MM/DD date
+ if (!*++dateString)
+ return NaN;
+ year = day;
+ month = strtol(dateString, &newPosStr, 10) - 1;
+ if (errno)
+ return NaN;
+ dateString = newPosStr;
+ if (*dateString++ != '/' || !*dateString)
+ return NaN;
+ day = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ dateString = newPosStr;
+ } else if (*dateString == '/' && month == -1) {
+ dateString++;
+ // This looks like a MM/DD/YYYY date, not an RFC date.
+ month = day - 1; // 0-based
+ day = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ if (day < 1 || day > 31)
+ return NaN;
+ dateString = newPosStr;
+ if (*dateString == '/')
+ dateString++;
+ if (!*dateString)
+ return NaN;
+ } else {
+ if (*dateString == '-')
+ dateString++;
+
+ skipSpacesAndComments(dateString);
+
+ if (*dateString == ',')
+ dateString++;
+
+ if (month == -1) { // not found yet
+ month = findMonth(dateString);
+ if (month == -1)
+ return NaN;
+
+ while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString))
+ dateString++;
+
+ if (!*dateString)
+ return NaN;
+
+ // '-99 23:12:40 GMT'
+ if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString))
+ return NaN;
+ dateString++;
+ }
+ }
+
+ if (month < 0 || month > 11)
+ return NaN;
+
+ // '99 23:12:40 GMT'
+ if (year <= 0 && *dateString) {
+ year = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ }
+
+ // Don't fail if the time is missing.
+ long hour = 0;
+ long minute = 0;
+ long second = 0;
+ if (!*newPosStr)
+ dateString = newPosStr;
+ else {
+ // ' 23:12:40 GMT'
+ if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) {
+ if (*newPosStr != ':')
+ return NaN;
+ // There was no year; the number was the hour.
+ year = -1;
+ } else {
+ // in the normal case (we parsed the year), advance to the next number
+ dateString = ++newPosStr;
+ skipSpacesAndComments(dateString);
+ }
+
+ hour = strtol(dateString, &newPosStr, 10);
+ // Do not check for errno here since we want to continue
+ // even if errno was set becasue we are still looking
+ // for the timezone!
+
+ // Read a number? If not, this might be a timezone name.
+ if (newPosStr != dateString) {
+ dateString = newPosStr;
+
+ if (hour < 0 || hour > 23)
+ return NaN;
+
+ if (!*dateString)
+ return NaN;
+
+ // ':12:40 GMT'
+ if (*dateString++ != ':')
+ return NaN;
+
+ minute = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ dateString = newPosStr;
+
+ if (minute < 0 || minute > 59)
+ return NaN;
+
+ // ':40 GMT'
+ if (*dateString && *dateString != ':' && !isASCIISpace(*dateString))
+ return NaN;
+
+ // seconds are optional in rfc822 + rfc2822
+ if (*dateString ==':') {
+ dateString++;
+
+ second = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ dateString = newPosStr;
+
+ if (second < 0 || second > 59)
+ return NaN;
+ }
+
+ skipSpacesAndComments(dateString);
+
+ if (strncasecmp(dateString, "AM", 2) == 0) {
+ if (hour > 12)
+ return NaN;
+ if (hour == 12)
+ hour = 0;
+ dateString += 2;
+ skipSpacesAndComments(dateString);
+ } else if (strncasecmp(dateString, "PM", 2) == 0) {
+ if (hour > 12)
+ return NaN;
+ if (hour != 12)
+ hour += 12;
+ dateString += 2;
+ skipSpacesAndComments(dateString);
+ }
+ }
+ }
+
+ bool haveTZ = false;
+ int offset = 0;
+
+ // Don't fail if the time zone is missing.
+ // Some websites omit the time zone (4275206).
+ if (*dateString) {
+ if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) {
+ dateString += 3;
+ haveTZ = true;
+ }
+
+ if (*dateString == '+' || *dateString == '-') {
+ long o = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ dateString = newPosStr;
+
+ if (o < -9959 || o > 9959)
+ return NaN;
+
+ int sgn = (o < 0) ? -1 : 1;
+ o = abs(o);
+ if (*dateString != ':') {
+ offset = ((o / 100) * 60 + (o % 100)) * sgn;
+ } else { // GMT+05:00
+ long o2 = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ dateString = newPosStr;
+ offset = (o * 60 + o2) * sgn;
+ }
+ haveTZ = true;
+ } else {
+ for (int i = 0; i < int(sizeof(known_zones) / sizeof(KnownZone)); i++) {
+ if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
+ offset = known_zones[i].tzOffset;
+ dateString += strlen(known_zones[i].tzName);
+ haveTZ = true;
+ break;
+ }
+ }
+ }
+ }
+
+ skipSpacesAndComments(dateString);
+
+ if (*dateString && year == -1) {
+ year = strtol(dateString, &newPosStr, 10);
+ if (errno)
+ return NaN;
+ dateString = newPosStr;
+ }
+
+ skipSpacesAndComments(dateString);
+
+ // Trailing garbage
+ if (*dateString)
+ return NaN;
+
+ // Y2K: Handle 2 digit years.
+ if (year >= 0 && year < 100) {
+ if (year < 50)
+ year += 2000;
+ else
+ year += 1900;
+ }
+
+ // fall back to local timezone
+ if (!haveTZ) {
+ GregorianDateTime t;
+ t.monthDay = day;
+ t.month = month;
+ t.year = year - 1900;
+ t.isDST = -1;
+ t.second = second;
+ t.minute = minute;
+ t.hour = hour;
+
+ // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range.
+ return gregorianDateTimeToMS(t, 0, false);
+ }
+
+ return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond;
+}
+
+double timeClip(double t)
+{
+ if (!isfinite(t))
+ return NaN;
+ if (fabs(t) > 8.64E15)
+ return NaN;
+ return trunc(t);
+}
+
+UString formatDate(const GregorianDateTime &t)
+{
+ char buffer[100];
+ snprintf(buffer, sizeof(buffer), "%s %s %02d %04d",
+ weekdayName[(t.weekDay + 6) % 7],
+ monthName[t.month], t.monthDay, t.year + 1900);
+ return buffer;
+}
+
+UString formatDateUTCVariant(const GregorianDateTime &t)
+{
+ char buffer[100];
+ snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d",
+ weekdayName[(t.weekDay + 6) % 7],
+ t.monthDay, monthName[t.month], t.year + 1900);
+ return buffer;
+}
+
+UString formatTime(const GregorianDateTime &t, bool utc)
+{
+ char buffer[100];
+ if (utc) {
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second);
+ } else {
+ int offset = abs(gmtoffset(t));
+ char tzname[70];
+ struct tm gtm = t;
+ strftime(tzname, sizeof(tzname), "%Z", &gtm);
+
+ if (tzname[0]) {
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)",
+ t.hour, t.minute, t.second,
+ gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, tzname);
+ } else {
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d",
+ t.hour, t.minute, t.second,
+ gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60);
+ }
+ }
+ return UString(buffer);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/DateMath.h b/JavaScriptCore/runtime/DateMath.h
new file mode 100644
index 0000000..ab939a7
--- /dev/null
+++ b/JavaScriptCore/runtime/DateMath.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ */
+
+#ifndef DateMath_h
+#define DateMath_h
+
+#include <time.h>
+#include <string.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+class UString;
+struct GregorianDateTime;
+
+void initDateMath();
+void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&);
+double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC);
+double getUTCOffset();
+int equivalentYearForDST(int year);
+double getCurrentUTCTime();
+double getCurrentUTCTimeWithMicroseconds();
+void getLocalTime(const time_t*, tm*);
+
+// Not really math related, but this is currently the only shared place to put these.
+double parseDate(const UString&);
+double timeClip(double);
+UString formatDate(const GregorianDateTime&);
+UString formatDateUTCVariant(const GregorianDateTime&);
+UString formatTime(const GregorianDateTime&, bool inputIsUTC);
+
+
+const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+const double hoursPerDay = 24.0;
+const double minutesPerHour = 60.0;
+const double secondsPerHour = 60.0 * 60.0;
+const double secondsPerMinute = 60.0;
+const double msPerSecond = 1000.0;
+const double msPerMinute = 60.0 * 1000.0;
+const double msPerHour = 60.0 * 60.0 * 1000.0;
+const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
+
+// Intentionally overridding the default tm of the system
+// Tee members of tm differ on various operating systems.
+struct GregorianDateTime : Noncopyable {
+ GregorianDateTime()
+ : second(0)
+ , minute(0)
+ , hour(0)
+ , weekDay(0)
+ , monthDay(0)
+ , yearDay(0)
+ , month(0)
+ , year(0)
+ , isDST(0)
+ , utcOffset(0)
+ , timeZone(0)
+ {
+ }
+
+ ~GregorianDateTime()
+ {
+ delete [] timeZone;
+ }
+
+ GregorianDateTime(const tm& inTm)
+ : second(inTm.tm_sec)
+ , minute(inTm.tm_min)
+ , hour(inTm.tm_hour)
+ , weekDay(inTm.tm_wday)
+ , monthDay(inTm.tm_mday)
+ , yearDay(inTm.tm_yday)
+ , month(inTm.tm_mon)
+ , year(inTm.tm_year)
+ , isDST(inTm.tm_isdst)
+ {
+#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS)
+ utcOffset = static_cast<int>(inTm.tm_gmtoff);
+
+ int inZoneSize = strlen(inTm.tm_zone) + 1;
+ timeZone = new char[inZoneSize];
+ strncpy(timeZone, inTm.tm_zone, inZoneSize);
+#else
+ utcOffset = static_cast<int>(getUTCOffset() / msPerSecond + (isDST ? secondsPerHour : 0));
+ timeZone = 0;
+#endif
+ }
+
+ operator tm() const
+ {
+ tm ret;
+ memset(&ret, 0, sizeof(ret));
+
+ ret.tm_sec = second;
+ ret.tm_min = minute;
+ ret.tm_hour = hour;
+ ret.tm_wday = weekDay;
+ ret.tm_mday = monthDay;
+ ret.tm_yday = yearDay;
+ ret.tm_mon = month;
+ ret.tm_year = year;
+ ret.tm_isdst = isDST;
+
+#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS)
+ ret.tm_gmtoff = static_cast<long>(utcOffset);
+ ret.tm_zone = timeZone;
+#endif
+
+ return ret;
+ }
+
+ void copyFrom(const GregorianDateTime& rhs)
+ {
+ second = rhs.second;
+ minute = rhs.minute;
+ hour = rhs.hour;
+ weekDay = rhs.weekDay;
+ monthDay = rhs.monthDay;
+ yearDay = rhs.yearDay;
+ month = rhs.month;
+ year = rhs.year;
+ isDST = rhs.isDST;
+ utcOffset = rhs.utcOffset;
+ if (rhs.timeZone) {
+ int inZoneSize = strlen(rhs.timeZone) + 1;
+ timeZone = new char[inZoneSize];
+ strncpy(timeZone, rhs.timeZone, inZoneSize);
+ } else
+ timeZone = 0;
+ }
+
+ int second;
+ int minute;
+ int hour;
+ int weekDay;
+ int monthDay;
+ int yearDay;
+ int month;
+ int year;
+ int isDST;
+ int utcOffset;
+ char* timeZone;
+};
+
+static inline int gmtoffset(const GregorianDateTime& t)
+{
+ return t.utcOffset;
+}
+
+} // namespace JSC
+
+#endif // DateMath_h
diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp
new file mode 100644
index 0000000..a3e792e
--- /dev/null
+++ b/JavaScriptCore/runtime/DatePrototype.cpp
@@ -0,0 +1,1056 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "DatePrototype.h"
+
+#include "DateMath.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "DateInstance.h"
+#include <float.h>
+#include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <time.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
+#include <wtf/UnusedParam.h>
+
+#if HAVE(SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if HAVE(SYS_TIMEB_H)
+#include <sys/timeb.h>
+#endif
+
+#if PLATFORM(MAC)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+using namespace WTF;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(DatePrototype);
+
+static JSValue* dateProtoFuncGetDate(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetDay(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetHours(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetMonth(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetTime(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncGetYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetDate(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetHours(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetMonth(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetTime(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncSetYear(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToDateString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToGMTString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToTimeString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncToUTCString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* dateProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+}
+
+#include "DatePrototype.lut.h"
+
+namespace JSC {
+
+#if PLATFORM(MAC)
+
+static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
+{
+ if (string == "short")
+ return kCFDateFormatterShortStyle;
+ if (string == "medium")
+ return kCFDateFormatterMediumStyle;
+ if (string == "long")
+ return kCFDateFormatterLongStyle;
+ if (string == "full")
+ return kCFDateFormatterFullStyle;
+ return defaultStyle;
+}
+
+static UString formatLocaleDate(ExecState* exec, double time, bool includeDate, bool includeTime, const ArgList& args)
+{
+ CFDateFormatterStyle dateStyle = (includeDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
+ CFDateFormatterStyle timeStyle = (includeTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
+
+ bool useCustomFormat = false;
+ UString customFormatString;
+
+ UString arg0String = args.at(exec, 0)->toString(exec);
+ if (arg0String == "custom" && !args.at(exec, 1)->isUndefined()) {
+ useCustomFormat = true;
+ customFormatString = args.at(exec, 1)->toString(exec);
+ } else if (includeDate && includeTime && !args.at(exec, 1)->isUndefined()) {
+ dateStyle = styleFromArgString(arg0String, dateStyle);
+ timeStyle = styleFromArgString(args.at(exec, 1)->toString(exec), timeStyle);
+ } else if (includeDate && !args.at(exec, 0)->isUndefined())
+ dateStyle = styleFromArgString(arg0String, dateStyle);
+ else if (includeTime && !args.at(exec, 0)->isUndefined())
+ timeStyle = styleFromArgString(arg0String, timeStyle);
+
+ CFLocaleRef locale = CFLocaleCopyCurrent();
+ CFDateFormatterRef formatter = CFDateFormatterCreate(0, locale, dateStyle, timeStyle);
+ CFRelease(locale);
+
+ if (useCustomFormat) {
+ CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, (UniChar *)customFormatString.data(), customFormatString.size());
+ CFDateFormatterSetFormat(formatter, customFormatCFString);
+ CFRelease(customFormatCFString);
+ }
+
+ CFStringRef string = CFDateFormatterCreateStringWithAbsoluteTime(0, formatter, time - kCFAbsoluteTimeIntervalSince1970);
+
+ CFRelease(formatter);
+
+ // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
+ // That's not great error handling, but it just won't happen so it doesn't matter.
+ UChar buffer[200];
+ const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
+ size_t length = CFStringGetLength(string);
+ ASSERT(length <= bufferLength);
+ if (length > bufferLength)
+ length = bufferLength;
+ CFStringGetCharacters(string, CFRangeMake(0, length), reinterpret_cast<UniChar *>(buffer));
+
+ CFRelease(string);
+
+ return UString(buffer, length);
+}
+
+#else
+
+enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
+
+static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, const LocaleDateTimeFormat format)
+{
+ static const char* formatStrings[] = {"%#c", "%#x", "%X"};
+
+ // Offset year if needed
+ struct tm localTM = gdt;
+ int year = gdt.year + 1900;
+ bool yearNeedsOffset = year < 1900 || year > 2038;
+ if (yearNeedsOffset)
+ localTM.tm_year = equivalentYearForDST(year) - 1900;
+
+ // Do the formatting
+ const int bufsize = 128;
+ char timebuffer[bufsize];
+ size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM);
+
+ if (ret == 0)
+ return jsEmptyString(exec);
+
+ // Copy original into the buffer
+ if (yearNeedsOffset && format != LocaleTime) {
+ static const int yearLen = 5; // FIXME will be a problem in the year 10,000
+ char yearString[yearLen];
+
+ snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900);
+ char* yearLocation = strstr(timebuffer, yearString);
+ snprintf(yearString, yearLen, "%d", year);
+
+ strncpy(yearLocation, yearString, yearLen - 1);
+ }
+
+ return jsNontrivialString(exec, timebuffer);
+}
+
+#endif // PLATFORM(WIN_OS)
+
+// Converts a list of arguments sent to a Date member function into milliseconds, updating
+// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
+//
+// Format of member function: f([hour,] [min,] [sec,] [ms])
+static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, int maxArgs, double* ms, GregorianDateTime* t)
+{
+ double milliseconds = 0;
+ bool ok = true;
+ int idx = 0;
+ int numArgs = args.size();
+
+ // JS allows extra trailing arguments -- ignore them
+ if (numArgs > maxArgs)
+ numArgs = maxArgs;
+
+ // hours
+ if (maxArgs >= 4 && idx < numArgs) {
+ t->hour = 0;
+ milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerHour;
+ }
+
+ // minutes
+ if (maxArgs >= 3 && idx < numArgs && ok) {
+ t->minute = 0;
+ milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerMinute;
+ }
+
+ // seconds
+ if (maxArgs >= 2 && idx < numArgs && ok) {
+ t->second = 0;
+ milliseconds += args.at(exec, idx++)->toInt32(exec, ok) * msPerSecond;
+ }
+
+ if (!ok)
+ return false;
+
+ // milliseconds
+ if (idx < numArgs) {
+ double millis = args.at(exec, idx)->toNumber(exec);
+ ok = isfinite(millis);
+ milliseconds += millis;
+ } else
+ milliseconds += *ms;
+
+ *ms = milliseconds;
+ return ok;
+}
+
+// Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
+// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
+//
+// Format of member function: f([years,] [months,] [days])
+static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, int maxArgs, double *ms, GregorianDateTime *t)
+{
+ int idx = 0;
+ bool ok = true;
+ int numArgs = args.size();
+
+ // JS allows extra trailing arguments -- ignore them
+ if (numArgs > maxArgs)
+ numArgs = maxArgs;
+
+ // years
+ if (maxArgs >= 3 && idx < numArgs)
+ t->year = args.at(exec, idx++)->toInt32(exec, ok) - 1900;
+
+ // months
+ if (maxArgs >= 2 && idx < numArgs && ok)
+ t->month = args.at(exec, idx++)->toInt32(exec, ok);
+
+ // days
+ if (idx < numArgs && ok) {
+ t->monthDay = 0;
+ *ms += args.at(exec, idx)->toInt32(exec, ok) * msPerDay;
+ }
+
+ return ok;
+}
+
+const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable};
+
+/* Source for DatePrototype.lut.h
+ FIXME: We could use templates to simplify the UTC variants.
+@begin dateTable
+ toString dateProtoFuncToString DontEnum|Function 0
+ toUTCString dateProtoFuncToUTCString DontEnum|Function 0
+ toDateString dateProtoFuncToDateString DontEnum|Function 0
+ toTimeString dateProtoFuncToTimeString DontEnum|Function 0
+ toLocaleString dateProtoFuncToLocaleString DontEnum|Function 0
+ toLocaleDateString dateProtoFuncToLocaleDateString DontEnum|Function 0
+ toLocaleTimeString dateProtoFuncToLocaleTimeString DontEnum|Function 0
+ valueOf dateProtoFuncValueOf DontEnum|Function 0
+ getTime dateProtoFuncGetTime DontEnum|Function 0
+ getFullYear dateProtoFuncGetFullYear DontEnum|Function 0
+ getUTCFullYear dateProtoFuncGetUTCFullYear DontEnum|Function 0
+ toGMTString dateProtoFuncToGMTString DontEnum|Function 0
+ getMonth dateProtoFuncGetMonth DontEnum|Function 0
+ getUTCMonth dateProtoFuncGetUTCMonth DontEnum|Function 0
+ getDate dateProtoFuncGetDate DontEnum|Function 0
+ getUTCDate dateProtoFuncGetUTCDate DontEnum|Function 0
+ getDay dateProtoFuncGetDay DontEnum|Function 0
+ getUTCDay dateProtoFuncGetUTCDay DontEnum|Function 0
+ getHours dateProtoFuncGetHours DontEnum|Function 0
+ getUTCHours dateProtoFuncGetUTCHours DontEnum|Function 0
+ getMinutes dateProtoFuncGetMinutes DontEnum|Function 0
+ getUTCMinutes dateProtoFuncGetUTCMinutes DontEnum|Function 0
+ getSeconds dateProtoFuncGetSeconds DontEnum|Function 0
+ getUTCSeconds dateProtoFuncGetUTCSeconds DontEnum|Function 0
+ getMilliseconds dateProtoFuncGetMilliSeconds DontEnum|Function 0
+ getUTCMilliseconds dateProtoFuncGetUTCMilliseconds DontEnum|Function 0
+ getTimezoneOffset dateProtoFuncGetTimezoneOffset DontEnum|Function 0
+ setTime dateProtoFuncSetTime DontEnum|Function 1
+ setMilliseconds dateProtoFuncSetMilliSeconds DontEnum|Function 1
+ setUTCMilliseconds dateProtoFuncSetUTCMilliseconds DontEnum|Function 1
+ setSeconds dateProtoFuncSetSeconds DontEnum|Function 2
+ setUTCSeconds dateProtoFuncSetUTCSeconds DontEnum|Function 2
+ setMinutes dateProtoFuncSetMinutes DontEnum|Function 3
+ setUTCMinutes dateProtoFuncSetUTCMinutes DontEnum|Function 3
+ setHours dateProtoFuncSetHours DontEnum|Function 4
+ setUTCHours dateProtoFuncSetUTCHours DontEnum|Function 4
+ setDate dateProtoFuncSetDate DontEnum|Function 1
+ setUTCDate dateProtoFuncSetUTCDate DontEnum|Function 1
+ setMonth dateProtoFuncSetMonth DontEnum|Function 2
+ setUTCMonth dateProtoFuncSetUTCMonth DontEnum|Function 2
+ setFullYear dateProtoFuncSetFullYear DontEnum|Function 3
+ setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
+ setYear dateProtoFuncSetYear DontEnum|Function 1
+ getYear dateProtoFuncGetYear DontEnum|Function 0
+@end
+*/
+// ECMA 15.9.4
+
+DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<StructureID> structure)
+ : DateInstance(structure)
+{
+ setInternalValue(jsNaN(exec));
+ // The constructor will be added later, after DateConstructor has been built.
+}
+
+bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
+}
+
+// Functions
+
+JSValue* dateProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc));
+}
+
+JSValue* dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+}
+
+JSValue* dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDate(t));
+}
+
+JSValue* dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatTime(t, utc));
+}
+
+JSValue* dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+#if PLATFORM(MAC)
+ double secs = floor(milli / msPerSecond);
+ return jsNontrivialString(exec, formatLocaleDate(exec, secs, true, true, args));
+#else
+ UNUSED_PARAM(args);
+
+ const bool utc = false;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return formatLocaleDate(exec, t, LocaleDateAndTime);
+#endif
+}
+
+JSValue* dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+#if PLATFORM(MAC)
+ double secs = floor(milli / msPerSecond);
+ return jsNontrivialString(exec, formatLocaleDate(exec, secs, true, false, args));
+#else
+ UNUSED_PARAM(args);
+
+ const bool utc = false;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return formatLocaleDate(exec, t, LocaleDate);
+#endif
+}
+
+JSValue* dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+#if PLATFORM(MAC)
+ double secs = floor(milli / msPerSecond);
+ return jsNontrivialString(exec, formatLocaleDate(exec, secs, false, true, args));
+#else
+ UNUSED_PARAM(args);
+
+ const bool utc = false;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return formatLocaleDate(exec, t, LocaleTime);
+#endif
+}
+
+JSValue* dateProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ return jsNumber(exec, milli);
+}
+
+JSValue* dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ return jsNumber(exec, milli);
+}
+
+JSValue* dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, 1900 + t.year);
+}
+
+JSValue* dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, 1900 + t.year);
+}
+
+JSValue* dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNontrivialString(exec, "Invalid Date");
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc));
+}
+
+JSValue* dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.month);
+}
+
+JSValue* dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.month);
+}
+
+JSValue* dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.monthDay);
+}
+
+JSValue* dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.monthDay);
+}
+
+JSValue* dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.weekDay);
+}
+
+JSValue* dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.weekDay);
+}
+
+JSValue* dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.hour);
+}
+
+JSValue* dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.hour);
+}
+
+JSValue* dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.minute);
+}
+
+JSValue* dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.minute);
+}
+
+JSValue* dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.second);
+}
+
+JSValue* dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = true;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, t.second);
+}
+
+JSValue* dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+ return jsNumber(exec, ms);
+}
+
+JSValue* dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+ return jsNumber(exec, ms);
+}
+
+JSValue* dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ return jsNumber(exec, -gmtoffset(t) / minutesPerHour);
+}
+
+JSValue* dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+
+ double milli = timeClip(args.at(exec, 0)->toNumber(exec));
+ JSValue* result = jsNumber(exec, milli);
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+static JSValue* setNewValueFromTimeArgs(ExecState* exec, JSValue* thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+
+ if (args.isEmpty() || isnan(milli)) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double secs = floor(milli / msPerSecond);
+ double ms = milli - secs * msPerSecond;
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+
+ if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+static JSValue* setNewValueFromDateArgs(ExecState* exec, JSValue* thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ if (args.isEmpty()) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double milli = thisDateObj->internalNumber();
+ double ms = 0;
+
+ GregorianDateTime t;
+ if (numArgsToUse == 3 && isnan(milli))
+ // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
+ // the time must be reset to +0 if it is NaN.
+ thisDateObj->msToGregorianDateTime(0, true, t);
+ else {
+ double secs = floor(milli / msPerSecond);
+ ms = milli - secs * msPerSecond;
+ thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
+ }
+
+ if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+JSValue* dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = false;
+ return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ const bool inputIsUTC = true;
+ return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
+}
+
+JSValue* dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ if (args.isEmpty()) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ double milli = thisDateObj->internalNumber();
+ double ms = 0;
+
+ GregorianDateTime t;
+ if (isnan(milli))
+ // Based on ECMA 262 B.2.5 (setYear)
+ // the time must be reset to +0 if it is NaN.
+ thisDateObj->msToGregorianDateTime(0, true, t);
+ else {
+ double secs = floor(milli / msPerSecond);
+ ms = milli - secs * msPerSecond;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+ }
+
+ bool ok = true;
+ int32_t year = args.at(exec, 0)->toInt32(exec, ok);
+ if (!ok) {
+ JSValue* result = jsNaN(exec);
+ thisDateObj->setInternalValue(result);
+ return result;
+ }
+
+ t.year = (year > 99 || year < 0) ? year - 1900 : year;
+ JSValue* result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc));
+ thisDateObj->setInternalValue(result);
+ return result;
+}
+
+JSValue* dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&DateInstance::info))
+ return throwError(exec, TypeError);
+
+ const bool utc = false;
+
+ DateInstance* thisDateObj = asDateInstance(thisValue);
+ double milli = thisDateObj->internalNumber();
+ if (isnan(milli))
+ return jsNaN(exec);
+
+ GregorianDateTime t;
+ thisDateObj->msToGregorianDateTime(milli, utc, t);
+
+ // NOTE: IE returns the full year even in getYear.
+ return jsNumber(exec, t.year);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/DatePrototype.h b/JavaScriptCore/runtime/DatePrototype.h
new file mode 100644
index 0000000..500b40d
--- /dev/null
+++ b/JavaScriptCore/runtime/DatePrototype.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef DatePrototype_h
+#define DatePrototype_h
+
+#include "DateInstance.h"
+
+namespace JSC {
+
+ class ObjectPrototype;
+
+ class DatePrototype : public DateInstance {
+ public:
+ DatePrototype(ExecState*, PassRefPtr<StructureID>);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+ };
+
+} // namespace JSC
+
+#endif // DatePrototype_h
diff --git a/JavaScriptCore/runtime/Error.cpp b/JavaScriptCore/runtime/Error.cpp
new file mode 100644
index 0000000..5e21c8e
--- /dev/null
+++ b/JavaScriptCore/runtime/Error.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Eric Seidel (eric@webkit.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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Error.h"
+
+#include "ConstructData.h"
+#include "ErrorConstructor.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include "NativeErrorConstructor.h"
+
+namespace JSC {
+
+const char* expressionBeginOffsetPropertyName = "expressionBeginOffset";
+const char* expressionCaretOffsetPropertyName = "expressionCaretOffset";
+const char* expressionEndOffsetPropertyName = "expressionEndOffset";
+
+JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL)
+{
+ JSObject* constructor;
+ const char* name;
+ switch (type) {
+ case EvalError:
+ constructor = exec->lexicalGlobalObject()->evalErrorConstructor();
+ name = "Evaluation error";
+ break;
+ case RangeError:
+ constructor = exec->lexicalGlobalObject()->rangeErrorConstructor();
+ name = "Range error";
+ break;
+ case ReferenceError:
+ constructor = exec->lexicalGlobalObject()->referenceErrorConstructor();
+ name = "Reference error";
+ break;
+ case SyntaxError:
+ constructor = exec->lexicalGlobalObject()->syntaxErrorConstructor();
+ name = "Syntax error";
+ break;
+ case TypeError:
+ constructor = exec->lexicalGlobalObject()->typeErrorConstructor();
+ name = "Type error";
+ break;
+ case URIError:
+ constructor = exec->lexicalGlobalObject()->URIErrorConstructor();
+ name = "URI error";
+ break;
+ default:
+ constructor = exec->lexicalGlobalObject()->errorConstructor();
+ name = "Error";
+ break;
+ }
+
+ ArgList args;
+ if (message.isEmpty())
+ args.append(jsString(exec, name));
+ else
+ args.append(jsString(exec, message));
+ ConstructData constructData;
+ ConstructType constructType = constructor->getConstructData(constructData);
+ JSObject* error = construct(exec, constructor, constructType, constructData, args);
+
+ if (lineNumber != -1)
+ error->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, lineNumber), ReadOnly | DontDelete);
+ if (sourceID != -1)
+ error->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, sourceID), ReadOnly | DontDelete);
+ if (!sourceURL.isNull())
+ error->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsString(exec, sourceURL), ReadOnly | DontDelete);
+
+ return error;
+}
+
+JSObject* Error::create(ExecState* exec, ErrorType type, const char* message)
+{
+ return create(exec, type, message, -1, -1, NULL);
+}
+
+JSObject* throwError(ExecState* exec, ErrorType type)
+{
+ JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL);
+ exec->setException(error);
+ return error;
+}
+
+JSObject* throwError(ExecState* exec, ErrorType type, const UString& message)
+{
+ JSObject* error = Error::create(exec, type, message, -1, -1, NULL);
+ exec->setException(error);
+ return error;
+}
+
+JSObject* throwError(ExecState* exec, ErrorType type, const char* message)
+{
+ JSObject* error = Error::create(exec, type, message, -1, -1, NULL);
+ exec->setException(error);
+ return error;
+}
+
+JSObject* throwError(ExecState* exec, ErrorType type, const UString& message, int line, intptr_t sourceID, const UString& sourceURL)
+{
+ JSObject* error = Error::create(exec, type, message, line, sourceID, sourceURL);
+ exec->setException(error);
+ return error;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/Error.h b/JavaScriptCore/runtime/Error.h
new file mode 100644
index 0000000..adf7fdf
--- /dev/null
+++ b/JavaScriptCore/runtime/Error.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Error_h
+#define Error_h
+
+#include <stdint.h>
+
+namespace JSC {
+
+ class ExecState;
+ class JSObject;
+ class UString;
+
+ /**
+ * Types of Native Errors available. For custom errors, GeneralError
+ * should be used.
+ */
+ enum ErrorType {
+ GeneralError = 0,
+ EvalError = 1,
+ RangeError = 2,
+ ReferenceError = 3,
+ SyntaxError = 4,
+ TypeError = 5,
+ URIError = 6
+ };
+
+ extern const char* expressionBeginOffsetPropertyName;
+ extern const char* expressionCaretOffsetPropertyName;
+ extern const char* expressionEndOffsetPropertyName;
+
+ class Error {
+ public:
+ static JSObject* create(ExecState*, ErrorType, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL);
+ static JSObject* create(ExecState*, ErrorType, const char* message);
+ };
+
+ JSObject* throwError(ExecState*, ErrorType, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL);
+ JSObject* throwError(ExecState*, ErrorType, const UString& message);
+ JSObject* throwError(ExecState*, ErrorType, const char* message);
+ JSObject* throwError(ExecState*, ErrorType);
+
+} // namespace JSC
+
+#endif // Error_h
diff --git a/JavaScriptCore/runtime/ErrorConstructor.cpp b/JavaScriptCore/runtime/ErrorConstructor.cpp
new file mode 100644
index 0000000..3c83fd4
--- /dev/null
+++ b/JavaScriptCore/runtime/ErrorConstructor.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ErrorConstructor.h"
+
+#include "ErrorPrototype.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
+
+ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<StructureID> structure, ErrorPrototype* errorPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, errorPrototype->classInfo()->className))
+{
+ // ECMA 15.11.3.1 Error.prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum);
+}
+
+// ECMA 15.9.3
+ErrorInstance* constructError(ExecState* exec, const ArgList& args)
+{
+ ErrorInstance* obj = new (exec) ErrorInstance(exec->lexicalGlobalObject()->errorStructure());
+ if (!args.at(exec, 0)->isUndefined())
+ obj->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0)->toString(exec)));
+ return obj;
+}
+
+static JSObject* constructWithErrorConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructError(exec, args);
+}
+
+ConstructType ErrorConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithErrorConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.9.2
+static JSValue* callErrorConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ // "Error()" gives the sames result as "new Error()"
+ return constructError(exec, args);
+}
+
+CallType ErrorConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callErrorConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ErrorConstructor.h b/JavaScriptCore/runtime/ErrorConstructor.h
new file mode 100644
index 0000000..45e4bb0
--- /dev/null
+++ b/JavaScriptCore/runtime/ErrorConstructor.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ErrorConstructor_h
+#define ErrorConstructor_h
+
+#include "ErrorInstance.h"
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class ErrorPrototype;
+
+ class ErrorConstructor : public InternalFunction {
+ public:
+ ErrorConstructor(ExecState*, PassRefPtr<StructureID>, ErrorPrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+ ErrorInstance* constructError(ExecState*, const ArgList&);
+
+} // namespace JSC
+
+#endif // ErrorConstructor_h
diff --git a/JavaScriptCore/runtime/ErrorInstance.cpp b/JavaScriptCore/runtime/ErrorInstance.cpp
new file mode 100644
index 0000000..1c55856
--- /dev/null
+++ b/JavaScriptCore/runtime/ErrorInstance.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ErrorInstance.h"
+
+namespace JSC {
+
+const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 };
+
+ErrorInstance::ErrorInstance(PassRefPtr<StructureID> structure)
+ : JSObject(structure)
+{
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ErrorInstance.h b/JavaScriptCore/runtime/ErrorInstance.h
new file mode 100644
index 0000000..8d86eec
--- /dev/null
+++ b/JavaScriptCore/runtime/ErrorInstance.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ErrorInstance_h
+#define ErrorInstance_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class ErrorInstance : public JSObject {
+ public:
+ explicit ErrorInstance(PassRefPtr<StructureID>);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // ErrorInstance_h
diff --git a/JavaScriptCore/runtime/ErrorPrototype.cpp b/JavaScriptCore/runtime/ErrorPrototype.cpp
new file mode 100644
index 0000000..69255c1
--- /dev/null
+++ b/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ErrorPrototype.h"
+
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "PrototypeFunction.h"
+#include "ustring.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
+
+static JSValue* errorProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+// ECMA 15.9.4
+ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure)
+ : ErrorInstance(structure)
+{
+ // The constructor will be added later in ErrorConstructor's constructor
+
+ putDirectWithoutTransition(exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum);
+ putDirectWithoutTransition(exec->propertyNames().message, jsNontrivialString(exec, "Unknown error"), DontEnum);
+
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum);
+}
+
+JSValue* errorProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ UString s = "Error";
+
+ JSValue* v = thisObj->get(exec, exec->propertyNames().name);
+ if (!v->isUndefined())
+ s = v->toString(exec);
+
+ v = thisObj->get(exec, exec->propertyNames().message);
+ if (!v->isUndefined()) {
+ // Mozilla-compatible format.
+ s += ": ";
+ s += v->toString(exec);
+ }
+
+ return jsNontrivialString(exec, s);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ErrorPrototype.h b/JavaScriptCore/runtime/ErrorPrototype.h
new file mode 100644
index 0000000..255ea11
--- /dev/null
+++ b/JavaScriptCore/runtime/ErrorPrototype.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ErrorPrototype_h
+#define ErrorPrototype_h
+
+#include "ErrorInstance.h"
+
+namespace JSC {
+
+ class ObjectPrototype;
+
+ class ErrorPrototype : public ErrorInstance {
+ public:
+ ErrorPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure);
+ };
+
+} // namespace JSC
+
+#endif // ErrorPrototype_h
diff --git a/JavaScriptCore/runtime/ExecState.cpp b/JavaScriptCore/runtime/ExecState.cpp
new file mode 100644
index 0000000..0144c14
--- /dev/null
+++ b/JavaScriptCore/runtime/ExecState.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ExecState.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+JSValue* CallFrame::thisValue()
+{
+ return this[codeBlock()->thisRegister].jsValue(this);
+}
+
+}
diff --git a/JavaScriptCore/runtime/ExecState.h b/JavaScriptCore/runtime/ExecState.h
new file mode 100644
index 0000000..f1891bb
--- /dev/null
+++ b/JavaScriptCore/runtime/ExecState.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ExecState_h
+#define ExecState_h
+
+// FIXME: Rename this file to CallFrame.h.
+
+#include "JSGlobalData.h"
+#include "Machine.h"
+#include "ScopeChain.h"
+
+namespace JSC {
+
+ class Arguments;
+ class JSActivation;
+
+ // Represents the current state of script execution.
+ // Passed as the first argument to most functions.
+ class ExecState : private Register {
+ public:
+ JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
+ CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
+ ScopeChainNode* scopeChain() const { return this[RegisterFile::ScopeChain].Register::scopeChain(); }
+
+ JSValue* thisValue();
+
+ // Global object in which execution began.
+ JSGlobalObject* dynamicGlobalObject();
+
+ // Global object in which the currently executing code was defined.
+ // Differs from dynamicGlobalObject() during function calls across web browser frames.
+ JSGlobalObject* lexicalGlobalObject() const
+ {
+ return scopeChain()->globalObject();
+ }
+
+ // Differs from lexicalGlobalObject because this will have DOM window shell rather than
+ // the actual DOM window, which can't be "this" for security reasons.
+ JSObject* globalThisValue() const
+ {
+ return scopeChain()->globalThisObject();
+ }
+
+ // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
+ // We should make this more uniform and either use a reference everywhere
+ // or a pointer everywhere.
+ JSGlobalData& globalData() const
+ {
+ return *scopeChain()->globalData;
+ }
+
+ // Convenience functions for access to global data.
+ // It takes a few memory references to get from a call frame to the global data
+ // pointer, so these are inefficient, and should be used sparingly in new code.
+ // But they're used in many places in legacy code, so they're not going away any time soon.
+
+ void setException(JSValue* exception) { globalData().exception = exception; }
+ void clearException() { globalData().exception = noValue(); }
+ JSValue* exception() const { return globalData().exception; }
+ JSValue** exceptionSlot() { return &globalData().exception; }
+ bool hadException() const { return !!globalData().exception; }
+
+ const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
+ const ArgList& emptyList() const { return *globalData().emptyList; }
+ Machine* machine() { return globalData().machine; }
+ Heap* heap() { return &globalData().heap; }
+
+ static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; }
+ static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; }
+ static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; }
+ static const HashTable* numberTable(CallFrame* callFrame) { return callFrame->globalData().numberTable; }
+ static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; }
+ static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
+ static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
+
+ private:
+ friend class Arguments;
+ friend class JSActivation;
+ friend class JSGlobalObject;
+ friend class Machine;
+
+ static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
+ Register* registers() { return this; }
+
+ CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
+
+ int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
+ CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
+ Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); }
+ Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
+ int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
+
+ void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = count; }
+ void setCallee(JSFunction* callee) { this[RegisterFile::Callee] = callee; }
+ void setCalleeArguments(Arguments* arguments) { this[RegisterFile::OptionalCalleeArguments] = arguments; }
+ void setCallerFrame(CallFrame* callerFrame) { this[RegisterFile::CallerFrame] = callerFrame; }
+ void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; }
+ void setScopeChain(ScopeChainNode* scopeChain) { this[RegisterFile::ScopeChain] = scopeChain; }
+
+ ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
+ CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function)
+ {
+ ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
+
+ setCodeBlock(codeBlock);
+ setScopeChain(scopeChain);
+ setCallerFrame(callerFrame);
+ this[RegisterFile::ReturnPC] = vPC;
+ this[RegisterFile::ReturnValueRegister] = returnValueRegister;
+ setArgumentCount(argc); // original argument count (for the sake of the "arguments" object)
+ setCallee(function);
+ setCalleeArguments(0);
+ }
+
+ static const intptr_t HostCallFrameFlag = 1;
+
+ static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
+ bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
+ CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
+ CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
+
+ ExecState();
+ ~ExecState();
+ };
+
+} // namespace JSC
+
+#endif // ExecState_h
diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp
new file mode 100644
index 0000000..adc3d3c
--- /dev/null
+++ b/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "FunctionConstructor.h"
+
+#include "FunctionPrototype.h"
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "Parser.h"
+#include "Debugger.h"
+#include "lexer.h"
+#include "nodes.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
+
+FunctionConstructor::FunctionConstructor(ExecState* exec, PassRefPtr<StructureID> structure, FunctionPrototype* functionPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className))
+{
+ putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // Number of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum);
+}
+
+static JSObject* constructWithFunctionConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructFunction(exec, args);
+}
+
+ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithFunctionConstructor;
+ return ConstructTypeHost;
+}
+
+static JSValue* callFunctionConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return constructFunction(exec, args);
+}
+
+// ECMA 15.3.1 The Function Constructor Called as a Function
+CallType FunctionConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callFunctionConstructor;
+ return CallTypeHost;
+}
+
+// ECMA 15.3.2 The Function Constructor
+JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
+{
+ UString p("");
+ UString body;
+ int argsSize = args.size();
+ if (argsSize == 0)
+ body = "";
+ else if (argsSize == 1)
+ body = args.at(exec, 0)->toString(exec);
+ else {
+ p = args.at(exec, 0)->toString(exec);
+ for (int k = 1; k < argsSize - 1; k++)
+ p += "," + args.at(exec, k)->toString(exec);
+ body = args.at(exec, argsSize - 1)->toString(exec);
+ }
+
+ // parse the source code
+ int errLine;
+ UString errMsg;
+ SourceCode source = makeSource(body, sourceURL, lineNumber);
+ RefPtr<FunctionBodyNode> functionBody = exec->globalData().parser->parse<FunctionBodyNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+
+ // No program node == syntax error - throw a syntax error
+ if (!functionBody)
+ // We can't return a Completion(Throw) here, so just set the exception
+ // and return it
+ return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
+
+ // parse parameter list. throw syntax error on illegal identifiers
+ int len = p.size();
+ const UChar* c = p.data();
+ int i = 0;
+ UString param;
+ Vector<Identifier> parameters;
+ while (i < len) {
+ while (*c == ' ' && i < len)
+ c++, i++;
+ if (Lexer::isIdentStart(c[0])) { // else error
+ param = UString(c, 1);
+ c++, i++;
+ while (i < len && (Lexer::isIdentPart(c[0]))) {
+ param.append(*c);
+ c++, i++;
+ }
+ while (i < len && *c == ' ')
+ c++, i++;
+ if (i == len) {
+ parameters.append(Identifier(exec, param));
+ break;
+ } else if (*c == ',') {
+ parameters.append(Identifier(exec, param));
+ c++, i++;
+ continue;
+ } // else error
+ }
+ return throwError(exec, SyntaxError, "Syntax error in parameter list");
+ }
+ size_t count = parameters.size();
+ functionBody->finishParsing(parameters.releaseBuffer(), count);
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue());
+ JSFunction* function = new (exec) JSFunction(exec, functionName, functionBody.get(), scopeChain.node());
+
+ JSObject* prototype = constructEmptyObject(exec);
+ prototype->putDirect(exec->propertyNames().constructor, function, DontEnum);
+ function->putDirect(exec->propertyNames().prototype, prototype, DontDelete);
+ return function;
+}
+
+// ECMA 15.3.2 The Function Constructor
+JSObject* constructFunction(ExecState* exec, const ArgList& args)
+{
+ return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/FunctionConstructor.h b/JavaScriptCore/runtime/FunctionConstructor.h
new file mode 100644
index 0000000..c309c41
--- /dev/null
+++ b/JavaScriptCore/runtime/FunctionConstructor.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef FunctionConstructor_h
+#define FunctionConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class FunctionPrototype;
+
+ class FunctionConstructor : public InternalFunction {
+ public:
+ FunctionConstructor(ExecState*, PassRefPtr<StructureID>, FunctionPrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+ JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
+ JSObject* constructFunction(ExecState*, const ArgList&);
+
+} // namespace JSC
+
+#endif // FunctionConstructor_h
diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp
new file mode 100644
index 0000000..8c3a260
--- /dev/null
+++ b/JavaScriptCore/runtime/FunctionPrototype.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "FunctionPrototype.h"
+
+#include "Arguments.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "JSString.h"
+#include "Machine.h"
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
+
+static JSValue* functionProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* functionProtoFuncApply(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* functionProtoFuncCall(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<StructureID> structure)
+ : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
+{
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
+}
+
+void FunctionPrototype::addFunctionProperties(ExecState* exec, StructureID* prototypeFunctionStructure)
+{
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall), DontEnum);
+}
+
+static JSValue* callFunctionPrototype(ExecState*, JSObject*, JSValue*, const ArgList&)
+{
+ return jsUndefined();
+}
+
+// ECMA 15.3.4
+CallType FunctionPrototype::getCallData(CallData& callData)
+{
+ callData.native.function = callFunctionPrototype;
+ return CallTypeHost;
+}
+
+// Functions
+
+JSValue* functionProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (thisValue->isObject(&JSFunction::info)) {
+ JSFunction* function = asFunction(thisValue);
+ return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->m_body->paramString() + ") " + function->m_body->toSourceString());
+ }
+
+ if (thisValue->isObject(&InternalFunction::info)) {
+ InternalFunction* function = asInternalFunction(thisValue);
+ return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}");
+ }
+
+ return throwError(exec, TypeError);
+}
+
+JSValue* functionProtoFuncApply(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ CallData callData;
+ CallType callType = thisValue->getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSValue* thisArg = args.at(exec, 0);
+ JSValue* argArray = args.at(exec, 1);
+
+ JSValue* applyThis;
+ if (thisArg->isUndefinedOrNull())
+ applyThis = exec->globalThisValue();
+ else
+ applyThis = thisArg->toObject(exec);
+
+ ArgList applyArgs;
+ if (!argArray->isUndefinedOrNull()) {
+ if (!argArray->isObject())
+ return throwError(exec, TypeError);
+ if (asObject(argArray)->classInfo() == &Arguments::info)
+ asArguments(argArray)->fillArgList(exec, applyArgs);
+ else if (exec->machine()->isJSArray(argArray))
+ asArray(argArray)->fillArgList(exec, applyArgs);
+ else if (asObject(argArray)->inherits(&JSArray::info)) {
+ unsigned length = asArray(argArray)->get(exec, exec->propertyNames().length)->toUInt32(exec);
+ for (unsigned i = 0; i < length; ++i)
+ applyArgs.append(asArray(argArray)->get(exec, i));
+ } else
+ return throwError(exec, TypeError);
+ }
+
+ return call(exec, thisValue, callType, callData, applyThis, applyArgs);
+}
+
+JSValue* functionProtoFuncCall(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ CallData callData;
+ CallType callType = thisValue->getCallData(callData);
+ if (callType == CallTypeNone)
+ return throwError(exec, TypeError);
+
+ JSValue* thisArg = args.at(exec, 0);
+
+ JSObject* callThis;
+ if (thisArg->isUndefinedOrNull())
+ callThis = exec->globalThisValue();
+ else
+ callThis = thisArg->toObject(exec);
+
+ ArgList argsTail;
+ args.getSlice(1, argsTail);
+ return call(exec, thisValue, callType, callData, callThis, argsTail);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/FunctionPrototype.h b/JavaScriptCore/runtime/FunctionPrototype.h
new file mode 100644
index 0000000..f493642
--- /dev/null
+++ b/JavaScriptCore/runtime/FunctionPrototype.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef FunctionPrototype_h
+#define FunctionPrototype_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class FunctionPrototype : public InternalFunction {
+ public:
+ FunctionPrototype(ExecState*, PassRefPtr<StructureID>);
+ void addFunctionProperties(ExecState*, StructureID* prototypeFunctionStructure);
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto)
+ {
+ return StructureID::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+ }
+
+ private:
+ virtual CallType getCallData(CallData&);
+ };
+
+} // namespace JSC
+
+#endif // FunctionPrototype_h
diff --git a/JavaScriptCore/runtime/GetterSetter.cpp b/JavaScriptCore/runtime/GetterSetter.cpp
new file mode 100644
index 0000000..c3d089f
--- /dev/null
+++ b/JavaScriptCore/runtime/GetterSetter.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "GetterSetter.h"
+
+#include "JSObject.h"
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+void GetterSetter::mark()
+{
+ JSCell::mark();
+
+ if (m_getter && !m_getter->marked())
+ m_getter->mark();
+ if (m_setter && !m_setter->marked())
+ m_setter->mark();
+}
+
+JSValue* GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ ASSERT_NOT_REACHED();
+ return jsNull();
+}
+
+bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
+{
+ ASSERT_NOT_REACHED();
+ number = 0;
+ value = noValue();
+ return true;
+}
+
+bool GetterSetter::toBoolean(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+double GetterSetter::toNumber(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0.0;
+}
+
+UString GetterSetter::toString(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return UString::null();
+}
+
+JSObject* GetterSetter::toObject(ExecState* exec) const
+{
+ ASSERT_NOT_REACHED();
+ return jsNull()->toObject(exec);
+}
+
+bool GetterSetter::isGetterSetter() const
+{
+ return true;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/GetterSetter.h b/JavaScriptCore/runtime/GetterSetter.h
new file mode 100644
index 0000000..da968b2
--- /dev/null
+++ b/JavaScriptCore/runtime/GetterSetter.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GetterSetter_h
+#define GetterSetter_h
+
+#include "JSCell.h"
+
+namespace JSC {
+
+ class JSObject;
+
+ // This is an internal value object which stores getter and setter functions
+ // for a property.
+ class GetterSetter : public JSCell {
+ public:
+ GetterSetter()
+ : JSCell(0)
+ , m_getter(0)
+ , m_setter(0)
+ {
+ }
+
+ virtual void mark();
+
+ JSObject* getter() const { return m_getter; }
+ void setGetter(JSObject* getter) { m_getter = getter; }
+ JSObject* setter() const { return m_setter; }
+ void setSetter(JSObject* setter) { m_setter = setter; }
+
+ private:
+ virtual bool isGetterSetter() const;
+
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ JSObject* m_getter;
+ JSObject* m_setter;
+ };
+
+ GetterSetter* asGetterSetter(JSValue*);
+
+ inline GetterSetter* asGetterSetter(JSValue* value)
+ {
+ ASSERT(asCell(value)->isGetterSetter());
+ return static_cast<GetterSetter*>(asCell(value));
+ }
+
+
+} // namespace JSC
+
+#endif // GetterSetter_h
diff --git a/JavaScriptCore/runtime/GlobalEvalFunction.cpp b/JavaScriptCore/runtime/GlobalEvalFunction.cpp
new file mode 100644
index 0000000..10b3a2f
--- /dev/null
+++ b/JavaScriptCore/runtime/GlobalEvalFunction.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "GlobalEvalFunction.h"
+
+#include "JSGlobalObject.h"
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction);
+
+GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<StructureID> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
+ : PrototypeFunction(exec, structure, len, name, function)
+ , m_cachedGlobalObject(cachedGlobalObject)
+{
+ ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
+}
+
+void GlobalEvalFunction::mark()
+{
+ PrototypeFunction::mark();
+ if (!m_cachedGlobalObject->marked())
+ m_cachedGlobalObject->mark();
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/GlobalEvalFunction.h b/JavaScriptCore/runtime/GlobalEvalFunction.h
new file mode 100644
index 0000000..2d207c4
--- /dev/null
+++ b/JavaScriptCore/runtime/GlobalEvalFunction.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GlobalEvalFunction_h
+#define GlobalEvalFunction_h
+
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+ class JSGlobalObject;
+
+ class GlobalEvalFunction : public PrototypeFunction {
+ public:
+ GlobalEvalFunction(ExecState*, PassRefPtr<StructureID>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);
+ JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }
+
+ private:
+ virtual void mark();
+
+ JSGlobalObject* m_cachedGlobalObject;
+ };
+
+} // namespace JSC
+
+#endif // GlobalEvalFunction_h
diff --git a/JavaScriptCore/runtime/InitializeThreading.cpp b/JavaScriptCore/runtime/InitializeThreading.cpp
new file mode 100644
index 0000000..9e14768
--- /dev/null
+++ b/JavaScriptCore/runtime/InitializeThreading.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InitializeThreading.h"
+
+#include "collector.h"
+#include "DateMath.h"
+#include "dtoa.h"
+#include "identifier.h"
+#include "JSGlobalObject.h"
+#include "ustring.h"
+#include <wtf/Threading.h>
+
+namespace JSC {
+
+#if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
+static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT;
+#endif
+
+static void initializeThreadingOnce()
+{
+ WTF::initializeThreading();
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ s_dtoaP5Mutex = new Mutex;
+ UString::null();
+ initDateMath();
+#endif
+}
+
+void initializeThreading()
+{
+#if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
+ pthread_once(&initializeThreadingKeyOnce, initializeThreadingOnce);
+#else
+ static bool initializedThreading = false;
+ if (!initializedThreading) {
+ initializeThreadingOnce();
+ initializedThreading = true;
+ }
+#endif
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/InitializeThreading.h b/JavaScriptCore/runtime/InitializeThreading.h
new file mode 100644
index 0000000..1a93ccb
--- /dev/null
+++ b/JavaScriptCore/runtime/InitializeThreading.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef InitializeThreading_h
+#define InitializeThreading_h
+
+namespace JSC {
+
+ // This function must be called from the main thread. It is safe to call it repeatedly.
+ // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
+ void initializeThreading();
+
+}
+
+#endif // InitializeThreading_h
diff --git a/JavaScriptCore/runtime/InternalFunction.cpp b/JavaScriptCore/runtime/InternalFunction.cpp
new file mode 100644
index 0000000..ee81a58
--- /dev/null
+++ b/JavaScriptCore/runtime/InternalFunction.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "InternalFunction.h"
+
+#include "FunctionPrototype.h"
+#include "JSString.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(InternalFunction);
+
+const ClassInfo InternalFunction::info = { "Function", 0, 0, 0 };
+
+const ClassInfo* InternalFunction::classInfo() const
+{
+ return &info;
+}
+
+InternalFunction::InternalFunction(JSGlobalData* globalData, PassRefPtr<StructureID> structure, const Identifier& name)
+ : JSObject(structure)
+{
+ putDirect(globalData->propertyNames->name, jsString(globalData, name.ustring()), DontDelete | ReadOnly | DontEnum);
+}
+
+const UString& InternalFunction::name(JSGlobalData* globalData)
+{
+ return asString(getDirect(globalData->propertyNames->name))->value();
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/InternalFunction.h b/JavaScriptCore/runtime/InternalFunction.h
new file mode 100644
index 0000000..54d90ae
--- /dev/null
+++ b/JavaScriptCore/runtime/InternalFunction.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef InternalFunction_h
+#define InternalFunction_h
+
+#include "JSObject.h"
+#include "identifier.h"
+
+namespace JSC {
+
+ class FunctionPrototype;
+
+ class InternalFunction : public JSObject {
+ public:
+ virtual const ClassInfo* classInfo() const;
+ static const ClassInfo info;
+
+ const UString& name(JSGlobalData*);
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto)
+ {
+ return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot));
+ }
+
+ protected:
+ InternalFunction(PassRefPtr<StructureID> structure) : JSObject(structure) { }
+ InternalFunction(JSGlobalData*, PassRefPtr<StructureID>, const Identifier&);
+
+ private:
+ virtual CallType getCallData(CallData&) = 0;
+ };
+
+ InternalFunction* asInternalFunction(JSValue*);
+
+ inline InternalFunction* asInternalFunction(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&InternalFunction::info));
+ return static_cast<InternalFunction*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // InternalFunction_h
diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp
new file mode 100644
index 0000000..9cb77e8
--- /dev/null
+++ b/JavaScriptCore/runtime/JSActivation.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSActivation.h"
+
+#include "Arguments.h"
+#include "Machine.h"
+#include "JSFunction.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSActivation);
+
+const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
+
+JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody)
+ : Base(callFrame->globalData().activationStructureID, new JSActivationData(functionBody, callFrame))
+{
+}
+
+JSActivation::~JSActivation()
+{
+ delete d();
+}
+
+void JSActivation::mark()
+{
+ Base::mark();
+
+ Register* registerArray = d()->registerArray.get();
+ if (!registerArray)
+ return;
+
+ size_t numParametersMinusThis = d()->functionBody->generatedByteCode().numParameters - 1;
+
+ size_t i = 0;
+ size_t count = numParametersMinusThis;
+ for ( ; i < count; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
+
+ size_t numVars = d()->functionBody->generatedByteCode().numVars;
+
+ // Skip the call frame, which sits between the parameters and vars.
+ i += RegisterFile::CallFrameHeaderSize;
+ count += RegisterFile::CallFrameHeaderSize + numVars;
+
+ for ( ; i < count; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
+}
+
+bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (symbolTableGet(propertyName, slot))
+ return true;
+
+ if (JSValue** location = getDirectLocation(propertyName)) {
+ slot.setValueSlot(location);
+ return true;
+ }
+
+ // Only return the built-in arguments object if it wasn't overridden above.
+ if (propertyName == exec->propertyNames().arguments) {
+ slot.setCustom(this, getArgumentsGetter());
+ return true;
+ }
+
+ // We don't call through to JSObject because there's no way to give an
+ // activation object getter properties or a prototype.
+ ASSERT(!hasGetterSetterProperties());
+ ASSERT(prototype()->isNull());
+ return false;
+}
+
+void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (symbolTablePut(propertyName, value))
+ return;
+
+ // We don't call through to JSObject because __proto__ and getter/setter
+ // properties are non-standard extensions that other implementations do not
+ // expose in the activation object.
+ ASSERT(!hasGetterSetterProperties());
+ putDirect(propertyName, value, 0, true, slot);
+}
+
+// FIXME: Make this function honor ReadOnly (const) and DontEnum
+void JSActivation::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ // We don't call through to JSObject because __proto__ and getter/setter
+ // properties are non-standard extensions that other implementations do not
+ // expose in the activation object.
+ ASSERT(!hasGetterSetterProperties());
+ PutPropertySlot slot;
+ putDirect(propertyName, value, attributes, true, slot);
+}
+
+bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().arguments)
+ return false;
+
+ return Base::deleteProperty(exec, propertyName);
+}
+
+JSObject* JSActivation::toThisObject(ExecState* exec) const
+{
+ return exec->globalThisValue();
+}
+
+bool JSActivation::isDynamicScope() const
+{
+ return d()->functionBody->usesEval();
+}
+
+JSValue* JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ JSActivation* activation = asActivation(slot.slotBase());
+
+ if (activation->d()->functionBody->usesArguments()) {
+ PropertySlot slot;
+ activation->symbolTableGet(exec->propertyNames().arguments, slot);
+ return slot.getValue(exec, exec->propertyNames().arguments);
+ }
+
+ CallFrame* callFrame = CallFrame::create(activation->d()->registers);
+ Arguments* arguments = callFrame->optionalCalleeArguments();
+ if (!arguments) {
+ arguments = new (callFrame) Arguments(callFrame);
+ arguments->copyRegisters();
+ callFrame->setCalleeArguments(arguments);
+ }
+ ASSERT(arguments->isObject(&Arguments::info));
+
+ return arguments;
+}
+
+// These two functions serve the purpose of isolating the common case from a
+// PIC branch.
+
+PropertySlot::GetValueFunc JSActivation::getArgumentsGetter()
+{
+ return argumentsGetter;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h
new file mode 100644
index 0000000..16d131b
--- /dev/null
+++ b/JavaScriptCore/runtime/JSActivation.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSActivation_h
+#define JSActivation_h
+
+#include "CodeBlock.h"
+#include "JSVariableObject.h"
+#include "RegisterFile.h"
+#include "SymbolTable.h"
+#include "nodes.h"
+
+namespace JSC {
+
+ class Arguments;
+ class Register;
+
+ class JSActivation : public JSVariableObject {
+ typedef JSVariableObject Base;
+ public:
+ JSActivation(CallFrame*, PassRefPtr<FunctionBodyNode>);
+ virtual ~JSActivation();
+
+ virtual void mark();
+
+ virtual bool isDynamicScope() const;
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&);
+
+ virtual void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+
+ virtual JSObject* toThisObject(ExecState*) const;
+
+ void copyRegisters(Arguments* arguments);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+
+ private:
+ struct JSActivationData : public JSVariableObjectData {
+ JSActivationData(PassRefPtr<FunctionBodyNode> functionBody, Register* registers)
+ : JSVariableObjectData(&functionBody->symbolTable(), registers)
+ , functionBody(functionBody)
+ {
+ }
+
+ RefPtr<FunctionBodyNode> functionBody;
+ };
+
+ static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
+ NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
+
+ JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); }
+ };
+
+ JSActivation* asActivation(JSValue*);
+
+ inline JSActivation* asActivation(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&JSActivation::info));
+ return static_cast<JSActivation*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // JSActivation_h
diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp
new file mode 100644
index 0000000..d2d38a4
--- /dev/null
+++ b/JavaScriptCore/runtime/JSArray.cpp
@@ -0,0 +1,1002 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "JSArray.h"
+
+#include "ArrayPrototype.h"
+#include "PropertyNameArray.h"
+#include <wtf/AVLTree.h>
+#include <wtf/Assertions.h>
+#include <operations.h>
+
+#define CHECK_ARRAY_CONSISTENCY 0
+
+using namespace std;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSArray);
+
+// Overview of JSArray
+//
+// Properties of JSArray objects may be stored in one of three locations:
+// * The regular JSObject property map.
+// * A storage vector.
+// * A sparse map of array entries.
+//
+// Properties with non-numeric identifiers, with identifiers that are not representable
+// as an unsigned integer, or where the value is greater than MAX_ARRAY_INDEX
+// (specifically, this is only one property - the value 0xFFFFFFFFU as an unsigned 32-bit
+// integer) are not considered array indices and will be stored in the JSObject property map.
+//
+// All properties with a numeric identifer, representable as an unsigned integer i,
+// where (i <= MAX_ARRAY_INDEX), are an array index and will be stored in either the
+// storage vector or the sparse map. An array index i will be handled in the following
+// fashion:
+//
+// * Where (i < MIN_SPARSE_ARRAY_INDEX) the value will be stored in the storage vector.
+// * Where (MIN_SPARSE_ARRAY_INDEX <= i <= MAX_STORAGE_VECTOR_INDEX) the value will either
+// be stored in the storage vector or in the sparse array, depending on the density of
+// data that would be stored in the vector (a vector being used where at least
+// (1 / minDensityMultiplier) of the entries would be populated).
+// * Where (MAX_STORAGE_VECTOR_INDEX < i <= MAX_ARRAY_INDEX) the value will always be stored
+// in the sparse array.
+
+// The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize
+// function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage
+// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(JSValue*)) +
+// (vectorLength * sizeof(JSValue*)) must be <= 0xFFFFFFFFU (which is maximum value of size_t).
+#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValue*))) / sizeof(JSValue*))
+
+// These values have to be macros to be used in max() and min() without introducing
+// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
+#define MIN_SPARSE_ARRAY_INDEX 10000U
+#define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1)
+// 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer.
+#define MAX_ARRAY_INDEX 0xFFFFFFFEU
+
+// Our policy for when to use a vector and when to use a sparse map.
+// For all array indices under MIN_SPARSE_ARRAY_INDEX, we always use a vector.
+// When indices greater than MIN_SPARSE_ARRAY_INDEX are involved, we use a vector
+// as long as it is 1/8 full. If more sparse than that, we use a map.
+static const unsigned minDensityMultiplier = 8;
+
+const ClassInfo JSArray::info = {"Array", 0, 0, 0};
+
+static inline size_t storageSize(unsigned vectorLength)
+{
+ ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH);
+
+ // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH)
+ // - as asserted above - the following calculation cannot overflow.
+ size_t size = (sizeof(ArrayStorage) - sizeof(JSValue*)) + (vectorLength * sizeof(JSValue*));
+ // Assertion to detect integer overflow in previous calculation (should not be possible, provided that
+ // MAX_STORAGE_VECTOR_LENGTH is correctly defined).
+ ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValue*))) / sizeof(JSValue*) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValue*))));
+
+ return size;
+}
+
+static inline unsigned increasedVectorLength(unsigned newLength)
+{
+ ASSERT(newLength <= MAX_STORAGE_VECTOR_LENGTH);
+
+ // Mathematically equivalent to:
+ // increasedLength = (newLength * 3 + 1) / 2;
+ // or:
+ // increasedLength = (unsigned)ceil(newLength * 1.5));
+ // This form is not prone to internal overflow.
+ unsigned increasedLength = newLength + (newLength >> 1) + (newLength & 1);
+ ASSERT(increasedLength >= newLength);
+
+ return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);
+}
+
+static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
+{
+ return length / minDensityMultiplier <= numValues;
+}
+
+#if !CHECK_ARRAY_CONSISTENCY
+
+inline void JSArray::checkConsistency(ConsistencyCheckType)
+{
+}
+
+#endif
+
+JSArray::JSArray(PassRefPtr<StructureID> structureID)
+ : JSObject(structureID)
+{
+ unsigned initialCapacity = 0;
+
+ m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
+ m_fastAccessCutoff = 0;
+ m_storage->m_vectorLength = initialCapacity;
+ m_storage->m_length = 0;
+
+ checkConsistency();
+}
+
+JSArray::JSArray(PassRefPtr<StructureID> structure, unsigned initialLength)
+ : JSObject(structure)
+{
+ unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX);
+
+ m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
+ m_fastAccessCutoff = 0;
+ m_storage->m_vectorLength = initialCapacity;
+ m_storage->m_length = initialLength;
+
+ Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue*));
+
+ checkConsistency();
+}
+
+JSArray::JSArray(ExecState* exec, PassRefPtr<StructureID> structure, const ArgList& list)
+ : JSObject(structure)
+{
+ unsigned length = list.size();
+
+ m_fastAccessCutoff = length;
+
+ ArrayStorage* storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(length)));
+
+ storage->m_vectorLength = length;
+ storage->m_numValuesInVector = length;
+ storage->m_sparseValueMap = 0;
+ storage->m_length = length;
+
+ size_t i = 0;
+ ArgList::const_iterator end = list.end();
+ for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i)
+ storage->m_vector[i] = (*it).jsValue(exec);
+
+ m_storage = storage;
+
+ // When the array is created non-empty, its cells are filled, so it's really no worse than
+ // a property map. Therefore don't report extra memory cost.
+
+ checkConsistency();
+}
+
+JSArray::~JSArray()
+{
+ checkConsistency(DestructorConsistencyCheck);
+
+ delete m_storage->m_sparseValueMap;
+ fastFree(m_storage);
+}
+
+bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
+{
+ ArrayStorage* storage = m_storage;
+
+ if (i >= storage->m_length) {
+ if (i > MAX_ARRAY_INDEX)
+ return getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
+ return false;
+ }
+
+ if (i < storage->m_vectorLength) {
+ JSValue*& valueSlot = storage->m_vector[i];
+ if (valueSlot) {
+ slot.setValueSlot(&valueSlot);
+ return true;
+ }
+ } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (i >= MIN_SPARSE_ARRAY_INDEX) {
+ SparseArrayValueMap::iterator it = map->find(i);
+ if (it != map->end()) {
+ slot.setValueSlot(&it->second);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setValue(jsNumber(exec, length()));
+ return true;
+ }
+
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex)
+ return JSArray::getOwnPropertySlot(exec, i, slot);
+
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+// ECMA 15.4.5.1
+void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex) {
+ put(exec, i, value);
+ return;
+ }
+
+ if (propertyName == exec->propertyNames().length) {
+ unsigned newLength = value->toUInt32(exec);
+ if (value->toNumber(exec) != static_cast<double>(newLength)) {
+ throwError(exec, RangeError, "Invalid array length.");
+ return;
+ }
+ setLength(newLength);
+ return;
+ }
+
+ JSObject::put(exec, propertyName, value, slot);
+}
+
+void JSArray::put(ExecState* exec, unsigned i, JSValue* value)
+{
+ checkConsistency();
+
+ unsigned length = m_storage->m_length;
+ if (i >= length && i <= MAX_ARRAY_INDEX) {
+ length = i + 1;
+ m_storage->m_length = length;
+ }
+
+ if (i < m_storage->m_vectorLength) {
+ JSValue*& valueSlot = m_storage->m_vector[i];
+ if (valueSlot) {
+ valueSlot = value;
+ checkConsistency();
+ return;
+ }
+ valueSlot = value;
+ if (++m_storage->m_numValuesInVector == m_storage->m_length)
+ m_fastAccessCutoff = m_storage->m_length;
+ checkConsistency();
+ return;
+ }
+
+ putSlowCase(exec, i, value);
+}
+
+NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue* value)
+{
+ ArrayStorage* storage = m_storage;
+ SparseArrayValueMap* map = storage->m_sparseValueMap;
+
+ if (i >= MIN_SPARSE_ARRAY_INDEX) {
+ if (i > MAX_ARRAY_INDEX) {
+ PutPropertySlot slot;
+ put(exec, Identifier::from(exec, i), value, slot);
+ return;
+ }
+
+ // We miss some cases where we could compact the storage, such as a large array that is being filled from the end
+ // (which will only be compacted as we reach indices that are less than cutoff) - but this makes the check much faster.
+ if ((i > MAX_STORAGE_VECTOR_INDEX) || !isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {
+ if (!map) {
+ map = new SparseArrayValueMap;
+ storage->m_sparseValueMap = map;
+ }
+ map->set(i, value);
+ return;
+ }
+ }
+
+ // We have decided that we'll put the new item into the vector.
+ // Fast case is when there is no sparse map, so we can increase the vector size without moving values from it.
+ if (!map || map->isEmpty()) {
+ if (increaseVectorLength(i + 1)) {
+ storage = m_storage;
+ storage->m_vector[i] = value;
+ if (++storage->m_numValuesInVector == storage->m_length)
+ m_fastAccessCutoff = storage->m_length;
+ checkConsistency();
+ } else
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ // Decide how many values it would be best to move from the map.
+ unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
+ unsigned newVectorLength = increasedVectorLength(i + 1);
+ for (unsigned j = max(storage->m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
+ newNumValuesInVector += map->contains(j);
+ if (i >= MIN_SPARSE_ARRAY_INDEX)
+ newNumValuesInVector -= map->contains(i);
+ if (isDenseEnoughForVector(newVectorLength, newNumValuesInVector)) {
+ unsigned proposedNewNumValuesInVector = newNumValuesInVector;
+ // If newVectorLength is already the maximum - MAX_STORAGE_VECTOR_LENGTH - then do not attempt to grow any further.
+ while (newVectorLength < MAX_STORAGE_VECTOR_LENGTH) {
+ unsigned proposedNewVectorLength = increasedVectorLength(newVectorLength + 1);
+ for (unsigned j = max(newVectorLength, MIN_SPARSE_ARRAY_INDEX); j < proposedNewVectorLength; ++j)
+ proposedNewNumValuesInVector += map->contains(j);
+ if (!isDenseEnoughForVector(proposedNewVectorLength, proposedNewNumValuesInVector))
+ break;
+ newVectorLength = proposedNewVectorLength;
+ newNumValuesInVector = proposedNewNumValuesInVector;
+ }
+ }
+
+ storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));
+ if (!storage) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ unsigned vectorLength = storage->m_vectorLength;
+ if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
+ for (unsigned j = vectorLength; j < newVectorLength; ++j)
+ storage->m_vector[j] = noValue();
+ if (i > MIN_SPARSE_ARRAY_INDEX)
+ map->remove(i);
+ } else {
+ for (unsigned j = vectorLength; j < max(vectorLength, MIN_SPARSE_ARRAY_INDEX); ++j)
+ storage->m_vector[j] = noValue();
+ for (unsigned j = max(vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
+ storage->m_vector[j] = map->take(j);
+ }
+
+ storage->m_vector[i] = value;
+
+ storage->m_vectorLength = newVectorLength;
+ storage->m_numValuesInVector = newNumValuesInVector;
+
+ m_storage = storage;
+
+ checkConsistency();
+}
+
+bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex)
+ return deleteProperty(exec, i);
+
+ if (propertyName == exec->propertyNames().length)
+ return false;
+
+ return JSObject::deleteProperty(exec, propertyName);
+}
+
+bool JSArray::deleteProperty(ExecState* exec, unsigned i)
+{
+ checkConsistency();
+
+ ArrayStorage* storage = m_storage;
+
+ if (i < storage->m_vectorLength) {
+ JSValue*& valueSlot = storage->m_vector[i];
+ if (!valueSlot) {
+ checkConsistency();
+ return false;
+ }
+ valueSlot = noValue();
+ --storage->m_numValuesInVector;
+ if (m_fastAccessCutoff > i)
+ m_fastAccessCutoff = i;
+ checkConsistency();
+ return true;
+ }
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ if (i >= MIN_SPARSE_ARRAY_INDEX) {
+ SparseArrayValueMap::iterator it = map->find(i);
+ if (it != map->end()) {
+ map->remove(it);
+ checkConsistency();
+ return true;
+ }
+ }
+ }
+
+ checkConsistency();
+
+ if (i > MAX_ARRAY_INDEX)
+ return deleteProperty(exec, Identifier::from(exec, i));
+
+ return false;
+}
+
+void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ // FIXME: Filling PropertyNameArray with an identifier for every integer
+ // is incredibly inefficient for large arrays. We need a different approach,
+ // which almost certainly means a different structure for PropertyNameArray.
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
+ for (unsigned i = 0; i < usedVectorLength; ++i) {
+ if (storage->m_vector[i])
+ propertyNames.add(Identifier::from(exec, i));
+ }
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+ propertyNames.add(Identifier::from(exec, it->first));
+ }
+
+ JSObject::getPropertyNames(exec, propertyNames);
+}
+
+bool JSArray::increaseVectorLength(unsigned newLength)
+{
+ // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map
+ // to the vector. Callers have to account for that, because they can do it more efficiently.
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned vectorLength = storage->m_vectorLength;
+ ASSERT(newLength > vectorLength);
+ ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
+ unsigned newVectorLength = increasedVectorLength(newLength);
+
+ storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));
+ if (!storage)
+ return false;
+
+ storage->m_vectorLength = newVectorLength;
+
+ for (unsigned i = vectorLength; i < newVectorLength; ++i)
+ storage->m_vector[i] = noValue();
+
+ m_storage = storage;
+ return true;
+}
+
+void JSArray::setLength(unsigned newLength)
+{
+ checkConsistency();
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned length = m_storage->m_length;
+
+ if (newLength < length) {
+ if (m_fastAccessCutoff > newLength)
+ m_fastAccessCutoff = newLength;
+
+ unsigned usedVectorLength = min(length, storage->m_vectorLength);
+ for (unsigned i = newLength; i < usedVectorLength; ++i) {
+ JSValue*& valueSlot = storage->m_vector[i];
+ bool hadValue = valueSlot;
+ valueSlot = noValue();
+ storage->m_numValuesInVector -= hadValue;
+ }
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ SparseArrayValueMap copy = *map;
+ SparseArrayValueMap::iterator end = copy.end();
+ for (SparseArrayValueMap::iterator it = copy.begin(); it != end; ++it) {
+ if (it->first >= newLength)
+ map->remove(it->first);
+ }
+ if (map->isEmpty()) {
+ delete map;
+ storage->m_sparseValueMap = 0;
+ }
+ }
+ }
+
+ m_storage->m_length = newLength;
+
+ checkConsistency();
+}
+
+JSValue* JSArray::pop()
+{
+ checkConsistency();
+
+ unsigned length = m_storage->m_length;
+ if (!length)
+ return jsUndefined();
+
+ --length;
+
+ JSValue* result;
+
+ if (m_fastAccessCutoff > length) {
+ JSValue*& valueSlot = m_storage->m_vector[length];
+ result = valueSlot;
+ ASSERT(result);
+ valueSlot = noValue();
+ --m_storage->m_numValuesInVector;
+ m_fastAccessCutoff = length;
+ } else if (length < m_storage->m_vectorLength) {
+ JSValue*& valueSlot = m_storage->m_vector[length];
+ result = valueSlot;
+ valueSlot = noValue();
+ if (result)
+ --m_storage->m_numValuesInVector;
+ else
+ result = jsUndefined();
+ } else {
+ result = jsUndefined();
+ if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator it = map->find(length);
+ if (it != map->end()) {
+ result = it->second;
+ map->remove(it);
+ if (map->isEmpty()) {
+ delete map;
+ m_storage->m_sparseValueMap = 0;
+ }
+ }
+ }
+ }
+
+ m_storage->m_length = length;
+
+ checkConsistency();
+
+ return result;
+}
+
+void JSArray::push(ExecState* exec, JSValue* value)
+{
+ checkConsistency();
+
+ if (m_storage->m_length < m_storage->m_vectorLength) {
+ ASSERT(!m_storage->m_vector[m_storage->m_length]);
+ m_storage->m_vector[m_storage->m_length] = value;
+ if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
+ m_fastAccessCutoff = m_storage->m_length;
+ checkConsistency();
+ return;
+ }
+
+ if (m_storage->m_length < MIN_SPARSE_ARRAY_INDEX) {
+ SparseArrayValueMap* map = m_storage->m_sparseValueMap;
+ if (!map || map->isEmpty()) {
+ if (increaseVectorLength(m_storage->m_length + 1)) {
+ m_storage->m_vector[m_storage->m_length] = value;
+ if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
+ m_fastAccessCutoff = m_storage->m_length;
+ checkConsistency();
+ return;
+ }
+ checkConsistency();
+ throwOutOfMemoryError(exec);
+ return;
+ }
+ }
+
+ putSlowCase(exec, m_storage->m_length++, value);
+}
+
+void JSArray::mark()
+{
+ JSObject::mark();
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
+ for (unsigned i = 0; i < usedVectorLength; ++i) {
+ JSValue* value = storage->m_vector[i];
+ if (value && !value->marked())
+ value->mark();
+ }
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
+ JSValue* value = it->second;
+ if (!value->marked())
+ value->mark();
+ }
+ }
+}
+
+typedef std::pair<JSValue*, UString> ArrayQSortPair;
+
+static int compareByStringPairForQSort(const void* a, const void* b)
+{
+ const ArrayQSortPair* va = static_cast<const ArrayQSortPair*>(a);
+ const ArrayQSortPair* vb = static_cast<const ArrayQSortPair*>(b);
+ return compare(va->second, vb->second);
+}
+
+void JSArray::sort(ExecState* exec)
+{
+ unsigned lengthNotIncludingUndefined = compactForSorting();
+ if (m_storage->m_sparseValueMap) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ if (!lengthNotIncludingUndefined)
+ return;
+
+ // Converting JavaScript values to strings can be expensive, so we do it once up front and sort based on that.
+ // This is a considerable improvement over doing it twice per comparison, though it requires a large temporary
+ // buffer. Besides, this protects us from crashing if some objects have custom toString methods that return
+ // random or otherwise changing results, effectively making compare function inconsistent.
+
+ Vector<ArrayQSortPair> values(lengthNotIncludingUndefined);
+ if (!values.begin()) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ for (size_t i = 0; i < lengthNotIncludingUndefined; i++) {
+ JSValue* value = m_storage->m_vector[i];
+ ASSERT(!value->isUndefined());
+ values[i].first = value;
+ }
+
+ // FIXME: While calling these toString functions, the array could be mutated.
+ // In that case, objects pointed to by values in this vector might get garbage-collected!
+
+ // FIXME: The following loop continues to call toString on subsequent values even after
+ // a toString call raises an exception.
+
+ for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
+ values[i].second = values[i].first->toString(exec);
+
+ if (exec->hadException())
+ return;
+
+ // FIXME: Since we sort by string value, a fast algorithm might be to use a radix sort. That would be O(N) rather
+ // than O(N log N).
+
+#if HAVE(MERGESORT)
+ mergesort(values.begin(), values.size(), sizeof(ArrayQSortPair), compareByStringPairForQSort);
+#else
+ // FIXME: The qsort library function is likely to not be a stable sort.
+ // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort.
+ qsort(values.begin(), values.size(), sizeof(ArrayQSortPair), compareByStringPairForQSort);
+#endif
+
+ // FIXME: If the toString function changed the length of the array, this might be
+ // modifying the vector incorrectly.
+
+ for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
+ m_storage->m_vector[i] = values[i].first;
+
+ checkConsistency(SortConsistencyCheck);
+}
+
+struct AVLTreeNodeForArrayCompare {
+ JSValue* value;
+
+ // Child pointers. The high bit of gt is robbed and used as the
+ // balance factor sign. The high bit of lt is robbed and used as
+ // the magnitude of the balance factor.
+ int32_t gt;
+ int32_t lt;
+};
+
+struct AVLTreeAbstractorForArrayCompare {
+ typedef int32_t handle; // Handle is an index into m_nodes vector.
+ typedef JSValue* key;
+ typedef int32_t size;
+
+ Vector<AVLTreeNodeForArrayCompare> m_nodes;
+ ExecState* m_exec;
+ JSValue* m_compareFunction;
+ CallType m_compareCallType;
+ const CallData* m_compareCallData;
+ JSValue* m_globalThisValue;
+
+ handle get_less(handle h) { return m_nodes[h].lt & 0x7FFFFFFF; }
+ void set_less(handle h, handle lh) { m_nodes[h].lt &= 0x80000000; m_nodes[h].lt |= lh; }
+ handle get_greater(handle h) { return m_nodes[h].gt & 0x7FFFFFFF; }
+ void set_greater(handle h, handle gh) { m_nodes[h].gt &= 0x80000000; m_nodes[h].gt |= gh; }
+
+ int get_balance_factor(handle h)
+ {
+ if (m_nodes[h].gt & 0x80000000)
+ return -1;
+ return static_cast<unsigned>(m_nodes[h].lt) >> 31;
+ }
+
+ void set_balance_factor(handle h, int bf)
+ {
+ if (bf == 0) {
+ m_nodes[h].lt &= 0x7FFFFFFF;
+ m_nodes[h].gt &= 0x7FFFFFFF;
+ } else {
+ m_nodes[h].lt |= 0x80000000;
+ if (bf < 0)
+ m_nodes[h].gt |= 0x80000000;
+ else
+ m_nodes[h].gt &= 0x7FFFFFFF;
+ }
+ }
+
+ int compare_key_key(key va, key vb)
+ {
+ ASSERT(!va->isUndefined());
+ ASSERT(!vb->isUndefined());
+
+ if (m_exec->hadException())
+ return 1;
+
+ ArgList arguments;
+ arguments.append(va);
+ arguments.append(vb);
+ double compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments)->toNumber(m_exec);
+ return (compareResult < 0) ? -1 : 1; // Not passing equality through, because we need to store all values, even if equivalent.
+ }
+
+ int compare_key_node(key k, handle h) { return compare_key_key(k, m_nodes[h].value); }
+ int compare_node_node(handle h1, handle h2) { return compare_key_key(m_nodes[h1].value, m_nodes[h2].value); }
+
+ static handle null() { return 0x7FFFFFFF; }
+};
+
+void JSArray::sort(ExecState* exec, JSValue* compareFunction, CallType callType, const CallData& callData)
+{
+ checkConsistency();
+
+ // FIXME: This ignores exceptions raised in the compare function or in toNumber.
+
+ // The maximum tree depth is compiled in - but the caller is clearly up to no good
+ // if a larger array is passed.
+ ASSERT(m_storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));
+ if (m_storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))
+ return;
+
+ if (!m_storage->m_length)
+ return;
+
+ unsigned usedVectorLength = min(m_storage->m_length, m_storage->m_vectorLength);
+
+ AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items
+ tree.abstractor().m_exec = exec;
+ tree.abstractor().m_compareFunction = compareFunction;
+ tree.abstractor().m_compareCallType = callType;
+ tree.abstractor().m_compareCallData = &callData;
+ tree.abstractor().m_globalThisValue = exec->globalThisValue();
+ tree.abstractor().m_nodes.resize(usedVectorLength + (m_storage->m_sparseValueMap ? m_storage->m_sparseValueMap->size() : 0));
+
+ if (!tree.abstractor().m_nodes.begin()) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ // FIXME: If the compare function modifies the array, the vector, map, etc. could be modified
+ // right out from under us while we're building the tree here.
+
+ unsigned numDefined = 0;
+ unsigned numUndefined = 0;
+
+ // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree.
+ for (; numDefined < usedVectorLength; ++numDefined) {
+ JSValue* v = m_storage->m_vector[numDefined];
+ if (!v || v->isUndefined())
+ break;
+ tree.abstractor().m_nodes[numDefined].value = v;
+ tree.insert(numDefined);
+ }
+ for (unsigned i = numDefined; i < usedVectorLength; ++i) {
+ if (JSValue* v = m_storage->m_vector[i]) {
+ if (v->isUndefined())
+ ++numUndefined;
+ else {
+ tree.abstractor().m_nodes[numDefined].value = v;
+ tree.insert(numDefined);
+ ++numDefined;
+ }
+ }
+ }
+
+ unsigned newUsedVectorLength = numDefined + numUndefined;
+
+ if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+ newUsedVectorLength += map->size();
+ if (newUsedVectorLength > m_storage->m_vectorLength) {
+ // Check that it is possible to allocate an array large enough to hold all the entries.
+ if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+ }
+
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
+ tree.abstractor().m_nodes[numDefined].value = it->second;
+ tree.insert(numDefined);
+ ++numDefined;
+ }
+
+ delete map;
+ m_storage->m_sparseValueMap = 0;
+ }
+
+ ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
+
+ // FIXME: If the compare function changed the length of the array, the following might be
+ // modifying the vector incorrectly.
+
+ // Copy the values back into m_storage.
+ AVLTree<AVLTreeAbstractorForArrayCompare, 44>::Iterator iter;
+ iter.start_iter_least(tree);
+ for (unsigned i = 0; i < numDefined; ++i) {
+ m_storage->m_vector[i] = tree.abstractor().m_nodes[*iter].value;
+ ++iter;
+ }
+
+ // Put undefined values back in.
+ for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
+ m_storage->m_vector[i] = jsUndefined();
+
+ // Ensure that unused values in the vector are zeroed out.
+ for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
+ m_storage->m_vector[i] = noValue();
+
+ m_fastAccessCutoff = newUsedVectorLength;
+ m_storage->m_numValuesInVector = newUsedVectorLength;
+
+ checkConsistency(SortConsistencyCheck);
+}
+
+void JSArray::fillArgList(ExecState* exec, ArgList& args)
+{
+ unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
+ unsigned i = 0;
+ for (; i < fastAccessLength; ++i)
+ args.append(getIndex(i));
+ for (; i < m_storage->m_length; ++i)
+ args.append(get(exec, i));
+}
+
+unsigned JSArray::compactForSorting()
+{
+ checkConsistency();
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned usedVectorLength = min(m_storage->m_length, storage->m_vectorLength);
+
+ unsigned numDefined = 0;
+ unsigned numUndefined = 0;
+
+ for (; numDefined < usedVectorLength; ++numDefined) {
+ JSValue* v = storage->m_vector[numDefined];
+ if (!v || v->isUndefined())
+ break;
+ }
+ for (unsigned i = numDefined; i < usedVectorLength; ++i) {
+ if (JSValue* v = storage->m_vector[i]) {
+ if (v->isUndefined())
+ ++numUndefined;
+ else
+ storage->m_vector[numDefined++] = v;
+ }
+ }
+
+ unsigned newUsedVectorLength = numDefined + numUndefined;
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ newUsedVectorLength += map->size();
+ if (newUsedVectorLength > storage->m_vectorLength) {
+ // Check that it is possible to allocate an array large enough to hold all the entries - if not,
+ // exception is thrown by caller.
+ if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))
+ return 0;
+ storage = m_storage;
+ }
+
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+ storage->m_vector[numDefined++] = it->second;
+
+ delete map;
+ storage->m_sparseValueMap = 0;
+ }
+
+ for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
+ storage->m_vector[i] = jsUndefined();
+ for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
+ storage->m_vector[i] = noValue();
+
+ m_fastAccessCutoff = newUsedVectorLength;
+ storage->m_numValuesInVector = newUsedVectorLength;
+
+ checkConsistency(SortConsistencyCheck);
+
+ return numDefined;
+}
+
+void* JSArray::lazyCreationData()
+{
+ return m_storage->lazyCreationData;
+}
+
+void JSArray::setLazyCreationData(void* d)
+{
+ m_storage->lazyCreationData = d;
+}
+
+#if CHECK_ARRAY_CONSISTENCY
+
+void JSArray::checkConsistency(ConsistencyCheckType type)
+{
+ ASSERT(m_storage);
+ if (type == SortConsistencyCheck)
+ ASSERT(!m_storage->m_sparseValueMap);
+
+ ASSERT(m_fastAccessCutoff <= m_storage->m_length);
+ ASSERT(m_fastAccessCutoff <= m_storage->m_numValuesInVector);
+
+ unsigned numValuesInVector = 0;
+ for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) {
+ if (JSValue* value = m_storage->m_vector[i]) {
+ ASSERT(i < m_storage->m_length);
+ if (type != DestructorConsistencyCheck)
+ value->type(); // Likely to crash if the object was deallocated.
+ ++numValuesInVector;
+ } else {
+ ASSERT(i >= m_fastAccessCutoff);
+ if (type == SortConsistencyCheck)
+ ASSERT(i >= m_storage->m_numValuesInVector);
+ }
+ }
+ ASSERT(numValuesInVector == m_storage->m_numValuesInVector);
+
+ if (m_storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end();
+ for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) {
+ unsigned index = it->first;
+ ASSERT(index < m_storage->m_length);
+ ASSERT(index >= m_storage->m_vectorLength);
+ ASSERT(index <= MAX_ARRAY_INDEX);
+ ASSERT(it->second);
+ if (type != DestructorConsistencyCheck)
+ it->second->type(); // Likely to crash if the object was deallocated.
+ }
+ }
+}
+
+#endif
+
+JSArray* constructEmptyArray(ExecState* exec)
+{
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
+}
+
+JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
+{
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
+}
+
+JSArray* constructArray(ExecState* exec, JSValue* singleItemValue)
+{
+ ArgList values;
+ values.append(singleItemValue);
+ return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values);
+}
+
+JSArray* constructArray(ExecState* exec, const ArgList& values)
+{
+ return new (exec) JSArray(exec, exec->lexicalGlobalObject()->arrayStructure(), values);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h
new file mode 100644
index 0000000..165fafd
--- /dev/null
+++ b/JavaScriptCore/runtime/JSArray.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef JSArray_h
+#define JSArray_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ typedef HashMap<unsigned, JSValue*> SparseArrayValueMap;
+
+ struct ArrayStorage {
+ unsigned m_length;
+ unsigned m_vectorLength;
+ unsigned m_numValuesInVector;
+ SparseArrayValueMap* m_sparseValueMap;
+ void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily.
+ JSValue* m_vector[1];
+ };
+
+ class JSArray : public JSObject {
+ friend class CTI;
+
+ public:
+ explicit JSArray(PassRefPtr<StructureID>);
+ JSArray(PassRefPtr<StructureID>, unsigned initialLength);
+ JSArray(ExecState*, PassRefPtr<StructureID>, const ArgList& initialValues);
+ virtual ~JSArray();
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue*); // FIXME: Make protected and add setItem.
+
+ static const ClassInfo info;
+
+ unsigned length() const { return m_storage->m_length; }
+ void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.
+
+ void sort(ExecState*);
+ void sort(ExecState*, JSValue* compareFunction, CallType, const CallData&);
+
+ void push(ExecState*, JSValue*);
+ JSValue* pop();
+
+ bool canGetIndex(unsigned i) { return i < m_fastAccessCutoff; }
+ JSValue* getIndex(unsigned i)
+ {
+ ASSERT(canGetIndex(i));
+ return m_storage->m_vector[i];
+ }
+
+ bool canSetIndex(unsigned i) { return i < m_fastAccessCutoff; }
+ JSValue* setIndex(unsigned i, JSValue* v)
+ {
+ ASSERT(canSetIndex(i));
+ return m_storage->m_vector[i] = v;
+ }
+
+ void fillArgList(ExecState*, ArgList&);
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+ protected:
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+ virtual void mark();
+
+ void* lazyCreationData();
+ void setLazyCreationData(void*);
+
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
+ void putSlowCase(ExecState*, unsigned propertyName, JSValue*);
+
+ bool increaseVectorLength(unsigned newLength);
+
+ unsigned compactForSorting();
+
+ enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
+ void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
+
+ unsigned m_fastAccessCutoff;
+ ArrayStorage* m_storage;
+ };
+
+ JSArray* asArray(JSValue*);
+
+ JSArray* constructEmptyArray(ExecState*);
+ JSArray* constructEmptyArray(ExecState*, unsigned initialLength);
+ JSArray* constructArray(ExecState*, JSValue* singleItemValue);
+ JSArray* constructArray(ExecState*, const ArgList& values);
+
+ inline JSArray* asArray(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&JSArray::info));
+ return static_cast<JSArray*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // JSArray_h
diff --git a/JavaScriptCore/runtime/JSCell.cpp b/JavaScriptCore/runtime/JSCell.cpp
new file mode 100644
index 0000000..cfe2f72
--- /dev/null
+++ b/JavaScriptCore/runtime/JSCell.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSCell.h"
+
+#include "JSFunction.h"
+#include "JSString.h"
+#include "JSObject.h"
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+#if defined NAN && defined INFINITY
+
+extern const double NaN = NAN;
+extern const double Inf = INFINITY;
+
+#else // !(defined NAN && defined INFINITY)
+
+// The trick is to define the NaN and Inf globals with a different type than the declaration.
+// This trick works because the mangled name of the globals does not include the type, although
+// I'm not sure that's guaranteed. There could be alignment issues with this, since arrays of
+// characters don't necessarily need the same alignment doubles do, but for now it seems to work.
+// It would be good to figure out a 100% clean way that still avoids code that runs at init time.
+
+// Note, we have to use union to ensure alignment. Otherwise, NaN_Bytes can start anywhere,
+// while NaN_double has to be 4-byte aligned for 32-bits.
+// With -fstrict-aliasing enabled, unions are the only safe way to do type masquerading.
+
+static const union {
+ struct {
+ unsigned char NaN_Bytes[8];
+ unsigned char Inf_Bytes[8];
+ } bytes;
+
+ struct {
+ double NaN_Double;
+ double Inf_Double;
+ } doubles;
+
+} NaNInf = { {
+#if PLATFORM(BIG_ENDIAN)
+ { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 },
+ { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
+#elif PLATFORM(MIDDLE_ENDIAN)
+ { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 },
+ { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }
+#else
+ { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f },
+ { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
+#endif
+} } ;
+
+extern const double NaN = NaNInf.doubles.NaN_Double;
+extern const double Inf = NaNInf.doubles.Inf_Double;
+
+#endif // !(defined NAN && defined INFINITY)
+
+void* JSCell::operator new(size_t size, ExecState* exec)
+{
+#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return exec->heap()->inlineAllocate(size);
+#else
+ return exec->heap()->allocate(size);
+#endif
+}
+
+bool JSCell::getUInt32(uint32_t&) const
+{
+ return false;
+}
+
+bool JSCell::getTruncatedInt32(int32_t&) const
+{
+ return false;
+}
+
+bool JSCell::getTruncatedUInt32(uint32_t&) const
+{
+ return false;
+}
+
+bool JSCell::getNumber(double& numericValue) const
+{
+ if (!isNumber())
+ return false;
+ numericValue = static_cast<const JSNumberCell*>(this)->value();
+ return true;
+}
+
+double JSCell::getNumber() const
+{
+ return isNumber() ? static_cast<const JSNumberCell*>(this)->value() : NaN;
+}
+
+bool JSCell::getString(UString&stringValue) const
+{
+ if (!isString())
+ return false;
+ stringValue = static_cast<const JSString*>(this)->value();
+ return true;
+}
+
+UString JSCell::getString() const
+{
+ return isString() ? static_cast<const JSString*>(this)->value() : UString();
+}
+
+JSObject* JSCell::getObject()
+{
+ return isObject() ? static_cast<JSObject*>(this) : 0;
+}
+
+const JSObject* JSCell::getObject() const
+{
+ return isObject() ? static_cast<const JSObject*>(this) : 0;
+}
+
+CallType JSCell::getCallData(CallData&)
+{
+ return CallTypeNone;
+}
+
+ConstructType JSCell::getConstructData(ConstructData&)
+{
+ return ConstructTypeNone;
+}
+
+bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot)
+{
+ // This is not a general purpose implementation of getOwnPropertySlot.
+ // It should only be called by JSValue::get.
+ // It calls getPropertySlot, not getOwnPropertySlot.
+ JSObject* object = toObject(exec);
+ slot.setBase(object);
+ if (!object->getPropertySlot(exec, identifier, slot))
+ slot.setUndefined();
+ return true;
+}
+
+bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot)
+{
+ // This is not a general purpose implementation of getOwnPropertySlot.
+ // It should only be called by JSValue::get.
+ // It calls getPropertySlot, not getOwnPropertySlot.
+ JSObject* object = toObject(exec);
+ slot.setBase(object);
+ if (!object->getPropertySlot(exec, identifier, slot))
+ slot.setUndefined();
+ return true;
+}
+
+void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue* value, PutPropertySlot& slot)
+{
+ toObject(exec)->put(exec, identifier, value, slot);
+}
+
+void JSCell::put(ExecState* exec, unsigned identifier, JSValue* value)
+{
+ toObject(exec)->put(exec, identifier, value);
+}
+
+bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier)
+{
+ return toObject(exec)->deleteProperty(exec, identifier);
+}
+
+bool JSCell::deleteProperty(ExecState* exec, unsigned identifier)
+{
+ return toObject(exec)->deleteProperty(exec, identifier);
+}
+
+JSObject* JSCell::toThisObject(ExecState* exec) const
+{
+ return toObject(exec);
+}
+
+UString JSCell::toThisString(ExecState* exec) const
+{
+ return toThisObject(exec)->toString(exec);
+}
+
+JSString* JSCell::toThisJSString(ExecState* exec)
+{
+ return jsString(exec, toThisString(exec));
+}
+
+const ClassInfo* JSCell::classInfo() const
+{
+ return 0;
+}
+
+JSValue* JSCell::getJSNumber()
+{
+ return noValue();
+}
+
+bool JSCell::isGetterSetter() const
+{
+ return false;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h
new file mode 100644
index 0000000..108dab6
--- /dev/null
+++ b/JavaScriptCore/runtime/JSCell.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSCell_h
+#define JSCell_h
+
+#include "StructureID.h"
+#include "JSValue.h"
+#include "collector.h"
+
+namespace JSC {
+
+ class JSCell : public JSValue {
+ friend class CTI;
+ friend class GetterSetter;
+ friend class Heap;
+ friend class JSNumberCell;
+ friend class JSObject;
+ friend class JSPropertyNameIterator;
+ friend class JSString;
+ friend class JSValue;
+ friend class Machine;
+
+ private:
+ explicit JSCell(StructureID*);
+ virtual ~JSCell();
+
+ public:
+ // Querying the type.
+ bool isNumber() const;
+ bool isString() const;
+ bool isObject() const;
+ virtual bool isGetterSetter() const;
+ virtual bool isObject(const ClassInfo*) const;
+
+ StructureID* structureID() const;
+
+ // Extracting the value.
+ bool getNumber(double&) const;
+ double getNumber() const; // NaN if not a number
+ bool getString(UString&) const;
+ UString getString() const; // null string if not a string
+ JSObject* getObject(); // NULL if not an object
+ const JSObject* getObject() const; // NULL if not an object
+
+ virtual CallType getCallData(CallData&);
+ virtual ConstructType getConstructData(ConstructData&);
+
+ // Extracting integer values.
+ virtual bool getUInt32(uint32_t&) const;
+ virtual bool getTruncatedInt32(int32_t&) const;
+ virtual bool getTruncatedUInt32(uint32_t&) const;
+
+ // Basic conversions.
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
+ virtual bool toBoolean(ExecState*) const = 0;
+ virtual double toNumber(ExecState*) const = 0;
+ virtual UString toString(ExecState*) const = 0;
+ virtual JSObject* toObject(ExecState*) const = 0;
+
+ // Garbage collection.
+ void* operator new(size_t, ExecState*);
+ void* operator new(size_t, JSGlobalData*);
+ void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
+ virtual void mark();
+ bool marked() const;
+
+ // Object operations, with the toObject operation included.
+ virtual const ClassInfo* classInfo() const;
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue*);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual UString toThisString(ExecState*) const;
+ virtual JSString* toThisJSString(ExecState*);
+ virtual JSValue* getJSNumber();
+ void* vptr() { return *reinterpret_cast<void**>(this); }
+
+ private:
+ // Base implementation; for non-object classes implements getPropertySlot.
+ bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ StructureID* m_structureID;
+ };
+
+ JSCell* asCell(JSValue*);
+
+ inline JSCell* asCell(JSValue* value)
+ {
+ ASSERT(!JSImmediate::isImmediate(value));
+ return static_cast<JSCell*>(value);
+ }
+
+ inline JSCell::JSCell(StructureID* structureID)
+ : m_structureID(structureID)
+ {
+ }
+
+ inline JSCell::~JSCell()
+ {
+ }
+
+ inline bool JSCell::isNumber() const
+ {
+ return Heap::isNumber(const_cast<JSCell*>(this));
+ }
+
+ inline bool JSCell::isObject() const
+ {
+ return m_structureID->typeInfo().type() == ObjectType;
+ }
+
+ inline bool JSCell::isString() const
+ {
+ return m_structureID->typeInfo().type() == StringType;
+ }
+
+ inline StructureID* JSCell::structureID() const
+ {
+ return m_structureID;
+ }
+
+ inline bool JSCell::marked() const
+ {
+ return Heap::isCellMarked(this);
+ }
+
+ inline void JSCell::mark()
+ {
+ return Heap::markCell(this);
+ }
+
+ ALWAYS_INLINE JSCell* JSValue::asCell() const
+ {
+ ASSERT(!JSImmediate::isImmediate(asValue()));
+ return reinterpret_cast<JSCell*>(const_cast<JSValue*>(this));
+ }
+
+ inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
+ {
+#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return globalData->heap.inlineAllocate(size);
+#else
+ return globalData->heap.allocate(size);
+#endif
+ }
+
+ // --- JSValue inlines ----------------------------
+
+ inline bool JSValue::isNumber() const
+ {
+ return JSImmediate::isNumber(asValue()) || (!JSImmediate::isImmediate(asValue()) && asCell()->isNumber());
+ }
+
+ inline bool JSValue::isString() const
+ {
+ return !JSImmediate::isImmediate(asValue()) && asCell()->isString();
+ }
+
+ inline bool JSValue::isGetterSetter() const
+ {
+ return !JSImmediate::isImmediate(asValue()) && asCell()->isGetterSetter();
+ }
+
+ inline bool JSValue::isObject() const
+ {
+ return !JSImmediate::isImmediate(asValue()) && asCell()->isObject();
+ }
+
+ inline double JSValue::getNumber() const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->getNumber();
+ }
+
+ inline bool JSValue::getString(UString& s) const
+ {
+ return !JSImmediate::isImmediate(asValue()) && asCell()->getString(s);
+ }
+
+ inline UString JSValue::getString() const
+ {
+ return JSImmediate::isImmediate(asValue()) ? UString() : asCell()->getString();
+ }
+
+ inline JSObject* JSValue::getObject() const
+ {
+ return JSImmediate::isImmediate(asValue()) ? 0 : asCell()->getObject();
+ }
+
+ inline CallType JSValue::getCallData(CallData& callData)
+ {
+ return JSImmediate::isImmediate(asValue()) ? CallTypeNone : asCell()->getCallData(callData);
+ }
+
+ inline ConstructType JSValue::getConstructData(ConstructData& constructData)
+ {
+ return JSImmediate::isImmediate(asValue()) ? ConstructTypeNone : asCell()->getConstructData(constructData);
+ }
+
+ ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::getUInt32(asValue(), v) : asCell()->getUInt32(v);
+ }
+
+ ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedInt32(asValue(), v) : asCell()->getTruncatedInt32(v);
+ }
+
+ inline bool JSValue::getTruncatedUInt32(uint32_t& v) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedUInt32(asValue(), v) : asCell()->getTruncatedUInt32(v);
+ }
+
+ inline void JSValue::mark()
+ {
+ asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells
+ }
+
+ inline bool JSValue::marked() const
+ {
+ return JSImmediate::isImmediate(asValue()) || asCell()->marked();
+ }
+
+ inline JSValue* JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? asValue() : asCell()->toPrimitive(exec, preferredType);
+ }
+
+ inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& value)
+ {
+ if (JSImmediate::isImmediate(asValue())) {
+ number = JSImmediate::toDouble(asValue());
+ value = asValue();
+ return true;
+ }
+ return asCell()->getPrimitiveNumber(exec, number, value);
+ }
+
+ inline bool JSValue::toBoolean(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toBoolean(asValue()) : asCell()->toBoolean(exec);
+ }
+
+ ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->toNumber(exec);
+ }
+
+ inline UString JSValue::toString(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toString(exec);
+ }
+
+ inline JSObject* JSValue::toObject(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toObject(asValue(), exec) : asCell()->toObject(exec);
+ }
+
+ inline JSObject* JSValue::toThisObject(ExecState* exec) const
+ {
+ if (UNLIKELY(JSImmediate::isImmediate(asValue())))
+ return JSImmediate::toObject(asValue(), exec);
+ return asCell()->toThisObject(exec);
+ }
+
+ inline bool JSValue::needsThisConversion() const
+ {
+ if (UNLIKELY(JSImmediate::isImmediate(asValue())))
+ return true;
+ return asCell()->structureID()->typeInfo().needsThisConversion();
+ }
+
+ inline UString JSValue::toThisString(ExecState* exec) const
+ {
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toThisString(exec);
+ }
+
+ inline JSValue* JSValue::getJSNumber()
+ {
+
+ return JSImmediate::isNumber(asValue()) ? asValue() : JSImmediate::isImmediate(asValue()) ? noValue() : asCell()->getJSNumber();
+ }
+
+} // namespace JSC
+
+#endif // JSCell_h
diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp
new file mode 100644
index 0000000..2973d2d
--- /dev/null
+++ b/JavaScriptCore/runtime/JSFunction.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSFunction.h"
+
+#include "CodeBlock.h"
+#include "CommonIdentifiers.h"
+#include "ExecState.h"
+#include "FunctionPrototype.h"
+#include "JSGlobalObject.h"
+#include "Machine.h"
+#include "ObjectPrototype.h"
+#include "Parser.h"
+#include "PropertyNameArray.h"
+#include "ScopeChainMark.h"
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSFunction);
+
+const ClassInfo JSFunction::info = { "Function", 0, 0, 0 };
+
+JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode)
+ : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name)
+ , m_body(body)
+ , m_scopeChain(scopeChainNode)
+{
+}
+
+JSFunction::~JSFunction()
+{
+#if ENABLE(CTI)
+ // JIT code for other functions may have had calls linked directly to the code for this function; these links
+ // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
+ // this memory is freed and may be reused (potentially for another, different JSFunction).
+ if (m_body.get() && m_body->isGenerated())
+ m_body->generatedByteCode().unlinkCallers();
+#endif
+}
+
+void JSFunction::mark()
+{
+ Base::mark();
+ m_body->mark();
+ m_scopeChain.mark();
+}
+
+CallType JSFunction::getCallData(CallData& callData)
+{
+ callData.js.functionBody = m_body.get();
+ callData.js.scopeChain = m_scopeChain.node();
+ return CallTypeJS;
+}
+
+JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args)
+{
+ return exec->machine()->execute(m_body.get(), exec, this, thisValue->toThisObject(exec), args, m_scopeChain.node(), exec->exceptionSlot());
+}
+
+JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ JSFunction* thisObj = asFunction(slot.slotBase());
+ return exec->machine()->retrieveArguments(exec, thisObj);
+}
+
+JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ JSFunction* thisObj = asFunction(slot.slotBase());
+ return exec->machine()->retrieveCaller(exec, thisObj);
+}
+
+JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ JSFunction* thisObj = asFunction(slot.slotBase());
+ return jsNumber(exec, thisObj->m_body->parameterCount());
+}
+
+bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().prototype) {
+ JSValue** location = getDirectLocation(propertyName);
+
+ if (!location) {
+ JSObject* prototype = new (exec) JSObject(m_scopeChain.globalObject()->emptyObjectStructure());
+ prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
+ putDirect(exec->propertyNames().prototype, prototype, DontDelete);
+ location = getDirectLocation(propertyName);
+ }
+
+ slot.setValueSlot(this, location, offsetForLocation(location));
+ }
+
+ if (propertyName == exec->propertyNames().arguments) {
+ slot.setCustom(this, argumentsGetter);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCustom(this, lengthGetter);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().caller) {
+ slot.setCustom(this, callerGetter);
+ return true;
+ }
+
+ return Base::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
+ return;
+ Base::put(exec, propertyName, value, slot);
+}
+
+bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
+ return false;
+ return Base::deleteProperty(exec, propertyName);
+}
+
+/* Returns the parameter name corresponding to the given index. eg:
+ * function f1(x, y, z): getParameterName(0) --> x
+ *
+ * If a name appears more than once, only the last index at which
+ * it appears associates with it. eg:
+ * function f2(x, x): getParameterName(0) --> null
+ */
+const Identifier& JSFunction::getParameterName(int index)
+{
+ const Identifier* parameters = m_body->parameters();
+
+ if (static_cast<size_t>(index) >= m_body->parameterCount())
+ return m_scopeChain.globalObject()->globalData()->propertyNames->nullIdentifier;
+
+ const Identifier& name = parameters[index];
+
+ // Are there any subsequent parameters with the same name?
+ size_t size = m_body->parameterCount();
+ for (size_t i = index + 1; i < size; ++i) {
+ if (parameters[i] == name)
+ return m_scopeChain.globalObject()->globalData()->propertyNames->nullIdentifier;
+ }
+
+ return name;
+}
+
+// ECMA 13.2.2 [[Construct]]
+ConstructType JSFunction::getConstructData(ConstructData& constructData)
+{
+ constructData.js.functionBody = m_body.get();
+ constructData.js.scopeChain = m_scopeChain.node();
+ return ConstructTypeJS;
+}
+
+JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
+{
+ StructureID* structure;
+ JSValue* prototype = get(exec, exec->propertyNames().prototype);
+ if (prototype->isObject())
+ structure = asObject(prototype)->inheritorID();
+ else
+ structure = exec->lexicalGlobalObject()->emptyObjectStructure();
+ JSObject* thisObj = new (exec) JSObject(structure);
+
+ JSValue* result = exec->machine()->execute(m_body.get(), exec, this, thisObj, args, m_scopeChain.node(), exec->exceptionSlot());
+ if (exec->hadException() || !result->isObject())
+ return thisObj;
+ return asObject(result);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSFunction.h b/JavaScriptCore/runtime/JSFunction.h
new file mode 100644
index 0000000..694a0f4
--- /dev/null
+++ b/JavaScriptCore/runtime/JSFunction.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSFunction_h
+#define JSFunction_h
+
+#include "InternalFunction.h"
+#include "JSVariableObject.h"
+#include "SymbolTable.h"
+#include "nodes.h"
+#include "JSObject.h"
+
+namespace JSC {
+
+ class FunctionBodyNode;
+ class FunctionPrototype;
+ class JSActivation;
+ class JSGlobalObject;
+
+ class JSFunction : public InternalFunction {
+ friend class CTI;
+ friend class Machine;
+
+ typedef InternalFunction Base;
+ JSFunction(PassRefPtr<JSC::StructureID> st) : InternalFunction(st), m_scopeChain(NoScopeChain()) {}
+ public:
+ JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);
+ ~JSFunction();
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+
+ JSObject* construct(ExecState*, const ArgList&);
+ JSValue* call(ExecState*, JSValue* thisValue, const ArgList&);
+
+ // Note: Returns a null identifier for any parameters that will never get set
+ // due to a later parameter with the same name.
+ const Identifier& getParameterName(int index);
+
+ void setScope(const ScopeChain& scopeChain) { m_scopeChain = scopeChain; }
+ ScopeChain& scope() { return m_scopeChain; }
+
+ virtual void mark();
+
+ static const ClassInfo info;
+
+ // FIXME: This should be private
+ RefPtr<FunctionBodyNode> m_body;
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+ }
+
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+
+ static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue* callerGetter(ExecState*, const Identifier&, const PropertySlot&);
+ static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
+
+ ScopeChain m_scopeChain;
+ };
+
+ JSFunction* asFunction(JSValue*);
+
+ inline JSFunction* asFunction(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&JSFunction::info));
+ return static_cast<JSFunction*>(asObject(value));
+ }
+
+} // namespace kJS
+
+#endif // JSFunction_h
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
new file mode 100644
index 0000000..8910679
--- /dev/null
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSGlobalData.h"
+
+#include "ArgList.h"
+#include "CommonIdentifiers.h"
+#include "JSActivation.h"
+#include "JSClassRef.h"
+#include "JSLock.h"
+#include "JSNotAnObject.h"
+#include "JSStaticScopeObject.h"
+#include "Machine.h"
+#include "Parser.h"
+#include "collector.h"
+#include "lexer.h"
+#include "lookup.h"
+#include "nodes.h"
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <wtf/Threading.h>
+#endif
+
+#if PLATFORM(MAC)
+#include "ProfilerServer.h"
+#endif
+
+using namespace WTF;
+
+namespace JSC {
+
+extern const HashTable arrayTable;
+extern const HashTable dateTable;
+extern const HashTable mathTable;
+extern const HashTable numberTable;
+extern const HashTable regExpTable;
+extern const HashTable regExpConstructorTable;
+extern const HashTable stringTable;
+
+JSGlobalData::JSGlobalData(bool isShared)
+ : machine(new Machine)
+ , exception(noValue())
+ , arrayTable(new HashTable(JSC::arrayTable))
+ , dateTable(new HashTable(JSC::dateTable))
+ , mathTable(new HashTable(JSC::mathTable))
+ , numberTable(new HashTable(JSC::numberTable))
+ , regExpTable(new HashTable(JSC::regExpTable))
+ , regExpConstructorTable(new HashTable(JSC::regExpConstructorTable))
+ , stringTable(new HashTable(JSC::stringTable))
+ , activationStructureID(JSActivation::createStructureID(jsNull()))
+ , interruptedExecutionErrorStructure(JSObject::createStructureID(jsNull()))
+ , staticScopeStructureID(JSStaticScopeObject::createStructureID(jsNull()))
+ , stringStructureID(JSString::createStructureID(jsNull()))
+ , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructureID(jsNull()))
+ , notAnObjectStructure(JSNotAnObject::createStructureID(jsNull()))
+ , numberStructureID(JSNumberCell::createStructureID(jsNull()))
+ , identifierTable(createIdentifierTable())
+ , propertyNames(new CommonIdentifiers(this))
+ , emptyList(new ArgList)
+ , newParserObjects(0)
+ , parserObjectExtraRefCounts(0)
+ , lexer(new Lexer(this))
+ , parser(new Parser)
+ , head(0)
+ , dynamicGlobalObject(0)
+ , isSharedInstance(isShared)
+ , clientData(0)
+ , heap(this)
+{
+#if PLATFORM(MAC)
+ startProfilerServerIfNeeded();
+#endif
+}
+
+JSGlobalData::~JSGlobalData()
+{
+ // By the time this is destroyed, heap.destroy() must already have been called.
+
+ delete machine;
+#ifndef NDEBUG
+ // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
+ machine = 0;
+#endif
+
+ arrayTable->deleteTable();
+ dateTable->deleteTable();
+ mathTable->deleteTable();
+ numberTable->deleteTable();
+ regExpTable->deleteTable();
+ regExpConstructorTable->deleteTable();
+ stringTable->deleteTable();
+ delete arrayTable;
+ delete dateTable;
+ delete mathTable;
+ delete numberTable;
+ delete regExpTable;
+ delete regExpConstructorTable;
+ delete stringTable;
+
+ delete parser;
+ delete lexer;
+
+ deleteAllValues(opaqueJSClassData);
+
+ delete emptyList;
+
+ delete propertyNames;
+ deleteIdentifierTable(identifierTable);
+
+ delete newParserObjects;
+ delete parserObjectExtraRefCounts;
+
+ delete clientData;
+}
+
+PassRefPtr<JSGlobalData> JSGlobalData::create()
+{
+ return adoptRef(new JSGlobalData);
+}
+
+PassRefPtr<JSGlobalData> JSGlobalData::createLeaked()
+{
+#ifndef NDEBUG
+ StructureID::startIgnoringLeaks();
+ RefPtr<JSGlobalData> data = create();
+ StructureID::stopIgnoringLeaks();
+ return data.release();
+#else
+ return create();
+#endif
+}
+
+bool JSGlobalData::sharedInstanceExists()
+{
+ return sharedInstanceInternal();
+}
+
+JSGlobalData& JSGlobalData::sharedInstance()
+{
+ JSGlobalData*& instance = sharedInstanceInternal();
+ if (!instance)
+ instance = new JSGlobalData(true);
+ return *instance;
+}
+
+JSGlobalData*& JSGlobalData::sharedInstanceInternal()
+{
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+ static JSGlobalData* sharedInstance;
+ return sharedInstance;
+}
+
+JSGlobalData::ClientData::~ClientData()
+{
+}
+
+}
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
new file mode 100644
index 0000000..3210149
--- /dev/null
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSGlobalData_h
+#define JSGlobalData_h
+
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include "collector.h"
+#include "SmallStrings.h"
+
+struct OpaqueJSClass;
+struct OpaqueJSClassContextData;
+
+namespace JSC {
+
+ class ArgList;
+ class CommonIdentifiers;
+ class Heap;
+ class IdentifierTable;
+ class JSGlobalObject;
+ class JSObject;
+ class Lexer;
+ class Machine;
+ class Parser;
+ class ParserRefCounted;
+ class StructureID;
+ class UString;
+ struct HashTable;
+
+ class JSGlobalData : public RefCounted<JSGlobalData> {
+ public:
+ static bool sharedInstanceExists();
+ static JSGlobalData& sharedInstance();
+
+ static PassRefPtr<JSGlobalData> create();
+ static PassRefPtr<JSGlobalData> createLeaked();
+ ~JSGlobalData();
+
+ Machine* machine;
+
+ JSValue* exception;
+#if ENABLE(CTI)
+ void* throwReturnAddress;
+#endif
+
+ const HashTable* arrayTable;
+ const HashTable* dateTable;
+ const HashTable* mathTable;
+ const HashTable* numberTable;
+ const HashTable* regExpTable;
+ const HashTable* regExpConstructorTable;
+ const HashTable* stringTable;
+
+ RefPtr<StructureID> activationStructureID;
+ RefPtr<StructureID> interruptedExecutionErrorStructure;
+ RefPtr<StructureID> staticScopeStructureID;
+ RefPtr<StructureID> stringStructureID;
+ RefPtr<StructureID> notAnObjectErrorStubStructure;
+ RefPtr<StructureID> notAnObjectStructure;
+ RefPtr<StructureID> numberStructureID;
+
+ IdentifierTable* identifierTable;
+ CommonIdentifiers* propertyNames;
+ const ArgList* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
+
+ SmallStrings smallStrings;
+
+ HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
+
+ HashSet<ParserRefCounted*>* newParserObjects;
+ HashCountedSet<ParserRefCounted*>* parserObjectExtraRefCounts;
+
+ Lexer* lexer;
+ Parser* parser;
+
+ JSGlobalObject* head;
+ JSGlobalObject* dynamicGlobalObject;
+
+ bool isSharedInstance;
+
+ struct ClientData {
+ virtual ~ClientData() = 0;
+ };
+
+ ClientData* clientData;
+
+ HashSet<JSObject*> arrayVisitedElements;
+
+ Heap heap;
+
+ private:
+ JSGlobalData(bool isShared = false);
+
+ static JSGlobalData*& sharedInstanceInternal();
+ };
+
+}
+
+#endif
diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp
new file mode 100644
index 0000000..89c32fd
--- /dev/null
+++ b/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSGlobalObject.h"
+
+#include "JSCallbackConstructor.h"
+#include "JSCallbackFunction.h"
+#include "JSCallbackObject.h"
+
+#include "Arguments.h"
+#include "ArrayConstructor.h"
+#include "ArrayPrototype.h"
+#include "BooleanConstructor.h"
+#include "BooleanPrototype.h"
+#include "CodeBlock.h"
+#include "DateConstructor.h"
+#include "DatePrototype.h"
+#include "ErrorConstructor.h"
+#include "ErrorPrototype.h"
+#include "FunctionConstructor.h"
+#include "FunctionPrototype.h"
+#include "GlobalEvalFunction.h"
+#include "JSGlobalObjectFunctions.h"
+#include "JSLock.h"
+#include "Machine.h"
+#include "MathObject.h"
+#include "NativeErrorConstructor.h"
+#include "NativeErrorPrototype.h"
+#include "NumberConstructor.h"
+#include "NumberPrototype.h"
+#include "ObjectConstructor.h"
+#include "ObjectPrototype.h"
+#include "Profiler.h"
+#include "PrototypeFunction.h"
+#include "RegExpConstructor.h"
+#include "RegExpMatchesArray.h"
+#include "RegExpObject.h"
+#include "RegExpPrototype.h"
+#include "ScopeChainMark.h"
+#include "StringConstructor.h"
+#include "StringPrototype.h"
+#include "Debugger.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSGlobalObject);
+
+// Default number of ticks before a timeout check should be done.
+static const int initialTickCountThreshold = 255;
+
+// Preferred number of milliseconds between each timeout check
+static const int preferredScriptCheckTimeInterval = 1000;
+
+static inline void markIfNeeded(JSValue* v)
+{
+ if (v && !v->marked())
+ v->mark();
+}
+
+static inline void markIfNeeded(const RefPtr<StructureID>& s)
+{
+ if (s)
+ s->mark();
+}
+
+JSGlobalObject::~JSGlobalObject()
+{
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+
+ if (d()->debugger)
+ d()->debugger->detach(this);
+
+ Profiler** profiler = Profiler::enabledProfilerReference();
+ if (UNLIKELY(*profiler != 0)) {
+ (*profiler)->stopProfiling(globalExec(), UString());
+ }
+
+ d()->next->d()->prev = d()->prev;
+ d()->prev->d()->next = d()->next;
+ JSGlobalObject*& headObject = head();
+ if (headObject == this)
+ headObject = d()->next;
+ if (headObject == this)
+ headObject = 0;
+
+ HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
+ for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+ (*it)->globalObject = 0;
+
+ RegisterFile& registerFile = globalData()->machine->registerFile();
+ if (registerFile.globalObject() == this) {
+ registerFile.setGlobalObject(0);
+ registerFile.setNumGlobals(0);
+ }
+ delete d();
+}
+
+void JSGlobalObject::init(JSObject* thisValue)
+{
+ ASSERT(JSLock::currentThreadIsHoldingLock());
+
+ d()->globalData = Heap::heap(this)->globalData();
+ d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), thisValue);
+
+ JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0, 0);
+
+ if (JSGlobalObject*& headObject = head()) {
+ d()->prev = headObject;
+ d()->next = headObject->d()->next;
+ headObject->d()->next->d()->prev = this;
+ headObject->d()->next = this;
+ } else
+ headObject = d()->next = d()->prev = this;
+
+ d()->recursion = 0;
+ d()->debugger = 0;
+
+ d()->profileGroup = 0;
+
+ reset(prototype());
+}
+
+void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (symbolTablePut(propertyName, value))
+ return;
+ JSVariableObject::put(exec, propertyName, value, slot);
+}
+
+void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue* value, unsigned attributes)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ JSValue* valueBefore = getDirect(propertyName);
+ PutPropertySlot slot;
+ JSVariableObject::put(exec, propertyName, value, slot);
+ if (!valueBefore) {
+ if (JSValue* valueAfter = getDirect(propertyName))
+ putDirect(propertyName, valueAfter, attributes);
+ }
+}
+
+void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc)
+{
+ PropertySlot slot;
+ if (!symbolTableGet(propertyName, slot))
+ JSVariableObject::defineGetter(exec, propertyName, getterFunc);
+}
+
+void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc)
+{
+ PropertySlot slot;
+ if (!symbolTableGet(propertyName, slot))
+ JSVariableObject::defineSetter(exec, propertyName, setterFunc);
+}
+
+static inline JSObject* lastInPrototypeChain(JSObject* object)
+{
+ JSObject* o = object;
+ while (o->prototype()->isObject())
+ o = asObject(o->prototype());
+ return o;
+}
+
+void JSGlobalObject::reset(JSValue* prototype)
+{
+ ExecState* exec = JSGlobalObject::globalExec();
+
+ // Prototypes
+
+ d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructureID(jsNull())); // The real prototype will be set once ObjectPrototype is created.
+ d()->prototypeFunctionStructure = PrototypeFunction::createStructureID(d()->functionPrototype);
+ d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get());
+ d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructureID(jsNull()), d()->prototypeFunctionStructure.get());
+ d()->functionPrototype->structureID()->setPrototypeWithoutTransition(d()->objectPrototype);
+
+ d()->emptyObjectStructure = d()->objectPrototype->inheritorID();
+
+ d()->functionStructure = JSFunction::createStructureID(d()->functionPrototype);
+ d()->callbackFunctionStructure = JSCallbackFunction::createStructureID(d()->functionPrototype);
+ d()->argumentsStructure = Arguments::createStructureID(d()->objectPrototype);
+ d()->callbackConstructorStructure = JSCallbackConstructor::createStructureID(d()->objectPrototype);
+ d()->callbackObjectStructure = JSCallbackObject<JSObject>::createStructureID(d()->objectPrototype);
+
+ d()->arrayPrototype = new (exec) ArrayPrototype(ArrayPrototype::createStructureID(d()->objectPrototype));
+ d()->arrayStructure = JSArray::createStructureID(d()->arrayPrototype);
+ d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructureID(d()->arrayPrototype);
+
+ d()->stringPrototype = new (exec) StringPrototype(exec, StringPrototype::createStructureID(d()->objectPrototype));
+ d()->stringObjectStructure = StringObject::createStructureID(d()->stringPrototype);
+
+ d()->booleanPrototype = new (exec) BooleanPrototype(exec, BooleanPrototype::createStructureID(d()->objectPrototype), d()->prototypeFunctionStructure.get());
+ d()->booleanObjectStructure = BooleanObject::createStructureID(d()->booleanPrototype);
+
+ d()->numberPrototype = new (exec) NumberPrototype(exec, NumberPrototype::createStructureID(d()->objectPrototype), d()->prototypeFunctionStructure.get());
+ d()->numberObjectStructure = NumberObject::createStructureID(d()->numberPrototype);
+
+ d()->datePrototype = new (exec) DatePrototype(exec, DatePrototype::createStructureID(d()->objectPrototype));
+ d()->dateStructure = DateInstance::createStructureID(d()->datePrototype);
+
+ d()->regExpPrototype = new (exec) RegExpPrototype(exec, RegExpPrototype::createStructureID(d()->objectPrototype), d()->prototypeFunctionStructure.get());
+ d()->regExpStructure = RegExpObject::createStructureID(d()->regExpPrototype);
+
+ ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructureID(d()->objectPrototype), d()->prototypeFunctionStructure.get());
+ d()->errorStructure = ErrorInstance::createStructureID(errorPrototype);
+
+ RefPtr<StructureID> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructureID(errorPrototype);
+
+ NativeErrorPrototype* evalErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "EvalError", "EvalError");
+ NativeErrorPrototype* rangeErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "RangeError", "RangeError");
+ NativeErrorPrototype* referenceErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "ReferenceError", "ReferenceError");
+ NativeErrorPrototype* syntaxErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "SyntaxError", "SyntaxError");
+ NativeErrorPrototype* typeErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "TypeError", "TypeError");
+ NativeErrorPrototype* URIErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "URIError", "URIError");
+
+ // Constructors
+
+ JSValue* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructureID(d()->functionPrototype), d()->objectPrototype);
+ JSValue* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructureID(d()->functionPrototype), d()->functionPrototype);
+ JSValue* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructureID(d()->functionPrototype), d()->arrayPrototype);
+ JSValue* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructureID(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
+ JSValue* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructureID(d()->functionPrototype), d()->booleanPrototype);
+ JSValue* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructureID(d()->functionPrototype), d()->numberPrototype);
+ JSValue* dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructureID(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype);
+
+ d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructureID(d()->functionPrototype), d()->regExpPrototype);
+
+ d()->errorConstructor = new (exec) ErrorConstructor(exec, ErrorConstructor::createStructureID(d()->functionPrototype), errorPrototype);
+
+ RefPtr<StructureID> nativeErrorStructure = NativeErrorConstructor::createStructureID(d()->functionPrototype);
+
+ d()->evalErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, evalErrorPrototype);
+ d()->rangeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, rangeErrorPrototype);
+ d()->referenceErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, referenceErrorPrototype);
+ d()->syntaxErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, syntaxErrorPrototype);
+ d()->typeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, typeErrorPrototype);
+ d()->URIErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, URIErrorPrototype);
+
+ d()->objectPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum);
+ d()->functionPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum);
+ d()->arrayPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum);
+ d()->booleanPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum);
+ d()->stringPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum);
+ d()->numberPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum);
+ d()->datePrototype->putDirectWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum);
+ d()->regExpPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum);
+ errorPrototype->putDirectWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum);
+
+ evalErrorPrototype->putDirect(exec->propertyNames().constructor, d()->evalErrorConstructor, DontEnum);
+ rangeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->rangeErrorConstructor, DontEnum);
+ referenceErrorPrototype->putDirect(exec->propertyNames().constructor, d()->referenceErrorConstructor, DontEnum);
+ syntaxErrorPrototype->putDirect(exec->propertyNames().constructor, d()->syntaxErrorConstructor, DontEnum);
+ typeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->typeErrorConstructor, DontEnum);
+ URIErrorPrototype->putDirect(exec->propertyNames().constructor, d()->URIErrorConstructor, DontEnum);
+
+ // Set global constructors
+
+ // FIXME: These properties could be handled by a static hash table.
+
+ putDirectWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum);
+ putDirectWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor);
+ putDirectWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor);
+
+ // Set global values.
+ GlobalPropertyInfo staticGlobals[] = {
+ GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, MathObject::createStructureID(d()->objectPrototype)), DontEnum | DontDelete),
+ GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(exec), DontEnum | DontDelete),
+ GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(exec, Inf), DontEnum | DontDelete),
+ GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete)
+ };
+
+ addStaticGlobals(staticGlobals, sizeof(staticGlobals) / sizeof(GlobalPropertyInfo));
+
+ // Set global functions.
+
+ d()->evalFunction = new (exec) GlobalEvalFunction(exec, GlobalEvalFunction::createStructureID(d()->functionPrototype), 1, exec->propertyNames().eval, globalFuncEval, this);
+ putDirectFunctionWithoutTransition(exec, d()->evalFunction, DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum);
+#ifndef NDEBUG
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "kjsprint"), globalFuncKJSPrint), DontEnum);
+#endif
+
+ resetPrototype(prototype);
+}
+
+// Set prototype, and also insert the object prototype at the end of the chain.
+void JSGlobalObject::resetPrototype(JSValue* prototype)
+{
+ setPrototype(prototype);
+ lastInPrototypeChain(this)->setPrototype(d()->objectPrototype);
+}
+
+void JSGlobalObject::setTimeoutTime(unsigned timeoutTime)
+{
+ globalData()->machine->setTimeoutTime(timeoutTime);
+}
+
+void JSGlobalObject::startTimeoutCheck()
+{
+ globalData()->machine->startTimeoutCheck();
+}
+
+void JSGlobalObject::stopTimeoutCheck()
+{
+ globalData()->machine->stopTimeoutCheck();
+}
+
+void JSGlobalObject::mark()
+{
+ JSVariableObject::mark();
+
+ HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
+ for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+ (*it)->mark();
+
+ RegisterFile& registerFile = globalData()->machine->registerFile();
+ if (registerFile.globalObject() == this)
+ registerFile.markGlobals(&globalData()->heap);
+
+ markIfNeeded(d()->regExpConstructor);
+ markIfNeeded(d()->errorConstructor);
+ markIfNeeded(d()->evalErrorConstructor);
+ markIfNeeded(d()->rangeErrorConstructor);
+ markIfNeeded(d()->referenceErrorConstructor);
+ markIfNeeded(d()->syntaxErrorConstructor);
+ markIfNeeded(d()->typeErrorConstructor);
+ markIfNeeded(d()->URIErrorConstructor);
+
+ markIfNeeded(d()->evalFunction);
+
+ markIfNeeded(d()->objectPrototype);
+ markIfNeeded(d()->functionPrototype);
+ markIfNeeded(d()->arrayPrototype);
+ markIfNeeded(d()->booleanPrototype);
+ markIfNeeded(d()->stringPrototype);
+ markIfNeeded(d()->numberPrototype);
+ markIfNeeded(d()->datePrototype);
+ markIfNeeded(d()->regExpPrototype);
+
+ markIfNeeded(d()->errorStructure);
+
+ // No need to mark the other structures, because their prototypes are all
+ // guaranteed to be referenced elsewhere.
+
+ Register* registerArray = d()->registerArray.get();
+ if (!registerArray)
+ return;
+
+ size_t size = d()->registerArraySize;
+ for (size_t i = 0; i < size; ++i) {
+ Register& r = registerArray[i];
+ if (!r.marked())
+ r.mark();
+ }
+}
+
+void JSGlobalObject::markCrossHeapDependentObjects()
+{
+ // Overridden by subclasses.
+}
+
+JSGlobalObject* JSGlobalObject::toGlobalObject(ExecState*) const
+{
+ return const_cast<JSGlobalObject*>(this);
+}
+
+ExecState* JSGlobalObject::globalExec()
+{
+ return CallFrame::create(d()->globalCallFrame + RegisterFile::CallFrameHeaderSize);
+}
+
+bool JSGlobalObject::isDynamicScope() const
+{
+ return true;
+}
+
+void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
+{
+ ASSERT(!d()->registerArray);
+ ASSERT(!d()->registerArraySize);
+
+ int numGlobals = registerFile.numGlobals();
+ if (!numGlobals) {
+ d()->registers = 0;
+ return;
+ }
+
+ Register* registerArray = copyRegisterArray(registerFile.lastGlobal(), numGlobals);
+ setRegisters(registerArray + numGlobals, registerArray, numGlobals);
+}
+
+void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
+{
+ JSGlobalObject* lastGlobalObject = registerFile.globalObject();
+ if (lastGlobalObject && lastGlobalObject != this)
+ lastGlobalObject->copyGlobalsFrom(registerFile);
+
+ registerFile.setGlobalObject(this);
+ registerFile.setNumGlobals(symbolTable().size());
+
+ if (d()->registerArray) {
+ memcpy(registerFile.start() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(Register));
+ setRegisters(registerFile.start(), 0, 0);
+ }
+}
+
+void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
+{
+#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return globalData->heap.inlineAllocate(size);
+#else
+ return globalData->heap.allocate(size);
+#endif
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h
new file mode 100644
index 0000000..d8a072a
--- /dev/null
+++ b/JavaScriptCore/runtime/JSGlobalObject.h
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSGlobalObject_h
+#define JSGlobalObject_h
+
+#include "JSGlobalData.h"
+#include "JSVariableObject.h"
+#include "NumberPrototype.h"
+#include "StringPrototype.h"
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+ class ArrayPrototype;
+ class BooleanPrototype;
+ class DatePrototype;
+ class Debugger;
+ class ErrorConstructor;
+ class FunctionPrototype;
+ class GlobalEvalFunction;
+ class NativeErrorConstructor;
+ class ProgramCodeBlock;
+ class RegExpConstructor;
+ class RegExpPrototype;
+ class RegisterFile;
+
+ struct ActivationStackNode;
+ struct HashTable;
+
+ typedef Vector<ExecState*, 16> ExecStateStack;
+
+ class JSGlobalObject : public JSVariableObject {
+ protected:
+ using JSVariableObject::JSVariableObjectData;
+
+ struct JSGlobalObjectData : public JSVariableObjectData {
+ JSGlobalObjectData()
+ : JSVariableObjectData(&symbolTable, 0)
+ , registerArraySize(0)
+ , globalScopeChain(NoScopeChain())
+ , regExpConstructor(0)
+ , errorConstructor(0)
+ , evalErrorConstructor(0)
+ , rangeErrorConstructor(0)
+ , referenceErrorConstructor(0)
+ , syntaxErrorConstructor(0)
+ , typeErrorConstructor(0)
+ , URIErrorConstructor(0)
+ , evalFunction(0)
+ , objectPrototype(0)
+ , functionPrototype(0)
+ , arrayPrototype(0)
+ , booleanPrototype(0)
+ , stringPrototype(0)
+ , numberPrototype(0)
+ , datePrototype(0)
+ , regExpPrototype(0)
+ {
+ }
+
+ virtual ~JSGlobalObjectData()
+ {
+ }
+
+ size_t registerArraySize;
+
+ JSGlobalObject* next;
+ JSGlobalObject* prev;
+
+ Debugger* debugger;
+
+ ScopeChain globalScopeChain;
+ Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
+
+ int recursion;
+
+ RegExpConstructor* regExpConstructor;
+ ErrorConstructor* errorConstructor;
+ NativeErrorConstructor* evalErrorConstructor;
+ NativeErrorConstructor* rangeErrorConstructor;
+ NativeErrorConstructor* referenceErrorConstructor;
+ NativeErrorConstructor* syntaxErrorConstructor;
+ NativeErrorConstructor* typeErrorConstructor;
+ NativeErrorConstructor* URIErrorConstructor;
+
+ GlobalEvalFunction* evalFunction;
+
+ ObjectPrototype* objectPrototype;
+ FunctionPrototype* functionPrototype;
+ ArrayPrototype* arrayPrototype;
+ BooleanPrototype* booleanPrototype;
+ StringPrototype* stringPrototype;
+ NumberPrototype* numberPrototype;
+ DatePrototype* datePrototype;
+ RegExpPrototype* regExpPrototype;
+
+ RefPtr<StructureID> argumentsStructure;
+ RefPtr<StructureID> arrayStructure;
+ RefPtr<StructureID> booleanObjectStructure;
+ RefPtr<StructureID> callbackConstructorStructure;
+ RefPtr<StructureID> callbackFunctionStructure;
+ RefPtr<StructureID> callbackObjectStructure;
+ RefPtr<StructureID> dateStructure;
+ RefPtr<StructureID> emptyObjectStructure;
+ RefPtr<StructureID> errorStructure;
+ RefPtr<StructureID> functionStructure;
+ RefPtr<StructureID> numberObjectStructure;
+ RefPtr<StructureID> prototypeFunctionStructure;
+ RefPtr<StructureID> regExpMatchesArrayStructure;
+ RefPtr<StructureID> regExpStructure;
+ RefPtr<StructureID> stringObjectStructure;
+
+ SymbolTable symbolTable;
+ unsigned profileGroup;
+
+ RefPtr<JSGlobalData> globalData;
+
+ HashSet<ProgramCodeBlock*> codeBlocks;
+ };
+
+ public:
+ void* operator new(size_t, JSGlobalData*);
+
+ explicit JSGlobalObject()
+ : JSVariableObject(JSGlobalObject::createStructureID(jsNull()), new JSGlobalObjectData)
+ {
+ init(this);
+ }
+
+ protected:
+ JSGlobalObject(PassRefPtr<StructureID> structure, JSGlobalObjectData* data, JSObject* thisValue)
+ : JSVariableObject(structure, data)
+ {
+ init(thisValue);
+ }
+
+ public:
+ virtual ~JSGlobalObject();
+
+ virtual void mark();
+ virtual void markCrossHeapDependentObjects();
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
+ virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&);
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes);
+
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
+
+ // Linked list of all global objects that use the same JSGlobalData.
+ JSGlobalObject*& head() { return d()->globalData->head; }
+ JSGlobalObject* next() { return d()->next; }
+
+ // The following accessors return pristine values, even if a script
+ // replaces the global object's associated property.
+
+ RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; }
+
+ ErrorConstructor* errorConstructor() const { return d()->errorConstructor; }
+ NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor; }
+ NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor; }
+ NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor; }
+ NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; }
+ NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor; }
+ NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor; }
+
+ GlobalEvalFunction* evalFunction() const { return d()->evalFunction; }
+
+ ObjectPrototype* objectPrototype() const { return d()->objectPrototype; }
+ FunctionPrototype* functionPrototype() const { return d()->functionPrototype; }
+ ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; }
+ BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; }
+ StringPrototype* stringPrototype() const { return d()->stringPrototype; }
+ NumberPrototype* numberPrototype() const { return d()->numberPrototype; }
+ DatePrototype* datePrototype() const { return d()->datePrototype; }
+ RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
+
+ StructureID* argumentsStructure() const { return d()->argumentsStructure.get(); }
+ StructureID* arrayStructure() const { return d()->arrayStructure.get(); }
+ StructureID* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); }
+ StructureID* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); }
+ StructureID* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); }
+ StructureID* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); }
+ StructureID* dateStructure() const { return d()->dateStructure.get(); }
+ StructureID* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); }
+ StructureID* errorStructure() const { return d()->errorStructure.get(); }
+ StructureID* functionStructure() const { return d()->functionStructure.get(); }
+ StructureID* numberObjectStructure() const { return d()->numberObjectStructure.get(); }
+ StructureID* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); }
+ StructureID* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); }
+ StructureID* regExpStructure() const { return d()->regExpStructure.get(); }
+ StructureID* stringObjectStructure() const { return d()->stringObjectStructure.get(); }
+
+ void setProfileGroup(unsigned value) { d()->profileGroup = value; }
+ unsigned profileGroup() const { return d()->profileGroup; }
+
+ void setTimeoutTime(unsigned timeoutTime);
+ void startTimeoutCheck();
+ void stopTimeoutCheck();
+
+ Debugger* debugger() const { return d()->debugger; }
+ void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
+
+ virtual bool supportsProfiling() const { return false; }
+
+ int recursion() { return d()->recursion; }
+ void incRecursion() { ++d()->recursion; }
+ void decRecursion() { --d()->recursion; }
+
+ ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
+
+ virtual bool isGlobalObject() const { return true; }
+ virtual JSGlobalObject* toGlobalObject(ExecState*) const;
+
+ virtual ExecState* globalExec();
+
+ virtual bool shouldInterruptScript() const { return true; }
+
+ virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
+
+ virtual bool isDynamicScope() const;
+
+ HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
+
+ void copyGlobalsFrom(RegisterFile&);
+ void copyGlobalsTo(RegisterFile&);
+
+ void resetPrototype(JSValue* prototype);
+
+ JSGlobalData* globalData() { return d()->globalData.get(); }
+ JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+ protected:
+ struct GlobalPropertyInfo {
+ GlobalPropertyInfo(const Identifier& i, JSValue* v, unsigned a)
+ : identifier(i)
+ , value(v)
+ , attributes(a)
+ {
+ }
+
+ const Identifier identifier;
+ JSValue* value;
+ unsigned attributes;
+ };
+ void addStaticGlobals(GlobalPropertyInfo*, int count);
+
+ private:
+ // FIXME: Fold reset into init.
+ void init(JSObject* thisValue);
+ void reset(JSValue* prototype);
+
+ void setRegisters(Register* registers, Register* registerArray, size_t count);
+
+ void* operator new(size_t); // can only be allocated with JSGlobalData
+ };
+
+ JSGlobalObject* asGlobalObject(JSValue*);
+
+ inline JSGlobalObject* asGlobalObject(JSValue* value)
+ {
+ ASSERT(asObject(value)->isGlobalObject());
+ return static_cast<JSGlobalObject*>(asObject(value));
+ }
+
+ inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count)
+ {
+ JSVariableObject::setRegisters(registers, registerArray);
+ d()->registerArraySize = count;
+ }
+
+ inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
+ {
+ size_t oldSize = d()->registerArraySize;
+ size_t newSize = oldSize + count;
+ Register* registerArray = new Register[newSize];
+ if (d()->registerArray)
+ memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
+ setRegisters(registerArray + newSize, registerArray, newSize);
+
+ for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
+ GlobalPropertyInfo& global = globals[i];
+ ASSERT(global.attributes & DontDelete);
+ SymbolTableEntry newEntry(index, global.attributes);
+ symbolTable().add(global.identifier.ustring().rep(), newEntry);
+ registerAt(index) = global.value;
+ }
+ }
+
+ inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ {
+ if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ return symbolTableGet(propertyName, slot);
+ }
+
+ inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+ {
+ if (JSVariableObject::getOwnPropertySlotForWrite(exec, propertyName, slot, slotIsWriteable))
+ return true;
+ return symbolTableGet(propertyName, slot, slotIsWriteable);
+ }
+
+ inline JSGlobalObject* ScopeChainNode::globalObject() const
+ {
+ const ScopeChainNode* n = this;
+ while (n->next)
+ n = n->next;
+ return asGlobalObject(n->object);
+ }
+
+ inline JSValue* StructureID::prototypeForLookup(ExecState* exec)
+ {
+ if (typeInfo().type() == ObjectType)
+ return m_prototype;
+
+ if (typeInfo().type() == StringType)
+ return exec->lexicalGlobalObject()->stringPrototype();
+
+ ASSERT(typeInfo().type() == NumberType);
+ return exec->lexicalGlobalObject()->numberPrototype();
+ }
+
+ inline JSGlobalObject* ExecState::dynamicGlobalObject()
+ {
+ if (this == lexicalGlobalObject()->globalExec())
+ return lexicalGlobalObject();
+
+ // For any ExecState that's not a globalExec, the
+ // dynamic global object must be set since code is running
+ ASSERT(globalData().dynamicGlobalObject);
+ return globalData().dynamicGlobalObject;
+ }
+
+} // namespace JSC
+
+#endif // JSGlobalObject_h
diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
new file mode 100644
index 0000000..8bb1c6b
--- /dev/null
+++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSGlobalObjectFunctions.h"
+
+#include "ExecState.h"
+#include "GlobalEvalFunction.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "Machine.h"
+#include "Parser.h"
+#include "dtoa.h"
+#include "lexer.h"
+#include "nodes.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/unicode/UTF8.h>
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace JSC {
+
+static JSValue* encode(ExecState* exec, const ArgList& args, const char* doNotEscape)
+{
+ UString str = args.at(exec, 0)->toString(exec);
+ CString cstr = str.UTF8String(true);
+ if (!cstr.c_str())
+ return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");
+
+ UString result = "";
+ const char* p = cstr.c_str();
+ for (size_t k = 0; k < cstr.size(); k++, p++) {
+ char c = *p;
+ if (c && strchr(doNotEscape, c))
+ result.append(c);
+ else {
+ char tmp[4];
+ sprintf(tmp, "%%%02X", static_cast<unsigned char>(c));
+ result += tmp;
+ }
+ }
+ return jsString(exec, result);
+}
+
+static JSValue* decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict)
+{
+ UString result = "";
+ UString str = args.at(exec, 0)->toString(exec);
+ int k = 0;
+ int len = str.size();
+ const UChar* d = str.data();
+ UChar u = 0;
+ while (k < len) {
+ const UChar* p = d + k;
+ UChar c = *p;
+ if (c == '%') {
+ int charLen = 0;
+ if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
+ const char b0 = Lexer::convertHex(p[1], p[2]);
+ const int sequenceLen = UTF8SequenceLength(b0);
+ if (sequenceLen != 0 && k <= len - sequenceLen * 3) {
+ charLen = sequenceLen * 3;
+ char sequence[5];
+ sequence[0] = b0;
+ for (int i = 1; i < sequenceLen; ++i) {
+ const UChar* q = p + i * 3;
+ if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))
+ sequence[i] = Lexer::convertHex(q[1], q[2]);
+ else {
+ charLen = 0;
+ break;
+ }
+ }
+ if (charLen != 0) {
+ sequence[sequenceLen] = 0;
+ const int character = decodeUTF8Sequence(sequence);
+ if (character < 0 || character >= 0x110000)
+ charLen = 0;
+ else if (character >= 0x10000) {
+ // Convert to surrogate pair.
+ result.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10)));
+ u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF));
+ } else
+ u = static_cast<UChar>(character);
+ }
+ }
+ }
+ if (charLen == 0) {
+ if (strict)
+ return throwError(exec, URIError);
+ // The only case where we don't use "strict" mode is the "unescape" function.
+ // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.
+ if (k <= len - 6 && p[1] == 'u'
+ && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])
+ && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {
+ charLen = 6;
+ u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);
+ }
+ }
+ if (charLen && (u == 0 || u >= 128 || !strchr(doNotUnescape, u))) {
+ c = u;
+ k += charLen - 1;
+ }
+ }
+ k++;
+ result.append(c);
+ }
+ return jsString(exec, result);
+}
+
+bool isStrWhiteSpace(UChar c)
+{
+ switch (c) {
+ case 0x0009:
+ case 0x000A:
+ case 0x000B:
+ case 0x000C:
+ case 0x000D:
+ case 0x0020:
+ case 0x00A0:
+ case 0x2028:
+ case 0x2029:
+ return true;
+ default:
+ return c > 0xff && isSeparatorSpace(c);
+ }
+}
+
+static int parseDigit(unsigned short c, int radix)
+{
+ int digit = -1;
+
+ if (c >= '0' && c <= '9')
+ digit = c - '0';
+ else if (c >= 'A' && c <= 'Z')
+ digit = c - 'A' + 10;
+ else if (c >= 'a' && c <= 'z')
+ digit = c - 'a' + 10;
+
+ if (digit >= radix)
+ return -1;
+ return digit;
+}
+
+double parseIntOverflow(const char* s, int length, int radix)
+{
+ double number = 0.0;
+ double radixMultiplier = 1.0;
+
+ for (const char* p = s + length - 1; p >= s; p--) {
+ if (radixMultiplier == Inf) {
+ if (*p != '0') {
+ number = Inf;
+ break;
+ }
+ } else {
+ int digit = parseDigit(*p, radix);
+ number += digit * radixMultiplier;
+ }
+
+ radixMultiplier *= radix;
+ }
+
+ return number;
+}
+
+static double parseInt(const UString& s, int radix)
+{
+ int length = s.size();
+ const UChar* data = s.data();
+ int p = 0;
+
+ while (p < length && isStrWhiteSpace(data[p]))
+ ++p;
+
+ double sign = 1;
+ if (p < length) {
+ if (data[p] == '+')
+ ++p;
+ else if (data[p] == '-') {
+ sign = -1;
+ ++p;
+ }
+ }
+
+ if ((radix == 0 || radix == 16) && length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X')) {
+ radix = 16;
+ p += 2;
+ } else if (radix == 0) {
+ if (p < length && data[p] == '0')
+ radix = 8;
+ else
+ radix = 10;
+ }
+
+ if (radix < 2 || radix > 36)
+ return NaN;
+
+ int firstDigitPosition = p;
+ bool sawDigit = false;
+ double number = 0;
+ while (p < length) {
+ int digit = parseDigit(data[p], radix);
+ if (digit == -1)
+ break;
+ sawDigit = true;
+ number *= radix;
+ number += digit;
+ ++p;
+ }
+
+ if (number >= mantissaOverflowLowerBound) {
+ if (radix == 10)
+ number = strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);
+ else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
+ number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);
+ }
+
+ if (!sawDigit)
+ return NaN;
+
+ return sign * number;
+}
+
+static double parseFloat(const UString& s)
+{
+ // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.
+ // Need to skip any whitespace and then one + or - sign.
+ int length = s.size();
+ const UChar* data = s.data();
+ int p = 0;
+ while (p < length && isStrWhiteSpace(data[p]))
+ ++p;
+
+ if (p < length && (data[p] == '+' || data[p] == '-'))
+ ++p;
+
+ if (length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X'))
+ return 0;
+
+ return s.toDouble(true /*tolerant*/, false /* NaN for empty string */);
+}
+
+JSValue* globalFuncEval(ExecState* exec, JSObject* function, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObject = thisValue->toThisObject(exec);
+ JSGlobalObject* globalObject = thisObject->toGlobalObject(exec);
+ if (!globalObject || globalObject->evalFunction() != function)
+ return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");
+
+ JSValue* x = args.at(exec, 0);
+ if (!x->isString())
+ return x;
+
+ UString s = x->toString(exec);
+
+ int errLine;
+ UString errMsg;
+
+ SourceCode source = makeSource(s);
+ RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+
+ if (!evalNode)
+ return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL);
+
+ return exec->machine()->execute(evalNode.get(), exec, thisObject, globalObject->globalScopeChain().node(), exec->exceptionSlot());
+}
+
+JSValue* globalFuncParseInt(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ JSValue* value = args.at(exec, 0);
+ int32_t radix = args.at(exec, 1)->toInt32(exec);
+
+ if (value->isNumber() && (radix == 0 || radix == 10)) {
+ if (JSImmediate::isImmediate(value))
+ return value;
+ double d = value->uncheckedGetNumber();
+ if (!isfinite(d))
+ return JSImmediate::zeroImmediate();
+ return jsNumber(exec, floor(d));
+ }
+
+ return jsNumber(exec, parseInt(value->toString(exec), radix));
+}
+
+JSValue* globalFuncParseFloat(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, parseFloat(args.at(exec, 0)->toString(exec)));
+}
+
+JSValue* globalFuncIsNaN(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsBoolean(isnan(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* globalFuncIsFinite(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ double n = args.at(exec, 0)->toNumber(exec);
+ return jsBoolean(!isnan(n) && !isinf(n));
+}
+
+JSValue* globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ static const char do_not_unescape_when_decoding_URI[] =
+ "#$&+,/:;=?@";
+
+ return decode(exec, args, do_not_unescape_when_decoding_URI, true);
+}
+
+JSValue* globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return decode(exec, args, "", true);
+}
+
+JSValue* globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ static const char do_not_escape_when_encoding_URI[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "!#$&'()*+,-./:;=?@_~";
+
+ return encode(exec, args, do_not_escape_when_encoding_URI);
+}
+
+JSValue* globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ static const char do_not_escape_when_encoding_URI_component[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "!'()*-._~";
+
+ return encode(exec, args, do_not_escape_when_encoding_URI_component);
+}
+
+JSValue* globalFuncEscape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ static const char do_not_escape[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "*+-./@_";
+
+ UString result = "";
+ UString s;
+ UString str = args.at(exec, 0)->toString(exec);
+ const UChar* c = str.data();
+ for (int k = 0; k < str.size(); k++, c++) {
+ int u = c[0];
+ if (u > 255) {
+ char tmp[7];
+ sprintf(tmp, "%%u%04X", u);
+ s = UString(tmp);
+ } else if (u != 0 && strchr(do_not_escape, static_cast<char>(u)))
+ s = UString(c, 1);
+ else {
+ char tmp[4];
+ sprintf(tmp, "%%%02X", u);
+ s = UString(tmp);
+ }
+ result += s;
+ }
+
+ return jsString(exec, result);
+}
+
+JSValue* globalFuncUnescape(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ UString result = "";
+ UString str = args.at(exec, 0)->toString(exec);
+ int k = 0;
+ int len = str.size();
+ while (k < len) {
+ const UChar* c = str.data() + k;
+ UChar u;
+ if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
+ if (Lexer::isHexDigit(c[2]) && Lexer::isHexDigit(c[3]) && Lexer::isHexDigit(c[4]) && Lexer::isHexDigit(c[5])) {
+ u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);
+ c = &u;
+ k += 5;
+ }
+ } else if (c[0] == '%' && k <= len - 3 && Lexer::isHexDigit(c[1]) && Lexer::isHexDigit(c[2])) {
+ u = UChar(Lexer::convertHex(c[1], c[2]));
+ c = &u;
+ k += 2;
+ }
+ k++;
+ result.append(*c);
+ }
+
+ return jsString(exec, result);
+}
+
+#ifndef NDEBUG
+JSValue* globalFuncKJSPrint(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ CStringBuffer string;
+ args.at(exec, 0)->toString(exec).getCString(string);
+ puts(string.data());
+ return jsUndefined();
+}
+#endif
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.h b/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
new file mode 100644
index 0000000..8df700d
--- /dev/null
+++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSGlobalObjectFunctions_h
+#define JSGlobalObjectFunctions_h
+
+#include "JSImmediate.h" // temporary until JSValue* becomes a class we can forward-declare
+
+namespace JSC {
+
+ class ArgList;
+ class ExecState;
+ class JSObject;
+
+ // FIXME: These functions should really be in JSGlobalObject.cpp, but putting them there
+ // is a 0.5% reduction.
+
+ JSValue* globalFuncEval(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncParseInt(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncParseFloat(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncIsNaN(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncIsFinite(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncDecodeURI(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncEncodeURI(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncEscape(ExecState*, JSObject*, JSValue*, const ArgList&);
+ JSValue* globalFuncUnescape(ExecState*, JSObject*, JSValue*, const ArgList&);
+#ifndef NDEBUG
+ JSValue* globalFuncKJSPrint(ExecState*, JSObject*, JSValue*, const ArgList&);
+#endif
+
+ static const double mantissaOverflowLowerBound = 9007199254740992.0;
+ double parseIntOverflow(const char*, int length, int radix);
+
+} // namespace JSC
+
+#endif // JSGlobalObjectFunctions_h
diff --git a/JavaScriptCore/runtime/JSImmediate.cpp b/JavaScriptCore/runtime/JSImmediate.cpp
new file mode 100644
index 0000000..e70d66a
--- /dev/null
+++ b/JavaScriptCore/runtime/JSImmediate.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2003-2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSImmediate.h"
+
+#include "BooleanConstructor.h"
+#include "BooleanPrototype.h"
+#include "Error.h"
+#include "ExceptionHelpers.h"
+#include "JSGlobalObject.h"
+#include "JSNotAnObject.h"
+#include "NumberConstructor.h"
+#include "NumberPrototype.h"
+
+namespace JSC {
+
+JSObject* JSImmediate::toObject(JSValue* v, ExecState* exec)
+{
+ ASSERT(isImmediate(v));
+ if (isNumber(v))
+ return constructNumberFromImmediateNumber(exec, v);
+ if (isBoolean(v))
+ return constructBooleanFromImmediateBoolean(exec, v);
+
+ JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull());
+ exec->setException(exception);
+ return new (exec) JSNotAnObject(exec, exception);
+}
+
+JSObject* JSImmediate::prototype(JSValue* v, ExecState* exec)
+{
+ ASSERT(isImmediate(v));
+ if (isNumber(v))
+ return exec->lexicalGlobalObject()->numberPrototype();
+ if (isBoolean(v))
+ return exec->lexicalGlobalObject()->booleanPrototype();
+
+ JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v->isNull());
+ exec->setException(exception);
+ return new (exec) JSNotAnObject(exec, exception);
+}
+
+UString JSImmediate::toString(JSValue* v)
+{
+ ASSERT(isImmediate(v));
+ if (isNumber(v))
+ return UString::from(getTruncatedInt32(v));
+ if (v == jsBoolean(false))
+ return "false";
+ if (v == jsBoolean(true))
+ return "true";
+ if (v->isNull())
+ return "null";
+ ASSERT(v == jsUndefined());
+ return "undefined";
+}
+
+NEVER_INLINE double JSImmediate::nonInlineNaN()
+{
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h
new file mode 100644
index 0000000..5214df5
--- /dev/null
+++ b/JavaScriptCore/runtime/JSImmediate.h
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KJS_JS_IMMEDIATE_H
+#define KJS_JS_IMMEDIATE_H
+
+#include <wtf/Assertions.h>
+#include <wtf/AlwaysInline.h>
+#include <wtf/MathExtras.h>
+#include <limits>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+namespace JSC {
+
+ class ExecState;
+ class JSCell;
+ class JSObject;
+ class JSValue;
+ class UString;
+
+ inline JSValue* noValue() { return 0; }
+ inline void* asPointer(JSValue* value) { return value; }
+
+ /*
+ * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
+ * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
+ * because allocator alignment guarantees they will be 00 in cell pointers.
+ *
+ * For example, on a 32 bit system:
+ *
+ * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00
+ * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ]
+ * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT
+ * [ high 30 bits: 'payload' ] [ low 2 bits -- tag ]
+ *
+ * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
+ * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
+ * tag used to indicate the exact type.
+ *
+ * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
+ * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
+ * two bits will form an extended tag.
+ *
+ * 31 bit signed int: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X1
+ * [ high 30 bits of the value ] [ high bit part of value ]
+ * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY ZZ 10
+ * [ extended 'payload' ] [ extended tag ] [ tag 'other' ]
+ *
+ * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
+ * bit would flag the value as undefined. If neither bits are set, the value is null.
+ *
+ * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY UB 10
+ * [ extended 'payload' ] [ undefined | bool ] [ tag 'other' ]
+ *
+ * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
+ * For undefined or null immediates the payload is zero.
+ *
+ * Boolean: 000000000000000000000000000V 01 10
+ * [ boolean value ] [ bool ] [ tag 'other' ]
+ * Undefined: 0000000000000000000000000000 10 10
+ * [ zero ] [ undefined ] [ tag 'other' ]
+ * Null: 0000000000000000000000000000 00 10
+ * [ zero ] [ zero ] [ tag 'other' ]
+ */
+
+ class JSImmediate {
+ private:
+ friend class CTI; // Whooo!
+
+ static const uintptr_t TagMask = 0x3u; // primary tag is 2 bits long
+ static const uintptr_t TagBitTypeInteger = 0x1u; // bottom bit set indicates integer, this dominates the following bit
+ static const uintptr_t TagBitTypeOther = 0x2u; // second bit set indicates immediate other than an integer
+
+ static const uintptr_t ExtendedTagMask = 0xCu; // extended tag holds a further two bits
+ static const uintptr_t ExtendedTagBitBool = 0x4u;
+ static const uintptr_t ExtendedTagBitUndefined = 0x8u;
+
+ static const uintptr_t FullTagTypeMask = TagMask | ExtendedTagMask;
+ static const uintptr_t FullTagTypeBool = TagBitTypeOther | ExtendedTagBitBool;
+ static const uintptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
+ static const uintptr_t FullTagTypeNull = TagBitTypeOther;
+
+ static const uint32_t IntegerPayloadShift = 1u;
+ static const uint32_t ExtendedPayloadShift = 4u;
+
+ static const uintptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
+
+ public:
+ static ALWAYS_INLINE bool isImmediate(JSValue* v)
+ {
+ return rawValue(v) & TagMask;
+ }
+
+ static ALWAYS_INLINE bool isNumber(JSValue* v)
+ {
+ return rawValue(v) & TagBitTypeInteger;
+ }
+
+ static ALWAYS_INLINE bool isPositiveNumber(JSValue* v)
+ {
+ // A single mask to check for the sign bit and the number tag all at once.
+ return (rawValue(v) & (0x80000000 | TagBitTypeInteger)) == TagBitTypeInteger;
+ }
+
+ static ALWAYS_INLINE bool isBoolean(JSValue* v)
+ {
+ return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
+ }
+
+ static ALWAYS_INLINE bool isUndefinedOrNull(JSValue* v)
+ {
+ // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
+ return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
+ }
+
+ static bool isNegative(JSValue* v)
+ {
+ ASSERT(isNumber(v));
+ return rawValue(v) & 0x80000000;
+ }
+
+ static JSValue* from(char);
+ static JSValue* from(signed char);
+ static JSValue* from(unsigned char);
+ static JSValue* from(short);
+ static JSValue* from(unsigned short);
+ static JSValue* from(int);
+ static JSValue* from(unsigned);
+ static JSValue* from(long);
+ static JSValue* from(unsigned long);
+ static JSValue* from(long long);
+ static JSValue* from(unsigned long long);
+ static JSValue* from(double);
+
+ static ALWAYS_INLINE bool isEitherImmediate(JSValue* v1, JSValue* v2)
+ {
+ return (rawValue(v1) | rawValue(v2)) & TagMask;
+ }
+
+ static ALWAYS_INLINE bool isAnyImmediate(JSValue* v1, JSValue* v2, JSValue* v3)
+ {
+ return (rawValue(v1) | rawValue(v2) | rawValue(v3)) & TagMask;
+ }
+
+ static ALWAYS_INLINE bool areBothImmediate(JSValue* v1, JSValue* v2)
+ {
+ return isImmediate(v1) & isImmediate(v2);
+ }
+
+ static ALWAYS_INLINE bool areBothImmediateNumbers(JSValue* v1, JSValue* v2)
+ {
+ return rawValue(v1) & rawValue(v2) & TagBitTypeInteger;
+ }
+
+ static ALWAYS_INLINE JSValue* andImmediateNumbers(JSValue* v1, JSValue* v2)
+ {
+ ASSERT(areBothImmediateNumbers(v1, v2));
+ return makeValue(rawValue(v1) & rawValue(v2));
+ }
+
+ static ALWAYS_INLINE JSValue* xorImmediateNumbers(JSValue* v1, JSValue* v2)
+ {
+ ASSERT(areBothImmediateNumbers(v1, v2));
+ return makeValue((rawValue(v1) ^ rawValue(v2)) | TagBitTypeInteger);
+ }
+
+ static ALWAYS_INLINE JSValue* orImmediateNumbers(JSValue* v1, JSValue* v2)
+ {
+ ASSERT(areBothImmediateNumbers(v1, v2));
+ return makeValue(rawValue(v1) | rawValue(v2));
+ }
+
+ static ALWAYS_INLINE JSValue* rightShiftImmediateNumbers(JSValue* val, JSValue* shift)
+ {
+ ASSERT(areBothImmediateNumbers(val, shift));
+ return makeValue((static_cast<intptr_t>(rawValue(val)) >> ((rawValue(shift) >> IntegerPayloadShift) & 0x1f)) | TagBitTypeInteger);
+ }
+
+ static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue* v)
+ {
+ // Number is non-negative and an operation involving two of these can't overflow.
+ // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
+ return (rawValue(v) & (TagBitTypeInteger + (3u << 30))) == TagBitTypeInteger;
+ }
+
+ static ALWAYS_INLINE JSValue* addImmediateNumbers(JSValue* v1, JSValue* v2)
+ {
+ ASSERT(canDoFastAdditiveOperations(v1));
+ ASSERT(canDoFastAdditiveOperations(v2));
+ return makeValue(rawValue(v1) + rawValue(v2) - TagBitTypeInteger);
+ }
+
+ static ALWAYS_INLINE JSValue* subImmediateNumbers(JSValue* v1, JSValue* v2)
+ {
+ ASSERT(canDoFastAdditiveOperations(v1));
+ ASSERT(canDoFastAdditiveOperations(v2));
+ return makeValue(rawValue(v1) - rawValue(v2) + TagBitTypeInteger);
+ }
+
+ static ALWAYS_INLINE JSValue* incImmediateNumber(JSValue* v)
+ {
+ ASSERT(canDoFastAdditiveOperations(v));
+ return makeValue(rawValue(v) + (1 << IntegerPayloadShift));
+ }
+
+ static ALWAYS_INLINE JSValue* decImmediateNumber(JSValue* v)
+ {
+ ASSERT(canDoFastAdditiveOperations(v));
+ return makeValue(rawValue(v) - (1 << IntegerPayloadShift));
+ }
+
+ static double toDouble(JSValue*);
+ static bool toBoolean(JSValue*);
+ static JSObject* toObject(JSValue*, ExecState*);
+ static UString toString(JSValue*);
+
+ static bool getUInt32(JSValue*, uint32_t&);
+ static bool getTruncatedInt32(JSValue*, int32_t&);
+ static bool getTruncatedUInt32(JSValue*, uint32_t&);
+
+ static int32_t getTruncatedInt32(JSValue*);
+ static uint32_t getTruncatedUInt32(JSValue*);
+
+ static JSValue* trueImmediate();
+ static JSValue* falseImmediate();
+ static JSValue* undefinedImmediate();
+ static JSValue* nullImmediate();
+ static JSValue* zeroImmediate();
+ static JSValue* oneImmediate();
+
+ static JSValue* impossibleValue();
+
+ static JSObject* prototype(JSValue*, ExecState*);
+
+ private:
+ static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
+ static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
+ static const unsigned maxImmediateUInt = maxImmediateInt;
+
+ static ALWAYS_INLINE JSValue* makeValue(uintptr_t integer)
+ {
+ return reinterpret_cast<JSValue*>(integer);
+ }
+
+ static ALWAYS_INLINE JSValue* makeInt(int32_t value)
+ {
+ return makeValue((value << IntegerPayloadShift) | TagBitTypeInteger);
+ }
+
+ static ALWAYS_INLINE JSValue* makeBool(bool b)
+ {
+ return makeValue((static_cast<uintptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
+ }
+
+ static ALWAYS_INLINE JSValue* makeUndefined()
+ {
+ return makeValue(FullTagTypeUndefined);
+ }
+
+ static ALWAYS_INLINE JSValue* makeNull()
+ {
+ return makeValue(FullTagTypeNull);
+ }
+
+ static ALWAYS_INLINE int32_t intValue(JSValue* v)
+ {
+ return static_cast<int32_t>(static_cast<intptr_t>(rawValue(v)) >> IntegerPayloadShift);
+ }
+
+ static ALWAYS_INLINE uint32_t uintValue(JSValue* v)
+ {
+ return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
+ }
+
+ static ALWAYS_INLINE bool boolValue(JSValue* v)
+ {
+ return rawValue(v) & ExtendedPayloadBitBoolValue;
+ }
+
+ static ALWAYS_INLINE uintptr_t rawValue(JSValue* v)
+ {
+ return reinterpret_cast<uintptr_t>(v);
+ }
+
+ static double nonInlineNaN();
+ };
+
+ ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return makeBool(true); }
+ ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return makeBool(false); }
+ ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return makeUndefined(); }
+ ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return makeNull(); }
+ ALWAYS_INLINE JSValue* JSImmediate::zeroImmediate() { return makeInt(0); }
+ ALWAYS_INLINE JSValue* JSImmediate::oneImmediate() { return makeInt(1); }
+
+ // This value is impossible because 0x4 is not a valid pointer but a tag of 0 would indicate non-immediate
+ ALWAYS_INLINE JSValue* JSImmediate::impossibleValue() { return makeValue(0x4); }
+
+ ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue* v)
+ {
+ ASSERT(isImmediate(v));
+ uintptr_t bits = rawValue(v);
+ return (bits & TagBitTypeInteger)
+ ? bits != TagBitTypeInteger // !0 ints
+ : bits == (FullTagTypeBool | ExtendedPayloadBitBoolValue); // bool true
+ }
+
+ ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue* v)
+ {
+ ASSERT(isNumber(v));
+ return intValue(v);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(char i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(signed char i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(short i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i)
+ {
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(int i)
+ {
+ if ((i < minImmediateInt) | (i > maxImmediateInt))
+ return noValue();
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i)
+ {
+ if (i > maxImmediateUInt)
+ return noValue();
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(long i)
+ {
+ if ((i < minImmediateInt) | (i > maxImmediateInt))
+ return noValue();
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i)
+ {
+ if (i > maxImmediateUInt)
+ return noValue();
+ return makeInt(i);
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(long long i)
+ {
+ if ((i < minImmediateInt) | (i > maxImmediateInt))
+ return noValue();
+ return makeInt(static_cast<uintptr_t>(i));
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i)
+ {
+ if (i > maxImmediateUInt)
+ return noValue();
+ return makeInt(static_cast<uintptr_t>(i));
+ }
+
+ ALWAYS_INLINE JSValue* JSImmediate::from(double d)
+ {
+ const int intVal = static_cast<int>(d);
+
+ if ((intVal < minImmediateInt) | (intVal > maxImmediateInt))
+ return noValue();
+
+ // Check for data loss from conversion to int.
+ if (intVal != d || (!intVal && signbit(d)))
+ return noValue();
+
+ return makeInt(intVal);
+ }
+
+ ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue* v)
+ {
+ ASSERT(isNumber(v));
+ return intValue(v);
+ }
+
+ ALWAYS_INLINE double JSImmediate::toDouble(JSValue* v)
+ {
+ ASSERT(isImmediate(v));
+ int i;
+ if (isNumber(v))
+ i = intValue(v);
+ else if (rawValue(v) == FullTagTypeUndefined)
+ return nonInlineNaN();
+ else
+ i = rawValue(v) >> ExtendedPayloadShift;
+ return i;
+ }
+
+ ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue* v, uint32_t& i)
+ {
+ i = uintValue(v);
+ return isPositiveNumber(v);
+ }
+
+ ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue* v, int32_t& i)
+ {
+ i = intValue(v);
+ return isNumber(v);
+ }
+
+ ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue* v, uint32_t& i)
+ {
+ return getUInt32(v, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsUndefined()
+ {
+ return JSImmediate::undefinedImmediate();
+ }
+
+ inline JSValue* jsNull()
+ {
+ return JSImmediate::nullImmediate();
+ }
+
+ inline JSValue* jsBoolean(bool b)
+ {
+ return b ? JSImmediate::trueImmediate() : JSImmediate::falseImmediate();
+ }
+
+} // namespace JSC
+
+#endif
diff --git a/JavaScriptCore/runtime/JSLock.cpp b/JavaScriptCore/runtime/JSLock.cpp
new file mode 100644
index 0000000..ee7fb3b
--- /dev/null
+++ b/JavaScriptCore/runtime/JSLock.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
+ *
+ * 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 NU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA
+ *
+ */
+
+#include "config.h"
+#include "JSLock.h"
+
+#include "collector.h"
+#include "ExecState.h"
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <pthread.h>
+#endif
+
+namespace JSC {
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+// Acquire this mutex before accessing lock-related data.
+static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
+
+// Thread-specific key that tells whether a thread holds the JSMutex, and how many times it was taken recursively.
+pthread_key_t JSLockCount;
+
+static void createJSLockCount()
+{
+ pthread_key_create(&JSLockCount, 0);
+}
+
+pthread_once_t createJSLockCountOnce = PTHREAD_ONCE_INIT;
+
+// Lock nesting count.
+intptr_t JSLock::lockCount()
+{
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+
+ return reinterpret_cast<intptr_t>(pthread_getspecific(JSLockCount));
+}
+
+static void setLockCount(intptr_t count)
+{
+ ASSERT(count >= 0);
+ pthread_setspecific(JSLockCount, reinterpret_cast<void*>(count));
+}
+
+JSLock::JSLock(ExecState* exec)
+ : m_lockingForReal(exec->globalData().isSharedInstance)
+{
+ lock(m_lockingForReal);
+}
+
+void JSLock::lock(bool lockForReal)
+{
+#ifdef NDEBUG
+ // Locking "not for real" is a debug-only feature.
+ if (!lockForReal)
+ return;
+#endif
+
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+
+ intptr_t currentLockCount = lockCount();
+ if (!currentLockCount && lockForReal) {
+ int result;
+ result = pthread_mutex_lock(&JSMutex);
+ ASSERT(!result);
+ }
+ setLockCount(currentLockCount + 1);
+}
+
+void JSLock::unlock(bool lockForReal)
+{
+ ASSERT(lockCount());
+
+#ifdef NDEBUG
+ // Locking "not for real" is a debug-only feature.
+ if (!lockForReal)
+ return;
+#endif
+
+ intptr_t newLockCount = lockCount() - 1;
+ setLockCount(newLockCount);
+ if (!newLockCount && lockForReal) {
+ int result;
+ result = pthread_mutex_unlock(&JSMutex);
+ ASSERT(!result);
+ }
+}
+
+void JSLock::lock(ExecState* exec)
+{
+ lock(exec->globalData().isSharedInstance);
+}
+
+void JSLock::unlock(ExecState* exec)
+{
+ unlock(exec->globalData().isSharedInstance);
+}
+
+bool JSLock::currentThreadIsHoldingLock()
+{
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+ return !!pthread_getspecific(JSLockCount);
+}
+
+JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
+ : m_lockingForReal(exec->globalData().isSharedInstance)
+{
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+
+ m_lockCount = JSLock::lockCount();
+ for (intptr_t i = 0; i < m_lockCount; i++)
+ JSLock::unlock(m_lockingForReal);
+}
+
+JSLock::DropAllLocks::DropAllLocks(bool lockingForReal)
+ : m_lockingForReal(lockingForReal)
+{
+ pthread_once(&createJSLockCountOnce, createJSLockCount);
+
+ // It is necessary to drop even "unreal" locks, because having a non-zero lock count
+ // will prevent a real lock from being taken.
+
+ m_lockCount = JSLock::lockCount();
+ for (intptr_t i = 0; i < m_lockCount; i++)
+ JSLock::unlock(m_lockingForReal);
+}
+
+JSLock::DropAllLocks::~DropAllLocks()
+{
+ for (intptr_t i = 0; i < m_lockCount; i++)
+ JSLock::lock(m_lockingForReal);
+}
+
+#else
+
+JSLock::JSLock(ExecState*)
+ : m_lockingForReal(false)
+{
+}
+
+// If threading support is off, set the lock count to a constant value of 1 so ssertions
+// that the lock is held don't fail
+intptr_t JSLock::lockCount()
+{
+ return 1;
+}
+
+bool JSLock::currentThreadIsHoldingLock()
+{
+ return true;
+}
+
+void JSLock::lock(bool)
+{
+}
+
+void JSLock::unlock(bool)
+{
+}
+
+void JSLock::lock(ExecState*)
+{
+}
+
+void JSLock::unlock(ExecState*)
+{
+}
+
+JSLock::DropAllLocks::DropAllLocks(ExecState*)
+{
+}
+
+JSLock::DropAllLocks::DropAllLocks(bool)
+{
+}
+
+JSLock::DropAllLocks::~DropAllLocks()
+{
+}
+
+#endif // USE(MULTIPLE_THREADS)
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSLock.h b/JavaScriptCore/runtime/JSLock.h
new file mode 100644
index 0000000..0c22ff8
--- /dev/null
+++ b/JavaScriptCore/runtime/JSLock.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KJS_JSLock_h
+#define KJS_JSLock_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+ // To make it safe to use JavaScript on multiple threads, it is
+ // important to lock before doing anything that allocates a
+ // JavaScript data structure or that interacts with shared state
+ // such as the protect count hash table. The simplest way to lock
+ // is to create a local JSLock object in the scope where the lock
+ // must be held. The lock is recursive so nesting is ok. The JSLock
+ // object also acts as a convenience short-hand for running important
+ // initialization routines.
+
+ // To avoid deadlock, sometimes it is necessary to temporarily
+ // release the lock. Since it is recursive you actually have to
+ // release all locks held by your thread. This is safe to do if
+ // you are executing code that doesn't require the lock, and you
+ // reacquire the right number of locks at the end. You can do this
+ // by constructing a locally scoped JSLock::DropAllLocks object. The
+ // DropAllLocks object takes care to release the JSLock only if your
+ // thread acquired it to begin with.
+
+ // For contexts other than the single shared one, implicit locking is not done,
+ // but we still need to perform all the counting in order to keep debug
+ // assertions working, so that clients that use the shared context don't break.
+
+ class ExecState;
+
+ class JSLock : Noncopyable {
+ public:
+ JSLock(ExecState*);
+
+ JSLock(bool lockingForReal)
+ : m_lockingForReal(lockingForReal)
+ {
+#ifdef NDEBUG
+ // Locking "not for real" is a debug-only feature.
+ if (!lockingForReal)
+ return;
+#endif
+ lock(lockingForReal);
+ }
+
+ ~JSLock()
+ {
+#ifdef NDEBUG
+ // Locking "not for real" is a debug-only feature.
+ if (!m_lockingForReal)
+ return;
+#endif
+ unlock(m_lockingForReal);
+ }
+
+ static void lock(bool);
+ static void unlock(bool);
+ static void lock(ExecState*);
+ static void unlock(ExecState*);
+
+ static intptr_t lockCount();
+ static bool currentThreadIsHoldingLock();
+
+ bool m_lockingForReal;
+
+ class DropAllLocks : Noncopyable {
+ public:
+ DropAllLocks(ExecState* exec);
+ DropAllLocks(bool);
+ ~DropAllLocks();
+
+ private:
+ intptr_t m_lockCount;
+ bool m_lockingForReal;
+ };
+ };
+
+} // namespace
+
+#endif // KJS_JSLock_h
diff --git a/JavaScriptCore/runtime/JSNotAnObject.cpp b/JavaScriptCore/runtime/JSNotAnObject.cpp
new file mode 100644
index 0000000..c4ca8fd
--- /dev/null
+++ b/JavaScriptCore/runtime/JSNotAnObject.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "JSNotAnObject.h"
+
+#include <wtf/UnusedParam.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
+
+// JSValue methods
+JSValue* JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+}
+
+bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValue*&)
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+bool JSNotAnObject::toBoolean(ExecState* exec) const
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+double JSNotAnObject::toNumber(ExecState* exec) const
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return NaN;
+}
+
+UString JSNotAnObject::toString(ExecState* exec) const
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return "";
+}
+
+JSObject* JSNotAnObject::toObject(ExecState* exec) const
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return m_exception;
+}
+
+// Marking
+void JSNotAnObject::mark()
+{
+ JSCell::mark();
+ if (!m_exception->marked())
+ m_exception->mark();
+}
+
+// JSObject methods
+bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, const Identifier&, PropertySlot&)
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&)
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue*, PutPropertySlot&)
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+}
+
+void JSNotAnObject::put(ExecState* exec, unsigned, JSValue*)
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+}
+
+bool JSNotAnObject::deleteProperty(ExecState* exec, const Identifier&)
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
+void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&)
+{
+ UNUSED_PARAM(exec);
+ ASSERT(exec->hadException() && exec->exception() == m_exception);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSNotAnObject.h b/JavaScriptCore/runtime/JSNotAnObject.h
new file mode 100644
index 0000000..b6e2931
--- /dev/null
+++ b/JavaScriptCore/runtime/JSNotAnObject.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSNotAnObject_h
+#define JSNotAnObject_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class JSNotAnObjectErrorStub : public JSObject {
+ public:
+ JSNotAnObjectErrorStub(ExecState* exec, bool isNull)
+ : JSObject(exec->globalData().notAnObjectErrorStubStructure)
+ , m_isNull(isNull)
+ {
+ }
+
+ bool isNull() const { return m_isNull; }
+
+ private:
+ virtual bool isNotAnObjectErrorStub() const { return true; }
+
+ bool m_isNull;
+ };
+
+ // This unholy class is used to allow us to avoid multiple exception checks
+ // in certain SquirrelFish opcodes -- effectively it just silently consumes
+ // any operations performed on the result of a failed toObject call.
+ class JSNotAnObject : public JSObject {
+ public:
+ JSNotAnObject(ExecState* exec, JSNotAnObjectErrorStub* exception)
+ : JSObject(exec->globalData().notAnObjectStructure)
+ , m_exception(exception)
+ {
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+ private:
+ // JSValue methods
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ // Marking
+ virtual void mark();
+
+ // JSObject methods
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue*);
+
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ JSNotAnObjectErrorStub* m_exception;
+ };
+
+} // namespace JSC
+
+#endif // JSNotAnObject_h
diff --git a/JavaScriptCore/runtime/JSNumberCell.cpp b/JavaScriptCore/runtime/JSNumberCell.cpp
new file mode 100644
index 0000000..5b3f3bd
--- /dev/null
+++ b/JavaScriptCore/runtime/JSNumberCell.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSNumberCell.h"
+
+#include "NumberObject.h"
+#include "ustring.h"
+
+namespace JSC {
+
+JSValue* JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ return const_cast<JSNumberCell*>(this);
+}
+
+bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
+{
+ number = m_value;
+ value = this;
+ return true;
+}
+
+bool JSNumberCell::toBoolean(ExecState*) const
+{
+ return m_value < 0.0 || m_value > 0.0; // false for NaN
+}
+
+double JSNumberCell::toNumber(ExecState*) const
+{
+ return m_value;
+}
+
+UString JSNumberCell::toString(ExecState*) const
+{
+ if (m_value == 0.0) // +0.0 or -0.0
+ return "0";
+ return UString::from(m_value);
+}
+
+UString JSNumberCell::toThisString(ExecState*) const
+{
+ if (m_value == 0.0) // +0.0 or -0.0
+ return "0";
+ return UString::from(m_value);
+}
+
+JSObject* JSNumberCell::toObject(ExecState* exec) const
+{
+ return constructNumber(exec, const_cast<JSNumberCell*>(this));
+}
+
+JSObject* JSNumberCell::toThisObject(ExecState* exec) const
+{
+ return constructNumber(exec, const_cast<JSNumberCell*>(this));
+}
+
+bool JSNumberCell::getUInt32(uint32_t& uint32) const
+{
+ uint32 = static_cast<uint32_t>(m_value);
+ return uint32 == m_value;
+}
+
+bool JSNumberCell::getTruncatedInt32(int32_t& int32) const
+{
+ if (!(m_value >= -2147483648.0 && m_value < 2147483648.0))
+ return false;
+ int32 = static_cast<int32_t>(m_value);
+ return true;
+}
+
+bool JSNumberCell::getTruncatedUInt32(uint32_t& uint32) const
+{
+ if (!(m_value >= 0.0 && m_value < 4294967296.0))
+ return false;
+ uint32 = static_cast<uint32_t>(m_value);
+ return true;
+}
+
+JSValue* JSNumberCell::getJSNumber()
+{
+ return this;
+}
+
+NEVER_INLINE JSValue* jsNumberCell(ExecState* exec, double d)
+{
+ return new (exec) JSNumberCell(exec, d);
+}
+
+NEVER_INLINE JSValue* jsNaN(ExecState* exec)
+{
+ return new (exec) JSNumberCell(exec, NaN);
+}
+
+NEVER_INLINE JSValue* jsNumberCell(JSGlobalData* globalData, double d)
+{
+ return new (globalData) JSNumberCell(globalData, d);
+}
+
+NEVER_INLINE JSValue* jsNaN(JSGlobalData* globalData)
+{
+ return new (globalData) JSNumberCell(globalData, NaN);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h
new file mode 100644
index 0000000..e2f6990
--- /dev/null
+++ b/JavaScriptCore/runtime/JSNumberCell.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSNumberCell_h
+#define JSNumberCell_h
+
+#include "ExecState.h"
+#include "JSCell.h"
+#include "JSImmediate.h"
+#include "collector.h"
+#include "ustring.h"
+#include <stddef.h> // for size_t
+
+namespace JSC {
+
+ class Identifier;
+ class JSCell;
+ class JSObject;
+ class JSString;
+ class PropertySlot;
+
+ struct ClassInfo;
+ struct Instruction;
+
+ class JSNumberCell : public JSCell {
+ friend class CTI;
+ friend JSValue* jsNumberCell(JSGlobalData*, double);
+ friend JSValue* jsNaN(JSGlobalData*);
+ friend JSValue* jsNumberCell(ExecState*, double);
+ friend JSValue* jsNaN(ExecState*);
+ public:
+ double value() const { return m_value; }
+
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ virtual UString toThisString(ExecState*) const;
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual JSValue* getJSNumber();
+
+ int32_t toInt32() const;
+ uint32_t toUInt32() const;
+
+ void* operator new(size_t size, ExecState* exec)
+ {
+ #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return exec->heap()->inlineAllocateNumber(size);
+ #else
+ return exec->heap()->allocateNumber(size);
+ #endif
+ }
+
+ void* operator new(size_t size, JSGlobalData* globalData)
+ {
+ #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
+ return globalData->heap.inlineAllocateNumber(size);
+ #else
+ return globalData->heap.allocateNumber(size);
+ #endif
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(NumberType, NeedsThisConversion)); }
+
+ JSNumberCell(JSGlobalData* globalData)
+ : JSCell(globalData->numberStructureID.get())
+ {
+ }
+
+ private:
+ JSNumberCell(JSGlobalData* globalData, double value)
+ : JSCell(globalData->numberStructureID.get())
+ , m_value(value)
+ {
+ }
+
+ JSNumberCell(ExecState* exec, double value)
+ : JSCell(exec->globalData().numberStructureID.get())
+ , m_value(value)
+ {
+ }
+
+ virtual bool getUInt32(uint32_t&) const;
+ virtual bool getTruncatedInt32(int32_t&) const;
+ virtual bool getTruncatedUInt32(uint32_t&) const;
+
+ double m_value;
+ };
+
+ extern const double NaN;
+ extern const double Inf;
+
+ JSNumberCell* asNumberCell(JSValue*);
+
+ JSValue* jsNumberCell(JSGlobalData*, double);
+ JSValue* jsNaN(JSGlobalData*);
+ JSValue* jsNumberCell(ExecState*, double);
+ JSValue* jsNaN(ExecState*);
+
+ inline JSNumberCell* asNumberCell(JSValue* value)
+ {
+ ASSERT(asCell(value)->isNumber());
+ return static_cast<JSNumberCell*>(asCell(value));
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, double d)
+ {
+ JSValue* v = JSImmediate::from(d);
+ return v ? v : jsNumberCell(exec, d);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, short i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned short i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, int i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, long i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned long i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, long long i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, static_cast<double>(i));
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(ExecState* exec, unsigned long long i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(exec, static_cast<double>(i));
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, double d)
+ {
+ JSValue* v = JSImmediate::from(d);
+ return v ? v : jsNumberCell(globalData, d);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, short i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, unsigned short i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, int i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, unsigned i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, long i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, unsigned long i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, i);
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, long long i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, static_cast<double>(i));
+ }
+
+ ALWAYS_INLINE JSValue* jsNumber(JSGlobalData* globalData, unsigned long long i)
+ {
+ JSValue* v = JSImmediate::from(i);
+ return v ? v : jsNumberCell(globalData, static_cast<double>(i));
+ }
+
+ // --- JSValue inlines ----------------------------
+
+ inline double JSValue::uncheckedGetNumber() const
+ {
+ ASSERT(JSImmediate::isImmediate(asValue()) || asCell()->isNumber());
+ return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asNumberCell(asValue())->value();
+ }
+
+ inline int32_t JSNumberCell::toInt32() const
+ {
+ if (m_value >= -2147483648.0 && m_value < 2147483648.0)
+ return static_cast<int32_t>(m_value);
+ bool scratch;
+ return JSC::toInt32SlowCase(m_value, scratch);
+ }
+
+ inline uint32_t JSNumberCell::toUInt32() const
+ {
+ if (m_value >= 0.0 && m_value < 4294967296.0)
+ return static_cast<uint32_t>(m_value);
+ bool scratch;
+ return JSC::toUInt32SlowCase(m_value, scratch);
+ }
+
+ ALWAYS_INLINE JSValue* JSValue::toJSNumber(ExecState* exec) const
+ {
+ return JSImmediate::isNumber(asValue()) ? asValue() : jsNumber(exec, this->toNumber(exec));
+ }
+
+} // namespace JSC
+
+#endif // JSNumberCell_h
diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp
new file mode 100644
index 0000000..82c1c63
--- /dev/null
+++ b/JavaScriptCore/runtime/JSObject.cpp
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Eric Seidel (eric@webkit.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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSObject.h"
+
+#include "DatePrototype.h"
+#include "ErrorConstructor.h"
+#include "GetterSetter.h"
+#include "JSGlobalObject.h"
+#include "NativeErrorConstructor.h"
+#include "ObjectPrototype.h"
+#include "PropertyNameArray.h"
+#include "lookup.h"
+#include "nodes.h"
+#include "operations.h"
+#include <math.h>
+#include <wtf/Assertions.h>
+
+#define JSOBJECT_MARK_TRACING 0
+
+#if JSOBJECT_MARK_TRACING
+
+#define JSOBJECT_MARK_BEGIN() \
+ static int markStackDepth = 0; \
+ for (int i = 0; i < markStackDepth; i++) \
+ putchar('-'); \
+ printf("%s (%p)\n", className().UTF8String().c_str(), this); \
+ markStackDepth++; \
+
+#define JSOBJECT_MARK_END() \
+ markStackDepth--;
+
+#else // JSOBJECT_MARK_TRACING
+
+#define JSOBJECT_MARK_BEGIN()
+#define JSOBJECT_MARK_END()
+
+#endif // JSOBJECT_MARK_TRACING
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSObject);
+
+void JSObject::mark()
+{
+ JSOBJECT_MARK_BEGIN();
+
+ JSCell::mark();
+ m_structureID->mark();
+
+ size_t storageSize = m_structureID->propertyStorageSize();
+ for (size_t i = 0; i < storageSize; ++i) {
+ JSValue* v = m_propertyStorage[i];
+ if (!v->marked())
+ v->mark();
+ }
+
+ JSOBJECT_MARK_END();
+}
+
+UString JSObject::className() const
+{
+ const ClassInfo* info = classInfo();
+ if (info)
+ return info->className;
+ return "Object";
+}
+
+bool JSObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+}
+
+static void throwSetterError(ExecState* exec)
+{
+ throwError(exec, TypeError, "setting a property that has only a getter");
+}
+
+// ECMA 8.6.2.2
+void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ ASSERT(value);
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (propertyName == exec->propertyNames().underscoreProto) {
+ JSObject* proto = value->getObject();
+
+ // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
+ if (!proto && !value->isNull())
+ return;
+
+ while (proto) {
+ if (proto == this) {
+ throwError(exec, GeneralError, "cyclic __proto__ value");
+ return;
+ }
+ proto = proto->prototype() ? proto->prototype()->getObject() : 0;
+ }
+
+ setPrototype(value);
+ return;
+ }
+
+ // Check if there are any setters or getters in the prototype chain
+ JSValue* prototype;
+ for (JSObject* obj = this; !obj->structureID()->hasGetterSetterProperties(); obj = asObject(prototype)) {
+ prototype = obj->prototype();
+ if (prototype->isNull()) {
+ putDirect(propertyName, value, 0, true, slot);
+ return;
+ }
+ }
+
+ unsigned attributes;
+ if ((m_structureID->get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)
+ return;
+
+ for (JSObject* obj = this; ; obj = asObject(prototype)) {
+ if (JSValue* gs = obj->getDirect(propertyName)) {
+ if (gs->isGetterSetter()) {
+ JSObject* setterFunc = asGetterSetter(gs)->setter();
+ if (!setterFunc) {
+ throwSetterError(exec);
+ return;
+ }
+
+ CallData callData;
+ CallType callType = setterFunc->getCallData(callData);
+ ArgList args;
+ args.append(value);
+ call(exec, setterFunc, callType, callData, this, args);
+ return;
+ }
+
+ // If there's an existing property on the object or one of its
+ // prototypes it should be replaced, so break here.
+ break;
+ }
+
+ prototype = obj->prototype();
+ if (prototype->isNull())
+ break;
+ }
+
+ putDirect(propertyName, value, 0, true, slot);
+ return;
+}
+
+void JSObject::put(ExecState* exec, unsigned propertyName, JSValue* value)
+{
+ PutPropertySlot slot;
+ put(exec, Identifier::from(exec, propertyName), value, slot);
+}
+
+void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes)
+{
+ putDirect(propertyName, value, attributes);
+}
+
+void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue* value, unsigned attributes)
+{
+ putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes);
+}
+
+bool JSObject::hasProperty(ExecState* exec, const Identifier& propertyName) const
+{
+ PropertySlot slot;
+ return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
+}
+
+bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const
+{
+ PropertySlot slot;
+ return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
+}
+
+// ECMA 8.6.2.5
+bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ unsigned attributes;
+ if (m_structureID->get(propertyName, attributes) != WTF::notFound) {
+ if ((attributes & DontDelete))
+ return false;
+ removeDirect(propertyName);
+ return true;
+ }
+
+ // Look in the static hashtable of properties
+ const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
+ if (entry && entry->attributes() & DontDelete)
+ return false; // this builtin property can't be deleted
+
+ // FIXME: Should the code here actually do some deletion?
+ return true;
+}
+
+bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
+{
+ PropertySlot slot;
+ return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName)
+{
+ return deleteProperty(exec, Identifier::from(exec, propertyName));
+}
+
+static ALWAYS_INLINE JSValue* callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
+{
+ JSValue* function = object->get(exec, propertyName);
+ CallData callData;
+ CallType callType = function->getCallData(callData);
+ if (callType == CallTypeNone)
+ return exec->exception();
+
+ // Prevent "toString" and "valueOf" from observing execution if an exception
+ // is pending.
+ if (exec->hadException())
+ return exec->exception();
+
+ JSValue* result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
+ ASSERT(!result->isGetterSetter());
+ if (exec->hadException())
+ return exec->exception();
+ if (result->isObject())
+ return noValue();
+ return result;
+}
+
+bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)
+{
+ result = defaultValue(exec, PreferNumber);
+ number = result->toNumber(exec);
+ return !result->isString();
+}
+
+// ECMA 8.6.2.6
+JSValue* JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+{
+ // Must call toString first for Date objects.
+ if ((hint == PreferString) || (hint != PreferNumber && prototype() == exec->lexicalGlobalObject()->datePrototype())) {
+ if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))
+ return value;
+ if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf))
+ return value;
+ } else {
+ if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf))
+ return value;
+ if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))
+ return value;
+ }
+
+ ASSERT(!exec->hadException());
+
+ return throwError(exec, TypeError, "No default value");
+}
+
+const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifier& propertyName) const
+{
+ for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
+ if (const HashTable* propHashTable = info->propHashTable(exec)) {
+ if (const HashEntry* entry = propHashTable->entry(exec, propertyName))
+ return entry;
+ }
+ }
+ return 0;
+}
+
+void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+{
+ JSValue* object = getDirect(propertyName);
+ if (object && object->isGetterSetter()) {
+ ASSERT(m_structureID->hasGetterSetterProperties());
+ asGetterSetter(object)->setGetter(getterFunction);
+ return;
+ }
+
+ PutPropertySlot slot;
+ GetterSetter* getterSetter = new (exec) GetterSetter;
+ putDirect(propertyName, getterSetter, None, true, slot);
+
+ // putDirect will change our StructureID if we add a new property. For
+ // getters and setters, though, we also need to change our StructureID
+ // if we override an existing non-getter or non-setter.
+ if (slot.type() != PutPropertySlot::NewProperty) {
+ if (!m_structureID->isDictionary()) {
+ RefPtr<StructureID> structureID = StructureID::getterSetterTransition(m_structureID);
+ setStructureID(structureID.release());
+ }
+ }
+
+ m_structureID->setHasGetterSetterProperties(true);
+ getterSetter->setGetter(getterFunction);
+}
+
+void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+{
+ JSValue* object = getDirect(propertyName);
+ if (object && object->isGetterSetter()) {
+ ASSERT(m_structureID->hasGetterSetterProperties());
+ asGetterSetter(object)->setSetter(setterFunction);
+ return;
+ }
+
+ PutPropertySlot slot;
+ GetterSetter* getterSetter = new (exec) GetterSetter;
+ putDirect(propertyName, getterSetter, None, true, slot);
+
+ // putDirect will change our StructureID if we add a new property. For
+ // getters and setters, though, we also need to change our StructureID
+ // if we override an existing non-getter or non-setter.
+ if (slot.type() != PutPropertySlot::NewProperty) {
+ if (!m_structureID->isDictionary()) {
+ RefPtr<StructureID> structureID = StructureID::getterSetterTransition(m_structureID);
+ setStructureID(structureID.release());
+ }
+ }
+
+ m_structureID->setHasGetterSetterProperties(true);
+ getterSetter->setSetter(setterFunction);
+}
+
+JSValue* JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
+{
+ JSObject* object = this;
+ while (true) {
+ JSValue* value = object->getDirect(propertyName);
+ if (value) {
+ if (!value->isGetterSetter())
+ return jsUndefined();
+ JSObject* functionObject = asGetterSetter(value)->getter();
+ if (!functionObject)
+ return jsUndefined();
+ return functionObject;
+ }
+
+ if (!object->prototype() || !object->prototype()->isObject())
+ return jsUndefined();
+ object = asObject(object->prototype());
+ }
+}
+
+JSValue* JSObject::lookupSetter(ExecState*, const Identifier& propertyName)
+{
+ JSObject* object = this;
+ while (true) {
+ JSValue* value = object->getDirect(propertyName);
+ if (value) {
+ if (!value->isGetterSetter())
+ return jsUndefined();
+ JSObject* functionObject = asGetterSetter(value)->setter();
+ if (!functionObject)
+ return jsUndefined();
+ return functionObject;
+ }
+
+ if (!object->prototype() || !object->prototype()->isObject())
+ return jsUndefined();
+ object = asObject(object->prototype());
+ }
+}
+
+bool JSObject::hasInstance(ExecState* exec, JSValue* value, JSValue* proto)
+{
+ if (!proto->isObject()) {
+ throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");
+ return false;
+ }
+
+ if (!value->isObject())
+ return false;
+
+ JSObject* object = asObject(value);
+ while ((object = object->prototype()->getObject())) {
+ if (object == proto)
+ return true;
+ }
+ return false;
+}
+
+bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
+{
+ unsigned attributes;
+ if (!getPropertyAttributes(exec, propertyName, attributes))
+ return false;
+ return !(attributes & DontEnum);
+}
+
+bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
+{
+ if (m_structureID->get(propertyName, attributes) != WTF::notFound)
+ return true;
+
+ // Look in the static hashtable of properties
+ const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
+ if (entry) {
+ attributes = entry->attributes();
+ return true;
+ }
+
+ return false;
+}
+
+void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ m_structureID->getEnumerablePropertyNames(exec, propertyNames, this);
+}
+
+bool JSObject::toBoolean(ExecState*) const
+{
+ return true;
+}
+
+double JSObject::toNumber(ExecState* exec) const
+{
+ JSValue* primitive = toPrimitive(exec, PreferNumber);
+ if (exec->hadException()) // should be picked up soon in nodes.cpp
+ return 0.0;
+ return primitive->toNumber(exec);
+}
+
+UString JSObject::toString(ExecState* exec) const
+{
+ JSValue* primitive = toPrimitive(exec, PreferString);
+ if (exec->hadException())
+ return "";
+ return primitive->toString(exec);
+}
+
+JSObject* JSObject::toObject(ExecState*) const
+{
+ return const_cast<JSObject*>(this);
+}
+
+JSObject* JSObject::toThisObject(ExecState*) const
+{
+ return const_cast<JSObject*>(this);
+}
+
+JSGlobalObject* JSObject::toGlobalObject(ExecState*) const
+{
+ return 0;
+}
+
+void JSObject::removeDirect(const Identifier& propertyName)
+{
+ size_t offset;
+ if (m_structureID->isDictionary()) {
+ offset = m_structureID->removePropertyWithoutTransition(propertyName);
+ if (offset != WTF::notFound)
+ m_propertyStorage[offset] = jsUndefined();
+ return;
+ }
+
+ RefPtr<StructureID> structureID = StructureID::removePropertyTransition(m_structureID, propertyName, offset);
+ if (offset != WTF::notFound)
+ m_propertyStorage[offset] = jsUndefined();
+ setStructureID(structureID.release());
+}
+
+void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
+{
+ putDirect(Identifier(exec, function->name(&exec->globalData())), function, attr);
+}
+
+void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr)
+{
+ putDirectWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr);
+}
+
+NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue** location)
+{
+ if (JSObject* getterFunction = asGetterSetter(*location)->getter())
+ slot.setGetterSlot(getterFunction);
+ else
+ slot.setUndefined();
+}
+
+StructureID* JSObject::createInheritorID()
+{
+ m_inheritorID = JSObject::createStructureID(this);
+ return m_inheritorID.get();
+}
+
+void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
+{
+ allocatePropertyStorageInline(oldSize, newSize);
+}
+
+JSObject* constructEmptyObject(ExecState* exec)
+{
+ return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h
new file mode 100644
index 0000000..d280b64
--- /dev/null
+++ b/JavaScriptCore/runtime/JSObject.h
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSObject_h
+#define JSObject_h
+
+#include "ArgList.h"
+#include "ClassInfo.h"
+#include "CommonIdentifiers.h"
+#include "ExecState.h"
+#include "JSNumberCell.h"
+#include "PropertySlot.h"
+#include "PutPropertySlot.h"
+#include "ScopeChain.h"
+#include "StructureID.h"
+
+namespace JSC {
+
+ class InternalFunction;
+ class PropertyNameArray;
+ class StructureID;
+ struct HashEntry;
+ struct HashTable;
+
+ // ECMA 262-3 8.6.1
+ // Property attributes
+ enum Attribute {
+ None = 0,
+ ReadOnly = 1 << 1, // property can be only read, not written
+ DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
+ DontDelete = 1 << 3, // property can't be deleted
+ Function = 1 << 4, // property is a function - only used by static hashtables
+ };
+
+ typedef JSValue** PropertyStorage;
+
+ class JSObject : public JSCell {
+ friend class BatchedTransitionOptimizer;
+ friend class CTI;
+ friend class JSCell;
+
+ public:
+ explicit JSObject(PassRefPtr<StructureID>);
+
+ virtual void mark();
+
+ // The inline virtual destructor cannot be the first virtual function declared
+ // in the class as it results in the vtable being generated as a weak symbol
+ virtual ~JSObject();
+
+ bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); }
+
+ JSValue* prototype() const;
+ void setPrototype(JSValue* prototype);
+
+ void setStructureID(PassRefPtr<StructureID>);
+ StructureID* inheritorID();
+
+ PropertyStorage& propertyStorage() { return m_propertyStorage; }
+
+ virtual UString className() const;
+
+ JSValue* get(ExecState*, const Identifier& propertyName) const;
+ JSValue* get(ExecState*, unsigned propertyName) const;
+
+ bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue* value, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue* value);
+
+ virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes);
+ virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValue* value, unsigned attributes);
+
+ bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
+
+ bool hasProperty(ExecState*, const Identifier& propertyName) const;
+ bool hasProperty(ExecState*, unsigned propertyName) const;
+ bool hasOwnProperty(ExecState*, const Identifier& propertyName) const;
+
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual bool deleteProperty(ExecState*, unsigned propertyName);
+
+ virtual JSValue* defaultValue(ExecState*, PreferredPrimitiveType) const;
+
+ virtual bool hasInstance(ExecState*, JSValue*, JSValue* prototypeProperty);
+
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual JSGlobalObject* toGlobalObject(ExecState*) const;
+
+ virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
+
+ // This get function only looks at the property map.
+ JSValue* getDirect(const Identifier& propertyName) const
+ {
+ size_t offset = m_structureID->get(propertyName);
+ return offset != WTF::notFound ? m_propertyStorage[offset] : noValue();
+ }
+
+ JSValue** getDirectLocation(const Identifier& propertyName)
+ {
+ size_t offset = m_structureID->get(propertyName);
+ return offset != WTF::notFound ? locationForOffset(offset) : 0;
+ }
+
+ JSValue** getDirectLocation(const Identifier& propertyName, unsigned& attributes)
+ {
+ size_t offset = m_structureID->get(propertyName, attributes);
+ return offset != WTF::notFound ? locationForOffset(offset) : 0;
+ }
+
+ size_t offsetForLocation(JSValue** location)
+ {
+ return location - m_propertyStorage;
+ }
+
+ JSValue** locationForOffset(size_t offset)
+ {
+ return &m_propertyStorage[offset];
+ }
+
+ void transitionTo(StructureID*);
+
+ void removeDirect(const Identifier& propertyName);
+ bool hasCustomProperties() { return !m_structureID->isEmpty(); }
+ bool hasGetterSetterProperties() { return m_structureID->hasGetterSetterProperties(); }
+
+ void putDirect(const Identifier& propertyName, JSValue* value, unsigned attr = 0);
+ void putDirect(const Identifier& propertyName, JSValue* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
+ void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0);
+ void putDirectWithoutTransition(const Identifier& propertyName, JSValue* value, unsigned attr = 0);
+ void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0);
+
+ // Fast access to known property offsets.
+ JSValue* getDirectOffset(size_t offset) { return m_propertyStorage[offset]; }
+ void putDirectOffset(size_t offset, JSValue* value) { m_propertyStorage[offset] = value; }
+
+ void fillGetterPropertySlot(PropertySlot&, JSValue** location);
+
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
+ virtual JSValue* lookupGetter(ExecState*, const Identifier& propertyName);
+ virtual JSValue* lookupSetter(ExecState*, const Identifier& propertyName);
+
+ virtual bool isGlobalObject() const { return false; }
+ virtual bool isVariableObject() const { return false; }
+ virtual bool isWatchdogException() const { return false; }
+ virtual bool isNotAnObjectErrorStub() const { return false; }
+
+ void allocatePropertyStorage(size_t oldSize, size_t newSize);
+ void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
+ bool usingInlineStorage() const { return m_propertyStorage == m_inlineStorage; }
+
+ static const size_t inlineStorageCapacity = 2;
+ static const size_t nonInlineBaseStorageCapacity = 16;
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+ }
+
+ protected:
+ bool getOwnPropertySlotForWrite(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
+
+ private:
+ bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+
+ const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
+ StructureID* createInheritorID();
+
+ RefPtr<StructureID> m_inheritorID;
+
+ PropertyStorage m_propertyStorage;
+ JSValue* m_inlineStorage[inlineStorageCapacity];
+ };
+
+ JSObject* asObject(JSValue*);
+
+ JSObject* constructEmptyObject(ExecState*);
+
+inline JSObject* asObject(JSValue* value)
+{
+ ASSERT(asCell(value)->isObject());
+ return static_cast<JSObject*>(asCell(value));
+}
+
+inline JSObject::JSObject(PassRefPtr<StructureID> structureID)
+ : JSCell(structureID.releaseRef()) // ~JSObject balances this ref()
+ , m_propertyStorage(m_inlineStorage)
+{
+ ASSERT(m_structureID);
+ ASSERT(m_structureID->propertyStorageCapacity() == inlineStorageCapacity);
+ ASSERT(m_structureID->isEmpty());
+ ASSERT(prototype()->isNull() || Heap::heap(this) == Heap::heap(prototype()));
+}
+
+inline JSObject::~JSObject()
+{
+ ASSERT(m_structureID);
+ if (m_propertyStorage != m_inlineStorage)
+ delete [] m_propertyStorage;
+ m_structureID->deref();
+}
+
+inline JSValue* JSObject::prototype() const
+{
+ return m_structureID->storedPrototype();
+}
+
+inline void JSObject::setPrototype(JSValue* prototype)
+{
+ ASSERT(prototype);
+ RefPtr<StructureID> newStructureID = StructureID::changePrototypeTransition(m_structureID, prototype);
+ setStructureID(newStructureID.release());
+}
+
+inline void JSObject::setStructureID(PassRefPtr<StructureID> structureID)
+{
+ m_structureID->deref();
+ m_structureID = structureID.releaseRef(); // ~JSObject balances this ref()
+}
+
+inline StructureID* JSObject::inheritorID()
+{
+ if (m_inheritorID)
+ return m_inheritorID.get();
+ return createInheritorID();
+}
+
+inline bool JSCell::isObject(const ClassInfo* info) const
+{
+ for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
+ if (ci == info)
+ return true;
+ }
+ return false;
+}
+
+// this method is here to be after the inline declaration of JSCell::isObject
+inline bool JSValue::isObject(const ClassInfo* classInfo) const
+{
+ return !JSImmediate::isImmediate(asValue()) && asCell()->isObject(classInfo);
+}
+
+ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (JSValue** location = getDirectLocation(propertyName)) {
+ if (m_structureID->hasGetterSetterProperties() && location[0]->isGetterSetter())
+ fillGetterPropertySlot(slot, location);
+ else
+ slot.setValueSlot(this, location, offsetForLocation(location));
+ return true;
+ }
+
+ // non-standard Netscape extension
+ if (propertyName == exec->propertyNames().underscoreProto) {
+ slot.setValue(prototype());
+ return true;
+ }
+
+ return false;
+}
+
+ALWAYS_INLINE bool JSObject::getOwnPropertySlotForWrite(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+{
+ unsigned attributes;
+ if (JSValue** location = getDirectLocation(propertyName, attributes)) {
+ if (m_structureID->hasGetterSetterProperties() && location[0]->isGetterSetter()) {
+ slotIsWriteable = false;
+ fillGetterPropertySlot(slot, location);
+ } else {
+ slotIsWriteable = !(attributes & ReadOnly);
+ slot.setValueSlot(this, location, offsetForLocation(location));
+ }
+ return true;
+ }
+
+ // non-standard Netscape extension
+ if (propertyName == exec->propertyNames().underscoreProto) {
+ slot.setValue(prototype());
+ slotIsWriteable = false;
+ return true;
+ }
+
+ return false;
+}
+
+// It may seem crazy to inline a function this large, especially a virtual function,
+// but it makes a big difference to property lookup that derived classes can inline their
+// base class call to this.
+ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return inlineGetOwnPropertySlot(exec, propertyName, slot);
+}
+
+ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (structureID()->typeInfo().hasStandardGetOwnPropertySlot())
+ return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
+ return getOwnPropertySlot(exec, propertyName, slot);
+}
+
+// It may seem crazy to inline a function this large but it makes a big difference
+// since this is function very hot in variable lookup
+inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ JSObject* object = this;
+ while (true) {
+ if (object->fastGetOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ JSValue* prototype = object->prototype();
+ if (!prototype->isObject())
+ return false;
+ object = asObject(prototype);
+ }
+}
+
+inline bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ JSObject* object = this;
+ while (true) {
+ if (object->getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ JSValue* prototype = object->prototype();
+ if (!prototype->isObject())
+ return false;
+ object = asObject(prototype);
+ }
+}
+
+inline JSValue* JSObject::get(ExecState* exec, const Identifier& propertyName) const
+{
+ PropertySlot slot(this);
+ if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+
+ return jsUndefined();
+}
+
+inline JSValue* JSObject::get(ExecState* exec, unsigned propertyName) const
+{
+ PropertySlot slot(this);
+ if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+
+ return jsUndefined();
+}
+
+inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value, unsigned attr)
+{
+ PutPropertySlot slot;
+ putDirect(propertyName, value, attr, false, slot);
+}
+
+inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ if (m_structureID->isDictionary()) {
+ unsigned currentAttributes;
+ size_t offset = m_structureID->get(propertyName, currentAttributes);
+ if (offset != WTF::notFound) {
+ if (checkReadOnly && currentAttributes & ReadOnly)
+ return;
+ m_propertyStorage[offset] = value;
+ slot.setExistingProperty(this, offset);
+ return;
+ }
+
+ size_t currentCapacity = m_structureID->propertyStorageCapacity();
+ offset = m_structureID->addPropertyWithoutTransition(propertyName, attributes);
+ if (currentCapacity != m_structureID->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, m_structureID->propertyStorageCapacity());
+
+ ASSERT(offset < m_structureID->propertyStorageCapacity());
+ m_propertyStorage[offset] = value;
+ slot.setNewProperty(this, offset);
+ return;
+ }
+
+ unsigned currentAttributes;
+ size_t offset = m_structureID->get(propertyName, currentAttributes);
+ if (offset != WTF::notFound) {
+ if (checkReadOnly && currentAttributes & ReadOnly)
+ return;
+ m_propertyStorage[offset] = value;
+ slot.setExistingProperty(this, offset);
+ return;
+ }
+
+ size_t currentCapacity = m_structureID->propertyStorageCapacity();
+ RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, attributes, offset);
+ if (currentCapacity != structureID->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, structureID->propertyStorageCapacity());
+
+ ASSERT(offset < structureID->propertyStorageCapacity());
+ m_propertyStorage[offset] = value;
+ slot.setNewProperty(this, offset);
+ slot.setWasTransition(true);
+ setStructureID(structureID.release());
+}
+
+inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValue* value, unsigned attributes)
+{
+ size_t currentCapacity = m_structureID->propertyStorageCapacity();
+ size_t offset = m_structureID->addPropertyWithoutTransition(propertyName, attributes);
+ if (currentCapacity != m_structureID->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, m_structureID->propertyStorageCapacity());
+ m_propertyStorage[offset] = value;
+}
+
+inline void JSObject::transitionTo(StructureID* newStructureID)
+{
+ if (m_structureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity())
+ allocatePropertyStorage(m_structureID->propertyStorageCapacity(), newStructureID->propertyStorageCapacity());
+ setStructureID(newStructureID);
+}
+
+inline JSValue* JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+{
+ return defaultValue(exec, preferredType);
+}
+
+inline JSValue* JSValue::get(ExecState* exec, const Identifier& propertyName) const
+{
+ PropertySlot slot(this);
+ return get(exec, propertyName, slot);
+}
+
+inline JSValue* JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const
+{
+ if (UNLIKELY(JSImmediate::isImmediate(asValue()))) {
+ JSObject* prototype = JSImmediate::prototype(asValue(), exec);
+ if (!prototype->getPropertySlot(exec, propertyName, slot))
+ return jsUndefined();
+ return slot.getValue(exec, propertyName);
+ }
+ JSCell* cell = asCell();
+ while (true) {
+ if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+ ASSERT(cell->isObject());
+ JSValue* prototype = static_cast<JSObject*>(cell)->prototype();
+ if (!prototype->isObject())
+ return jsUndefined();
+ cell = asObject(prototype);
+ }
+}
+
+inline JSValue* JSValue::get(ExecState* exec, unsigned propertyName) const
+{
+ PropertySlot slot(this);
+ return get(exec, propertyName, slot);
+}
+
+inline JSValue* JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
+{
+ if (UNLIKELY(JSImmediate::isImmediate(asValue()))) {
+ JSObject* prototype = JSImmediate::prototype(asValue(), exec);
+ if (!prototype->getPropertySlot(exec, propertyName, slot))
+ return jsUndefined();
+ return slot.getValue(exec, propertyName);
+ }
+ JSCell* cell = const_cast<JSCell*>(asCell());
+ while (true) {
+ if (cell->getOwnPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+ ASSERT(cell->isObject());
+ JSValue* prototype = static_cast<JSObject*>(cell)->prototype();
+ if (!prototype->isObject())
+ return jsUndefined();
+ cell = prototype->asCell();
+ }
+}
+
+inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ if (UNLIKELY(JSImmediate::isImmediate(asValue()))) {
+ JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value, slot);
+ return;
+ }
+ asCell()->put(exec, propertyName, value, slot);
+}
+
+inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue* value)
+{
+ if (UNLIKELY(JSImmediate::isImmediate(asValue()))) {
+ JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value);
+ return;
+ }
+ asCell()->put(exec, propertyName, value);
+}
+
+ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_t newSize)
+{
+ ASSERT(newSize > oldSize);
+
+ JSValue** oldPropertyStorage = m_propertyStorage;
+ m_propertyStorage = new JSValue*[newSize];
+
+ for (unsigned i = 0; i < oldSize; ++i)
+ m_propertyStorage[i] = oldPropertyStorage[i];
+
+ if (oldPropertyStorage != m_inlineStorage)
+ delete [] oldPropertyStorage;
+}
+
+} // namespace JSC
+
+#endif // JSObject_h
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
new file mode 100644
index 0000000..55f4ced
--- /dev/null
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSPropertyNameIterator.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
+
+JSPropertyNameIterator::~JSPropertyNameIterator()
+{
+}
+
+JSValue* JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ ASSERT_NOT_REACHED();
+ return noValue();
+}
+
+bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValue*&)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+bool JSPropertyNameIterator::toBoolean(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+double JSPropertyNameIterator::toNumber(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+UString JSPropertyNameIterator::toString(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return "";
+}
+
+JSObject* JSPropertyNameIterator::toObject(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+void JSPropertyNameIterator::mark()
+{
+ JSCell::mark();
+ if (m_object && !m_object->marked())
+ m_object->mark();
+}
+
+void JSPropertyNameIterator::invalidate()
+{
+ ASSERT(m_position == m_end);
+ m_object = 0;
+ m_data.clear();
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.h b/JavaScriptCore/runtime/JSPropertyNameIterator.h
new file mode 100644
index 0000000..1853999
--- /dev/null
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSPropertyNameIterator_h
+#define JSPropertyNameIterator_h
+
+#include "JSObject.h"
+#include "JSString.h"
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+ class Identifier;
+ class JSObject;
+
+ class JSPropertyNameIterator : public JSCell {
+ public:
+ static JSPropertyNameIterator* create(ExecState*, JSValue*);
+
+ virtual ~JSPropertyNameIterator();
+
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double&, JSValue*&);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+
+ virtual void mark();
+
+ JSValue* next(ExecState*);
+ void invalidate();
+
+ private:
+ JSPropertyNameIterator();
+ JSPropertyNameIterator(JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData);
+
+ JSObject* m_object;
+ RefPtr<PropertyNameArrayData> m_data;
+ PropertyNameArrayData::const_iterator m_position;
+ PropertyNameArrayData::const_iterator m_end;
+ };
+
+inline JSPropertyNameIterator::JSPropertyNameIterator()
+ : JSCell(0)
+ , m_object(0)
+ , m_position(0)
+ , m_end(0)
+{
+}
+
+inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData)
+ : JSCell(0)
+ , m_object(object)
+ , m_data(propertyNameArrayData)
+ , m_position(m_data->begin())
+ , m_end(m_data->end())
+{
+}
+
+inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue* v)
+{
+ if (v->isUndefinedOrNull())
+ return new (exec) JSPropertyNameIterator;
+
+ JSObject* o = v->toObject(exec);
+ PropertyNameArray propertyNames(exec);
+ o->getPropertyNames(exec, propertyNames);
+ return new (exec) JSPropertyNameIterator(o, propertyNames.releaseData());
+}
+
+inline JSValue* JSPropertyNameIterator::next(ExecState* exec)
+{
+ if (m_position == m_end)
+ return noValue();
+
+ if (m_data->cachedStructureID() == m_object->structureID() && structureIDChainsAreEqual(m_data->cachedPrototypeChain(), m_object->structureID()->cachedPrototypeChain()))
+ return jsOwnedString(exec, (*m_position++).ustring());
+
+ do {
+ if (m_object->hasProperty(exec, *m_position))
+ return jsOwnedString(exec, (*m_position++).ustring());
+ m_position++;
+ } while (m_position != m_end);
+
+ return noValue();
+}
+
+} // namespace JSC
+
+#endif // JSPropertyNameIterator_h
diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/JavaScriptCore/runtime/JSStaticScopeObject.cpp
new file mode 100644
index 0000000..0698250
--- /dev/null
+++ b/JavaScriptCore/runtime/JSStaticScopeObject.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "JSStaticScopeObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
+
+void JSStaticScopeObject::mark()
+{
+ JSVariableObject::mark();
+
+ if (!d()->registerStore.marked())
+ d()->registerStore.mark();
+}
+
+JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
+{
+ return exec->globalThisValue();
+}
+
+void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue* value, PutPropertySlot&)
+{
+ if (symbolTablePut(propertyName, value))
+ return;
+
+ ASSERT_NOT_REACHED();
+}
+
+void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes)
+{
+ if (symbolTablePutWithAttributes(propertyName, value, attributes))
+ return;
+
+ ASSERT_NOT_REACHED();
+}
+
+bool JSStaticScopeObject::isDynamicScope() const
+{
+ return false;
+}
+
+JSStaticScopeObject::~JSStaticScopeObject()
+{
+ ASSERT(d());
+ delete d();
+}
+
+inline bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot)
+{
+ return symbolTableGet(propertyName, slot);
+}
+
+inline bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+{
+ return symbolTableGet(propertyName, slot, slotIsWriteable);
+}
+
+}
diff --git a/JavaScriptCore/runtime/JSStaticScopeObject.h b/JavaScriptCore/runtime/JSStaticScopeObject.h
new file mode 100644
index 0000000..b152862
--- /dev/null
+++ b/JavaScriptCore/runtime/JSStaticScopeObject.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSStaticScopeObject_h
+#define JSStaticScopeObject_h
+
+#include "JSVariableObject.h"
+
+namespace JSC{
+
+ class JSStaticScopeObject : public JSVariableObject {
+ protected:
+ using JSVariableObject::JSVariableObjectData;
+ struct JSStaticScopeObjectData : public JSVariableObjectData {
+ JSStaticScopeObjectData()
+ : JSVariableObjectData(&symbolTable, &registerStore + 1)
+ {
+ }
+ SymbolTable symbolTable;
+ Register registerStore;
+ };
+
+ public:
+ JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue* value, unsigned attributes)
+ : JSVariableObject(exec->globalData().staticScopeStructureID, new JSStaticScopeObjectData())
+ {
+ d()->registerStore = value;
+ symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes));
+ }
+ virtual ~JSStaticScopeObject();
+ virtual void mark();
+ bool isDynamicScope() const;
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
+ virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&);
+ void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes);
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); }
+
+ private:
+ JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
+ };
+
+}
+
+#endif // JSStaticScopeObject_h
diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp
new file mode 100644
index 0000000..49503d5
--- /dev/null
+++ b/JavaScriptCore/runtime/JSString.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSString.h"
+
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "StringObject.h"
+#include "StringPrototype.h"
+
+namespace JSC {
+
+JSValue* JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ return const_cast<JSString*>(this);
+}
+
+bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
+{
+ value = this;
+ number = m_value.toDouble();
+ return false;
+}
+
+bool JSString::toBoolean(ExecState*) const
+{
+ return !m_value.isEmpty();
+}
+
+double JSString::toNumber(ExecState*) const
+{
+ return m_value.toDouble();
+}
+
+UString JSString::toString(ExecState*) const
+{
+ return m_value;
+}
+
+UString JSString::toThisString(ExecState*) const
+{
+ return m_value;
+}
+
+JSString* JSString::toThisJSString(ExecState*)
+{
+ return this;
+}
+
+inline StringObject* StringObject::create(ExecState* exec, JSString* string)
+{
+ return new (exec) StringObject(exec->lexicalGlobalObject()->stringObjectStructure(), string);
+}
+
+JSObject* JSString::toObject(ExecState* exec) const
+{
+ return StringObject::create(exec, const_cast<JSString*>(this));
+}
+
+JSObject* JSString::toThisObject(ExecState* exec) const
+{
+ return StringObject::create(exec, const_cast<JSString*>(this));
+}
+
+bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ // The semantics here are really getPropertySlot, not getOwnPropertySlot.
+ // This function should only be called by JSValue::get.
+ if (getStringPropertySlot(exec, propertyName, slot))
+ return true;
+ slot.setBase(this);
+ JSObject* object;
+ for (JSValue* prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype->isNull(); prototype = object->prototype()) {
+ object = asObject(prototype);
+ if (object->getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+ }
+ slot.setUndefined();
+ return true;
+}
+
+bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ // The semantics here are really getPropertySlot, not getOwnPropertySlot.
+ // This function should only be called by JSValue::get.
+ if (getStringPropertySlot(exec, propertyName, slot))
+ return true;
+ return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+}
+
+JSString* jsString(JSGlobalData* globalData, const UString& s)
+{
+ int size = s.size();
+ if (!size)
+ return globalData->smallStrings.emptyString(globalData);
+ if (size == 1) {
+ UChar c = s.data()[0];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, s);
+}
+
+JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
+{
+ ASSERT(offset <= static_cast<unsigned>(s.size()));
+ ASSERT(length <= static_cast<unsigned>(s.size()));
+ ASSERT(offset + length <= static_cast<unsigned>(s.size()));
+ if (!length)
+ return globalData->smallStrings.emptyString(globalData);
+ if (length == 1) {
+ UChar c = s.data()[offset];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, length));
+}
+
+JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
+{
+ int size = s.size();
+ if (!size)
+ return globalData->smallStrings.emptyString(globalData);
+ if (size == 1) {
+ UChar c = s.data()[0];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ }
+ return new (globalData) JSString(globalData, s, JSString::HasOtherOwner);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h
new file mode 100644
index 0000000..b6275e7
--- /dev/null
+++ b/JavaScriptCore/runtime/JSString.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSString_h
+#define JSString_h
+
+#include "CommonIdentifiers.h"
+#include "ExecState.h"
+#include "JSNumberCell.h"
+#include "PropertySlot.h"
+#include "identifier.h"
+
+namespace JSC {
+
+ class JSString;
+
+ JSString* jsEmptyString(JSGlobalData*);
+ JSString* jsEmptyString(ExecState*);
+ JSString* jsString(JSGlobalData*, const UString&); // returns empty string if passed null string
+ JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string
+
+ JSString* jsSingleCharacterString(JSGlobalData*, UChar);
+ JSString* jsSingleCharacterString(ExecState*, UChar);
+ JSString* jsSingleCharacterSubstring(JSGlobalData*, const UString&, unsigned offset);
+ JSString* jsSingleCharacterSubstring(ExecState*, const UString&, unsigned offset);
+ JSString* jsSubstring(JSGlobalData*, const UString&, unsigned offset, unsigned length);
+ JSString* jsSubstring(ExecState*, const UString&, unsigned offset, unsigned length);
+
+ // Non-trivial strings are two or more characters long.
+ // These functions are faster than just calling jsString.
+ JSString* jsNontrivialString(JSGlobalData*, const UString&);
+ JSString* jsNontrivialString(ExecState*, const UString&);
+ JSString* jsNontrivialString(JSGlobalData*, const char*);
+ JSString* jsNontrivialString(ExecState*, const char*);
+
+ // Should be used for strings that are owned by an object that will
+ // likely outlive the JSValue this makes, such as the parse tree or a
+ // DOM object that contains a UString
+ JSString* jsOwnedString(JSGlobalData*, const UString&);
+ JSString* jsOwnedString(ExecState*, const UString&);
+
+ class JSString : public JSCell {
+ friend class CTI;
+ friend class Machine;
+
+ public:
+ JSString(JSGlobalData* globalData, const UString& value)
+ : JSCell(globalData->stringStructureID.get())
+ , m_value(value)
+ {
+ Heap::heap(this)->reportExtraMemoryCost(value.cost());
+ }
+
+ enum HasOtherOwnerType { HasOtherOwner };
+ JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
+ : JSCell(globalData->stringStructureID.get())
+ , m_value(value)
+ {
+ }
+ JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType)
+ : JSCell(globalData->stringStructureID.get())
+ , m_value(value)
+ {
+ }
+
+ const UString& value() const { return m_value; }
+
+ bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); }
+ JSString* getIndex(JSGlobalData*, unsigned);
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(StringType, NeedsThisConversion)); }
+
+ private:
+ enum VPtrStealingHackType { VPtrStealingHack };
+ JSString(VPtrStealingHackType)
+ : JSCell(0)
+ {
+ }
+
+ virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+
+ virtual JSObject* toThisObject(ExecState*) const;
+ virtual UString toThisString(ExecState*) const;
+ virtual JSString* toThisJSString(ExecState*);
+
+ // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ UString m_value;
+ };
+
+ JSString* asString(JSValue*);
+
+ inline JSString* asString(JSValue* value)
+ {
+ ASSERT(asCell(value)->isString());
+ return static_cast<JSString*>(asCell(value));
+ }
+
+ inline JSString* jsEmptyString(JSGlobalData* globalData)
+ {
+ return globalData->smallStrings.emptyString(globalData);
+ }
+
+ inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
+ {
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ return new (globalData) JSString(globalData, UString(&c, 1));
+ }
+
+ inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset)
+ {
+ ASSERT(offset < static_cast<unsigned>(s.size()));
+ UChar c = s.data()[offset];
+ if (c <= 0xFF)
+ return globalData->smallStrings.singleCharacterString(globalData, c);
+ return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, 1));
+ }
+
+ inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
+ {
+ ASSERT(s);
+ ASSERT(s[0]);
+ ASSERT(s[1]);
+ return new (globalData) JSString(globalData, s);
+ }
+
+ inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
+ {
+ ASSERT(s.size() > 1);
+ return new (globalData) JSString(globalData, s);
+ }
+
+ inline JSString* JSString::getIndex(JSGlobalData* globalData, unsigned i)
+ {
+ ASSERT(canGetIndex(i));
+ return jsSingleCharacterSubstring(globalData, m_value, i);
+ }
+
+ inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
+ inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); }
+ inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
+ inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { return jsSingleCharacterSubstring(&exec->globalData(), s, offset); }
+ inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); }
+ inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); }
+ inline JSString* jsNontrivialString(ExecState* exec, const char* s) { return jsNontrivialString(&exec->globalData(), s); }
+ inline JSString* jsOwnedString(ExecState* exec, const UString& s) { return jsOwnedString(&exec->globalData(), s); }
+
+ ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ {
+ if (propertyName == exec->propertyNames().length) {
+ slot.setValue(jsNumber(exec, m_value.size()));
+ return true;
+ }
+
+ bool isStrictUInt32;
+ unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
+ if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) {
+ slot.setValue(jsSingleCharacterSubstring(exec, m_value, i));
+ return true;
+ }
+
+ return false;
+ }
+
+ ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+ {
+ if (propertyName < static_cast<unsigned>(m_value.size())) {
+ slot.setValue(jsSingleCharacterSubstring(exec, m_value, propertyName));
+ return true;
+ }
+
+ return false;
+ }
+
+ // --- JSValue inlines ----------------------------
+
+ inline JSString* JSValue::toThisJSString(ExecState* exec)
+ {
+ return JSImmediate::isImmediate(asValue()) ? jsString(exec, JSImmediate::toString(asValue())) : asCell()->toThisJSString(exec);
+ }
+
+} // namespace JSC
+
+#endif // JSString_h
diff --git a/JavaScriptCore/runtime/JSType.h b/JavaScriptCore/runtime/JSType.h
new file mode 100644
index 0000000..f0fa28f
--- /dev/null
+++ b/JavaScriptCore/runtime/JSType.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2006 Apple Computer, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KJS_JSTYPE_H
+#define KJS_JSTYPE_H
+
+namespace JSC {
+
+ /**
+ * Primitive types
+ */
+ enum JSType {
+ UnspecifiedType = 0,
+ UndefinedType = 1,
+ BooleanType = 2,
+ NumberType = 3,
+ NullType = 4,
+ StringType = 5,
+ ObjectType = 6,
+ GetterSetterType = 7
+ };
+
+} // namespace JSC
+
+#endif
diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp
new file mode 100644
index 0000000..73580b0
--- /dev/null
+++ b/JavaScriptCore/runtime/JSValue.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSValue.h"
+
+#include "JSFunction.h"
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+static const double D32 = 4294967296.0;
+
+// ECMA 9.4
+double JSValue::toInteger(ExecState* exec) const
+{
+ int32_t i;
+ if (getTruncatedInt32(i))
+ return i;
+ double d = toNumber(exec);
+ return isnan(d) ? 0.0 : trunc(d);
+}
+
+double JSValue::toIntegerPreserveNaN(ExecState* exec) const
+{
+ int32_t i;
+ if (getTruncatedInt32(i))
+ return i;
+ return trunc(toNumber(exec));
+}
+
+int32_t toInt32SlowCase(double d, bool& ok)
+{
+ ok = true;
+
+ if (d >= -D32 / 2 && d < D32 / 2)
+ return static_cast<int32_t>(d);
+
+ if (isnan(d) || isinf(d)) {
+ ok = false;
+ return 0;
+ }
+
+ double d32 = fmod(trunc(d), D32);
+ if (d32 >= D32 / 2)
+ d32 -= D32;
+ else if (d32 < -D32 / 2)
+ d32 += D32;
+ return static_cast<int32_t>(d32);
+}
+
+int32_t JSValue::toInt32SlowCase(ExecState* exec, bool& ok) const
+{
+ return JSC::toInt32SlowCase(toNumber(exec), ok);
+}
+
+uint32_t toUInt32SlowCase(double d, bool& ok)
+{
+ ok = true;
+
+ if (d >= 0.0 && d < D32)
+ return static_cast<uint32_t>(d);
+
+ if (isnan(d) || isinf(d)) {
+ ok = false;
+ return 0;
+ }
+
+ double d32 = fmod(trunc(d), D32);
+ if (d32 < 0)
+ d32 += D32;
+ return static_cast<uint32_t>(d32);
+}
+
+uint32_t JSValue::toUInt32SlowCase(ExecState* exec, bool& ok) const
+{
+ return JSC::toUInt32SlowCase(toNumber(exec), ok);
+}
+
+float JSValue::toFloat(ExecState* exec) const
+{
+ return static_cast<float>(toNumber(exec));
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h
new file mode 100644
index 0000000..059a5e6
--- /dev/null
+++ b/JavaScriptCore/runtime/JSValue.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef JSValue_h
+#define JSValue_h
+
+#include "CallData.h"
+#include "ConstructData.h"
+#include "JSImmediate.h"
+#include "ustring.h"
+#include <stddef.h> // for size_t
+
+// The magic number 0x4000 is not important here, it is being subtracted back out (avoiding using zero since this
+// can have unexpected effects in this type of macro, particularly where multiple-inheritance is involved).
+#define OBJECT_OFFSET(class, member) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->member)) - 0x4000)
+
+namespace JSC {
+
+ class Identifier;
+ class JSString;
+ class PropertySlot;
+ class PutPropertySlot;
+
+ struct ClassInfo;
+ struct Instruction;
+
+ enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
+
+ class JSValue : Noncopyable {
+ protected:
+ JSValue() { }
+ virtual ~JSValue() { }
+
+ public:
+ // Querying the type.
+ bool isUndefined() const;
+ bool isNull() const;
+ bool isUndefinedOrNull() const;
+ bool isBoolean() const;
+ bool isNumber() const;
+ bool isString() const;
+ bool isGetterSetter() const;
+ bool isObject() const;
+ bool isObject(const ClassInfo*) const;
+
+ // Extracting the value.
+ bool getBoolean(bool&) const;
+ bool getBoolean() const; // false if not a boolean
+ double getNumber() const; // NaN if not a number
+ double uncheckedGetNumber() const;
+ bool getString(UString&) const;
+ UString getString() const; // null string if not a string
+ JSObject* getObject() const; // 0 if not an object
+
+ CallType getCallData(CallData&);
+ ConstructType getConstructData(ConstructData&);
+
+ // Extracting integer values.
+ bool getUInt32(uint32_t&) const;
+ bool getTruncatedInt32(int32_t&) const;
+ bool getTruncatedUInt32(uint32_t&) const;
+
+ // Basic conversions.
+ JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+ bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
+
+ bool toBoolean(ExecState*) const;
+
+ // toNumber conversion is expected to be side effect free if an exception has
+ // been set in the ExecState already.
+ double toNumber(ExecState*) const;
+ JSValue* toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
+
+ UString toString(ExecState*) const;
+ JSObject* toObject(ExecState*) const;
+
+ // Integer conversions.
+ double toInteger(ExecState*) const;
+ double toIntegerPreserveNaN(ExecState*) const;
+ int32_t toInt32(ExecState*) const;
+ int32_t toInt32(ExecState*, bool& ok) const;
+ uint32_t toUInt32(ExecState*) const;
+ uint32_t toUInt32(ExecState*, bool& ok) const;
+
+ // Floating point conversions.
+ float toFloat(ExecState*) const;
+
+ // Garbage collection.
+ void mark();
+ bool marked() const;
+
+ // Object operations, with the toObject operation included.
+ JSValue* get(ExecState*, const Identifier& propertyName) const;
+ JSValue* get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
+ JSValue* get(ExecState*, unsigned propertyName) const;
+ JSValue* get(ExecState*, unsigned propertyName, PropertySlot&) const;
+ void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ void put(ExecState*, unsigned propertyName, JSValue*);
+ bool deleteProperty(ExecState*, const Identifier& propertyName);
+ bool deleteProperty(ExecState*, unsigned propertyName);
+
+ bool needsThisConversion() const;
+ JSObject* toThisObject(ExecState*) const;
+ UString toThisString(ExecState*) const;
+ JSString* toThisJSString(ExecState*);
+
+ JSValue* getJSNumber(); // 0 if this is not a JSNumber or number object
+
+ JSValue* asValue() const;
+
+ JSCell* asCell() const;
+
+ private:
+ bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ int32_t toInt32SlowCase(ExecState*, bool& ok) const;
+ uint32_t toUInt32SlowCase(ExecState*, bool& ok) const;
+ };
+
+ // These are identical logic to the JSValue functions above, and faster than jsNumber(number)->toInt32().
+ int32_t toInt32(double);
+ uint32_t toUInt32(double);
+ int32_t toInt32SlowCase(double, bool& ok);
+ uint32_t toUInt32SlowCase(double, bool& ok);
+
+ inline JSValue* JSValue::asValue() const
+ {
+ return const_cast<JSValue*>(this);
+ }
+
+ inline bool JSValue::isUndefined() const
+ {
+ return asValue() == jsUndefined();
+ }
+
+ inline bool JSValue::isNull() const
+ {
+ return asValue() == jsNull();
+ }
+
+ inline bool JSValue::isUndefinedOrNull() const
+ {
+ return JSImmediate::isUndefinedOrNull(asValue());
+ }
+
+ inline bool JSValue::isBoolean() const
+ {
+ return JSImmediate::isBoolean(asValue());
+ }
+
+ inline bool JSValue::getBoolean(bool& v) const
+ {
+ if (JSImmediate::isBoolean(asValue())) {
+ v = JSImmediate::toBoolean(asValue());
+ return true;
+ }
+
+ return false;
+ }
+
+ inline bool JSValue::getBoolean() const
+ {
+ return asValue() == jsBoolean(true);
+ }
+
+ ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
+ {
+ int32_t i;
+ if (getTruncatedInt32(i))
+ return i;
+ bool ok;
+ return toInt32SlowCase(exec, ok);
+ }
+
+ inline uint32_t JSValue::toUInt32(ExecState* exec) const
+ {
+ uint32_t i;
+ if (getTruncatedUInt32(i))
+ return i;
+ bool ok;
+ return toUInt32SlowCase(exec, ok);
+ }
+
+ inline int32_t toInt32(double val)
+ {
+ if (!(val >= -2147483648.0 && val < 2147483648.0)) {
+ bool ignored;
+ return toInt32SlowCase(val, ignored);
+ }
+ return static_cast<int32_t>(val);
+ }
+
+ inline uint32_t toUInt32(double val)
+ {
+ if (!(val >= 0.0 && val < 4294967296.0)) {
+ bool ignored;
+ return toUInt32SlowCase(val, ignored);
+ }
+ return static_cast<uint32_t>(val);
+ }
+
+ inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
+ {
+ int32_t i;
+ if (getTruncatedInt32(i)) {
+ ok = true;
+ return i;
+ }
+ return toInt32SlowCase(exec, ok);
+ }
+
+ inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
+ {
+ uint32_t i;
+ if (getTruncatedUInt32(i)) {
+ ok = true;
+ return i;
+ }
+ return toUInt32SlowCase(exec, ok);
+ }
+
+} // namespace JSC
+
+#endif // JSValue_h
diff --git a/JavaScriptCore/runtime/JSVariableObject.cpp b/JavaScriptCore/runtime/JSVariableObject.cpp
new file mode 100644
index 0000000..a36cefa
--- /dev/null
+++ b/JavaScriptCore/runtime/JSVariableObject.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSVariableObject.h"
+
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (symbolTable().contains(propertyName.ustring().rep()))
+ return false;
+
+ return JSObject::deleteProperty(exec, propertyName);
+}
+
+void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ SymbolTable::const_iterator end = symbolTable().end();
+ for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
+ if (!(it->second.getAttributes() & DontEnum))
+ propertyNames.add(Identifier(exec, it->first.get()));
+ }
+
+ JSObject::getPropertyNames(exec, propertyNames);
+}
+
+bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
+{
+ SymbolTableEntry entry = symbolTable().get(propertyName.ustring().rep());
+ if (!entry.isNull()) {
+ attributes = entry.getAttributes() | DontDelete;
+ return true;
+ }
+ return JSObject::getPropertyAttributes(exec, propertyName, attributes);
+}
+
+bool JSVariableObject::isVariableObject() const
+{
+ return true;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSVariableObject.h b/JavaScriptCore/runtime/JSVariableObject.h
new file mode 100644
index 0000000..1194517
--- /dev/null
+++ b/JavaScriptCore/runtime/JSVariableObject.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSVariableObject_h
+#define JSVariableObject_h
+
+#include "JSObject.h"
+#include "Register.h"
+#include "SymbolTable.h"
+#include "UnusedParam.h"
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/UnusedParam.h>
+
+namespace JSC {
+
+ class Register;
+
+ class JSVariableObject : public JSObject {
+ public:
+ SymbolTable& symbolTable() const { return *d->symbolTable; }
+
+ virtual void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes) = 0;
+
+ virtual bool deleteProperty(ExecState*, const Identifier&);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual bool isVariableObject() const;
+ virtual bool isDynamicScope() const = 0;
+
+ virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
+
+ Register& registerAt(int index) const { return d->registers[index]; }
+
+ protected:
+ // Subclasses of JSVariableObject can subclass this struct to add data
+ // without increasing their own size (since there's a hard limit on the
+ // size of a JSCell).
+ struct JSVariableObjectData {
+ JSVariableObjectData(SymbolTable* symbolTable, Register* registers)
+ : symbolTable(symbolTable)
+ , registers(registers)
+ {
+ ASSERT(symbolTable);
+ }
+
+ SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
+ Register* registers; // "r" in the register file.
+ OwnArrayPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
+
+ static inline ptrdiff_t offsetOf_registers()
+ {
+ return OBJECT_OFFSET(JSVariableObjectData, registers);
+ }
+
+ private:
+ JSVariableObjectData(const JSVariableObjectData&);
+ JSVariableObjectData& operator=(const JSVariableObjectData&);
+ };
+
+ JSVariableObject(PassRefPtr<StructureID> structureID, JSVariableObjectData* data)
+ : JSObject(structureID)
+ , d(data) // Subclass owns this pointer.
+ {
+ }
+
+ Register* copyRegisterArray(Register* src, size_t count);
+ void setRegisters(Register* r, Register* registerArray);
+
+ bool symbolTableGet(const Identifier&, PropertySlot&);
+ bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
+ bool symbolTablePut(const Identifier&, JSValue*);
+ bool symbolTablePutWithAttributes(const Identifier&, JSValue*, unsigned attributes);
+
+ JSVariableObjectData* d;
+
+ public:
+ static inline ptrdiff_t offsetOf_d()
+ {
+ return OBJECT_OFFSET(JSVariableObject, d);
+ }
+
+ static inline ptrdiff_t offsetOf_Data_registers()
+ {
+ return JSVariableObjectData::offsetOf_registers();
+ }
+ };
+
+ inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
+ {
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (!entry.isNull()) {
+ slot.setRegisterSlot(&registerAt(entry.getIndex()));
+ return true;
+ }
+ return false;
+ }
+
+ inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
+ {
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (!entry.isNull()) {
+ slot.setRegisterSlot(&registerAt(entry.getIndex()));
+ slotIsWriteable = !entry.isReadOnly();
+ return true;
+ }
+ return false;
+ }
+
+ inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue* value)
+ {
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (entry.isNull())
+ return false;
+ if (entry.isReadOnly())
+ return true;
+ registerAt(entry.getIndex()) = value;
+ return true;
+ }
+
+ inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue* value, unsigned attributes)
+ {
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+
+ SymbolTable::iterator iter = symbolTable().find(propertyName.ustring().rep());
+ if (iter == symbolTable().end())
+ return false;
+ SymbolTableEntry& entry = iter->second;
+ ASSERT(!entry.isNull());
+ entry.setAttributes(attributes);
+ registerAt(entry.getIndex()) = value;
+ return true;
+ }
+
+ inline Register* JSVariableObject::copyRegisterArray(Register* src, size_t count)
+ {
+ Register* registerArray = new Register[count];
+ memcpy(registerArray, src, count * sizeof(Register));
+
+ return registerArray;
+ }
+
+ inline void JSVariableObject::setRegisters(Register* registers, Register* registerArray)
+ {
+ ASSERT(registerArray != d->registerArray.get());
+ d->registerArray.set(registerArray);
+ d->registers = registers;
+ }
+
+} // namespace JSC
+
+#endif // JSVariableObject_h
diff --git a/JavaScriptCore/runtime/JSWrapperObject.cpp b/JavaScriptCore/runtime/JSWrapperObject.cpp
new file mode 100644
index 0000000..c791d93
--- /dev/null
+++ b/JavaScriptCore/runtime/JSWrapperObject.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2006 Maks Orlovich
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "JSWrapperObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
+
+void JSWrapperObject::mark()
+{
+ JSObject::mark();
+ if (m_internalValue && !m_internalValue->marked())
+ m_internalValue->mark();
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSWrapperObject.h b/JavaScriptCore/runtime/JSWrapperObject.h
new file mode 100644
index 0000000..5e4ba17
--- /dev/null
+++ b/JavaScriptCore/runtime/JSWrapperObject.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 Maks Orlovich
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef KJS_JSWrapperObject_h
+#define KJS_JSWrapperObject_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ // This class is used as a base for classes such as String,
+ // Number, Boolean and Date which are wrappers for primitive types.
+ class JSWrapperObject : public JSObject {
+ protected:
+ explicit JSWrapperObject(PassRefPtr<StructureID>);
+
+ public:
+ JSValue* internalValue() const { return m_internalValue; }
+ void setInternalValue(JSValue*);
+
+ virtual void mark();
+
+ private:
+ JSValue* m_internalValue;
+ };
+
+ inline JSWrapperObject::JSWrapperObject(PassRefPtr<StructureID> structure)
+ : JSObject(structure)
+ , m_internalValue(noValue())
+ {
+ }
+
+ inline void JSWrapperObject::setInternalValue(JSValue* value)
+ {
+ ASSERT(value);
+ ASSERT(!value->isObject());
+ m_internalValue = value;
+ }
+
+} // namespace JSC
+
+#endif // KJS_JSWrapperObject_h
diff --git a/JavaScriptCore/runtime/MathObject.cpp b/JavaScriptCore/runtime/MathObject.cpp
new file mode 100644
index 0000000..8b972d3
--- /dev/null
+++ b/JavaScriptCore/runtime/MathObject.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "MathObject.h"
+
+#include "ObjectPrototype.h"
+#include "operations.h"
+#include <time.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(MathObject);
+
+static JSValue* mathProtoFuncAbs(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncACos(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncASin(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncATan(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncATan2(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncCeil(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncCos(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncExp(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncFloor(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncLog(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncMax(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncMin(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncPow(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncRandom(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncRound(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncSin(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncSqrt(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* mathProtoFuncTan(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+}
+
+#include "MathObject.lut.h"
+
+namespace JSC {
+
+// ------------------------------ MathObject --------------------------------
+
+const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
+
+/* Source for MathObject.lut.h
+@begin mathTable
+ abs mathProtoFuncAbs DontEnum|Function 1
+ acos mathProtoFuncACos DontEnum|Function 1
+ asin mathProtoFuncASin DontEnum|Function 1
+ atan mathProtoFuncATan DontEnum|Function 1
+ atan2 mathProtoFuncATan2 DontEnum|Function 2
+ ceil mathProtoFuncCeil DontEnum|Function 1
+ cos mathProtoFuncCos DontEnum|Function 1
+ exp mathProtoFuncExp DontEnum|Function 1
+ floor mathProtoFuncFloor DontEnum|Function 1
+ log mathProtoFuncLog DontEnum|Function 1
+ max mathProtoFuncMax DontEnum|Function 2
+ min mathProtoFuncMin DontEnum|Function 2
+ pow mathProtoFuncPow DontEnum|Function 2
+ random mathProtoFuncRandom DontEnum|Function 0
+ round mathProtoFuncRound DontEnum|Function 1
+ sin mathProtoFuncSin DontEnum|Function 1
+ sqrt mathProtoFuncSqrt DontEnum|Function 1
+ tan mathProtoFuncTan DontEnum|Function 1
+@end
+*/
+
+MathObject::MathObject(ExecState* exec, PassRefPtr<StructureID> structure)
+ : JSObject(structure)
+{
+ putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "LN2"), jsNumber(exec, log(2.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "LN10"), jsNumber(exec, log(10.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "LOG2E"), jsNumber(exec, 1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "LOG10E"), jsNumber(exec, 1.0 / log(10.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
+}
+
+// ECMA 15.8
+
+bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+ const HashEntry* entry = ExecState::mathTable(exec)->entry(exec, propertyName);
+
+ if (!entry)
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+
+ ASSERT(entry->attributes() & Function);
+ setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
+ return true;
+}
+
+// ------------------------------ Functions --------------------------------
+
+JSValue* mathProtoFuncAbs(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, fabs(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncACos(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, acos(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncASin(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, asin(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncATan(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, atan(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, atan2(args.at(exec, 0)->toNumber(exec), args.at(exec, 1)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, ceil(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncCos(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, cos(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncExp(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, exp(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, floor(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncLog(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, log(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncMax(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ unsigned argsCount = args.size();
+ double result = -Inf;
+ for (unsigned k = 0; k < argsCount; ++k) {
+ double val = args.at(exec, k)->toNumber(exec);
+ if (isnan(val)) {
+ result = NaN;
+ break;
+ }
+ if (val > result || (val == 0 && result == 0 && !signbit(val)))
+ result = val;
+ }
+ return jsNumber(exec, result);
+}
+
+JSValue* mathProtoFuncMin(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ unsigned argsCount = args.size();
+ double result = +Inf;
+ for (unsigned k = 0; k < argsCount; ++k) {
+ double val = args.at(exec, k)->toNumber(exec);
+ if (isnan(val)) {
+ result = NaN;
+ break;
+ }
+ if (val < result || (val == 0 && result == 0 && signbit(val)))
+ result = val;
+ }
+ return jsNumber(exec, result);
+}
+
+JSValue* mathProtoFuncPow(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ // ECMA 15.8.2.1.13
+
+ double arg = args.at(exec, 0)->toNumber(exec);
+ double arg2 = args.at(exec, 1)->toNumber(exec);
+
+ if (isnan(arg2))
+ return jsNaN(exec);
+ if (isinf(arg2) && fabs(arg) == 1)
+ return jsNaN(exec);
+ return jsNumber(exec, pow(arg, arg2));
+}
+
+JSValue* mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue*, const ArgList&)
+{
+#if !ENABLE(JSC_MULTIPLE_THREADS)
+ static bool didInitRandom;
+ if (!didInitRandom) {
+ wtf_random_init();
+ didInitRandom = true;
+ }
+#endif
+
+ return jsNumber(exec, wtf_random());
+}
+
+JSValue* mathProtoFuncRound(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ double arg = args.at(exec, 0)->toNumber(exec);
+ if (signbit(arg) && arg >= -0.5)
+ return jsNumber(exec, -0.0);
+ return jsNumber(exec, floor(arg + 0.5));
+}
+
+JSValue* mathProtoFuncSin(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, sin(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, sqrt(args.at(exec, 0)->toNumber(exec)));
+}
+
+JSValue* mathProtoFuncTan(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, tan(args.at(exec, 0)->toNumber(exec)));
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/MathObject.h b/JavaScriptCore/runtime/MathObject.h
new file mode 100644
index 0000000..704b10e
--- /dev/null
+++ b/JavaScriptCore/runtime/MathObject.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef MathObject_h
+#define MathObject_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class MathObject : public JSObject {
+ public:
+ MathObject(ExecState*, PassRefPtr<StructureID>);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+ };
+
+} // namespace JSC
+
+#endif // MathObject_h
diff --git a/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/JavaScriptCore/runtime/NativeErrorConstructor.cpp
new file mode 100644
index 0000000..05159f0
--- /dev/null
+++ b/JavaScriptCore/runtime/NativeErrorConstructor.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "NativeErrorConstructor.h"
+
+#include "ErrorInstance.h"
+#include "JSFunction.h"
+#include "NativeErrorPrototype.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
+
+const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 };
+
+NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<StructureID> structure, NativeErrorPrototype* nativeErrorPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name)->getString()))
+ , m_errorStructure(ErrorInstance::createStructureID(nativeErrorPrototype))
+{
+ putDirect(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
+ putDirect(exec->propertyNames().prototype, nativeErrorPrototype, DontDelete | ReadOnly | DontEnum);
+}
+
+ErrorInstance* NativeErrorConstructor::construct(ExecState* exec, const ArgList& args)
+{
+ ErrorInstance* object = new (exec) ErrorInstance(m_errorStructure);
+ if (!args.at(exec, 0)->isUndefined())
+ object->putDirect(exec->propertyNames().message, jsString(exec, args.at(exec, 0)->toString(exec)));
+ return object;
+}
+
+static JSObject* constructWithNativeErrorConstructor(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args);
+}
+
+ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithNativeErrorConstructor;
+ return ConstructTypeHost;
+}
+
+static JSValue* callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValue*, const ArgList& args)
+{
+ return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args);
+}
+
+CallType NativeErrorConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callNativeErrorConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/NativeErrorConstructor.h b/JavaScriptCore/runtime/NativeErrorConstructor.h
new file mode 100644
index 0000000..85acbb9
--- /dev/null
+++ b/JavaScriptCore/runtime/NativeErrorConstructor.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NativeErrorConstructor_h
+#define NativeErrorConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class ErrorInstance;
+ class FunctionPrototype;
+ class NativeErrorPrototype;
+
+ class NativeErrorConstructor : public InternalFunction {
+ public:
+ NativeErrorConstructor(ExecState*, PassRefPtr<StructureID>, NativeErrorPrototype*);
+
+ static const ClassInfo info;
+
+ ErrorInstance* construct(ExecState*, const ArgList&);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ RefPtr<StructureID> m_errorStructure;
+ };
+
+} // namespace JSC
+
+#endif // NativeErrorConstructor_h
diff --git a/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/JavaScriptCore/runtime/NativeErrorPrototype.cpp
new file mode 100644
index 0000000..9403aa9
--- /dev/null
+++ b/JavaScriptCore/runtime/NativeErrorPrototype.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "NativeErrorPrototype.h"
+
+#include "ErrorPrototype.h"
+#include "JSString.h"
+#include "ustring.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
+
+NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, PassRefPtr<StructureID> structure, const UString& name, const UString& message)
+ : JSObject(structure)
+{
+ putDirect(exec->propertyNames().name, jsString(exec, name), 0);
+ putDirect(exec->propertyNames().message, jsString(exec, message), 0);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/NativeErrorPrototype.h b/JavaScriptCore/runtime/NativeErrorPrototype.h
new file mode 100644
index 0000000..719cb90
--- /dev/null
+++ b/JavaScriptCore/runtime/NativeErrorPrototype.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NativeErrorPrototype_h
+#define NativeErrorPrototype_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class NativeErrorPrototype : public JSObject {
+ public:
+ NativeErrorPrototype(ExecState*, PassRefPtr<StructureID>, const UString& name, const UString& message);
+ };
+
+} // namespace JSC
+
+#endif // NativeErrorPrototype_h
diff --git a/JavaScriptCore/runtime/NumberConstructor.cpp b/JavaScriptCore/runtime/NumberConstructor.cpp
new file mode 100644
index 0000000..5b6ccf8
--- /dev/null
+++ b/JavaScriptCore/runtime/NumberConstructor.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "NumberConstructor.h"
+
+#include "NumberObject.h"
+#include "NumberPrototype.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NumberConstructor);
+
+static JSValue* numberConstructorNaNValue(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* numberConstructorNegInfinity(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* numberConstructorPosInfinity(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* numberConstructorMaxValue(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* numberConstructorMinValue(ExecState*, const Identifier&, const PropertySlot&);
+
+} // namespace JSC
+
+#include "NumberConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::numberTable };
+
+/* Source for NumberConstructor.lut.h
+@begin numberTable
+ NaN numberConstructorNaNValue DontEnum|DontDelete|ReadOnly
+ NEGATIVE_INFINITY numberConstructorNegInfinity DontEnum|DontDelete|ReadOnly
+ POSITIVE_INFINITY numberConstructorPosInfinity DontEnum|DontDelete|ReadOnly
+ MAX_VALUE numberConstructorMaxValue DontEnum|DontDelete|ReadOnly
+ MIN_VALUE numberConstructorMinValue DontEnum|DontDelete|ReadOnly
+@end
+*/
+
+NumberConstructor::NumberConstructor(ExecState* exec, PassRefPtr<StructureID> structure, NumberPrototype* numberPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, numberPrototype->info.className))
+{
+ // Number.Prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+}
+
+bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);
+}
+
+JSValue* numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNaN(exec);
+}
+
+JSValue* numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNumberCell(exec, -Inf);
+}
+
+JSValue* numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNumberCell(exec, Inf);
+}
+
+JSValue* numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNumberCell(exec, 1.7976931348623157E+308);
+}
+
+JSValue* numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&)
+{
+ return jsNumberCell(exec, 5E-324);
+}
+
+// ECMA 15.7.1
+static JSObject* constructWithNumberConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
+ double n = args.isEmpty() ? 0 : args.at(exec, 0)->toNumber(exec);
+ object->setInternalValue(jsNumber(exec, n));
+ return object;
+}
+
+ConstructType NumberConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithNumberConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.7.2
+static JSValue* callNumberConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return jsNumber(exec, args.isEmpty() ? 0 : args.at(exec, 0)->toNumber(exec));
+}
+
+CallType NumberConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callNumberConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/NumberConstructor.h b/JavaScriptCore/runtime/NumberConstructor.h
new file mode 100644
index 0000000..8da23c4
--- /dev/null
+++ b/JavaScriptCore/runtime/NumberConstructor.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NumberConstructor_h
+#define NumberConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class NumberPrototype;
+
+ class NumberConstructor : public InternalFunction {
+ public:
+ NumberConstructor(ExecState*, PassRefPtr<StructureID>, NumberPrototype*);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ JSValue* getValueProperty(ExecState*, int token) const;
+
+ static const ClassInfo info;
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto)
+ {
+ return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance));
+ }
+
+ enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ };
+
+} // namespace JSC
+
+#endif // NumberConstructor_h
diff --git a/JavaScriptCore/runtime/NumberObject.cpp b/JavaScriptCore/runtime/NumberObject.cpp
new file mode 100644
index 0000000..252671b
--- /dev/null
+++ b/JavaScriptCore/runtime/NumberObject.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "NumberObject.h"
+
+#include "JSGlobalObject.h"
+#include "NumberPrototype.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NumberObject);
+
+const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };
+
+NumberObject::NumberObject(PassRefPtr<StructureID> structure)
+ : JSWrapperObject(structure)
+{
+}
+
+JSValue* NumberObject::getJSNumber()
+{
+ return internalValue();
+}
+
+NumberObject* constructNumber(ExecState* exec, JSNumberCell* number)
+{
+ NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
+ object->setInternalValue(number);
+ return object;
+}
+
+NumberObject* constructNumberFromImmediateNumber(ExecState* exec, JSValue* value)
+{
+ NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
+ object->setInternalValue(value);
+ return object;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/NumberObject.h b/JavaScriptCore/runtime/NumberObject.h
new file mode 100644
index 0000000..eddecd1
--- /dev/null
+++ b/JavaScriptCore/runtime/NumberObject.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NumberObject_h
+#define NumberObject_h
+
+#include "JSWrapperObject.h"
+
+namespace JSC {
+
+ class JSNumberCell;
+
+ class NumberObject : public JSWrapperObject {
+ public:
+ explicit NumberObject(PassRefPtr<StructureID>);
+
+ static const ClassInfo info;
+
+ private:
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ virtual JSValue* getJSNumber();
+ };
+
+ NumberObject* constructNumber(ExecState*, JSNumberCell*);
+ NumberObject* constructNumberFromImmediateNumber(ExecState*, JSValue*);
+
+} // namespace JSC
+
+#endif // NumberObject_h
diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp
new file mode 100644
index 0000000..d203e3f
--- /dev/null
+++ b/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ *
+ */
+
+#include "config.h"
+#include "NumberPrototype.h"
+
+#include "Error.h"
+#include "JSString.h"
+#include "PrototypeFunction.h"
+#include "dtoa.h"
+#include "operations.h"
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
+
+static JSValue* numberProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* numberProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* numberProtoFuncToFixed(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* numberProtoFuncToExponential(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* numberProtoFuncToPrecision(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+// ECMA 15.7.4
+
+NumberPrototype::NumberPrototype(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure)
+ : NumberObject(structure)
+{
+ setInternalValue(jsNumber(exec, 0));
+
+ // The constructor will be added later, after NumberConstructor has been constructed
+
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);
+}
+
+// ------------------------------ Functions ---------------------------
+
+// ECMA 15.7.4.2 - 15.7.4.7
+
+static UString integerPartNoExp(double d)
+{
+ int decimalPoint;
+ int sign;
+ char* result = dtoa(d, 0, &decimalPoint, &sign, NULL);
+ bool resultIsInfOrNan = (decimalPoint == 9999);
+ size_t length = strlen(result);
+
+ UString str = sign ? "-" : "";
+ if (resultIsInfOrNan)
+ str += result;
+ else if (decimalPoint <= 0)
+ str += "0";
+ else {
+ Vector<char, 1024> buf(decimalPoint + 1);
+
+ if (static_cast<int>(length) <= decimalPoint) {
+ strcpy(buf.data(), result);
+ memset(buf.data() + length, '0', decimalPoint - length);
+ } else
+ strncpy(buf.data(), result, decimalPoint);
+
+ buf[decimalPoint] = '\0';
+ str.append(buf.data());
+ }
+
+ freedtoa(result);
+
+ return str;
+}
+
+static UString charSequence(char c, int count)
+{
+ Vector<char, 2048> buf(count + 1, c);
+ buf[count] = '\0';
+
+ return UString(buf.data());
+}
+
+static double intPow10(int e)
+{
+ // This function uses the "exponentiation by squaring" algorithm and
+ // long double to quickly and precisely calculate integer powers of 10.0.
+
+ // This is a handy workaround for <rdar://problem/4494756>
+
+ if (e == 0)
+ return 1.0;
+
+ bool negative = e < 0;
+ unsigned exp = negative ? -e : e;
+
+ long double result = 10.0;
+ bool foundOne = false;
+ for (int bit = 31; bit >= 0; bit--) {
+ if (!foundOne) {
+ if ((exp >> bit) & 1)
+ foundOne = true;
+ } else {
+ result = result * result;
+ if ((exp >> bit) & 1)
+ result = result * 10.0;
+ }
+ }
+
+ if (negative)
+ return static_cast<double>(1.0 / result);
+ return static_cast<double>(result);
+}
+
+JSValue* numberProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSValue* v = thisValue->getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ double radixAsDouble = args.at(exec, 0)->toInteger(exec); // nan -> 0
+ if (radixAsDouble == 10 || args.at(exec, 0)->isUndefined())
+ return jsString(exec, v->toString(exec));
+
+ if (radixAsDouble < 2 || radixAsDouble > 36)
+ return throwError(exec, RangeError, "toString() radix argument must be between 2 and 36");
+
+ int radix = static_cast<int>(radixAsDouble);
+ const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ // INT_MAX results in 1024 characters left of the dot with radix 2
+ // give the same space on the right side. safety checks are in place
+ // unless someone finds a precise rule.
+ char s[2048 + 3];
+ const char* lastCharInString = s + sizeof(s) - 1;
+ double x = v->uncheckedGetNumber();
+ if (isnan(x) || isinf(x))
+ return jsString(exec, UString::from(x));
+
+ bool isNegative = x < 0.0;
+ if (isNegative)
+ x = -x;
+
+ double integerPart = floor(x);
+ char* decimalPoint = s + sizeof(s) / 2;
+
+ // convert integer portion
+ char* p = decimalPoint;
+ double d = integerPart;
+ do {
+ int remainderDigit = static_cast<int>(fmod(d, radix));
+ *--p = digits[remainderDigit];
+ d /= radix;
+ } while ((d <= -1.0 || d >= 1.0) && s < p);
+
+ if (isNegative)
+ *--p = '-';
+ char* startOfResultString = p;
+ ASSERT(s <= startOfResultString);
+
+ d = x - integerPart;
+ p = decimalPoint;
+ const double epsilon = 0.001; // TODO: guessed. base on radix ?
+ bool hasFractionalPart = (d < -epsilon || d > epsilon);
+ if (hasFractionalPart) {
+ *p++ = '.';
+ do {
+ d *= radix;
+ const int digit = static_cast<int>(d);
+ *p++ = digits[digit];
+ d -= digit;
+ } while ((d < -epsilon || d > epsilon) && p < lastCharInString);
+ }
+ *p = '\0';
+ ASSERT(p < s + sizeof(s));
+
+ return jsString(exec, startOfResultString);
+}
+
+JSValue* numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ // FIXME: Not implemented yet.
+
+ JSValue* v = thisValue->getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ return jsString(exec, v->toString(exec));
+}
+
+JSValue* numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ JSValue* v = thisValue->getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ return v;
+}
+
+JSValue* numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSValue* v = thisValue->getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ JSValue* fractionDigits = args.at(exec, 0);
+ double df = fractionDigits->toInteger(exec);
+ if (!(df >= 0 && df <= 20))
+ return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20");
+ int f = static_cast<int>(df);
+
+ double x = v->uncheckedGetNumber();
+ if (isnan(x))
+ return jsNontrivialString(exec, "NaN");
+
+ UString s;
+ if (x < 0) {
+ s.append('-');
+ x = -x;
+ } else if (x == -0.0)
+ x = 0;
+
+ if (x >= pow(10.0, 21.0))
+ return jsString(exec, s + UString::from(x));
+
+ const double tenToTheF = pow(10.0, f);
+ double n = floor(x * tenToTheF);
+ if (fabs(n / tenToTheF - x) >= fabs((n + 1) / tenToTheF - x))
+ n++;
+
+ UString m = integerPartNoExp(n);
+
+ int k = m.size();
+ if (k <= f) {
+ UString z;
+ for (int i = 0; i < f + 1 - k; i++)
+ z.append('0');
+ m = z + m;
+ k = f + 1;
+ ASSERT(k == m.size());
+ }
+ int kMinusf = k - f;
+ if (kMinusf < m.size())
+ return jsString(exec, s + m.substr(0, kMinusf) + "." + m.substr(kMinusf));
+ return jsString(exec, s + m.substr(0, kMinusf));
+}
+
+static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)
+{
+ if (fractionalDigits <= 0)
+ return;
+
+ int fDigitsInResult = static_cast<int>(resultLength) - 1;
+ buf[i++] = '.';
+ if (fDigitsInResult > 0) {
+ if (fractionalDigits < fDigitsInResult) {
+ strncpy(buf + i, result + 1, fractionalDigits);
+ i += fractionalDigits;
+ } else {
+ strcpy(buf + i, result + 1);
+ i += static_cast<int>(resultLength) - 1;
+ }
+ }
+
+ for (int j = 0; j < fractionalDigits - fDigitsInResult; j++)
+ buf[i++] = '0';
+}
+
+static void exponentialPartToString(char* buf, int& i, int decimalPoint)
+{
+ buf[i++] = 'e';
+ // decimalPoint can't be more than 3 digits decimal given the
+ // nature of float representation
+ int exponential = decimalPoint - 1;
+ buf[i++] = (exponential >= 0) ? '+' : '-';
+ if (exponential < 0)
+ exponential *= -1;
+ if (exponential >= 100)
+ buf[i++] = static_cast<char>('0' + exponential / 100);
+ if (exponential >= 10)
+ buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
+ buf[i++] = static_cast<char>('0' + exponential % 10);
+}
+
+JSValue* numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSValue* v = thisValue->getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ double x = v->uncheckedGetNumber();
+
+ if (isnan(x) || isinf(x))
+ return jsString(exec, UString::from(x));
+
+ JSValue* fractionalDigitsValue = args.at(exec, 0);
+ double df = fractionalDigitsValue->toInteger(exec);
+ if (!(df >= 0 && df <= 20))
+ return throwError(exec, RangeError, "toExponential() argument must between 0 and 20");
+ int fractionalDigits = static_cast<int>(df);
+ bool includeAllDigits = fractionalDigitsValue->isUndefined();
+
+ int decimalAdjust = 0;
+ if (x && !includeAllDigits) {
+ double logx = floor(log10(fabs(x)));
+ x /= pow(10.0, logx);
+ const double tenToTheF = pow(10.0, fractionalDigits);
+ double fx = floor(x * tenToTheF) / tenToTheF;
+ double cx = ceil(x * tenToTheF) / tenToTheF;
+
+ if (fabs(fx - x) < fabs(cx - x))
+ x = fx;
+ else
+ x = cx;
+
+ decimalAdjust = static_cast<int>(logx);
+ }
+
+ if (isnan(x))
+ return jsNontrivialString(exec, "NaN");
+
+ if (x == -0.0) // (-0.0).toExponential() should print as 0 instead of -0
+ x = 0;
+
+ int decimalPoint;
+ int sign;
+ char* result = dtoa(x, 0, &decimalPoint, &sign, NULL);
+ size_t resultLength = strlen(result);
+ decimalPoint += decimalAdjust;
+
+ int i = 0;
+ char buf[80]; // digit + '.' + fractionDigits (max 20) + 'e' + sign + exponent (max?)
+ if (sign)
+ buf[i++] = '-';
+
+ if (decimalPoint == 999) // ? 9999 is the magical "result is Inf or NaN" value. what's 999??
+ strcpy(buf + i, result);
+ else {
+ buf[i++] = result[0];
+
+ if (includeAllDigits)
+ fractionalDigits = static_cast<int>(resultLength) - 1;
+
+ fractionalPartToString(buf, i, result, resultLength, fractionalDigits);
+ exponentialPartToString(buf, i, decimalPoint);
+ buf[i++] = '\0';
+ }
+ ASSERT(i <= 80);
+
+ freedtoa(result);
+
+ return jsString(exec, buf);
+}
+
+JSValue* numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSValue* v = thisValue->getJSNumber();
+ if (!v)
+ return throwError(exec, TypeError);
+
+ double doublePrecision = args.at(exec, 0)->toIntegerPreserveNaN(exec);
+ double x = v->uncheckedGetNumber();
+ if (args.at(exec, 0)->isUndefined() || isnan(x) || isinf(x))
+ return jsString(exec, v->toString(exec));
+
+ UString s;
+ if (x < 0) {
+ s = "-";
+ x = -x;
+ }
+
+ if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN
+ return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21");
+ int precision = static_cast<int>(doublePrecision);
+
+ int e = 0;
+ UString m;
+ if (x) {
+ e = static_cast<int>(log10(x));
+ double tens = intPow10(e - precision + 1);
+ double n = floor(x / tens);
+ if (n < intPow10(precision - 1)) {
+ e = e - 1;
+ tens = intPow10(e - precision + 1);
+ n = floor(x / tens);
+ }
+
+ if (fabs((n + 1.0) * tens - x) <= fabs(n * tens - x))
+ ++n;
+ // maintain n < 10^(precision)
+ if (n >= intPow10(precision)) {
+ n /= 10.0;
+ e += 1;
+ }
+ ASSERT(intPow10(precision - 1) <= n);
+ ASSERT(n < intPow10(precision));
+
+ m = integerPartNoExp(n);
+ if (e < -6 || e >= precision) {
+ if (m.size() > 1)
+ m = m.substr(0, 1) + "." + m.substr(1);
+ if (e >= 0)
+ return jsNontrivialString(exec, s + m + "e+" + UString::from(e));
+ return jsNontrivialString(exec, s + m + "e-" + UString::from(-e));
+ }
+ } else {
+ m = charSequence('0', precision);
+ e = 0;
+ }
+
+ if (e == precision - 1)
+ return jsString(exec, s + m);
+ if (e >= 0) {
+ if (e + 1 < m.size())
+ return jsString(exec, s + m.substr(0, e + 1) + "." + m.substr(e + 1));
+ return jsString(exec, s + m);
+ }
+ return jsNontrivialString(exec, s + "0." + charSequence('0', -(e + 1)) + m);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/NumberPrototype.h b/JavaScriptCore/runtime/NumberPrototype.h
new file mode 100644
index 0000000..d70f260
--- /dev/null
+++ b/JavaScriptCore/runtime/NumberPrototype.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef NumberPrototype_h
+#define NumberPrototype_h
+
+#include "NumberObject.h"
+
+namespace JSC {
+
+ class NumberPrototype : public NumberObject {
+ public:
+ NumberPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure);
+ };
+
+} // namespace JSC
+
+#endif // NumberPrototype_h
diff --git a/JavaScriptCore/runtime/ObjectConstructor.cpp b/JavaScriptCore/runtime/ObjectConstructor.cpp
new file mode 100644
index 0000000..329816f
--- /dev/null
+++ b/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ObjectConstructor.h"
+
+#include "JSGlobalObject.h"
+#include "ObjectPrototype.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
+
+ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<StructureID> structure, ObjectPrototype* objectPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
+{
+ // ECMA 15.2.3.1
+ putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+}
+
+// ECMA 15.2.2
+static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args)
+{
+ JSValue* arg = args.at(exec, 0);
+ if (arg->isUndefinedOrNull())
+ return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+ return arg->toObject(exec);
+}
+
+static JSObject* constructWithObjectConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructObject(exec, args);
+}
+
+ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithObjectConstructor;
+ return ConstructTypeHost;
+}
+
+static JSValue* callObjectConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return constructObject(exec, args);
+}
+
+CallType ObjectConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callObjectConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ObjectConstructor.h b/JavaScriptCore/runtime/ObjectConstructor.h
new file mode 100644
index 0000000..c100424
--- /dev/null
+++ b/JavaScriptCore/runtime/ObjectConstructor.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ObjectConstructor_h
+#define ObjectConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class ObjectPrototype;
+
+ class ObjectConstructor : public InternalFunction {
+ public:
+ ObjectConstructor(ExecState*, PassRefPtr<StructureID>, ObjectPrototype*);
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+} // namespace JSC
+
+#endif // ObjectConstructor_h
diff --git a/JavaScriptCore/runtime/ObjectPrototype.cpp b/JavaScriptCore/runtime/ObjectPrototype.cpp
new file mode 100644
index 0000000..42a8063
--- /dev/null
+++ b/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "ObjectPrototype.h"
+
+#include "Error.h"
+#include "JSString.h"
+#include "PrototypeFunction.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype);
+
+static JSValue* objectProtoFuncValueOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<StructureID> stucture, StructureID* prototypeFunctionStructure)
+ : JSObject(stucture)
+{
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum);
+
+ // Mozilla extensions
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
+}
+
+// ------------------------------ Functions --------------------------------
+
+// ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
+
+JSValue* objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ return thisValue->toThisObject(exec);
+}
+
+JSValue* objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ return jsBoolean(thisValue->toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(exec, 0)->toString(exec))));
+}
+
+JSValue* objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSObject* thisObj = thisValue->toThisObject(exec);
+
+ if (!args.at(exec, 0)->isObject())
+ return jsBoolean(false);
+
+ JSValue* v = asObject(args.at(exec, 0))->prototype();
+
+ while (true) {
+ if (!v->isObject())
+ return jsBoolean(false);
+ if (thisObj == v)
+ return jsBoolean(true);
+ v = asObject(v)->prototype();
+ }
+}
+
+JSValue* objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ CallData callData;
+ if (args.at(exec, 1)->getCallData(callData) == CallTypeNone)
+ return throwError(exec, SyntaxError, "invalid getter usage");
+ thisValue->toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec)), asObject(args.at(exec, 1)));
+ return jsUndefined();
+}
+
+JSValue* objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ CallData callData;
+ if (args.at(exec, 1)->getCallData(callData) == CallTypeNone)
+ return throwError(exec, SyntaxError, "invalid setter usage");
+ thisValue->toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec)), asObject(args.at(exec, 1)));
+ return jsUndefined();
+}
+
+JSValue* objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ return thisValue->toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec)));
+}
+
+JSValue* objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ return thisValue->toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(exec, 0)->toString(exec)));
+}
+
+JSValue* objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ return jsBoolean(thisValue->toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(exec, 0)->toString(exec))));
+}
+
+JSValue* objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ return thisValue->toThisJSString(exec);
+}
+
+JSValue* objectProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ return jsNontrivialString(exec, "[object " + thisValue->toThisObject(exec)->className() + "]");
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ObjectPrototype.h b/JavaScriptCore/runtime/ObjectPrototype.h
new file mode 100644
index 0000000..aefdf95
--- /dev/null
+++ b/JavaScriptCore/runtime/ObjectPrototype.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef ObjectPrototype_h
+#define ObjectPrototype_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class ObjectPrototype : public JSObject {
+ public:
+ ObjectPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure);
+ };
+
+ JSValue* objectProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+} // namespace JSC
+
+#endif // ObjectPrototype_h
diff --git a/JavaScriptCore/runtime/PropertyMapHashTable.h b/JavaScriptCore/runtime/PropertyMapHashTable.h
new file mode 100644
index 0000000..98b0727
--- /dev/null
+++ b/JavaScriptCore/runtime/PropertyMapHashTable.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PropertyMapHashTable_h
+#define PropertyMapHashTable_h
+
+#include "ustring.h"
+
+namespace JSC {
+
+ struct PropertyMapEntry {
+ UString::Rep* key;
+ unsigned offset;
+ unsigned attributes;
+ unsigned index;
+
+ PropertyMapEntry(UString::Rep* k, int a)
+ : key(k)
+ , offset(0)
+ , attributes(a)
+ , index(0)
+ {
+ }
+ };
+
+ // lastIndexUsed is an ever-increasing index used to identify the order items
+ // were inserted into the property map. It's required that getEnumerablePropertyNames
+ // return the properties in the order they were added for compatibility with other
+ // browsers' JavaScript implementations.
+ struct PropertyMapHashTable {
+ unsigned sizeMask;
+ unsigned size;
+ unsigned keyCount;
+ unsigned deletedSentinelCount;
+ unsigned lastIndexUsed;
+ unsigned entryIndices[1];
+
+ PropertyMapEntry* entries()
+ {
+ // The entries vector comes after the indices vector.
+ // The 0th item in the entries vector is not really used; it has to
+ // have a 0 in its key to allow the hash table lookup to handle deleted
+ // sentinels without any special-case code, but the other fields are unused.
+ return reinterpret_cast<PropertyMapEntry*>(&entryIndices[size]);
+ }
+
+ static size_t allocationSize(unsigned size)
+ {
+ // We never let a hash table get more than half full,
+ // So the number of indices we need is the size of the hash table.
+ // But the number of entries is half that (plus one for the deleted sentinel).
+ return sizeof(PropertyMapHashTable)
+ + (size - 1) * sizeof(unsigned)
+ + (1 + size / 2) * sizeof(PropertyMapEntry);
+ }
+ };
+
+} // namespace JSC
+
+#endif // PropertyMapHashTable_h
diff --git a/JavaScriptCore/runtime/PropertyNameArray.cpp b/JavaScriptCore/runtime/PropertyNameArray.cpp
new file mode 100644
index 0000000..47e9d84
--- /dev/null
+++ b/JavaScriptCore/runtime/PropertyNameArray.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+static const size_t setThreshold = 20;
+
+void PropertyNameArray::add(UString::Rep* identifier)
+{
+ ASSERT(identifier == &UString::Rep::null || identifier == &UString::Rep::empty || identifier->identifierTable());
+
+ size_t size = m_data->propertyNameVector().size();
+ if (size < setThreshold) {
+ for (size_t i = 0; i < size; ++i) {
+ if (identifier == m_data->propertyNameVector()[i].ustring().rep())
+ return;
+ }
+ } else {
+ if (m_set.isEmpty()) {
+ for (size_t i = 0; i < size; ++i)
+ m_set.add(m_data->propertyNameVector()[i].ustring().rep());
+ }
+ if (!m_set.add(identifier).second)
+ return;
+ }
+
+ m_data->propertyNameVector().append(Identifier(m_globalData, identifier));
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/PropertyNameArray.h b/JavaScriptCore/runtime/PropertyNameArray.h
new file mode 100644
index 0000000..d19c2e5
--- /dev/null
+++ b/JavaScriptCore/runtime/PropertyNameArray.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PropertyNameArray_h
+#define PropertyNameArray_h
+
+#include "ExecState.h"
+#include "StructureID.h"
+#include "identifier.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+ class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
+ public:
+ typedef Vector<Identifier, 20> PropertyNameVector;
+ typedef PropertyNameVector::const_iterator const_iterator;
+
+ static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); }
+
+ const_iterator begin() const { return m_propertyNameVector.begin(); }
+ const_iterator end() const { return m_propertyNameVector.end(); }
+
+ PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
+
+ void setCachedStructureID(StructureID* structureID) { m_cachedStructureID = structureID; }
+ StructureID* cachedStructureID() const { return m_cachedStructureID; }
+
+ void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+ StructureIDChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
+
+ private:
+ PropertyNameArrayData()
+ : m_cachedStructureID(0)
+ {
+ }
+
+ PropertyNameVector m_propertyNameVector;
+ StructureID* m_cachedStructureID;
+ RefPtr<StructureIDChain> m_cachedPrototypeChain;
+ };
+
+ class PropertyNameArray {
+ public:
+ typedef PropertyNameArrayData::const_iterator const_iterator;
+
+ PropertyNameArray(JSGlobalData* globalData)
+ : m_data(PropertyNameArrayData::create())
+ , m_globalData(globalData)
+ , m_cacheable(true)
+ {
+ }
+
+ PropertyNameArray(ExecState* exec)
+ : m_data(PropertyNameArrayData::create())
+ , m_globalData(&exec->globalData())
+ , m_cacheable(true)
+ {
+ }
+
+ JSGlobalData* globalData() { return m_globalData; }
+
+ void add(const Identifier& identifier) { add(identifier.ustring().rep()); }
+ void add(UString::Rep*);
+ void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
+
+ size_t size() const { return m_data->propertyNameVector().size(); }
+
+ Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
+ const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
+
+ const_iterator begin() const { return m_data->begin(); }
+ const_iterator end() const { return m_data->end(); }
+
+ void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; }
+ PropertyNameArrayData* data() { return m_data.get(); }
+
+ PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
+
+ void setCacheable(bool cacheable) { m_cacheable = cacheable; }
+ bool cacheable() const { return m_cacheable; }
+
+ private:
+ typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
+
+ RefPtr<PropertyNameArrayData> m_data;
+ IdentifierSet m_set;
+ JSGlobalData* m_globalData;
+ bool m_cacheable;
+ };
+
+} // namespace JSC
+
+#endif // PropertyNameArray_h
diff --git a/JavaScriptCore/runtime/PropertySlot.cpp b/JavaScriptCore/runtime/PropertySlot.cpp
new file mode 100644
index 0000000..37df83a
--- /dev/null
+++ b/JavaScriptCore/runtime/PropertySlot.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "PropertySlot.h"
+
+#include "JSFunction.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+
+namespace JSC {
+
+JSValue* PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ // Prevent getter functions from observing execution if an exception is pending.
+ if (exec->hadException())
+ return exec->exception();
+
+ CallData callData;
+ CallType callType = slot.m_data.getterFunc->getCallData(callData);
+ if (callType == CallTypeHost)
+ return callData.native.function(exec, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList());
+ ASSERT(callType == CallTypeJS);
+ // FIXME: Can this be done more efficiently using the callData?
+ return static_cast<JSFunction*>(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList());
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/PropertySlot.h b/JavaScriptCore/runtime/PropertySlot.h
new file mode 100644
index 0000000..29c19d4
--- /dev/null
+++ b/JavaScriptCore/runtime/PropertySlot.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PropertySlot_h
+#define PropertySlot_h
+
+#include "Register.h"
+#include "JSValue.h"
+#include "identifier.h"
+#include <wtf/Assertions.h>
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+ class ExecState;
+ class JSObject;
+
+#define JSC_VALUE_SLOT_MARKER 0
+#define JSC_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
+
+ class PropertySlot {
+ public:
+ PropertySlot()
+ : m_offset(WTF::notFound)
+ {
+ clearBase();
+ clearValue();
+ }
+
+ explicit PropertySlot(const JSValue* base)
+ : m_slotBase(const_cast<JSValue*>(base))
+ , m_offset(WTF::notFound)
+ {
+ clearValue();
+ }
+
+ typedef JSValue* (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
+
+ JSValue* getValue(ExecState* exec, const Identifier& propertyName) const
+ {
+ if (m_getValue == JSC_VALUE_SLOT_MARKER)
+ return *m_data.valueSlot;
+ if (m_getValue == JSC_REGISTER_SLOT_MARKER)
+ return (*m_data.registerSlot).jsValue(exec);
+ return m_getValue(exec, propertyName, *this);
+ }
+
+ JSValue* getValue(ExecState* exec, unsigned propertyName) const
+ {
+ if (m_getValue == JSC_VALUE_SLOT_MARKER)
+ return *m_data.valueSlot;
+ if (m_getValue == JSC_REGISTER_SLOT_MARKER)
+ return (*m_data.registerSlot).jsValue(exec);
+ return m_getValue(exec, Identifier::from(exec, propertyName), *this);
+ }
+
+ bool isCacheable() const { return m_offset != WTF::notFound; }
+ size_t cachedOffset() const
+ {
+ ASSERT(isCacheable());
+ return m_offset;
+ }
+
+ void putValue(JSValue* value)
+ {
+ if (m_getValue == JSC_VALUE_SLOT_MARKER) {
+ *m_data.valueSlot = value;
+ return;
+ }
+ ASSERT(m_getValue == JSC_REGISTER_SLOT_MARKER);
+ *m_data.registerSlot = value;
+ }
+
+ void setValueSlot(JSValue** valueSlot)
+ {
+ ASSERT(valueSlot);
+ m_getValue = JSC_VALUE_SLOT_MARKER;
+ clearBase();
+ m_data.valueSlot = valueSlot;
+ }
+
+ void setValueSlot(JSValue* slotBase, JSValue** valueSlot)
+ {
+ ASSERT(valueSlot);
+ m_getValue = JSC_VALUE_SLOT_MARKER;
+ m_slotBase = slotBase;
+ m_data.valueSlot = valueSlot;
+ }
+
+ void setValueSlot(JSValue* slotBase, JSValue** valueSlot, size_t offset)
+ {
+ ASSERT(valueSlot);
+ m_getValue = JSC_VALUE_SLOT_MARKER;
+ m_slotBase = slotBase;
+ m_data.valueSlot = valueSlot;
+ m_offset = offset;
+ }
+
+ void setValue(JSValue* value)
+ {
+ ASSERT(value);
+ m_getValue = JSC_VALUE_SLOT_MARKER;
+ clearBase();
+ m_value = value;
+ m_data.valueSlot = &m_value;
+ }
+
+ void setRegisterSlot(Register* registerSlot)
+ {
+ ASSERT(registerSlot);
+ m_getValue = JSC_REGISTER_SLOT_MARKER;
+ clearBase();
+ m_data.registerSlot = registerSlot;
+ }
+
+ void setCustom(JSValue* slotBase, GetValueFunc getValue)
+ {
+ ASSERT(slotBase);
+ ASSERT(getValue);
+ m_getValue = getValue;
+ m_slotBase = slotBase;
+ }
+
+ void setCustomIndex(JSValue* slotBase, unsigned index, GetValueFunc getValue)
+ {
+ ASSERT(slotBase);
+ ASSERT(getValue);
+ m_getValue = getValue;
+ m_slotBase = slotBase;
+ m_data.index = index;
+ }
+
+ void setGetterSlot(JSObject* getterFunc)
+ {
+ ASSERT(getterFunc);
+ m_getValue = functionGetter;
+ m_data.getterFunc = getterFunc;
+ }
+
+ void setUndefined()
+ {
+ clearBase();
+ setValue(jsUndefined());
+ }
+
+ JSValue* slotBase() const
+ {
+ ASSERT(m_slotBase);
+ return m_slotBase;
+ }
+
+ void setBase(JSValue* base)
+ {
+ ASSERT(m_slotBase);
+ ASSERT(base);
+ m_slotBase = base;
+ }
+
+ void clearBase()
+ {
+#ifndef NDEBUG
+ m_slotBase = noValue();
+#endif
+ }
+
+ void clearValue()
+ {
+#ifndef NDEBUG
+ m_value = noValue();
+#endif
+ }
+
+ unsigned index() const { return m_data.index; }
+
+ private:
+ static JSValue* functionGetter(ExecState*, const Identifier&, const PropertySlot&);
+
+ GetValueFunc m_getValue;
+
+ JSValue* m_slotBase;
+ union {
+ JSObject* getterFunc;
+ JSValue** valueSlot;
+ Register* registerSlot;
+ unsigned index;
+ } m_data;
+
+ JSValue* m_value;
+
+ size_t m_offset;
+ };
+
+} // namespace JSC
+
+#endif // PropertySlot_h
diff --git a/JavaScriptCore/runtime/PrototypeFunction.cpp b/JavaScriptCore/runtime/PrototypeFunction.cpp
new file mode 100644
index 0000000..8afe6a4
--- /dev/null
+++ b/JavaScriptCore/runtime/PrototypeFunction.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "PrototypeFunction.h"
+
+#include "JSGlobalObject.h"
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(PrototypeFunction);
+
+PrototypeFunction::PrototypeFunction(ExecState* exec, int length, const Identifier& name, NativeFunction function)
+ : InternalFunction(&exec->globalData(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), name)
+ , m_function(function)
+{
+ ASSERT_ARG(function, function);
+ putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
+}
+
+PrototypeFunction::PrototypeFunction(ExecState* exec, PassRefPtr<StructureID> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function)
+ : InternalFunction(&exec->globalData(), prototypeFunctionStructure, name)
+ , m_function(function)
+{
+ ASSERT_ARG(function, function);
+ putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
+}
+
+CallType PrototypeFunction::getCallData(CallData& callData)
+{
+ callData.native.function = m_function;
+ return CallTypeHost;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/PrototypeFunction.h b/JavaScriptCore/runtime/PrototypeFunction.h
new file mode 100644
index 0000000..1592995
--- /dev/null
+++ b/JavaScriptCore/runtime/PrototypeFunction.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ * Copyright (C) 2007 Maks Orlovich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PrototypeFunction_h
+#define PrototypeFunction_h
+
+#include "InternalFunction.h"
+#include "CallData.h"
+
+namespace JSC {
+
+ class PrototypeFunction : public InternalFunction {
+ public:
+ PrototypeFunction(ExecState*, int length, const Identifier&, NativeFunction);
+ PrototypeFunction(ExecState*, PassRefPtr<StructureID>, int length, const Identifier&, NativeFunction);
+
+ private:
+ virtual CallType getCallData(CallData&);
+
+ const NativeFunction m_function;
+ };
+
+} // namespace JSC
+
+#endif // PrototypeFunction_h
diff --git a/JavaScriptCore/runtime/PutPropertySlot.h b/JavaScriptCore/runtime/PutPropertySlot.h
new file mode 100644
index 0000000..1e2dfe9
--- /dev/null
+++ b/JavaScriptCore/runtime/PutPropertySlot.h
@@ -0,0 +1,81 @@
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PutPropertySlot_h
+#define PutPropertySlot_h
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ class JSObject;
+
+ class PutPropertySlot {
+ public:
+ enum Type { Invalid, ExistingProperty, NewProperty };
+
+ PutPropertySlot()
+ : m_type(Invalid)
+ , m_base(0)
+ , m_wasTransition(false)
+ {
+ }
+
+ void setExistingProperty(JSObject* base, size_t offset)
+ {
+ m_type = ExistingProperty;
+ m_base = base;
+ m_offset = offset;
+ }
+
+ void setNewProperty(JSObject* base, size_t offset)
+ {
+ m_type = NewProperty;
+ m_base = base;
+ m_offset = offset;
+ }
+
+ Type type() const { return m_type; }
+ JSObject* base() const { return m_base; }
+
+ bool isCacheable() const { return m_type != Invalid; }
+ size_t cachedOffset() const {
+ ASSERT(isCacheable());
+ return m_offset;
+ }
+
+ bool wasTransition() const { return m_wasTransition; }
+ void setWasTransition(bool wasTransition) { m_wasTransition = wasTransition; }
+ private:
+ Type m_type;
+ JSObject* m_base;
+ bool m_wasTransition;
+ size_t m_offset;
+ };
+
+} // namespace JSC
+
+#endif // PutPropertySlot_h
diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp
new file mode 100644
index 0000000..4c4db39
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "RegExpConstructor.h"
+
+#include "ArrayPrototype.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "JSString.h"
+#include "ObjectPrototype.h"
+#include "RegExpMatchesArray.h"
+#include "RegExpObject.h"
+#include "RegExpPrototype.h"
+#include "regexp.h"
+
+namespace JSC {
+
+static JSValue* regExpConstructorInput(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorLastMatch(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorLastParen(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorLeftContext(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorRightContext(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar1(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar2(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar3(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar4(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar5(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar6(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar7(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar8(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpConstructorDollar9(ExecState*, const Identifier&, const PropertySlot&);
+
+static void setRegExpConstructorInput(ExecState*, JSObject*, JSValue*);
+static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValue*);
+
+} // namespace JSC
+
+#include "RegExpConstructor.lut.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
+
+const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable };
+
+/* Source for RegExpConstructor.lut.h
+@begin regExpConstructorTable
+ input regExpConstructorInput None
+ $_ regExpConstructorInput DontEnum
+ multiline regExpConstructorMultiline None
+ $* regExpConstructorMultiline DontEnum
+ lastMatch regExpConstructorLastMatch DontDelete|ReadOnly
+ $& regExpConstructorLastMatch DontDelete|ReadOnly|DontEnum
+ lastParen regExpConstructorLastParen DontDelete|ReadOnly
+ $+ regExpConstructorLastParen DontDelete|ReadOnly|DontEnum
+ leftContext regExpConstructorLeftContext DontDelete|ReadOnly
+ $` regExpConstructorLeftContext DontDelete|ReadOnly|DontEnum
+ rightContext regExpConstructorRightContext DontDelete|ReadOnly
+ $' regExpConstructorRightContext DontDelete|ReadOnly|DontEnum
+ $1 regExpConstructorDollar1 DontDelete|ReadOnly
+ $2 regExpConstructorDollar2 DontDelete|ReadOnly
+ $3 regExpConstructorDollar3 DontDelete|ReadOnly
+ $4 regExpConstructorDollar4 DontDelete|ReadOnly
+ $5 regExpConstructorDollar5 DontDelete|ReadOnly
+ $6 regExpConstructorDollar6 DontDelete|ReadOnly
+ $7 regExpConstructorDollar7 DontDelete|ReadOnly
+ $8 regExpConstructorDollar8 DontDelete|ReadOnly
+ $9 regExpConstructorDollar9 DontDelete|ReadOnly
+@end
+*/
+
+struct RegExpConstructorPrivate {
+ // Global search cache / settings
+ RegExpConstructorPrivate()
+ : lastNumSubPatterns(0)
+ , multiline(false)
+ {
+ }
+
+ UString input;
+ UString lastInput;
+ OwnArrayPtr<int> lastOvector;
+ unsigned lastNumSubPatterns : 31;
+ bool multiline : 1;
+};
+
+RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<StructureID> structure, RegExpPrototype* regExpPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp"))
+ , d(new RegExpConstructorPrivate)
+{
+ // ECMA 15.10.5.1 RegExp.prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum);
+}
+
+/*
+ To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
+ expression matching through the performMatch function. We use cached results to calculate,
+ e.g., RegExp.lastMatch and RegExp.leftParen.
+*/
+void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
+{
+ OwnArrayPtr<int> tmpOvector;
+ position = r->match(s, startOffset, &tmpOvector);
+
+ if (ovector)
+ *ovector = tmpOvector.get();
+
+ if (position != -1) {
+ ASSERT(tmpOvector);
+
+ length = tmpOvector[1] - tmpOvector[0];
+
+ d->input = s;
+ d->lastInput = s;
+ d->lastOvector.set(tmpOvector.release());
+ d->lastNumSubPatterns = r->numSubpatterns();
+ }
+}
+
+RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
+ : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1)
+{
+ RegExpConstructorPrivate* d = new RegExpConstructorPrivate;
+ d->input = data->lastInput;
+ d->lastInput = data->lastInput;
+ d->lastNumSubPatterns = data->lastNumSubPatterns;
+ unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector
+ d->lastOvector.set(new int[offsetVectorSize]);
+ memcpy(d->lastOvector.get(), data->lastOvector.get(), offsetVectorSize * sizeof(int));
+ // d->multiline is not needed, and remains uninitialized
+
+ setLazyCreationData(d);
+}
+
+RegExpMatchesArray::~RegExpMatchesArray()
+{
+ delete static_cast<RegExpConstructorPrivate*>(lazyCreationData());
+}
+
+void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
+{
+ RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(lazyCreationData());
+ ASSERT(d);
+
+ unsigned lastNumSubpatterns = d->lastNumSubPatterns;
+
+ for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
+ int start = d->lastOvector[2 * i];
+ if (start >= 0)
+ JSArray::put(exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start));
+ }
+
+ PutPropertySlot slot;
+ JSArray::put(exec, exec->propertyNames().index, jsNumber(exec, d->lastOvector[0]), slot);
+ JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->input), slot);
+
+ delete d;
+ setLazyCreationData(0);
+}
+
+JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const
+{
+ return new (exec) RegExpMatchesArray(exec, d.get());
+}
+
+JSValue* RegExpConstructor::getBackref(ExecState* exec, unsigned i) const
+{
+ if (d->lastOvector && i <= d->lastNumSubPatterns) {
+ int start = d->lastOvector[2 * i];
+ if (start >= 0)
+ return jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start);
+ }
+ return jsEmptyString(exec);
+}
+
+JSValue* RegExpConstructor::getLastParen(ExecState* exec) const
+{
+ unsigned i = d->lastNumSubPatterns;
+ if (i > 0) {
+ ASSERT(d->lastOvector);
+ int start = d->lastOvector[2 * i];
+ if (start >= 0)
+ return jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start);
+ }
+ return jsEmptyString(exec);
+}
+
+JSValue* RegExpConstructor::getLeftContext(ExecState* exec) const
+{
+ if (d->lastOvector)
+ return jsSubstring(exec, d->lastInput, 0, d->lastOvector[0]);
+ return jsEmptyString(exec);
+}
+
+JSValue* RegExpConstructor::getRightContext(ExecState* exec) const
+{
+ if (d->lastOvector)
+ return jsSubstring(exec, d->lastInput, d->lastOvector[1], d->lastInput.size() - d->lastOvector[1]);
+ return jsEmptyString(exec);
+}
+
+bool RegExpConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot);
+}
+
+JSValue* regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1);
+}
+
+JSValue* regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 2);
+}
+
+JSValue* regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 3);
+}
+
+JSValue* regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 4);
+}
+
+JSValue* regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 5);
+}
+
+JSValue* regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 6);
+}
+
+JSValue* regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 7);
+}
+
+JSValue* regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 8);
+}
+
+JSValue* regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 9);
+}
+
+JSValue* regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return jsString(exec, asRegExpConstructor(slot.slotBase())->input());
+}
+
+JSValue* regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
+{
+ return jsBoolean(asRegExpConstructor(slot.slotBase())->multiline());
+}
+
+JSValue* regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getBackref(exec, 0);
+}
+
+JSValue* regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getLastParen(exec);
+}
+
+JSValue* regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getLeftContext(exec);
+}
+
+JSValue* regExpConstructorRightContext(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return asRegExpConstructor(slot.slotBase())->getRightContext(exec);
+}
+
+void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this, slot);
+}
+
+void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue* value)
+{
+ asRegExpConstructor(baseObject)->setInput(value->toString(exec));
+}
+
+void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue* value)
+{
+ asRegExpConstructor(baseObject)->setMultiline(value->toBoolean(exec));
+}
+
+// ECMA 15.10.4
+JSObject* constructRegExp(ExecState* exec, const ArgList& args)
+{
+ JSValue* arg0 = args.at(exec, 0);
+ JSValue* arg1 = args.at(exec, 1);
+
+ if (arg0->isObject(&RegExpObject::info)) {
+ if (!arg1->isUndefined())
+ return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
+ return asObject(arg0);
+ }
+
+ UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec);
+ UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
+
+ RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags);
+ if (!regExp->isValid())
+ return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+ return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
+}
+
+static JSObject* constructWithRegExpConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ return constructRegExp(exec, args);
+}
+
+ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithRegExpConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.10.3
+static JSValue* callRegExpConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ return constructRegExp(exec, args);
+}
+
+CallType RegExpConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callRegExpConstructor;
+ return CallTypeHost;
+}
+
+void RegExpConstructor::setInput(const UString& input)
+{
+ d->input = input;
+}
+
+const UString& RegExpConstructor::input() const
+{
+ // Can detect a distinct initial state that is invisible to JavaScript, by checking for null
+ // state (since jsString turns null strings to empty strings).
+ return d->input;
+}
+
+void RegExpConstructor::setMultiline(bool multiline)
+{
+ d->multiline = multiline;
+}
+
+bool RegExpConstructor::multiline() const
+{
+ return d->multiline;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/RegExpConstructor.h b/JavaScriptCore/runtime/RegExpConstructor.h
new file mode 100644
index 0000000..c5a94a5
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpConstructor.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExpConstructor_h
+#define RegExpConstructor_h
+
+#include "InternalFunction.h"
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+ class RegExp;
+ class RegExpPrototype;
+ struct RegExpConstructorPrivate;
+
+ class RegExpConstructor : public InternalFunction {
+ public:
+ RegExpConstructor(ExecState*, PassRefPtr<StructureID>, RegExpPrototype*);
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+ }
+
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+
+ static const ClassInfo info;
+
+ void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
+ JSObject* arrayOfMatches(ExecState*) const;
+
+ void setInput(const UString&);
+ const UString& input() const;
+
+ void setMultiline(bool);
+ bool multiline() const;
+
+ JSValue* getBackref(ExecState*, unsigned) const;
+ JSValue* getLastParen(ExecState*) const;
+ JSValue* getLeftContext(ExecState*) const;
+ JSValue* getRightContext(ExecState*) const;
+
+ private:
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+
+ OwnPtr<RegExpConstructorPrivate> d;
+ };
+
+ RegExpConstructor* asRegExpConstructor(JSValue*);
+
+ JSObject* constructRegExp(ExecState*, const ArgList&);
+
+ inline RegExpConstructor* asRegExpConstructor(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&RegExpConstructor::info));
+ return static_cast<RegExpConstructor*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // RegExpConstructor_h
diff --git a/JavaScriptCore/runtime/RegExpMatchesArray.h b/JavaScriptCore/runtime/RegExpMatchesArray.h
new file mode 100644
index 0000000..6a4279e
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpMatchesArray.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExpMatchesArray_h
+#define RegExpMatchesArray_h
+
+#include "JSArray.h"
+
+namespace JSC {
+
+ class RegExpMatchesArray : public JSArray {
+ public:
+ RegExpMatchesArray(ExecState*, RegExpConstructorPrivate*);
+ virtual ~RegExpMatchesArray();
+
+ private:
+ virtual bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::getOwnPropertySlot(exec, propertyName, slot);
+ }
+
+ virtual bool getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::getOwnPropertySlot(exec, propertyName, slot);
+ }
+
+ virtual void put(ExecState* exec, const Identifier& propertyName, JSValue* v, PutPropertySlot& slot)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ JSArray::put(exec, propertyName, v, slot);
+ }
+
+ virtual void put(ExecState* exec, unsigned propertyName, JSValue* v)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ JSArray::put(exec, propertyName, v);
+ }
+
+ virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::deleteProperty(exec, propertyName);
+ }
+
+ virtual bool deleteProperty(ExecState* exec, unsigned propertyName)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::deleteProperty(exec, propertyName);
+ }
+
+ virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ JSArray::getPropertyNames(exec, arr);
+ }
+
+ void fillArrayInstance(ExecState*);
+};
+
+}
+
+#endif // RegExpMatchesArray_h
diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp
new file mode 100644
index 0000000..127a71e
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpObject.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "RegExpObject.h"
+
+#include "JSArray.h"
+#include "JSGlobalObject.h"
+#include "JSString.h"
+#include "RegExpConstructor.h"
+#include "RegExpPrototype.h"
+
+namespace JSC {
+
+static JSValue* regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&);
+static JSValue* regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&);
+static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue*);
+
+} // namespace JSC
+
+#include "RegExpObject.lut.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
+
+const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
+
+/* Source for RegExpObject.lut.h
+@begin regExpTable
+ global regExpObjectGlobal DontDelete|ReadOnly|DontEnum
+ ignoreCase regExpObjectIgnoreCase DontDelete|ReadOnly|DontEnum
+ multiline regExpObjectMultiline DontDelete|ReadOnly|DontEnum
+ source regExpObjectSource DontDelete|ReadOnly|DontEnum
+ lastIndex regExpObjectLastIndex DontDelete|DontEnum
+@end
+*/
+
+RegExpObject::RegExpObject(PassRefPtr<StructureID> structure, PassRefPtr<RegExp> regExp)
+ : JSObject(structure)
+ , d(new RegExpObjectData(regExp, 0))
+{
+}
+
+RegExpObject::~RegExpObject()
+{
+}
+
+bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
+}
+
+JSValue* regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
+{
+ return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global());
+}
+
+JSValue* regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot)
+{
+ return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->ignoreCase());
+}
+
+JSValue* regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot)
+{
+ return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->multiline());
+}
+
+JSValue* regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return jsString(exec, asRegExpObject(slot.slotBase())->regExp()->pattern());
+}
+
+JSValue* regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot)
+{
+ return jsNumber(exec, asRegExpObject(slot.slotBase())->lastIndex());
+}
+
+void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot);
+}
+
+void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue* value)
+{
+ asRegExpObject(baseObject)->setLastIndex(value->toInteger(exec));
+}
+
+bool RegExpObject::match(ExecState* exec, const ArgList& args)
+{
+ RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
+
+ UString input;
+ if (!args.isEmpty())
+ input = args.at(exec, 0)->toString(exec);
+ else {
+ input = regExpObj->input();
+ if (input.isNull()) {
+ throwError(exec, GeneralError, "No input.");
+ return false;
+ }
+ }
+
+ bool global = get(exec, exec->propertyNames().global)->toBoolean(exec);
+ int lastIndex = 0;
+ if (global) {
+ if (d->lastIndex < 0 || d->lastIndex > input.size()) {
+ d->lastIndex = 0;
+ return false;
+ }
+ lastIndex = static_cast<int>(d->lastIndex);
+ }
+
+ int foundIndex;
+ int foundLength;
+ regExpObj->performMatch(d->regExp.get(), input, lastIndex, foundIndex, foundLength);
+
+ if (global) {
+ lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength;
+ d->lastIndex = lastIndex;
+ }
+
+ return foundIndex >= 0;
+}
+
+JSValue* RegExpObject::test(ExecState* exec, const ArgList& args)
+{
+ return jsBoolean(match(exec, args));
+}
+
+JSValue* RegExpObject::exec(ExecState* exec, const ArgList& args)
+{
+ if (match(exec, args))
+ return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec);
+ return jsNull();
+}
+
+static JSValue* callRegExpObject(ExecState* exec, JSObject* function, JSValue*, const ArgList& args)
+{
+ return asRegExpObject(function)->exec(exec, args);
+}
+
+CallType RegExpObject::getCallData(CallData& callData)
+{
+ callData.native.function = callRegExpObject;
+ return CallTypeHost;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/RegExpObject.h b/JavaScriptCore/runtime/RegExpObject.h
new file mode 100644
index 0000000..d80b47c
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpObject.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExpObject_h
+#define RegExpObject_h
+
+#include "JSObject.h"
+#include "regexp.h"
+
+namespace JSC {
+
+ class RegExpObject : public JSObject {
+ public:
+ RegExpObject(PassRefPtr<StructureID>, PassRefPtr<RegExp>);
+ virtual ~RegExpObject();
+
+ void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; }
+ RegExp* regExp() const { return d->regExp.get(); }
+
+ void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; }
+ double lastIndex() const { return d->lastIndex; }
+
+ JSValue* test(ExecState*, const ArgList&);
+ JSValue* exec(ExecState*, const ArgList&);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+ private:
+ bool match(ExecState*, const ArgList&);
+
+ virtual CallType getCallData(CallData&);
+
+ struct RegExpObjectData {
+ RegExpObjectData(PassRefPtr<RegExp> regExp, double lastIndex)
+ : regExp(regExp)
+ , lastIndex(lastIndex)
+ {
+ }
+
+ RefPtr<RegExp> regExp;
+ double lastIndex;
+ };
+
+ OwnPtr<RegExpObjectData> d;
+ };
+
+ RegExpObject* asRegExpObject(JSValue*);
+
+ inline RegExpObject* asRegExpObject(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&RegExpObject::info));
+ return static_cast<RegExpObject*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // RegExpObject_h
diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp
new file mode 100644
index 0000000..ceee32a
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "RegExpPrototype.h"
+
+#include "ArrayPrototype.h"
+#include "JSArray.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include "JSValue.h"
+#include "ObjectPrototype.h"
+#include "PrototypeFunction.h"
+#include "RegExpObject.h"
+#include "regexp.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype);
+
+static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* regExpProtoFuncExec(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* regExpProtoFuncCompile(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* regExpProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+// ECMA 15.10.5
+
+const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };
+
+RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure)
+ : JSObject(structure)
+{
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
+}
+
+// ------------------------------ Functions ---------------------------
+
+JSValue* regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&RegExpObject::info))
+ return throwError(exec, TypeError);
+ return asRegExpObject(thisValue)->test(exec, args);
+}
+
+JSValue* regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&RegExpObject::info))
+ return throwError(exec, TypeError);
+ return asRegExpObject(thisValue)->exec(exec, args);
+}
+
+JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (!thisValue->isObject(&RegExpObject::info))
+ return throwError(exec, TypeError);
+
+ RefPtr<RegExp> regExp;
+ JSValue* arg0 = args.at(exec, 0);
+ JSValue* arg1 = args.at(exec, 1);
+
+ if (arg0->isObject(&RegExpObject::info)) {
+ if (!arg1->isUndefined())
+ return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
+ regExp = asRegExpObject(arg0)->regExp();
+ } else {
+ UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);
+ UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
+ regExp = RegExp::create(&exec->globalData(), pattern, flags);
+ }
+
+ if (!regExp->isValid())
+ return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+
+ asRegExpObject(thisValue)->setRegExp(regExp.release());
+ asRegExpObject(thisValue)->setLastIndex(0);
+ return jsUndefined();
+}
+
+JSValue* regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ if (!thisValue->isObject(&RegExpObject::info)) {
+ if (thisValue->isObject(&RegExpPrototype::info))
+ return jsNontrivialString(exec, "//");
+ return throwError(exec, TypeError);
+ }
+
+ UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source)->toString(exec);
+ result.append('/');
+ if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global)->toBoolean(exec))
+ result.append('g');
+ if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec))
+ result.append('i');
+ if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline)->toBoolean(exec))
+ result.append('m');
+ return jsNontrivialString(exec, result);
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/RegExpPrototype.h b/JavaScriptCore/runtime/RegExpPrototype.h
new file mode 100644
index 0000000..44a0f32
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpPrototype.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef RegExpPrototype_h
+#define RegExpPrototype_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+ class RegExpPrototype : public JSObject {
+ public:
+ RegExpPrototype(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // RegExpPrototype_h
diff --git a/JavaScriptCore/runtime/ScopeChain.cpp b/JavaScriptCore/runtime/ScopeChain.cpp
new file mode 100644
index 0000000..e90b565
--- /dev/null
+++ b/JavaScriptCore/runtime/ScopeChain.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ScopeChain.h"
+
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "PropertyNameArray.h"
+#include <stdio.h>
+
+namespace JSC {
+
+#ifndef NDEBUG
+
+void ScopeChainNode::print() const
+{
+ ScopeChainIterator scopeEnd = end();
+ for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
+ JSObject* o = *scopeIter;
+ PropertyNameArray propertyNames(globalObject()->globalExec());
+ o->getPropertyNames(globalObject()->globalExec(), propertyNames);
+ PropertyNameArray::const_iterator propEnd = propertyNames.end();
+
+ fprintf(stderr, "----- [scope %p] -----\n", o);
+ for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
+ Identifier name = *propIter;
+ fprintf(stderr, "%s, ", name.ascii());
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
+#endif
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/ScopeChain.h b/JavaScriptCore/runtime/ScopeChain.h
new file mode 100644
index 0000000..834217c
--- /dev/null
+++ b/JavaScriptCore/runtime/ScopeChain.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ScopeChain_h
+#define ScopeChain_h
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+ class JSGlobalData;
+ class JSGlobalObject;
+ class JSObject;
+ class ScopeChainIterator;
+
+ class ScopeChainNode {
+ public:
+ ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSObject* globalThis)
+ : next(next)
+ , object(object)
+ , globalData(globalData)
+ , globalThis(globalThis)
+ , refCount(1)
+ {
+ ASSERT(globalData);
+ }
+
+ ScopeChainNode* next;
+ JSObject* object;
+ JSGlobalData* globalData;
+ JSObject* globalThis;
+ int refCount;
+
+ void deref() { if (--refCount == 0) release(); }
+ void ref() { ++refCount; }
+ void release();
+
+ // Before calling "push" on a bare ScopeChainNode, a client should
+ // logically "copy" the node. Later, the client can "deref" the head
+ // of its chain of ScopeChainNodes to reclaim all the nodes it added
+ // after the logical copy, leaving nodes added before the logical copy
+ // (nodes shared with other clients) untouched.
+ ScopeChainNode* copy()
+ {
+ ref();
+ return this;
+ }
+
+ ScopeChainNode* push(JSObject*);
+ ScopeChainNode* pop();
+
+ ScopeChainIterator begin() const;
+ ScopeChainIterator end() const;
+
+ JSGlobalObject* globalObject() const; // defined in JSGlobalObject.h
+ JSObject* globalThisObject() const { return globalThis; }
+
+#ifndef NDEBUG
+ void print() const;
+#endif
+ };
+
+ inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
+ {
+ ASSERT(o);
+ return new ScopeChainNode(this, o, globalData, globalThis);
+ }
+
+ inline ScopeChainNode* ScopeChainNode::pop()
+ {
+ ASSERT(next);
+ ScopeChainNode* result = next;
+
+ if (--refCount != 0)
+ ++result->refCount;
+ else
+ delete this;
+
+ return result;
+ }
+
+ inline void ScopeChainNode::release()
+ {
+ // This function is only called by deref(),
+ // Deref ensures these conditions are true.
+ ASSERT(refCount == 0);
+ ScopeChainNode* n = this;
+ do {
+ ScopeChainNode* next = n->next;
+ delete n;
+ n = next;
+ } while (n && --n->refCount == 0);
+ }
+
+ class ScopeChainIterator {
+ public:
+ ScopeChainIterator(const ScopeChainNode* node)
+ : m_node(node)
+ {
+ }
+
+ JSObject* const & operator*() const { return m_node->object; }
+ JSObject* const * operator->() const { return &(operator*()); }
+
+ ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
+
+ // postfix ++ intentionally omitted
+
+ bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
+ bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
+
+ private:
+ const ScopeChainNode* m_node;
+ };
+
+ inline ScopeChainIterator ScopeChainNode::begin() const
+ {
+ return ScopeChainIterator(this);
+ }
+
+ inline ScopeChainIterator ScopeChainNode::end() const
+ {
+ return ScopeChainIterator(0);
+ }
+
+ class NoScopeChain {};
+
+ class ScopeChain {
+ friend class CTI;
+ public:
+ ScopeChain(NoScopeChain)
+ : m_node(0)
+ {
+ }
+
+ ScopeChain(JSObject* o, JSGlobalData* globalData, JSObject* globalThis)
+ : m_node(new ScopeChainNode(0, o, globalData, globalThis))
+ {
+ }
+
+ ScopeChain(const ScopeChain& c)
+ : m_node(c.m_node->copy())
+ {
+ }
+
+ ScopeChain& operator=(const ScopeChain& c);
+
+ explicit ScopeChain(ScopeChainNode* node)
+ : m_node(node->copy())
+ {
+ }
+
+ ~ScopeChain()
+ {
+ if (m_node)
+ m_node->deref();
+ }
+
+ void swap(ScopeChain&);
+
+ ScopeChainNode* node() const { return m_node; }
+
+ JSObject* top() const { return m_node->object; }
+
+ ScopeChainIterator begin() const { return m_node->begin(); }
+ ScopeChainIterator end() const { return m_node->end(); }
+
+ void push(JSObject* o) { m_node = m_node->push(o); }
+
+ void pop() { m_node = m_node->pop(); }
+ void clear() { m_node->deref(); m_node = 0; }
+
+ JSGlobalObject* globalObject() const { return m_node->globalObject(); }
+
+ void mark() const;
+
+#ifndef NDEBUG
+ void print() const { m_node->print(); }
+#endif
+
+ private:
+ ScopeChainNode* m_node;
+ };
+
+ inline void ScopeChain::swap(ScopeChain& o)
+ {
+ ScopeChainNode* tmp = m_node;
+ m_node = o.m_node;
+ o.m_node = tmp;
+ }
+
+ inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)
+ {
+ ScopeChain tmp(c);
+ swap(tmp);
+ return *this;
+ }
+
+} // namespace JSC
+
+#endif // ScopeChain_h
diff --git a/JavaScriptCore/runtime/ScopeChainMark.h b/JavaScriptCore/runtime/ScopeChainMark.h
new file mode 100644
index 0000000..b80b8ef
--- /dev/null
+++ b/JavaScriptCore/runtime/ScopeChainMark.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ScopeChainMark_h
+#define ScopeChainMark_h
+
+#include "ScopeChain.h"
+
+namespace JSC {
+
+ inline void ScopeChain::mark() const
+ {
+ for (ScopeChainNode* n = m_node; n; n = n->next) {
+ JSObject* o = n->object;
+ if (!o->marked())
+ o->mark();
+ }
+ }
+
+} // namespace JSC
+
+#endif // ScopeChainMark_h
diff --git a/JavaScriptCore/runtime/SmallStrings.cpp b/JavaScriptCore/runtime/SmallStrings.cpp
new file mode 100644
index 0000000..06811b9
--- /dev/null
+++ b/JavaScriptCore/runtime/SmallStrings.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SmallStrings.h"
+
+#include "JSGlobalObject.h"
+#include "JSString.h"
+
+namespace JSC {
+
+class SmallStringsStorage {
+public:
+ SmallStringsStorage();
+ ~SmallStringsStorage();
+
+ UString::Rep* rep(unsigned char character) { return &reps[character]; }
+
+private:
+ UChar characters[0x100];
+ UString::Rep* reps;
+};
+
+SmallStringsStorage::SmallStringsStorage()
+ : reps(static_cast<UString::Rep*>(fastZeroedMalloc(sizeof(UString::Rep) * 0x100)))
+{
+ for (unsigned i = 0; i < 0x100; ++i) {
+ characters[i] = i;
+ reps[i].offset = i;
+ reps[i].len = 1;
+ reps[i].rc = 1;
+ reps[i].baseString = &reps[0];
+ }
+ reps[0].rc = 0x101;
+ reps[0].buf = characters;
+
+ // make sure UString doesn't try to reuse the buffer by pretending we have one more character in it
+ reps[0].usedCapacity = 0x101;
+ reps[0].capacity = 0x101;
+}
+
+SmallStringsStorage::~SmallStringsStorage()
+{
+ fastFree(reps);
+}
+
+SmallStrings::SmallStrings()
+ : m_emptyString(0)
+ , m_storage(0)
+{
+ for (unsigned i = 0; i < 0x100; ++i)
+ m_singleCharacterStrings[i] = 0;
+}
+
+SmallStrings::~SmallStrings()
+{
+}
+
+void SmallStrings::mark()
+{
+ if (m_emptyString && !m_emptyString->marked())
+ m_emptyString->mark();
+ for (unsigned i = 0; i < 0x100; ++i) {
+ if (m_singleCharacterStrings[i] && !m_singleCharacterStrings[i]->marked())
+ m_singleCharacterStrings[i]->mark();
+ }
+}
+
+void SmallStrings::createEmptyString(JSGlobalData* globalData)
+{
+ ASSERT(!m_emptyString);
+ m_emptyString = new (globalData) JSString(globalData, "", JSString::HasOtherOwner);
+}
+
+void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character)
+{
+ if (!m_storage)
+ m_storage.set(new SmallStringsStorage);
+ ASSERT(!m_singleCharacterStrings[character]);
+ m_singleCharacterStrings[character] = new (globalData) JSString(globalData, m_storage->rep(character), JSString::HasOtherOwner);
+}
+
+UString::Rep* SmallStrings::singleCharacterStringRep(unsigned char character)
+{
+ if (!m_storage)
+ m_storage.set(new SmallStringsStorage);
+ return m_storage->rep(character);
+}
+
+}
diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h
new file mode 100644
index 0000000..7c71208
--- /dev/null
+++ b/JavaScriptCore/runtime/SmallStrings.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SmallStrings_h
+#define SmallStrings_h
+
+#include "ustring.h"
+#include <wtf/OwnPtr.h>
+
+namespace JSC {
+
+ class JSGlobalData;
+ class JSString;
+
+ class SmallStringsStorage;
+
+ class SmallStrings : Noncopyable {
+ public:
+ SmallStrings();
+ ~SmallStrings();
+
+ JSString* emptyString(JSGlobalData* globalData)
+ {
+ if (!m_emptyString)
+ createEmptyString(globalData);
+ return m_emptyString;
+ }
+ JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character)
+ {
+ if (!m_singleCharacterStrings[character])
+ createSingleCharacterString(globalData, character);
+ return m_singleCharacterStrings[character];
+ }
+
+ UString::Rep* singleCharacterStringRep(unsigned char character);
+
+ void mark();
+
+ private:
+ void createEmptyString(JSGlobalData*);
+ void createSingleCharacterString(JSGlobalData*, unsigned char);
+
+ JSString* m_emptyString;
+ JSString* m_singleCharacterStrings[0x100];
+ OwnPtr<SmallStringsStorage> m_storage;
+ };
+
+}
+
+#endif
diff --git a/JavaScriptCore/runtime/StringConstructor.cpp b/JavaScriptCore/runtime/StringConstructor.cpp
new file mode 100644
index 0000000..850310e
--- /dev/null
+++ b/JavaScriptCore/runtime/StringConstructor.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "StringConstructor.h"
+
+#include "JSGlobalObject.h"
+#include "PrototypeFunction.h"
+#include "StringPrototype.h"
+
+namespace JSC {
+
+static NEVER_INLINE JSValue* stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args)
+{
+ UChar* buf = static_cast<UChar*>(fastMalloc(args.size() * sizeof(UChar)));
+ UChar* p = buf;
+ ArgList::const_iterator end = args.end();
+ for (ArgList::const_iterator it = args.begin(); it != end; ++it)
+ *p++ = static_cast<UChar>((*it).jsValue(exec)->toUInt32(exec));
+ return jsString(exec, UString(buf, p - buf, false));
+}
+
+static JSValue* stringFromCharCode(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ if (LIKELY(args.size() == 1))
+ return jsSingleCharacterString(exec, args.at(exec, 0)->toUInt32(exec));
+ return stringFromCharCodeSlowCase(exec, args);
+}
+
+ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
+
+StringConstructor::StringConstructor(ExecState* exec, PassRefPtr<StructureID> structure, StructureID* prototypeFunctionStructure, StringPrototype* stringPrototype)
+ : InternalFunction(&exec->globalData(), structure, Identifier(exec, stringPrototype->classInfo()->className))
+{
+ // ECMA 15.5.3.1 String.prototype
+ putDirectWithoutTransition(exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
+
+ // ECMA 15.5.3.2 fromCharCode()
+ putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+}
+
+// ECMA 15.5.2
+static JSObject* constructWithStringConstructor(ExecState* exec, JSObject*, const ArgList& args)
+{
+ if (args.isEmpty())
+ return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure());
+ return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), args.at(exec, 0)->toString(exec));
+}
+
+ConstructType StringConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructWithStringConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.5.1
+static JSValue* callStringConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
+{
+ if (args.isEmpty())
+ return jsEmptyString(exec);
+ return jsString(exec, args.at(exec, 0)->toString(exec));
+}
+
+CallType StringConstructor::getCallData(CallData& callData)
+{
+ callData.native.function = callStringConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/StringConstructor.h b/JavaScriptCore/runtime/StringConstructor.h
new file mode 100644
index 0000000..3376134
--- /dev/null
+++ b/JavaScriptCore/runtime/StringConstructor.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringConstructor_h
+#define StringConstructor_h
+
+#include "InternalFunction.h"
+
+namespace JSC {
+
+ class StringPrototype;
+
+ class StringConstructor : public InternalFunction {
+ public:
+ StringConstructor(ExecState*, PassRefPtr<StructureID>, StructureID* prototypeFunctionStructure, StringPrototype*);
+
+ virtual ConstructType getConstructData(ConstructData&);
+ virtual CallType getCallData(CallData&);
+ };
+
+} // namespace JSC
+
+#endif // StringConstructor_h
diff --git a/JavaScriptCore/runtime/StringObject.cpp b/JavaScriptCore/runtime/StringObject.cpp
new file mode 100644
index 0000000..5959395
--- /dev/null
+++ b/JavaScriptCore/runtime/StringObject.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "StringObject.h"
+
+#include "PropertyNameArray.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(StringObject);
+
+const ClassInfo StringObject::info = { "String", 0, 0, 0 };
+
+StringObject::StringObject(ExecState* exec, PassRefPtr<StructureID> structure)
+ : JSWrapperObject(structure)
+{
+ setInternalValue(jsEmptyString(exec));
+}
+
+StringObject::StringObject(PassRefPtr<StructureID> structure, JSString* string)
+ : JSWrapperObject(structure)
+{
+ setInternalValue(string);
+}
+
+StringObject::StringObject(ExecState* exec, PassRefPtr<StructureID> structure, const UString& string)
+ : JSWrapperObject(structure)
+{
+ setInternalValue(jsString(exec, string));
+}
+
+bool StringObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ if (internalValue()->getStringPropertySlot(exec, propertyName, slot))
+ return true;
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
+bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ if (internalValue()->getStringPropertySlot(exec, propertyName, slot))
+ return true;
+ return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+}
+
+void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length)
+ return;
+ JSObject::put(exec, propertyName, value, slot);
+}
+
+bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().length)
+ return false;
+ return JSObject::deleteProperty(exec, propertyName);
+}
+
+void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ int size = internalValue()->value().size();
+ for (int i = 0; i < size; ++i)
+ propertyNames.add(Identifier(exec, UString::from(i)));
+ return JSObject::getPropertyNames(exec, propertyNames);
+}
+
+UString StringObject::toString(ExecState*) const
+{
+ return internalValue()->value();
+}
+
+UString StringObject::toThisString(ExecState*) const
+{
+ return internalValue()->value();
+}
+
+JSString* StringObject::toThisJSString(ExecState*)
+{
+ return internalValue();
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/StringObject.h b/JavaScriptCore/runtime/StringObject.h
new file mode 100644
index 0000000..9297fd7
--- /dev/null
+++ b/JavaScriptCore/runtime/StringObject.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringObject_h
+#define StringObject_h
+
+#include "JSWrapperObject.h"
+#include "JSString.h"
+
+namespace JSC {
+
+ class StringObject : public JSWrapperObject {
+ public:
+ StringObject(ExecState*, PassRefPtr<StructureID>);
+ StringObject(ExecState*, PassRefPtr<StructureID>, const UString&);
+
+ static StringObject* create(ExecState*, JSString*);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ virtual void put(ExecState* exec, const Identifier& propertyName, JSValue*, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ JSString* internalValue() const { return asString(JSWrapperObject::internalValue());}
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* prototype)
+ {
+ return StructureID::create(prototype, TypeInfo(ObjectType));
+ }
+
+ protected:
+ StringObject(PassRefPtr<StructureID>, JSString*);
+
+ private:
+ virtual UString toString(ExecState*) const;
+ virtual UString toThisString(ExecState*) const;
+ virtual JSString* toThisJSString(ExecState*);
+ };
+
+ StringObject* asStringObject(JSValue*);
+
+ inline StringObject* asStringObject(JSValue* value)
+ {
+ ASSERT(asObject(value)->inherits(&StringObject::info));
+ return static_cast<StringObject*>(asObject(value));
+ }
+
+} // namespace JSC
+
+#endif // StringObject_h
diff --git a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
new file mode 100644
index 0000000..d703228
--- /dev/null
+++ b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringObjectThatMasqueradesAsUndefined_h
+#define StringObjectThatMasqueradesAsUndefined_h
+
+#include "JSGlobalObject.h"
+#include "StringObject.h"
+#include "ustring.h"
+
+namespace JSC {
+
+ // WebCore uses this to make style.filter undetectable
+ class StringObjectThatMasqueradesAsUndefined : public StringObject {
+ public:
+ static StringObjectThatMasqueradesAsUndefined* create(ExecState* exec, const UString& string)
+ {
+ return new (exec) StringObjectThatMasqueradesAsUndefined(exec,
+ createStructureID(exec->lexicalGlobalObject()->stringPrototype()), string);
+ }
+
+ private:
+ StringObjectThatMasqueradesAsUndefined(ExecState* exec, PassRefPtr<StructureID> structure, const UString& string)
+ : StringObject(exec, structure, string)
+ {
+ }
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto)
+ {
+ return StructureID::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined));
+ }
+
+ virtual bool toBoolean(ExecState*) const { return false; }
+ };
+
+} // namespace JSC
+
+#endif // StringObjectThatMasqueradesAsUndefined_h
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp
new file mode 100644
index 0000000..0b11c24
--- /dev/null
+++ b/JavaScriptCore/runtime/StringPrototype.cpp
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include "StringPrototype.h"
+
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "ObjectPrototype.h"
+#include "PropertyNameArray.h"
+#include "RegExpConstructor.h"
+#include "RegExpObject.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/MathExtras.h>
+#include <wtf/unicode/Collator.h>
+
+using namespace WTF;
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(StringPrototype);
+
+static JSValue* stringProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncCharAt(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncConcat(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncMatch(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncReplace(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncSearch(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncSlice(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncSplit(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncSubstr(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncSubstring(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+static JSValue* stringProtoFuncBig(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncSmall(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncBlink(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncBold(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncFixed(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncItalics(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncStrike(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncSub(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncSup(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncFontcolor(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncFontsize(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncAnchor(ExecState*, JSObject*, JSValue*, const ArgList&);
+static JSValue* stringProtoFuncLink(ExecState*, JSObject*, JSValue*, const ArgList&);
+
+}
+
+#include "StringPrototype.lut.h"
+
+namespace JSC {
+
+const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, ExecState::stringTable };
+
+/* Source for StringPrototype.lut.h
+@begin stringTable 26
+ toString stringProtoFuncToString DontEnum|Function 0
+ valueOf stringProtoFuncToString DontEnum|Function 0
+ charAt stringProtoFuncCharAt DontEnum|Function 1
+ charCodeAt stringProtoFuncCharCodeAt DontEnum|Function 1
+ concat stringProtoFuncConcat DontEnum|Function 1
+ indexOf stringProtoFuncIndexOf DontEnum|Function 1
+ lastIndexOf stringProtoFuncLastIndexOf DontEnum|Function 1
+ match stringProtoFuncMatch DontEnum|Function 1
+ replace stringProtoFuncReplace DontEnum|Function 2
+ search stringProtoFuncSearch DontEnum|Function 1
+ slice stringProtoFuncSlice DontEnum|Function 2
+ split stringProtoFuncSplit DontEnum|Function 2
+ substr stringProtoFuncSubstr DontEnum|Function 2
+ substring stringProtoFuncSubstring DontEnum|Function 2
+ toLowerCase stringProtoFuncToLowerCase DontEnum|Function 0
+ toUpperCase stringProtoFuncToUpperCase DontEnum|Function 0
+ localeCompare stringProtoFuncLocaleCompare DontEnum|Function 1
+
+ # toLocaleLowerCase and toLocaleUpperCase are currently identical to toLowerCase and toUpperCase
+ toLocaleLowerCase stringProtoFuncToLowerCase DontEnum|Function 0
+ toLocaleUpperCase stringProtoFuncToUpperCase DontEnum|Function 0
+
+ big stringProtoFuncBig DontEnum|Function 0
+ small stringProtoFuncSmall DontEnum|Function 0
+ blink stringProtoFuncBlink DontEnum|Function 0
+ bold stringProtoFuncBold DontEnum|Function 0
+ fixed stringProtoFuncFixed DontEnum|Function 0
+ italics stringProtoFuncItalics DontEnum|Function 0
+ strike stringProtoFuncStrike DontEnum|Function 0
+ sub stringProtoFuncSub DontEnum|Function 0
+ sup stringProtoFuncSup DontEnum|Function 0
+ fontcolor stringProtoFuncFontcolor DontEnum|Function 1
+ fontsize stringProtoFuncFontsize DontEnum|Function 1
+ anchor stringProtoFuncAnchor DontEnum|Function 1
+ link stringProtoFuncLink DontEnum|Function 1
+@end
+*/
+
+// ECMA 15.5.4
+StringPrototype::StringPrototype(ExecState* exec, PassRefPtr<StructureID> structure)
+ : StringObject(exec, structure)
+{
+ // The constructor will be added later, after StringConstructor has been built
+ putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
+}
+
+bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+ return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);
+}
+
+// ------------------------------ Functions --------------------------
+
+static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg)
+{
+ UString substitutedReplacement;
+ int offset = 0;
+ int i = -1;
+ while ((i = replacement.find('$', i + 1)) != -1) {
+ if (i + 1 == replacement.size())
+ break;
+
+ unsigned short ref = replacement[i + 1];
+ if (ref == '$') {
+ // "$$" -> "$"
+ ++i;
+ substitutedReplacement.append(replacement.data() + offset, i - offset);
+ offset = i + 1;
+ substitutedReplacement.append('$');
+ continue;
+ }
+
+ int backrefStart;
+ int backrefLength;
+ int advance = 0;
+ if (ref == '&') {
+ backrefStart = ovector[0];
+ backrefLength = ovector[1] - backrefStart;
+ } else if (ref == '`') {
+ backrefStart = 0;
+ backrefLength = ovector[0];
+ } else if (ref == '\'') {
+ backrefStart = ovector[1];
+ backrefLength = source.size() - backrefStart;
+ } else if (ref >= '0' && ref <= '9') {
+ // 1- and 2-digit back references are allowed
+ unsigned backrefIndex = ref - '0';
+ if (backrefIndex > reg->numSubpatterns())
+ continue;
+ if (replacement.size() > i + 2) {
+ ref = replacement[i + 2];
+ if (ref >= '0' && ref <= '9') {
+ backrefIndex = 10 * backrefIndex + ref - '0';
+ if (backrefIndex > reg->numSubpatterns())
+ backrefIndex = backrefIndex / 10; // Fall back to the 1-digit reference
+ else
+ advance = 1;
+ }
+ }
+ backrefStart = ovector[2 * backrefIndex];
+ backrefLength = ovector[2 * backrefIndex + 1] - backrefStart;
+ } else
+ continue;
+
+ if (i - offset)
+ substitutedReplacement.append(replacement.data() + offset, i - offset);
+ i += 1 + advance;
+ offset = i + 1;
+ substitutedReplacement.append(source.data() + backrefStart, backrefLength);
+ }
+
+ if (!offset)
+ return replacement;
+
+ if (replacement.size() - offset)
+ substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset);
+
+ return substitutedReplacement;
+}
+
+static inline int localeCompare(const UString& a, const UString& b)
+{
+ return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.data()), a.size(), reinterpret_cast<const ::UChar*>(b.data()), b.size());
+}
+
+JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ JSString* sourceVal = thisValue->toThisJSString(exec);
+ const UString& source = sourceVal->value();
+
+ JSValue* pattern = args.at(exec, 0);
+
+ JSValue* replacement = args.at(exec, 1);
+ UString replacementString;
+ CallData callData;
+ CallType callType = replacement->getCallData(callData);
+ if (callType == CallTypeNone)
+ replacementString = replacement->toString(exec);
+
+ if (pattern->isObject(&RegExpObject::info)) {
+ RegExp* reg = asRegExpObject(pattern)->regExp();
+ bool global = reg->global();
+
+ RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
+
+ int lastIndex = 0;
+ int startPosition = 0;
+
+ Vector<UString::Range, 16> sourceRanges;
+ Vector<UString, 16> replacements;
+
+ // This is either a loop (if global is set) or a one-way (if not).
+ do {
+ int matchIndex;
+ int matchLen;
+ int* ovector;
+ regExpObj->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
+ if (matchIndex < 0)
+ break;
+
+ sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
+
+ if (callType != CallTypeNone) {
+ int completeMatchStart = ovector[0];
+ ArgList args;
+
+ for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) {
+ int matchStart = ovector[i * 2];
+ int matchLen = ovector[i * 2 + 1] - matchStart;
+
+ if (matchStart < 0)
+ args.append(jsUndefined());
+ else
+ args.append(jsSubstring(exec, source, matchStart, matchLen));
+ }
+
+ args.append(jsNumber(exec, completeMatchStart));
+ args.append(sourceVal);
+
+ replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec));
+ if (exec->hadException())
+ break;
+ } else
+ replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
+
+ lastIndex = matchIndex + matchLen;
+ startPosition = lastIndex;
+
+ // special case of empty match
+ if (matchLen == 0) {
+ startPosition++;
+ if (startPosition > source.size())
+ break;
+ }
+ } while (global);
+
+ if (lastIndex < source.size())
+ sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));
+
+ UString result = source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size());
+
+ if (result == source)
+ return sourceVal;
+
+ return jsString(exec, result);
+ }
+
+ // First arg is a string
+ UString patternString = pattern->toString(exec);
+ int matchPos = source.find(patternString);
+ int matchLen = patternString.size();
+ // Do the replacement
+ if (matchPos == -1)
+ return sourceVal;
+
+ if (callType != CallTypeNone) {
+ ArgList args;
+ args.append(jsSubstring(exec, source, matchPos, matchLen));
+ args.append(jsNumber(exec, matchPos));
+ args.append(sourceVal);
+
+ replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec);
+ }
+
+ return jsString(exec, source.substr(0, matchPos) + replacementString + source.substr(matchPos + matchLen));
+}
+
+JSValue* stringProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ // Also used for valueOf.
+
+ if (thisValue->isString())
+ return thisValue;
+
+ if (thisValue->isObject(&StringObject::info))
+ return asStringObject(thisValue)->internalValue();
+
+ return throwError(exec, TypeError);
+}
+
+JSValue* stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ unsigned len = s.size();
+ JSValue* a0 = args.at(exec, 0);
+ if (JSImmediate::isNumber(a0)) {
+ uint32_t i;
+ if (JSImmediate::getUInt32(a0, i) && i < len)
+ return jsSingleCharacterSubstring(exec, s, i);
+ return jsEmptyString(exec);
+ }
+ double dpos = a0->toInteger(exec);
+ if (dpos >= 0 && dpos < len)
+ return jsSingleCharacterSubstring(exec, s, static_cast<unsigned>(dpos));
+ return jsEmptyString(exec);
+}
+
+JSValue* stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ unsigned len = s.size();
+ JSValue* a0 = args.at(exec, 0);
+ if (JSImmediate::isNumber(a0)) {
+ uint32_t i;
+ if (JSImmediate::getUInt32(a0, i) && i < len)
+ return jsNumber(exec, s.data()[i]);
+ return jsNaN(exec);
+ }
+ double dpos = a0->toInteger(exec);
+ if (dpos >= 0 && dpos < len)
+ return jsNumber(exec, s[static_cast<int>(dpos)]);
+ return jsNaN(exec);
+}
+
+JSValue* stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+
+ ArgList::const_iterator end = args.end();
+ for (ArgList::const_iterator it = args.begin(); it != end; ++it)
+ s += (*it).jsValue(exec)->toString(exec);
+ return jsString(exec, s);
+}
+
+JSValue* stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ int len = s.size();
+
+ JSValue* a0 = args.at(exec, 0);
+ JSValue* a1 = args.at(exec, 1);
+ UString u2 = a0->toString(exec);
+ double dpos = a1->toInteger(exec);
+ if (dpos < 0)
+ dpos = 0;
+ else if (dpos > len)
+ dpos = len;
+ return jsNumber(exec, s.find(u2, static_cast<int>(dpos)));
+}
+
+JSValue* stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ int len = s.size();
+
+ JSValue* a0 = args.at(exec, 0);
+ JSValue* a1 = args.at(exec, 1);
+
+ UString u2 = a0->toString(exec);
+ double dpos = a1->toIntegerPreserveNaN(exec);
+ if (dpos < 0)
+ dpos = 0;
+ else if (!(dpos <= len)) // true for NaN
+ dpos = len;
+ return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos)));
+}
+
+JSValue* stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+
+ JSValue* a0 = args.at(exec, 0);
+
+ UString u = s;
+ RefPtr<RegExp> reg;
+ RegExpObject* imp = 0;
+ if (a0->isObject(&RegExpObject::info))
+ reg = asRegExpObject(a0)->regExp();
+ else {
+ /*
+ * ECMA 15.5.4.12 String.prototype.search (regexp)
+ * If regexp is not an object whose [[Class]] property is "RegExp", it is
+ * replaced with the result of the expression new RegExp(regexp).
+ */
+ reg = RegExp::create(&exec->globalData(), a0->toString(exec));
+ }
+ RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
+ int pos;
+ int matchLength;
+ regExpObj->performMatch(reg.get(), u, 0, pos, matchLength);
+ if (!(reg->global())) {
+ // case without 'g' flag is handled like RegExp.prototype.exec
+ if (pos < 0)
+ return jsNull();
+ return regExpObj->arrayOfMatches(exec);
+ }
+
+ // return array of matches
+ ArgList list;
+ int lastIndex = 0;
+ while (pos >= 0) {
+ list.append(jsSubstring(exec, u, pos, matchLength));
+ lastIndex = pos;
+ pos += matchLength == 0 ? 1 : matchLength;
+ regExpObj->performMatch(reg.get(), u, pos, pos, matchLength);
+ }
+ if (imp)
+ imp->setLastIndex(lastIndex);
+ if (list.isEmpty()) {
+ // if there are no matches at all, it's important to return
+ // Null instead of an empty array, because this matches
+ // other browsers and because Null is a false value.
+ return jsNull();
+ }
+
+ return constructArray(exec, list);
+}
+
+JSValue* stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+
+ JSValue* a0 = args.at(exec, 0);
+
+ UString u = s;
+ RefPtr<RegExp> reg;
+ if (a0->isObject(&RegExpObject::info))
+ reg = asRegExpObject(a0)->regExp();
+ else {
+ /*
+ * ECMA 15.5.4.12 String.prototype.search (regexp)
+ * If regexp is not an object whose [[Class]] property is "RegExp", it is
+ * replaced with the result of the expression new RegExp(regexp).
+ */
+ reg = RegExp::create(&exec->globalData(), a0->toString(exec));
+ }
+ RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
+ int pos;
+ int matchLength;
+ regExpObj->performMatch(reg.get(), u, 0, pos, matchLength);
+ return jsNumber(exec, pos);
+}
+
+JSValue* stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ int len = s.size();
+
+ JSValue* a0 = args.at(exec, 0);
+ JSValue* a1 = args.at(exec, 1);
+
+ // The arg processing is very much like ArrayProtoFunc::Slice
+ double start = a0->toInteger(exec);
+ double end = a1->isUndefined() ? len : a1->toInteger(exec);
+ double from = start < 0 ? len + start : start;
+ double to = end < 0 ? len + end : end;
+ if (to > from && to > 0 && from < len) {
+ if (from < 0)
+ from = 0;
+ if (to > len)
+ to = len;
+ return jsSubstring(exec, s, static_cast<unsigned>(from), static_cast<unsigned>(to) - static_cast<unsigned>(from));
+ }
+
+ return jsEmptyString(exec);
+}
+
+JSValue* stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+
+ JSValue* a0 = args.at(exec, 0);
+ JSValue* a1 = args.at(exec, 1);
+
+ JSArray* result = constructEmptyArray(exec);
+ unsigned i = 0;
+ int p0 = 0;
+ unsigned limit = a1->isUndefined() ? 0xFFFFFFFFU : a1->toUInt32(exec);
+ if (a0->isObject(&RegExpObject::info)) {
+ RegExp* reg = asRegExpObject(a0)->regExp();
+ if (s.isEmpty() && reg->match(s, 0) >= 0) {
+ // empty string matched by regexp -> empty array
+ return result;
+ }
+ int pos = 0;
+ while (i != limit && pos < s.size()) {
+ OwnArrayPtr<int> ovector;
+ int mpos = reg->match(s, pos, &ovector);
+ if (mpos < 0)
+ break;
+ int mlen = ovector[1] - ovector[0];
+ pos = mpos + (mlen == 0 ? 1 : mlen);
+ if (mpos != p0 || mlen) {
+ result->put(exec, i++, jsSubstring(exec, s, p0, mpos - p0));
+ p0 = mpos + mlen;
+ }
+ for (unsigned si = 1; si <= reg->numSubpatterns(); ++si) {
+ int spos = ovector[si * 2];
+ if (spos < 0)
+ result->put(exec, i++, jsUndefined());
+ else
+ result->put(exec, i++, jsSubstring(exec, s, spos, ovector[si * 2 + 1] - spos));
+ }
+ }
+ } else {
+ UString u2 = a0->toString(exec);
+ if (u2.isEmpty()) {
+ if (s.isEmpty()) {
+ // empty separator matches empty string -> empty array
+ return result;
+ }
+ while (i != limit && p0 < s.size() - 1)
+ result->put(exec, i++, jsSingleCharacterSubstring(exec, s, p0++));
+ } else {
+ int pos;
+ while (i != limit && (pos = s.find(u2, p0)) >= 0) {
+ result->put(exec, i++, jsSubstring(exec, s, p0, pos - p0));
+ p0 = pos + u2.size();
+ }
+ }
+ }
+
+ // add remaining string
+ if (i != limit)
+ result->put(exec, i++, jsSubstring(exec, s, p0, s.size() - p0));
+
+ return result;
+}
+
+JSValue* stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ int len = s.size();
+
+ JSValue* a0 = args.at(exec, 0);
+ JSValue* a1 = args.at(exec, 1);
+
+ double start = a0->toInteger(exec);
+ double length = a1->isUndefined() ? len : a1->toInteger(exec);
+ if (start >= len || length <= 0)
+ return jsEmptyString(exec);
+ if (start < 0) {
+ start += len;
+ if (start < 0)
+ start = 0;
+ }
+ if (start + length > len)
+ length = len - start;
+ return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(length));
+}
+
+JSValue* stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ int len = s.size();
+
+ JSValue* a0 = args.at(exec, 0);
+ JSValue* a1 = args.at(exec, 1);
+
+ double start = a0->toNumber(exec);
+ double end = a1->toNumber(exec);
+ if (isnan(start))
+ start = 0;
+ if (isnan(end))
+ end = 0;
+ if (start < 0)
+ start = 0;
+ if (end < 0)
+ end = 0;
+ if (start > len)
+ start = len;
+ if (end > len)
+ end = len;
+ if (a1->isUndefined())
+ end = len;
+ if (start > end) {
+ double temp = end;
+ end = start;
+ start = temp;
+ }
+ return jsSubstring(exec, s, static_cast<unsigned>(start), static_cast<unsigned>(end) - static_cast<unsigned>(start));
+}
+
+JSValue* stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ JSString* sVal = thisValue->toThisJSString(exec);
+ const UString& s = sVal->value();
+
+ int sSize = s.size();
+ if (!sSize)
+ return sVal;
+
+ const UChar* sData = s.data();
+ Vector<UChar> buffer(sSize);
+
+ UChar ored = 0;
+ for (int i = 0; i < sSize; i++) {
+ UChar c = sData[i];
+ ored |= c;
+ buffer[i] = toASCIILower(c);
+ }
+ if (!(ored & ~0x7f))
+ return jsString(exec, UString(buffer.releaseBuffer(), sSize, false));
+
+ bool error;
+ int length = Unicode::toLower(buffer.data(), sSize, sData, sSize, &error);
+ if (error) {
+ buffer.resize(length);
+ length = Unicode::toLower(buffer.data(), length, sData, sSize, &error);
+ if (error)
+ return sVal;
+ }
+ if (length == sSize && memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
+ return sVal;
+ return jsString(exec, UString(buffer.releaseBuffer(), length, false));
+}
+
+JSValue* stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ JSString* sVal = thisValue->toThisJSString(exec);
+ const UString& s = sVal->value();
+
+ int sSize = s.size();
+ if (!sSize)
+ return sVal;
+
+ const UChar* sData = s.data();
+ Vector<UChar> buffer(sSize);
+
+ UChar ored = 0;
+ for (int i = 0; i < sSize; i++) {
+ UChar c = sData[i];
+ ored |= c;
+ buffer[i] = toASCIIUpper(c);
+ }
+ if (!(ored & ~0x7f))
+ return jsString(exec, UString(buffer.releaseBuffer(), sSize, false));
+
+ bool error;
+ int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error);
+ if (error) {
+ buffer.resize(length);
+ length = Unicode::toUpper(buffer.data(), length, sData, sSize, &error);
+ if (error)
+ return sVal;
+ }
+ if (length == sSize && memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
+ return sVal;
+ return jsString(exec, UString(buffer.releaseBuffer(), length, false));
+}
+
+JSValue* stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ if (args.size() < 1)
+ return jsNumber(exec, 0);
+
+ UString s = thisValue->toThisString(exec);
+ JSValue* a0 = args.at(exec, 0);
+ return jsNumber(exec, localeCompare(s, a0->toString(exec)));
+}
+
+JSValue* stringProtoFuncBig(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<big>" + s + "</big>");
+}
+
+JSValue* stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<small>" + s + "</small>");
+}
+
+JSValue* stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<blink>" + s + "</blink>");
+}
+
+JSValue* stringProtoFuncBold(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<b>" + s + "</b>");
+}
+
+JSValue* stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<tt>" + s + "</tt>");
+}
+
+JSValue* stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<i>" + s + "</i>");
+}
+
+JSValue* stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<strike>" + s + "</strike>");
+}
+
+JSValue* stringProtoFuncSub(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<sub>" + s + "</sub>");
+}
+
+JSValue* stringProtoFuncSup(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
+{
+ UString s = thisValue->toThisString(exec);
+ return jsString(exec, "<sup>" + s + "</sup>");
+}
+
+JSValue* stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ JSValue* a0 = args.at(exec, 0);
+ return jsString(exec, "<font color=\"" + a0->toString(exec) + "\">" + s + "</font>");
+}
+
+JSValue* stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ JSValue* a0 = args.at(exec, 0);
+ return jsString(exec, "<font size=\"" + a0->toString(exec) + "\">" + s + "</font>");
+}
+
+JSValue* stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ JSValue* a0 = args.at(exec, 0);
+ return jsString(exec, "<a name=\"" + a0->toString(exec) + "\">" + s + "</a>");
+}
+
+JSValue* stringProtoFuncLink(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
+{
+ UString s = thisValue->toThisString(exec);
+ JSValue* a0 = args.at(exec, 0);
+ return jsString(exec, "<a href=\"" + a0->toString(exec) + "\">" + s + "</a>");
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/StringPrototype.h b/JavaScriptCore/runtime/StringPrototype.h
new file mode 100644
index 0000000..b127885
--- /dev/null
+++ b/JavaScriptCore/runtime/StringPrototype.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef StringPrototype_h
+#define StringPrototype_h
+
+#include "StringObject.h"
+
+namespace JSC {
+
+ class ObjectPrototype;
+
+ class StringPrototype : public StringObject {
+ public:
+ StringPrototype(ExecState*, PassRefPtr<StructureID>);
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+} // namespace JSC
+
+#endif // StringPrototype_h
diff --git a/JavaScriptCore/runtime/StructureID.cpp b/JavaScriptCore/runtime/StructureID.cpp
new file mode 100644
index 0000000..8333595
--- /dev/null
+++ b/JavaScriptCore/runtime/StructureID.cpp
@@ -0,0 +1,902 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StructureID.h"
+
+#include "JSObject.h"
+#include "PropertyNameArray.h"
+#include "StructureIDChain.h"
+#include "identifier.h"
+#include "lookup.h"
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/RefPtr.h>
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <wtf/Threading.h>
+#endif
+
+#define DUMP_STRUCTURE_ID_STATISTICS 0
+
+#ifndef NDEBUG
+#define DO_PROPERTYMAP_CONSTENCY_CHECK 0
+#else
+#define DO_PROPERTYMAP_CONSTENCY_CHECK 0
+#endif
+
+using namespace std;
+using WTF::doubleHash;
+
+namespace JSC {
+
+// Choose a number for the following so that most property maps are smaller,
+// but it's not going to blow out the stack to allocate this number of pointers.
+static const int smallMapThreshold = 1024;
+
+// The point at which the function call overhead of the qsort implementation
+// becomes small compared to the inefficiency of insertion sort.
+static const unsigned tinyMapThreshold = 20;
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter structureIDCounter("StructureID");
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+static Mutex ignoreSetMutex;
+#endif
+
+static bool shouldIgnoreLeaks;
+static HashSet<StructureID*> ignoreSet;
+#endif
+
+#if DUMP_STRUCTURE_ID_STATISTICS
+static HashSet<StructureID*> liveStructureIDSet;
+#endif
+
+void StructureID::dumpStatistics()
+{
+#if DUMP_STRUCTURE_ID_STATISTICS
+ unsigned numberLeaf = 0;
+ unsigned numberUsingSingleSlot = 0;
+ unsigned numberSingletons = 0;
+ unsigned totalPropertyMapsSize = 0;
+
+ HashSet<StructureID*>::const_iterator end = liveStructureIDSet.end();
+ for (HashSet<StructureID*>::const_iterator it = liveStructureIDSet.begin(); it != end; ++it) {
+ StructureID* structureID = *it;
+ if (structureID->m_usingSingleTransitionSlot) {
+ if (!structureID->m_transitions.singleTransition)
+ ++numberLeaf;
+ else
+ ++numberUsingSingleSlot;
+
+ if (!structureID->m_previous && !structureID->m_transitions.singleTransition)
+ ++numberSingletons;
+ }
+
+ if (structureID->m_propertyTable)
+ totalPropertyMapsSize += PropertyMapHashTable::allocationSize(structureID->m_propertyTable->size);
+ }
+
+ printf("Number of live StructureIDs: %d\n", liveStructureIDSet.size());
+ printf("Number of StructureIDs using the single item optimization for transition map: %d\n", numberUsingSingleSlot);
+ printf("Number of StructureIDs that are leaf nodes: %d\n", numberLeaf);
+ printf("Number of StructureIDs that singletons: %d\n", numberSingletons);
+
+ printf("Size of a single StructureIDs: %d\n", static_cast<unsigned>(sizeof(StructureID)));
+ printf("Size of sum of all property maps: %d\n", totalPropertyMapsSize);
+ printf("Size of average of all property maps: %f\n", static_cast<double>(totalPropertyMapsSize) / static_cast<double>(liveStructureIDSet.size()));
+#else
+ printf("Dumping StructureID statistics is not enabled.\n");
+#endif
+}
+
+StructureID::StructureID(JSValue* prototype, const TypeInfo& typeInfo)
+ : m_typeInfo(typeInfo)
+ , m_prototype(prototype)
+ , m_cachedPrototypeChain(0)
+ , m_previous(0)
+ , m_nameInPrevious(0)
+ , m_transitionCount(0)
+ , m_propertyTable(0)
+ , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
+ , m_cachedTransistionOffset(WTF::notFound)
+ , m_isDictionary(false)
+ , m_hasGetterSetterProperties(false)
+ , m_usingSingleTransitionSlot(true)
+ , m_attributesInPrevious(0)
+{
+ ASSERT(m_prototype);
+ ASSERT(m_prototype->isObject() || m_prototype->isNull());
+
+ m_transitions.singleTransition = 0;
+
+#ifndef NDEBUG
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ MutexLocker protect(ignoreSetMutex);
+#endif
+ if (shouldIgnoreLeaks)
+ ignoreSet.add(this);
+ else
+ structureIDCounter.increment();
+#endif
+
+#if DUMP_STRUCTURE_ID_STATISTICS
+ liveStructureIDSet.add(this);
+#endif
+}
+
+StructureID::~StructureID()
+{
+ if (m_previous) {
+ if (m_previous->m_usingSingleTransitionSlot) {
+ m_previous->m_transitions.singleTransition = 0;
+ } else {
+ ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious, m_attributesInPrevious)));
+ m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious, m_attributesInPrevious));
+ }
+ }
+
+ if (m_cachedPropertyNameArrayData)
+ m_cachedPropertyNameArrayData->setCachedStructureID(0);
+
+ if (!m_usingSingleTransitionSlot)
+ delete m_transitions.table;
+
+ if (m_propertyTable) {
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; i++) {
+ if (UString::Rep* key = m_propertyTable->entries()[i].key)
+ key->deref();
+ }
+ fastFree(m_propertyTable);
+ }
+
+#ifndef NDEBUG
+#if ENABLE(JSC_MULTIPLE_THREADS)
+ MutexLocker protect(ignoreSetMutex);
+#endif
+ HashSet<StructureID*>::iterator it = ignoreSet.find(this);
+ if (it != ignoreSet.end())
+ ignoreSet.remove(it);
+ else
+ structureIDCounter.decrement();
+#endif
+
+#if DUMP_STRUCTURE_ID_STATISTICS
+ liveStructureIDSet.remove(this);
+#endif
+}
+
+void StructureID::startIgnoringLeaks()
+{
+#ifndef NDEBUG
+ shouldIgnoreLeaks = true;
+#endif
+}
+
+void StructureID::stopIgnoringLeaks()
+{
+#ifndef NDEBUG
+ shouldIgnoreLeaks = false;
+#endif
+}
+
+void StructureID::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
+{
+ bool shouldCache = propertyNames.cacheable() && !(propertyNames.size() || m_isDictionary);
+
+ if (shouldCache) {
+ if (m_cachedPropertyNameArrayData) {
+ if (structureIDChainsAreEqual(m_cachedPropertyNameArrayData->cachedPrototypeChain(), cachedPrototypeChain())) {
+ propertyNames.setData(m_cachedPropertyNameArrayData);
+ return;
+ }
+ }
+ propertyNames.setCacheable(false);
+ }
+
+ getEnumerablePropertyNamesInternal(propertyNames);
+
+ // Add properties from the static hashtables of properties
+ for (const ClassInfo* info = baseObject->classInfo(); info; info = info->parentClass) {
+ const HashTable* table = info->propHashTable(exec);
+ if (!table)
+ continue;
+ table->initializeIfNeeded(exec);
+ ASSERT(table->table);
+ int hashSizeMask = table->hashSizeMask;
+ const HashEntry* entry = table->table;
+ for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
+ if (entry->key() && !(entry->attributes() & DontEnum))
+ propertyNames.add(entry->key());
+ }
+ }
+
+ if (m_prototype->isObject())
+ asObject(m_prototype)->getPropertyNames(exec, propertyNames);
+
+ if (shouldCache) {
+ if (m_cachedPropertyNameArrayData)
+ m_cachedPropertyNameArrayData->setCachedStructureID(0);
+
+ m_cachedPropertyNameArrayData = propertyNames.data();
+
+ StructureIDChain* chain = cachedPrototypeChain();
+ if (!chain)
+ chain = createCachedPrototypeChain();
+ m_cachedPropertyNameArrayData->setCachedPrototypeChain(chain);
+ m_cachedPropertyNameArrayData->setCachedStructureID(this);
+ }
+}
+
+void StructureID::clearEnumerationCache()
+{
+ if (m_cachedPropertyNameArrayData)
+ m_cachedPropertyNameArrayData->setCachedStructureID(0);
+ m_cachedPropertyNameArrayData.clear();
+}
+
+void StructureID::growPropertyStorageCapacity()
+{
+ if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
+ m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity;
+ else
+ m_propertyStorageCapacity *= 2;
+}
+
+PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, unsigned attributes, size_t& offset)
+{
+ ASSERT(!structureID->m_isDictionary);
+ ASSERT(structureID->typeInfo().type() == ObjectType);
+
+ if (structureID->m_usingSingleTransitionSlot) {
+ StructureID* existingTransition = structureID->m_transitions.singleTransition;
+ if (existingTransition && existingTransition->m_nameInPrevious == propertyName.ustring().rep() && existingTransition->m_attributesInPrevious == attributes) {
+ offset = structureID->m_transitions.singleTransition->cachedTransistionOffset();
+ ASSERT(offset != WTF::notFound);
+ return existingTransition;
+ }
+ } else {
+ if (StructureID* existingTransition = structureID->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes))) {
+ offset = existingTransition->cachedTransistionOffset();
+ ASSERT(offset != WTF::notFound);
+ return existingTransition;
+ }
+ }
+
+ if (structureID->m_transitionCount > s_maxTransitionLength) {
+ RefPtr<StructureID> transition = toDictionaryTransition(structureID);
+ offset = transition->put(propertyName, attributes);
+ if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
+ transition->growPropertyStorageCapacity();
+ return transition.release();
+ }
+
+ RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo());
+ transition->m_cachedPrototypeChain = structureID->m_cachedPrototypeChain;
+ transition->m_previous = structureID;
+ transition->m_nameInPrevious = propertyName.ustring().rep();
+ transition->m_attributesInPrevious = attributes;
+ transition->m_transitionCount = structureID->m_transitionCount + 1;
+ transition->m_propertyTable = structureID->copyPropertyTable();
+ transition->m_deletedOffsets = structureID->m_deletedOffsets;
+ transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties;
+
+ offset = transition->put(propertyName, attributes);
+ if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
+ transition->growPropertyStorageCapacity();
+
+ transition->setCachedTransistionOffset(offset);
+
+ if (structureID->m_usingSingleTransitionSlot) {
+ if (!structureID->m_transitions.singleTransition) {
+ structureID->m_transitions.singleTransition = transition.get();
+ return transition.release();
+ }
+
+ StructureID* existingTransition = structureID->m_transitions.singleTransition;
+ structureID->m_usingSingleTransitionSlot = false;
+ StructureIDTransitionTable* transitionTable = new StructureIDTransitionTable;
+ structureID->m_transitions.table = transitionTable;
+ transitionTable->add(make_pair(existingTransition->m_nameInPrevious, existingTransition->m_attributesInPrevious), existingTransition);
+ }
+ structureID->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get());
+ return transition.release();
+}
+
+PassRefPtr<StructureID> StructureID::removePropertyTransition(StructureID* structureID, const Identifier& propertyName, size_t& offset)
+{
+ ASSERT(!structureID->m_isDictionary);
+
+ RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo());
+ transition->m_isDictionary = true;
+ transition->m_propertyTable = structureID->copyPropertyTable();
+ transition->m_deletedOffsets = structureID->m_deletedOffsets;
+ transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties;
+
+ offset = transition->remove(propertyName);
+
+ return transition.release();
+}
+
+PassRefPtr<StructureID> StructureID::toDictionaryTransition(StructureID* structureID)
+{
+ ASSERT(!structureID->m_isDictionary);
+
+ RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo());
+ transition->m_isDictionary = true;
+ transition->m_propertyTable = structureID->copyPropertyTable();
+ transition->m_deletedOffsets = structureID->m_deletedOffsets;
+ transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties;
+ return transition.release();
+}
+
+PassRefPtr<StructureID> StructureID::fromDictionaryTransition(StructureID* structureID)
+{
+ ASSERT(structureID->m_isDictionary);
+
+ // Since dictionary StructureIDs are not shared, and no opcodes specialize
+ // for them, we don't need to allocate a new StructureID when transitioning
+ // to non-dictionary status.
+ structureID->m_isDictionary = false;
+ return structureID;
+}
+
+PassRefPtr<StructureID> StructureID::changePrototypeTransition(StructureID* structureID, JSValue* prototype)
+{
+ RefPtr<StructureID> transition = create(prototype, structureID->typeInfo());
+ transition->m_transitionCount = structureID->m_transitionCount + 1;
+ transition->m_propertyTable = structureID->copyPropertyTable();
+ transition->m_deletedOffsets = structureID->m_deletedOffsets;
+ transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structureID->m_hasGetterSetterProperties;
+ return transition.release();
+}
+
+PassRefPtr<StructureID> StructureID::getterSetterTransition(StructureID* structureID)
+{
+ RefPtr<StructureID> transition = create(structureID->storedPrototype(), structureID->typeInfo());
+ transition->m_transitionCount = structureID->m_transitionCount + 1;
+ transition->m_propertyTable = structureID->copyPropertyTable();
+ transition->m_deletedOffsets = structureID->m_deletedOffsets;
+ transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
+ return transition.release();
+}
+
+size_t StructureID::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes)
+{
+ size_t offset = put(propertyName, attributes);
+ if (propertyStorageSize() > propertyStorageCapacity())
+ growPropertyStorageCapacity();
+ clearEnumerationCache();
+ return offset;
+}
+
+size_t StructureID::removePropertyWithoutTransition(const Identifier& propertyName)
+{
+ size_t offset = remove(propertyName);
+ clearEnumerationCache();
+ return offset;
+}
+
+StructureIDChain* StructureID::createCachedPrototypeChain()
+{
+ ASSERT(typeInfo().type() == ObjectType);
+ ASSERT(!m_cachedPrototypeChain);
+
+ JSValue* prototype = storedPrototype();
+ if (JSImmediate::isImmediate(prototype))
+ return 0;
+
+ RefPtr<StructureIDChain> chain = StructureIDChain::create(asObject(prototype)->structureID());
+ setCachedPrototypeChain(chain.release());
+ return cachedPrototypeChain();
+}
+
+#if DUMP_PROPERTYMAP_STATS
+
+static int numProbes;
+static int numCollisions;
+static int numRehashes;
+static int numRemoves;
+
+struct PropertyMapStatisticsExitLogger {
+ ~PropertyMapStatisticsExitLogger();
+};
+
+static PropertyMapStatisticsExitLogger logger;
+
+PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
+{
+ printf("\nJSC::PropertyMap statistics\n\n");
+ printf("%d probes\n", numProbes);
+ printf("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
+ printf("%d rehashes\n", numRehashes);
+ printf("%d removes\n", numRemoves);
+}
+
+#endif
+
+static const unsigned deletedSentinelIndex = 1;
+
+#if !DO_PROPERTYMAP_CONSTENCY_CHECK
+
+inline void StructureID::checkConsistency()
+{
+}
+
+#endif
+
+PropertyMapHashTable* StructureID::copyPropertyTable()
+{
+ if (!m_propertyTable)
+ return 0;
+
+ size_t tableSize = PropertyMapHashTable::allocationSize(m_propertyTable->size);
+ PropertyMapHashTable* newTable = static_cast<PropertyMapHashTable*>(fastMalloc(tableSize));
+ memcpy(newTable, m_propertyTable, tableSize);
+
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; ++i) {
+ if (UString::Rep* key = newTable->entries()[i].key)
+ key->ref();
+ }
+
+ return newTable;
+}
+
+size_t StructureID::get(const Identifier& propertyName, unsigned& attributes) const
+{
+ ASSERT(!propertyName.isNull());
+
+ if (!m_propertyTable)
+ return WTF::notFound;
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ unsigned i = rep->computedHash();
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return WTF::notFound;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
+ return m_propertyTable->entries()[entryIndex - 1].offset;
+ }
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+
+ unsigned k = 1 | doubleHash(rep->computedHash());
+
+ while (1) {
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return WTF::notFound;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
+ return m_propertyTable->entries()[entryIndex - 1].offset;
+ }
+ }
+}
+
+size_t StructureID::put(const Identifier& propertyName, unsigned attributes)
+{
+ ASSERT(!propertyName.isNull());
+ ASSERT(get(propertyName) == WTF::notFound);
+
+ checkConsistency();
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ if (!m_propertyTable)
+ createPropertyMapHashTable();
+
+ // FIXME: Consider a fast case for tables with no deleted sentinels.
+
+ unsigned i = rep->computedHash();
+ unsigned k = 0;
+ bool foundDeletedElement = false;
+ unsigned deletedElementIndex = 0; // initialize to make the compiler happy
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ while (1) {
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ break;
+
+ if (entryIndex == deletedSentinelIndex) {
+ // If we find a deleted-element sentinel, remember it for use later.
+ if (!foundDeletedElement) {
+ foundDeletedElement = true;
+ deletedElementIndex = i;
+ }
+ }
+
+ if (k == 0) {
+ k = 1 | doubleHash(rep->computedHash());
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+ }
+
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+ }
+
+ // Figure out which entry to use.
+ unsigned entryIndex = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount + 2;
+ if (foundDeletedElement) {
+ i = deletedElementIndex;
+ --m_propertyTable->deletedSentinelCount;
+
+ // Since we're not making the table bigger, we can't use the entry one past
+ // the end that we were planning on using, so search backwards for the empty
+ // slot that we can use. We know it will be there because we did at least one
+ // deletion in the past that left an entry empty.
+ while (m_propertyTable->entries()[--entryIndex - 1].key) { }
+ }
+
+ // Create a new hash table entry.
+ m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = entryIndex;
+
+ // Create a new hash table entry.
+ rep->ref();
+ m_propertyTable->entries()[entryIndex - 1].key = rep;
+ m_propertyTable->entries()[entryIndex - 1].attributes = attributes;
+ m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed;
+
+ unsigned newOffset;
+ if (!m_deletedOffsets.isEmpty()) {
+ newOffset = m_deletedOffsets.last();
+ m_deletedOffsets.removeLast();
+ } else
+ newOffset = m_propertyTable->keyCount;
+ m_propertyTable->entries()[entryIndex - 1].offset = newOffset;
+
+ ++m_propertyTable->keyCount;
+
+ if ((m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount) * 2 >= m_propertyTable->size)
+ expandPropertyMapHashTable();
+
+ checkConsistency();
+ return newOffset;
+}
+
+size_t StructureID::remove(const Identifier& propertyName)
+{
+ ASSERT(!propertyName.isNull());
+
+ checkConsistency();
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ if (!m_propertyTable)
+ return WTF::notFound;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+ ++numRemoves;
+#endif
+
+ // Find the thing to remove.
+ unsigned i = rep->computedHash();
+ unsigned k = 0;
+ unsigned entryIndex;
+ UString::Rep* key = 0;
+ while (1) {
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return WTF::notFound;
+
+ key = m_propertyTable->entries()[entryIndex - 1].key;
+ if (rep == key)
+ break;
+
+ if (k == 0) {
+ k = 1 | doubleHash(rep->computedHash());
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+ }
+
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+ }
+
+ // Replace this one element with the deleted sentinel. Also clear out
+ // the entry so we can iterate all the entries as needed.
+ m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = deletedSentinelIndex;
+
+ size_t offset = m_propertyTable->entries()[entryIndex - 1].offset;
+
+ key->deref();
+ m_propertyTable->entries()[entryIndex - 1].key = 0;
+ m_propertyTable->entries()[entryIndex - 1].attributes = 0;
+ m_propertyTable->entries()[entryIndex - 1].offset = 0;
+ m_deletedOffsets.append(offset);
+
+ ASSERT(m_propertyTable->keyCount >= 1);
+ --m_propertyTable->keyCount;
+ ++m_propertyTable->deletedSentinelCount;
+
+ if (m_propertyTable->deletedSentinelCount * 4 >= m_propertyTable->size)
+ rehashPropertyMapHashTable();
+
+ checkConsistency();
+ return offset;
+}
+
+void StructureID::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry)
+{
+ ASSERT(m_propertyTable);
+
+ unsigned i = entry.key->computedHash();
+ unsigned k = 0;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ while (1) {
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ break;
+
+ if (k == 0) {
+ k = 1 | doubleHash(entry.key->computedHash());
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+ }
+
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+ }
+
+ unsigned entryIndex = m_propertyTable->keyCount + 2;
+ m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = entryIndex;
+ m_propertyTable->entries()[entryIndex - 1] = entry;
+
+ ++m_propertyTable->keyCount;
+}
+
+void StructureID::expandPropertyMapHashTable()
+{
+ ASSERT(m_propertyTable);
+ rehashPropertyMapHashTable(m_propertyTable->size * 2);
+}
+
+void StructureID::createPropertyMapHashTable()
+{
+ const unsigned newTableSize = 16;
+
+ ASSERT(!m_propertyTable);
+
+ checkConsistency();
+
+ m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
+ m_propertyTable->size = newTableSize;
+ m_propertyTable->sizeMask = newTableSize - 1;
+
+ checkConsistency();
+}
+
+void StructureID::rehashPropertyMapHashTable()
+{
+ ASSERT(m_propertyTable);
+ ASSERT(m_propertyTable->size);
+ rehashPropertyMapHashTable(m_propertyTable->size);
+}
+
+void StructureID::rehashPropertyMapHashTable(unsigned newTableSize)
+{
+ ASSERT(m_propertyTable);
+
+ checkConsistency();
+
+ PropertyMapHashTable* oldTable = m_propertyTable;
+
+ m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
+ m_propertyTable->size = newTableSize;
+ m_propertyTable->sizeMask = newTableSize - 1;
+
+ unsigned lastIndexUsed = 0;
+ unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; ++i) {
+ if (oldTable->entries()[i].key) {
+ lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
+ insertIntoPropertyMapHashTable(oldTable->entries()[i]);
+ }
+ }
+ m_propertyTable->lastIndexUsed = lastIndexUsed;
+
+ fastFree(oldTable);
+
+ checkConsistency();
+}
+
+static int comparePropertyMapEntryIndices(const void* a, const void* b)
+{
+ unsigned ia = static_cast<PropertyMapEntry* const*>(a)[0]->index;
+ unsigned ib = static_cast<PropertyMapEntry* const*>(b)[0]->index;
+ if (ia < ib)
+ return -1;
+ if (ia > ib)
+ return +1;
+ return 0;
+}
+
+void StructureID::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNames) const
+{
+ if (!m_propertyTable)
+ return;
+
+ if (m_propertyTable->keyCount < tinyMapThreshold) {
+ PropertyMapEntry* a[tinyMapThreshold];
+ int i = 0;
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned k = 1; k <= entryCount; k++) {
+ if (m_propertyTable->entries()[k].key && !(m_propertyTable->entries()[k].attributes & DontEnum)) {
+ PropertyMapEntry* value = &m_propertyTable->entries()[k];
+ int j;
+ for (j = i - 1; j >= 0 && a[j]->index > value->index; --j)
+ a[j + 1] = a[j];
+ a[j + 1] = value;
+ ++i;
+ }
+ }
+ if (!propertyNames.size()) {
+ for (int k = 0; k < i; ++k)
+ propertyNames.addKnownUnique(a[k]->key);
+ } else {
+ for (int k = 0; k < i; ++k)
+ propertyNames.add(a[k]->key);
+ }
+
+ return;
+ }
+
+ // Allocate a buffer to use to sort the keys.
+ Vector<PropertyMapEntry*, smallMapThreshold> sortedEnumerables(m_propertyTable->keyCount);
+
+ // Get pointers to the enumerable entries in the buffer.
+ PropertyMapEntry** p = sortedEnumerables.data();
+ unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
+ for (unsigned i = 1; i <= entryCount; i++) {
+ if (m_propertyTable->entries()[i].key && !(m_propertyTable->entries()[i].attributes & DontEnum))
+ *p++ = &m_propertyTable->entries()[i];
+ }
+
+ size_t enumerableCount = p - sortedEnumerables.data();
+ // Sort the entries by index.
+ qsort(sortedEnumerables.data(), enumerableCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
+ sortedEnumerables.resize(enumerableCount);
+
+ // Put the keys of the sorted entries into the list.
+ if (!propertyNames.size()) {
+ for (size_t i = 0; i < sortedEnumerables.size(); ++i)
+ propertyNames.addKnownUnique(sortedEnumerables[i]->key);
+ } else {
+ for (size_t i = 0; i < sortedEnumerables.size(); ++i)
+ propertyNames.add(sortedEnumerables[i]->key);
+ }
+}
+
+#if DO_PROPERTYMAP_CONSTENCY_CHECK
+
+void StructureID::checkConsistency()
+{
+ if (!m_propertyTable)
+ return;
+
+ ASSERT(m_propertyTable->size >= 16);
+ ASSERT(m_propertyTable->sizeMask);
+ ASSERT(m_propertyTable->size == m_propertyTable->sizeMask + 1);
+ ASSERT(!(m_propertyTable->size & m_propertyTable->sizeMask));
+
+ ASSERT(m_propertyTable->keyCount <= m_propertyTable->size / 2);
+ ASSERT(m_propertyTable->deletedSentinelCount <= m_propertyTable->size / 4);
+
+ ASSERT(m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount <= m_propertyTable->size / 2);
+
+ unsigned indexCount = 0;
+ unsigned deletedIndexCount = 0;
+ for (unsigned a = 0; a != m_propertyTable->size; ++a) {
+ unsigned entryIndex = m_propertyTable->entryIndices[a];
+ if (entryIndex == emptyEntryIndex)
+ continue;
+ if (entryIndex == deletedSentinelIndex) {
+ ++deletedIndexCount;
+ continue;
+ }
+ ASSERT(entryIndex > deletedSentinelIndex);
+ ASSERT(entryIndex - 1 <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount);
+ ++indexCount;
+
+ for (unsigned b = a + 1; b != m_propertyTable->size; ++b)
+ ASSERT(m_propertyTable->entryIndices[b] != entryIndex);
+ }
+ ASSERT(indexCount == m_propertyTable->keyCount);
+ ASSERT(deletedIndexCount == m_propertyTable->deletedSentinelCount);
+
+ ASSERT(m_propertyTable->entries()[0].key == 0);
+
+ unsigned nonEmptyEntryCount = 0;
+ for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) {
+ UString::Rep* rep = m_propertyTable->entries()[c].key;
+ if (!rep)
+ continue;
+ ++nonEmptyEntryCount;
+ unsigned i = rep->computedHash();
+ unsigned k = 0;
+ unsigned entryIndex;
+ while (1) {
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ ASSERT(entryIndex != emptyEntryIndex);
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key)
+ break;
+ if (k == 0)
+ k = 1 | doubleHash(rep->computedHash());
+ i += k;
+ }
+ ASSERT(entryIndex == c + 1);
+ }
+
+ ASSERT(nonEmptyEntryCount == m_propertyTable->keyCount);
+}
+
+#endif // DO_PROPERTYMAP_CONSTENCY_CHECK
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/StructureID.h b/JavaScriptCore/runtime/StructureID.h
new file mode 100644
index 0000000..4f45dac
--- /dev/null
+++ b/JavaScriptCore/runtime/StructureID.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureID_h
+#define StructureID_h
+
+#include "JSType.h"
+#include "JSValue.h"
+#include "PropertyMapHashTable.h"
+#include "StructureIDChain.h"
+#include "StructureIDTransitionTable.h"
+#include "TypeInfo.h"
+#include "identifier.h"
+#include "ustring.h"
+#include <wtf/HashFunctions.h>
+#include <wtf/HashTraits.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+#ifndef NDEBUG
+#define DUMP_PROPERTYMAP_STATS 0
+#else
+#define DUMP_PROPERTYMAP_STATS 0
+#endif
+
+namespace JSC {
+
+ class PropertyNameArray;
+ class PropertyNameArrayData;
+
+ class StructureID : public RefCounted<StructureID> {
+ public:
+ friend class CTI;
+ static PassRefPtr<StructureID> create(JSValue* prototype, const TypeInfo& typeInfo)
+ {
+ return adoptRef(new StructureID(prototype, typeInfo));
+ }
+
+ static void startIgnoringLeaks();
+ static void stopIgnoringLeaks();
+
+ static void dumpStatistics();
+
+ static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype);
+ static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, unsigned attributes, size_t& offset);
+ static PassRefPtr<StructureID> removePropertyTransition(StructureID*, const Identifier& propertyName, size_t& offset);
+ static PassRefPtr<StructureID> getterSetterTransition(StructureID*);
+ static PassRefPtr<StructureID> toDictionaryTransition(StructureID*);
+ static PassRefPtr<StructureID> fromDictionaryTransition(StructureID*);
+
+ ~StructureID();
+
+ void mark()
+ {
+ if (!m_prototype->marked())
+ m_prototype->mark();
+ }
+
+ // These should be used with caution.
+ size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes);
+ size_t removePropertyWithoutTransition(const Identifier& propertyName);
+ void setPrototypeWithoutTransition(JSValue* prototype) { m_prototype = prototype; }
+
+ bool isDictionary() const { return m_isDictionary; }
+
+ const TypeInfo& typeInfo() const { return m_typeInfo; }
+
+ // For use when first creating a new structure.
+ TypeInfo& mutableTypeInfo() { return m_typeInfo; }
+
+ JSValue* storedPrototype() const { return m_prototype; }
+ JSValue* prototypeForLookup(ExecState*);
+
+ StructureID* previousID() const { return m_previous.get(); }
+
+ StructureIDChain* createCachedPrototypeChain();
+ void setCachedPrototypeChain(PassRefPtr<StructureIDChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+ StructureIDChain* cachedPrototypeChain() const { return m_cachedPrototypeChain.get(); }
+
+ void setCachedTransistionOffset(size_t offset) { m_cachedTransistionOffset = offset; }
+ size_t cachedTransistionOffset() const { return m_cachedTransistionOffset; }
+
+ void growPropertyStorageCapacity();
+ size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
+ size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_deletedOffsets.size() : 0; }
+
+ size_t get(const Identifier& propertyName) const;
+ size_t get(const Identifier& propertyName, unsigned& attributes) const;
+ void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
+
+ bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
+ void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
+
+ bool isEmpty() const { return !m_propertyTable; }
+
+ private:
+ StructureID(JSValue* prototype, const TypeInfo&);
+
+ size_t put(const Identifier& propertyName, unsigned attributes);
+ size_t remove(const Identifier& propertyName);
+ void getEnumerablePropertyNamesInternal(PropertyNameArray&) const;
+
+ void expandPropertyMapHashTable();
+ void rehashPropertyMapHashTable();
+ void rehashPropertyMapHashTable(unsigned newTableSize);
+ void createPropertyMapHashTable();
+ void insertIntoPropertyMapHashTable(const PropertyMapEntry&);
+ void checkConsistency();
+
+ PropertyMapHashTable* copyPropertyTable();
+
+ void clearEnumerationCache();
+
+ static const unsigned emptyEntryIndex = 0;
+
+ static const size_t s_maxTransitionLength = 64;
+
+ TypeInfo m_typeInfo;
+
+ JSValue* m_prototype;
+ RefPtr<StructureIDChain> m_cachedPrototypeChain;
+
+ RefPtr<StructureID> m_previous;
+ UString::Rep* m_nameInPrevious;
+
+ size_t m_transitionCount;
+ union {
+ StructureID* singleTransition;
+ StructureIDTransitionTable* table;
+ } m_transitions;
+
+ RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
+
+ PropertyMapHashTable* m_propertyTable;
+ Vector<unsigned> m_deletedOffsets;
+
+ size_t m_propertyStorageCapacity;
+
+ size_t m_cachedTransistionOffset;
+
+ bool m_isDictionary : 1;
+ bool m_hasGetterSetterProperties : 1;
+ bool m_usingSingleTransitionSlot : 1;
+ unsigned m_attributesInPrevious : 5;
+ };
+
+ inline size_t StructureID::get(const Identifier& propertyName) const
+ {
+ ASSERT(!propertyName.isNull());
+
+ if (!m_propertyTable)
+ return WTF::notFound;
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ unsigned i = rep->computedHash();
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return WTF::notFound;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key)
+ return m_propertyTable->entries()[entryIndex - 1].offset;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+
+ unsigned k = 1 | WTF::doubleHash(rep->computedHash());
+
+ while (1) {
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return WTF::notFound;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key)
+ return m_propertyTable->entries()[entryIndex - 1].offset;
+ }
+ }
+
+} // namespace JSC
+
+#endif // StructureID_h
diff --git a/JavaScriptCore/runtime/StructureIDChain.cpp b/JavaScriptCore/runtime/StructureIDChain.cpp
new file mode 100644
index 0000000..83d9254
--- /dev/null
+++ b/JavaScriptCore/runtime/StructureIDChain.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StructureIDChain.h"
+
+#include "JSObject.h"
+#include "StructureID.h"
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+StructureIDChain::StructureIDChain(StructureID* structureID)
+{
+ size_t size = 1;
+
+ StructureID* tmp = structureID;
+ while (!tmp->storedPrototype()->isNull()) {
+ ++size;
+ tmp = asCell(tmp->storedPrototype())->structureID();
+ }
+
+ m_vector.set(new RefPtr<StructureID>[size + 1]);
+
+ size_t i;
+ for (i = 0; i < size - 1; ++i) {
+ m_vector[i] = structureID;
+ structureID = asObject(structureID->storedPrototype())->structureID();
+ }
+ m_vector[i] = structureID;
+ m_vector[i + 1] = 0;
+}
+
+bool structureIDChainsAreEqual(StructureIDChain* chainA, StructureIDChain* chainB)
+{
+ if (!chainA || !chainB)
+ return false;
+
+ RefPtr<StructureID>* a = chainA->head();
+ RefPtr<StructureID>* b = chainB->head();
+ while (1) {
+ if (*a != *b)
+ return false;
+ if (!*a)
+ return true;
+ a++;
+ b++;
+ }
+}
+
+} // namespace JSC
diff --git a/JavaScriptCore/runtime/StructureIDChain.h b/JavaScriptCore/runtime/StructureIDChain.h
new file mode 100644
index 0000000..2d554a7
--- /dev/null
+++ b/JavaScriptCore/runtime/StructureIDChain.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureIDChain_h
+#define StructureIDChain_h
+
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class StructureID;
+
+ class StructureIDChain : public RefCounted<StructureIDChain> {
+ public:
+ static PassRefPtr<StructureIDChain> create(StructureID* structureID) { return adoptRef(new StructureIDChain(structureID)); }
+
+ RefPtr<StructureID>* head() { return m_vector.get(); }
+
+ private:
+ StructureIDChain(StructureID* structureID);
+
+ OwnArrayPtr<RefPtr<StructureID> > m_vector;
+ };
+
+ bool structureIDChainsAreEqual(StructureIDChain*, StructureIDChain*);
+
+} // namespace JSC
+
+#endif // StructureIDChain_h
diff --git a/JavaScriptCore/runtime/StructureIDTransitionTable.h b/JavaScriptCore/runtime/StructureIDTransitionTable.h
new file mode 100644
index 0000000..dd65971
--- /dev/null
+++ b/JavaScriptCore/runtime/StructureIDTransitionTable.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureIDTransitionTable_h
+#define StructureIDTransitionTable_h
+
+#include "ustring.h"
+#include <wtf/HashFunctions.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashTraits.h>
+#include <wtf/RefPtr.h>
+
+namespace JSC {
+
+ class StructureID;
+
+ struct StructureIDTransitionTableHash {
+ typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
+ static unsigned hash(const Key& p)
+ {
+ return p.first->computedHash();
+ }
+
+ static bool equal(const Key& a, const Key& b)
+ {
+ return a == b;
+ }
+
+ static const bool safeToCompareToEmptyOrDeleted = true;
+ };
+
+ struct StructureIDTransitionTableHashTraits {
+ typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
+ typedef WTF::GenericHashTraits<unsigned> SecondTraits;
+ typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType> TraitType;
+
+ static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
+ static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
+
+ static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
+
+ static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
+ static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
+ };
+
+ typedef HashMap<StructureIDTransitionTableHash::Key, StructureID*, StructureIDTransitionTableHash, StructureIDTransitionTableHashTraits> StructureIDTransitionTable;
+
+} // namespace JSC
+
+#endif // StructureIDTransitionTable_h
diff --git a/JavaScriptCore/runtime/SymbolTable.h b/JavaScriptCore/runtime/SymbolTable.h
new file mode 100644
index 0000000..d730d58
--- /dev/null
+++ b/JavaScriptCore/runtime/SymbolTable.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SymbolTable_h
+#define SymbolTable_h
+
+#include "JSObject.h"
+#include "ustring.h"
+#include <wtf/AlwaysInline.h>
+
+namespace JSC {
+
+ static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); }
+
+ // The bit twiddling in this class assumes that every register index is a
+ // reasonably small positive or negative number, and therefore has its high
+ // four bits all set or all unset.
+
+ struct SymbolTableEntry {
+ SymbolTableEntry()
+ : m_bits(0)
+ {
+ }
+
+ SymbolTableEntry(int index)
+ {
+ ASSERT(isValidIndex(index));
+ pack(index, false, false);
+ }
+
+ SymbolTableEntry(int index, unsigned attributes)
+ {
+ ASSERT(isValidIndex(index));
+ pack(index, attributes & ReadOnly, attributes & DontEnum);
+ }
+
+ bool isNull() const
+ {
+ return !m_bits;
+ }
+
+ int getIndex() const
+ {
+ return m_bits >> FlagBits;
+ }
+
+ unsigned getAttributes() const
+ {
+ unsigned attributes = 0;
+ if (m_bits & ReadOnlyFlag)
+ attributes |= ReadOnly;
+ if (m_bits & DontEnumFlag)
+ attributes |= DontEnum;
+ return attributes;
+ }
+
+ void setAttributes(unsigned attributes)
+ {
+ pack(getIndex(), attributes & ReadOnly, attributes & DontEnum);
+ }
+
+ bool isReadOnly() const
+ {
+ return m_bits & ReadOnlyFlag;
+ }
+
+ private:
+ static const unsigned ReadOnlyFlag = 0x1;
+ static const unsigned DontEnumFlag = 0x2;
+ static const unsigned NotNullFlag = 0x4;
+ static const unsigned FlagBits = 3;
+
+ void pack(int index, bool readOnly, bool dontEnum)
+ {
+ m_bits = (index << FlagBits) | NotNullFlag;
+ if (readOnly)
+ m_bits |= ReadOnlyFlag;
+ if (dontEnum)
+ m_bits |= DontEnumFlag;
+ }
+
+ bool isValidIndex(int index)
+ {
+ return ((index << FlagBits) >> FlagBits) == index;
+ }
+
+ int m_bits;
+ };
+
+ struct SymbolTableIndexHashTraits {
+ typedef SymbolTableEntry TraitType;
+ static SymbolTableEntry emptyValue() { return SymbolTableEntry(); }
+ static const bool emptyValueIsZero = true;
+ static const bool needsDestruction = false;
+ };
+
+ typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
+
+} // namespace JSC
+
+#endif // SymbolTable_h
diff --git a/JavaScriptCore/runtime/Tracing.d b/JavaScriptCore/runtime/Tracing.d
new file mode 100644
index 0000000..b9efaff
--- /dev/null
+++ b/JavaScriptCore/runtime/Tracing.d
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+provider JavaScriptCore
+{
+ probe gc__begin();
+ probe gc__marked();
+ probe gc__end(int, int);
+
+ probe profile__will_execute(int, char*, char*, int);
+ probe profile__did_execute(int, char*, char*, int);
+};
+
+#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore provider
+#pragma D attributes Private/Private/Unknown provider JavaScriptCore module
+#pragma D attributes Private/Private/Unknown provider JavaScriptCore function
+#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore name
+#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore args
diff --git a/JavaScriptCore/runtime/Tracing.h b/JavaScriptCore/runtime/Tracing.h
new file mode 100644
index 0000000..e544f66
--- /dev/null
+++ b/JavaScriptCore/runtime/Tracing.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Tracing_h
+#define Tracing_h
+
+#if HAVE(DTRACE)
+#include "TracingDtrace.h"
+#else
+
+#define JAVASCRIPTCORE_GC_BEGIN()
+#define JAVASCRIPTCORE_GC_BEGIN_ENABLED() 0
+
+#define JAVASCRIPTCORE_GC_END(arg0, arg1)
+#define JAVASCRIPTCORE_GC_END_ENABLED() 0
+
+#define JAVASCRIPTCORE_GC_MARKED()
+#define JAVASCRIPTCORE_GC_MARKED_ENABLED() 0
+
+#define JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(arg0, arg1, arg2, arg3)
+#define JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED() 0
+
+#define JAVASCRIPTCORE_PROFILE_DID_EXECUTE(arg0, arg1, arg2, arg3)
+#define JAVASCRIPTCORE_PROFILE_DID_EXECUTE_ENABLED() 0
+
+#endif
+
+#endif // Tracing_h