From 7c8266360b23964c46d246abb01c1f9cd762acf9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 21 Jan 2013 22:03:14 +0100 Subject: [PATCH] Move ArrayCtor and ArrayProto into their own file Change-Id: I304f50704dbad396abc7c6c8ae73d454ebd73e01 Reviewed-by: Simon Hausmann --- qmljs_engine.cpp | 1 + qv4arrayobject.cpp | 720 +++++++++++++++++++++++++++++++++++++++++++++++++++++ qv4arrayobject.h | 95 +++++++ qv4ecmaobjects.cpp | 678 ------------------------------------------------- qv4ecmaobjects_p.h | 39 --- v4.pro | 2 + 6 files changed, 818 insertions(+), 717 deletions(-) create mode 100644 qv4arrayobject.cpp create mode 100644 qv4arrayobject.h diff --git a/qmljs_engine.cpp b/qmljs_engine.cpp index 231c6b8..0e9abb5 100644 --- a/qmljs_engine.cpp +++ b/qmljs_engine.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include diff --git a/qv4arrayobject.cpp b/qv4arrayobject.cpp new file mode 100644 index 0000000..3021229 --- /dev/null +++ b/qv4arrayobject.cpp @@ -0,0 +1,720 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the V4VM module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4arrayobject.h" +#include "qv4array.h" + +using namespace QQmlJS::VM; + +ArrayCtor::ArrayCtor(ExecutionContext *scope) + : FunctionObject(scope) +{ +} + +Value ArrayCtor::call(ExecutionContext *ctx) +{ + ArrayObject *a = ctx->engine->newArrayObject(ctx); + Array &value = a->array; + if (ctx->argumentCount == 1 && ctx->argument(0).isNumber()) { + bool ok; + uint len = ctx->argument(0).asArrayLength(ctx, &ok); + + if (!ok) { + ctx->throwRangeError(ctx->argument(0)); + return Value::undefinedValue(); + } + + value.setLengthUnchecked(len); + } else { + for (unsigned int i = 0; i < ctx->argumentCount; ++i) { + value.set(i, ctx->argument(i)); + } + } + + return Value::fromObject(a); +} + +void ArrayPrototype::init(ExecutionContext *ctx, const Value &ctor) +{ + ctor.objectValue()->defineReadonlyProperty(ctx->engine->id_prototype, Value::fromObject(this)); + ctor.objectValue()->defineReadonlyProperty(ctx->engine->id_length, Value::fromInt32(1)); + ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("isArray"), method_isArray, 1); + defineDefaultProperty(ctx, QStringLiteral("constructor"), ctor); + defineDefaultProperty(ctx, QStringLiteral("toString"), method_toString, 0); + defineDefaultProperty(ctx, QStringLiteral("toLocalString"), method_toLocaleString, 0); + defineDefaultProperty(ctx, QStringLiteral("concat"), method_concat, 1); + defineDefaultProperty(ctx, QStringLiteral("join"), method_join, 1); + defineDefaultProperty(ctx, QStringLiteral("pop"), method_pop, 0); + defineDefaultProperty(ctx, QStringLiteral("push"), method_push, 1); + defineDefaultProperty(ctx, QStringLiteral("reverse"), method_reverse, 0); + defineDefaultProperty(ctx, QStringLiteral("shift"), method_shift, 0); + defineDefaultProperty(ctx, QStringLiteral("slice"), method_slice, 2); + defineDefaultProperty(ctx, QStringLiteral("sort"), method_sort, 1); + defineDefaultProperty(ctx, QStringLiteral("splice"), method_splice, 2); + defineDefaultProperty(ctx, QStringLiteral("unshift"), method_unshift, 1); + defineDefaultProperty(ctx, QStringLiteral("indexOf"), method_indexOf, 1); + defineDefaultProperty(ctx, QStringLiteral("lastIndexOf"), method_lastIndexOf, 1); + defineDefaultProperty(ctx, QStringLiteral("every"), method_every, 1); + defineDefaultProperty(ctx, QStringLiteral("some"), method_some, 1); + defineDefaultProperty(ctx, QStringLiteral("forEach"), method_forEach, 1); + defineDefaultProperty(ctx, QStringLiteral("map"), method_map, 1); + defineDefaultProperty(ctx, QStringLiteral("filter"), method_filter, 1); + defineDefaultProperty(ctx, QStringLiteral("reduce"), method_reduce, 1); + defineDefaultProperty(ctx, QStringLiteral("reduceRight"), method_reduceRight, 1); +} + +uint ArrayPrototype::getLength(ExecutionContext *ctx, Object *o) +{ + if (o->isArray) + return o->array.length(); + return o->__get__(ctx, ctx->engine->id_length).toUInt32(ctx); +} + +Value ArrayPrototype::method_isArray(ExecutionContext *ctx) +{ + Value arg = ctx->argument(0); + bool isArray = arg.asArrayObject(); + return Value::fromBoolean(isArray); +} + +Value ArrayPrototype::method_toString(ExecutionContext *ctx) +{ + return method_join(ctx); +} + +Value ArrayPrototype::method_toLocaleString(ExecutionContext *ctx) +{ + return method_toString(ctx); +} + +Value ArrayPrototype::method_concat(ExecutionContext *ctx) +{ + Array result; + + if (ArrayObject *instance = ctx->thisObject.asArrayObject()) + result = instance->array; + else { + QString v = ctx->thisObject.toString(ctx)->toQString(); + result.set(0, Value::fromString(ctx, v)); + } + + for (uint i = 0; i < ctx->argumentCount; ++i) { + quint32 k = result.length(); + Value arg = ctx->argument(i); + + if (ArrayObject *elt = arg.asArrayObject()) + result.concat(elt->array); + + else + result.set(k, arg); + } + + return Value::fromObject(ctx->engine->newArrayObject(ctx, result)); +} + +Value ArrayPrototype::method_join(ExecutionContext *ctx) +{ + Value arg = ctx->argument(0); + + QString r4; + if (arg.isUndefined()) + r4 = QStringLiteral(","); + else + r4 = arg.toString(ctx)->toQString(); + + Value self = ctx->thisObject; + const Value length = self.property(ctx, ctx->engine->id_length); + const quint32 r2 = Value::toUInt32(length.isUndefined() ? 0 : length.toNumber(ctx)); + + static QSet visitedArrayElements; + + if (! r2 || visitedArrayElements.contains(self.objectValue())) + return Value::fromString(ctx, QString()); + + // avoid infinite recursion + visitedArrayElements.insert(self.objectValue()); + + QString R; + + // ### FIXME + if (ArrayObject *a = self.asArrayObject()) { + for (uint i = 0; i < a->array.length(); ++i) { + if (i) + R += r4; + + Value e = a->__get__(ctx, i); + if (! (e.isUndefined() || e.isNull())) + R += e.toString(ctx)->toQString(); + } + } else { + // + // crazy! + // + Value r6 = self.property(ctx, ctx->engine->identifier(QStringLiteral("0"))); + if (!(r6.isUndefined() || r6.isNull())) + R = r6.toString(ctx)->toQString(); + + for (quint32 k = 1; k < r2; ++k) { + R += r4; + + String *name = Value::fromDouble(k).toString(ctx); + Value r12 = self.property(ctx, name); + + if (! (r12.isUndefined() || r12.isNull())) + R += r12.toString(ctx)->toQString(); + } + } + + visitedArrayElements.remove(self.objectValue()); + return Value::fromString(ctx, R); +} + +Value ArrayPrototype::method_pop(ExecutionContext *ctx) +{ + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + Value v = instance->getValueChecked(ctx, instance->array.back()); + instance->array.pop_back(); + return v; + } + + Value r1 = self.property(ctx, ctx->engine->id_length); + quint32 r2 = !r1.isUndefined() ? r1.toUInt32(ctx) : 0; + if (r2) { + String *r6 = Value::fromDouble(r2 - 1).toString(ctx); + Value r7 = self.property(ctx, r6); + self.objectValue()->__delete__(ctx, r6); + self.objectValue()->__put__(ctx, ctx->engine->id_length, Value::fromDouble(2 - 1)); + return r7; + } + + self.objectValue()->__put__(ctx, ctx->engine->id_length, Value::fromDouble(0)); + return Value::undefinedValue(); +} + +Value ArrayPrototype::method_push(ExecutionContext *ctx) +{ + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + for (unsigned int i = 0; i < ctx->argumentCount; ++i) { + Value val = ctx->argument(i); + instance->array.push_back(val); + } + return Value::fromDouble(instance->array.length()); + } + + Value r1 = self.property(ctx, ctx->engine->id_length); + quint32 n = !r1.isUndefined() ? r1.toUInt32(ctx) : 0; + for (unsigned int index = 0; index < ctx->argumentCount; ++index, ++n) { + Value r3 = ctx->argument(index); + String *name = Value::fromDouble(n).toString(ctx); + self.objectValue()->__put__(ctx, name, r3); + } + Value r = Value::fromDouble(n); + self.objectValue()->__put__(ctx, ctx->engine->id_length, r); + return r; +} + +Value ArrayPrototype::method_reverse(ExecutionContext *ctx) +{ + ArrayObject *instance = ctx->thisObject.asArrayObject(); + if (!instance) + ctx->throwUnimplemented(QStringLiteral("Array.prototype.reverse")); + + int lo = 0, hi = instance->array.length() - 1; + + // ### + for (; lo < hi; ++lo, --hi) { + Value tmp = instance->__get__(ctx, lo); + instance->array.set(lo, instance->__get__(ctx, hi)); + instance->array.set(hi, tmp); + } + return Value::undefinedValue(); +} + +Value ArrayPrototype::method_shift(ExecutionContext *ctx) +{ + ArrayObject *instance = ctx->thisObject.asArrayObject(); + if (!instance) + ctx->throwUnimplemented(QStringLiteral("Array.prototype.shift")); + + Value v = instance->getValueChecked(ctx, instance->array.front()); + instance->array.pop_front(); + return v; +} + +Value ArrayPrototype::method_slice(ExecutionContext *ctx) +{ + Object *o = ctx->thisObject.toObject(ctx).objectValue(); + + Array result; + uint len = o->__get__(ctx, ctx->engine->id_length).toUInt32(ctx); + double s = ctx->argument(0).toInteger(ctx); + uint start; + if (s < 0) + start = (uint)qMax(len + s, 0.); + else if (s > len) + start = len; + else + start = (uint) s; + uint end = len; + if (!ctx->argument(1).isUndefined()) { + double e = ctx->argument(1).toInteger(ctx); + if (e < 0) + end = (uint)qMax(len + e, 0.); + else if (e > len) + end = len; + else + end = (uint) e; + } + + uint n = 0; + for (uint i = start; i < end; ++i) { + bool exists; + Value v = o->__get__(ctx, i, &exists); + if (exists) + result.set(n, v); + ++n; + } + return Value::fromObject(ctx->engine->newArrayObject(ctx, result)); +} + +Value ArrayPrototype::method_sort(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + + uint len = getLength(ctx, instance); + + Value comparefn = ctx->argument(0); + instance->array.sort(ctx, instance, comparefn, len); + return ctx->thisObject; +} + +Value ArrayPrototype::method_splice(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + uint len = getLength(ctx, instance); + + ArrayObject *newArray = ctx->engine->newArrayObject(ctx); + + double rs = ctx->argument(0).toInteger(ctx); + uint start; + if (rs < 0) + start = (uint) qMax(0., len + rs); + else + start = (uint) qMin(rs, (double)len); + + uint deleteCount = (uint)qMin(qMax(ctx->argument(1).toInteger(ctx), 0.), (double)(len - start)); + + newArray->array.values.resize(deleteCount); + PropertyDescriptor *pd = newArray->array.values.data(); + for (uint i = 0; i < deleteCount; ++i) { + pd->type = PropertyDescriptor::Data; + pd->writable = PropertyDescriptor::Enabled; + pd->enumberable = PropertyDescriptor::Enabled; + pd->configurable = PropertyDescriptor::Enabled; + pd->value = instance->__get__(ctx, start + i); + ++pd; + } + newArray->array.setLengthUnchecked(deleteCount); + + uint itemCount = ctx->argumentCount < 2 ? 0 : ctx->argumentCount - 2; + + if (itemCount < deleteCount) { + for (uint k = start; k < len - deleteCount; ++k) { + bool exists; + Value v = instance->__get__(ctx, k + deleteCount, &exists); + if (exists) + instance->array.set(k + itemCount, v); + else + instance->__delete__(ctx, k + itemCount); + } + for (uint k = len; k > len - deleteCount + itemCount; --k) + instance->__delete__(ctx, k - 1); + } else if (itemCount > deleteCount) { + uint k = len - deleteCount; + while (k > start) { + bool exists; + Value v = instance->__get__(ctx, k + deleteCount - 1, &exists); + if (exists) + instance->array.set(k + itemCount - 1, v); + else + instance->__delete__(ctx, k + itemCount - 1); + --k; + } + } + + for (uint i = 0; i < itemCount; ++i) + instance->array.set(start + i, ctx->argument(i + 2)); + + ctx->strictMode = true; + instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(len - deleteCount + itemCount)); + + return Value::fromObject(newArray); +} + +Value ArrayPrototype::method_unshift(ExecutionContext *ctx) +{ + ArrayObject *instance = ctx->thisObject.asArrayObject(); + if (!instance) + ctx->throwUnimplemented(QStringLiteral("Array.prototype.shift")); + + for (int i = ctx->argumentCount - 1; i >= 0; --i) { + Value v = ctx->argument(i); + instance->array.push_front(v); + } + + uint l = instance->array.length(); + if (l < INT_MAX) + return Value::fromInt32(l); + return Value::fromDouble((double)l); +} + +Value ArrayPrototype::method_indexOf(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + uint len = getLength(ctx, instance); + if (!len) + return Value::fromInt32(-1); + + Value searchValue; + uint fromIndex = 0; + + if (ctx->argumentCount >= 1) + searchValue = ctx->argument(0); + else + searchValue = Value::undefinedValue(); + + if (ctx->argumentCount >= 2) { + double f = ctx->argument(1).toInteger(ctx); + if (f >= len) + return Value::fromInt32(-1); + if (f < 0) + f = qMax(len + f, 0.); + fromIndex = (uint) f; + } + + if (instance->isString) { + for (uint k = fromIndex; k < len; ++k) { + bool exists; + Value v = instance->__get__(ctx, k, &exists); + if (exists && __qmljs_strict_equal(v, searchValue)) + return Value::fromDouble(k); + } + return Value::fromInt32(-1); + } + + return instance->array.indexOf(searchValue, fromIndex, len, ctx, instance); +} + +Value ArrayPrototype::method_lastIndexOf(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + uint len = getLength(ctx, instance); + if (!len) + return Value::fromInt32(-1); + + Value searchValue; + uint fromIndex = len - 1; + + if (ctx->argumentCount >= 1) + searchValue = ctx->argument(0); + else + searchValue = Value::undefinedValue(); + + if (ctx->argumentCount >= 2) { + double f = ctx->argument(1).toInteger(ctx); + if (f >= len) + return Value::fromInt32(-1); + if (f < 0) + f = qMax(len + f, 0.); + fromIndex = (uint) f; + } + + for (uint k = fromIndex; k > 0; --k) { + bool exists; + Value v = instance->__get__(ctx, k, &exists); + if (exists && __qmljs_strict_equal(v, searchValue)) + return Value::fromDouble(k); + } + return Value::fromInt32(-1); +} + +Value ArrayPrototype::method_every(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + + uint len = getLength(ctx, instance); + + FunctionObject *callback = ctx->argument(0).asFunctionObject(); + if (!callback) + __qmljs_throw_type_error(ctx); + + Value thisArg = ctx->argument(1); + + bool ok = true; + for (uint k = 0; ok && k < len; ++k) { + bool exists; + Value v = instance->__get__(ctx, k, &exists); + if (!exists) + continue; + + Value args[3]; + args[0] = v; + args[1] = Value::fromDouble(k); + args[2] = ctx->thisObject; + Value r = callback->call(ctx, thisArg, args, 3); + ok = __qmljs_to_boolean(r, ctx); + } + return Value::fromBoolean(ok); +} + +Value ArrayPrototype::method_some(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + + uint len = getLength(ctx, instance); + + FunctionObject *callback = ctx->argument(0).asFunctionObject(); + if (!callback) + __qmljs_throw_type_error(ctx); + + Value thisArg = ctx->argument(1); + + for (uint k = 0; k < len; ++k) { + bool exists; + Value v = instance->__get__(ctx, k, &exists); + if (!exists) + continue; + + Value args[3]; + args[0] = v; + args[1] = Value::fromDouble(k); + args[2] = ctx->thisObject; + Value r = callback->call(ctx, thisArg, args, 3); + if (__qmljs_to_boolean(r, ctx)) + return Value::fromBoolean(true); + } + return Value::fromBoolean(false); +} + +Value ArrayPrototype::method_forEach(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + + uint len = getLength(ctx, instance); + + FunctionObject *callback = ctx->argument(0).asFunctionObject(); + if (!callback) + __qmljs_throw_type_error(ctx); + + Value thisArg = ctx->argument(1); + + for (uint k = 0; k < len; ++k) { + bool exists; + Value v = instance->__get__(ctx, k, &exists); + if (!exists) + continue; + + Value args[3]; + args[0] = v; + args[1] = Value::fromDouble(k); + args[2] = ctx->thisObject; + callback->call(ctx, thisArg, args, 3); + } + return Value::undefinedValue(); +} + +Value ArrayPrototype::method_map(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + + uint len = getLength(ctx, instance); + + FunctionObject *callback = ctx->argument(0).asFunctionObject(); + if (!callback) + __qmljs_throw_type_error(ctx); + + Value thisArg = ctx->argument(1); + + ArrayObject *a = ctx->engine->newArrayObject(ctx); + a->array.setLength(len); + + for (uint k = 0; k < len; ++k) { + bool exists; + Value v = instance->__get__(ctx, k, &exists); + if (!exists) + continue; + + Value args[3]; + args[0] = v; + args[1] = Value::fromDouble(k); + args[2] = ctx->thisObject; + Value mapped = callback->call(ctx, thisArg, args, 3); + a->array.set(k, mapped); + } + return Value::fromObject(a); +} + +Value ArrayPrototype::method_filter(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + + uint len = getLength(ctx, instance); + + FunctionObject *callback = ctx->argument(0).asFunctionObject(); + if (!callback) + __qmljs_throw_type_error(ctx); + + Value thisArg = ctx->argument(1); + + ArrayObject *a = ctx->engine->newArrayObject(ctx); + + uint to = 0; + for (uint k = 0; k < len; ++k) { + bool exists; + Value v = instance->__get__(ctx, k, &exists); + if (!exists) + continue; + + Value args[3]; + args[0] = v; + args[1] = Value::fromDouble(k); + args[2] = ctx->thisObject; + Value selected = callback->call(ctx, thisArg, args, 3); + if (__qmljs_to_boolean(selected, ctx)) { + a->array.set(to, v); + ++to; + } + } + return Value::fromObject(a); +} + +Value ArrayPrototype::method_reduce(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + + uint len = getLength(ctx, instance); + + FunctionObject *callback = ctx->argument(0).asFunctionObject(); + if (!callback) + __qmljs_throw_type_error(ctx); + + uint k = 0; + Value acc; + if (ctx->argumentCount > 1) { + acc = ctx->argument(1); + } else { + bool kPresent = false; + while (k < len && !kPresent) { + Value v = instance->__get__(ctx, k, &kPresent); + if (kPresent) + acc = v; + ++k; + } + if (!kPresent) + __qmljs_throw_type_error(ctx); + } + + while (k < len) { + bool kPresent; + Value v = instance->__get__(ctx, k, &kPresent); + if (kPresent) { + Value args[4]; + args[0] = acc; + args[1] = v; + args[2] = Value::fromDouble(k); + args[3] = ctx->thisObject; + acc = callback->call(ctx, Value::undefinedValue(), args, 4); + } + ++k; + } + return acc; +} + +Value ArrayPrototype::method_reduceRight(ExecutionContext *ctx) +{ + Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); + + uint len = getLength(ctx, instance); + + FunctionObject *callback = ctx->argument(0).asFunctionObject(); + if (!callback) + __qmljs_throw_type_error(ctx); + + if (len == 0) { + if (ctx->argumentCount == 1) + __qmljs_throw_type_error(ctx); + return ctx->argument(1); + } + + uint k = len; + Value acc; + if (ctx->argumentCount > 1) { + acc = ctx->argument(1); + } else { + bool kPresent = false; + while (k > 0 && !kPresent) { + Value v = instance->__get__(ctx, k - 1, &kPresent); + if (kPresent) + acc = v; + --k; + } + if (!kPresent) + __qmljs_throw_type_error(ctx); + } + + while (k > 0) { + bool kPresent; + Value v = instance->__get__(ctx, k - 1, &kPresent); + if (kPresent) { + Value args[4]; + args[0] = acc; + args[1] = v; + args[2] = Value::fromDouble(k - 1); + args[3] = ctx->thisObject; + acc = callback->call(ctx, Value::undefinedValue(), args, 4); + } + --k; + } + return acc; +} + diff --git a/qv4arrayobject.h b/qv4arrayobject.h new file mode 100644 index 0000000..8a15546 --- /dev/null +++ b/qv4arrayobject.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the V4VM module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QV4ARRAYOBJECT_H +#define QV4ARRAYOBJECT_H + +#include "qv4object.h" +#include "qv4functionobject.h" +#include + +namespace QQmlJS { +namespace VM { + + +struct ArrayCtor: FunctionObject +{ + ArrayCtor(ExecutionContext *scope); + + virtual Value call(ExecutionContext *ctx); +}; + +struct ArrayPrototype: ArrayObject +{ + ArrayPrototype(ExecutionContext *context) : ArrayObject(context) {} + + void init(ExecutionContext *ctx, const Value &ctor); + + static uint getLength(ExecutionContext *ctx, Object *o); + + static Value method_isArray(ExecutionContext *ctx); + static Value method_toString(ExecutionContext *ctx); + static Value method_toLocaleString(ExecutionContext *ctx); + static Value method_concat(ExecutionContext *ctx); + static Value method_join(ExecutionContext *ctx); + static Value method_pop(ExecutionContext *ctx); + static Value method_push(ExecutionContext *ctx); + static Value method_reverse(ExecutionContext *ctx); + static Value method_shift(ExecutionContext *ctx); + static Value method_slice(ExecutionContext *ctx); + static Value method_sort(ExecutionContext *ctx); + static Value method_splice(ExecutionContext *ctx); + static Value method_unshift(ExecutionContext *ctx); + static Value method_indexOf(ExecutionContext *ctx); + static Value method_lastIndexOf(ExecutionContext *ctx); + static Value method_every(ExecutionContext *ctx); + static Value method_some(ExecutionContext *ctx); + static Value method_forEach(ExecutionContext *ctx); + static Value method_map(ExecutionContext *ctx); + static Value method_filter(ExecutionContext *ctx); + static Value method_reduce(ExecutionContext *ctx); + static Value method_reduceRight(ExecutionContext *ctx); +}; + + +} // end of namespace VM +} // end of namespace QQmlJS + +#endif // QV4ECMAOBJECTS_P_H diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp index 206d349..e64852e 100644 --- a/qv4ecmaobjects.cpp +++ b/qv4ecmaobjects.cpp @@ -783,681 +783,3 @@ Value BooleanPrototype::method_valueOf(ExecutionContext *ctx) return thisObject->value; } - -// -// Array object -// -ArrayCtor::ArrayCtor(ExecutionContext *scope) - : FunctionObject(scope) -{ -} - -Value ArrayCtor::call(ExecutionContext *ctx) -{ - ArrayObject *a = ctx->engine->newArrayObject(ctx); - Array &value = a->array; - if (ctx->argumentCount == 1 && ctx->argument(0).isNumber()) { - bool ok; - uint len = ctx->argument(0).asArrayLength(ctx, &ok); - - if (!ok) { - ctx->throwRangeError(ctx->argument(0)); - return Value::undefinedValue(); - } - - value.setLengthUnchecked(len); - } else { - for (unsigned int i = 0; i < ctx->argumentCount; ++i) { - value.set(i, ctx->argument(i)); - } - } - - return Value::fromObject(a); -} - -void ArrayPrototype::init(ExecutionContext *ctx, const Value &ctor) -{ - ctor.objectValue()->defineReadonlyProperty(ctx->engine->id_prototype, Value::fromObject(this)); - ctor.objectValue()->defineReadonlyProperty(ctx->engine->id_length, Value::fromInt32(1)); - ctor.objectValue()->defineDefaultProperty(ctx, QStringLiteral("isArray"), method_isArray, 1); - defineDefaultProperty(ctx, QStringLiteral("constructor"), ctor); - defineDefaultProperty(ctx, QStringLiteral("toString"), method_toString, 0); - defineDefaultProperty(ctx, QStringLiteral("toLocalString"), method_toLocaleString, 0); - defineDefaultProperty(ctx, QStringLiteral("concat"), method_concat, 1); - defineDefaultProperty(ctx, QStringLiteral("join"), method_join, 1); - defineDefaultProperty(ctx, QStringLiteral("pop"), method_pop, 0); - defineDefaultProperty(ctx, QStringLiteral("push"), method_push, 1); - defineDefaultProperty(ctx, QStringLiteral("reverse"), method_reverse, 0); - defineDefaultProperty(ctx, QStringLiteral("shift"), method_shift, 0); - defineDefaultProperty(ctx, QStringLiteral("slice"), method_slice, 2); - defineDefaultProperty(ctx, QStringLiteral("sort"), method_sort, 1); - defineDefaultProperty(ctx, QStringLiteral("splice"), method_splice, 2); - defineDefaultProperty(ctx, QStringLiteral("unshift"), method_unshift, 1); - defineDefaultProperty(ctx, QStringLiteral("indexOf"), method_indexOf, 1); - defineDefaultProperty(ctx, QStringLiteral("lastIndexOf"), method_lastIndexOf, 1); - defineDefaultProperty(ctx, QStringLiteral("every"), method_every, 1); - defineDefaultProperty(ctx, QStringLiteral("some"), method_some, 1); - defineDefaultProperty(ctx, QStringLiteral("forEach"), method_forEach, 1); - defineDefaultProperty(ctx, QStringLiteral("map"), method_map, 1); - defineDefaultProperty(ctx, QStringLiteral("filter"), method_filter, 1); - defineDefaultProperty(ctx, QStringLiteral("reduce"), method_reduce, 1); - defineDefaultProperty(ctx, QStringLiteral("reduceRight"), method_reduceRight, 1); -} - -uint ArrayPrototype::getLength(ExecutionContext *ctx, Object *o) -{ - if (o->isArray) - return o->array.length(); - return o->__get__(ctx, ctx->engine->id_length).toUInt32(ctx); -} - -Value ArrayPrototype::method_isArray(ExecutionContext *ctx) -{ - Value arg = ctx->argument(0); - bool isArray = arg.asArrayObject(); - return Value::fromBoolean(isArray); -} - -Value ArrayPrototype::method_toString(ExecutionContext *ctx) -{ - return method_join(ctx); -} - -Value ArrayPrototype::method_toLocaleString(ExecutionContext *ctx) -{ - return method_toString(ctx); -} - -Value ArrayPrototype::method_concat(ExecutionContext *ctx) -{ - Array result; - - if (ArrayObject *instance = ctx->thisObject.asArrayObject()) - result = instance->array; - else { - QString v = ctx->thisObject.toString(ctx)->toQString(); - result.set(0, Value::fromString(ctx, v)); - } - - for (uint i = 0; i < ctx->argumentCount; ++i) { - quint32 k = result.length(); - Value arg = ctx->argument(i); - - if (ArrayObject *elt = arg.asArrayObject()) - result.concat(elt->array); - - else - result.set(k, arg); - } - - return Value::fromObject(ctx->engine->newArrayObject(ctx, result)); -} - -Value ArrayPrototype::method_join(ExecutionContext *ctx) -{ - Value arg = ctx->argument(0); - - QString r4; - if (arg.isUndefined()) - r4 = QStringLiteral(","); - else - r4 = arg.toString(ctx)->toQString(); - - Value self = ctx->thisObject; - const Value length = self.property(ctx, ctx->engine->id_length); - const quint32 r2 = Value::toUInt32(length.isUndefined() ? 0 : length.toNumber(ctx)); - - static QSet visitedArrayElements; - - if (! r2 || visitedArrayElements.contains(self.objectValue())) - return Value::fromString(ctx, QString()); - - // avoid infinite recursion - visitedArrayElements.insert(self.objectValue()); - - QString R; - - // ### FIXME - if (ArrayObject *a = self.asArrayObject()) { - for (uint i = 0; i < a->array.length(); ++i) { - if (i) - R += r4; - - Value e = a->__get__(ctx, i); - if (! (e.isUndefined() || e.isNull())) - R += e.toString(ctx)->toQString(); - } - } else { - // - // crazy! - // - Value r6 = self.property(ctx, ctx->engine->identifier(QStringLiteral("0"))); - if (!(r6.isUndefined() || r6.isNull())) - R = r6.toString(ctx)->toQString(); - - for (quint32 k = 1; k < r2; ++k) { - R += r4; - - String *name = Value::fromDouble(k).toString(ctx); - Value r12 = self.property(ctx, name); - - if (! (r12.isUndefined() || r12.isNull())) - R += r12.toString(ctx)->toQString(); - } - } - - visitedArrayElements.remove(self.objectValue()); - return Value::fromString(ctx, R); -} - -Value ArrayPrototype::method_pop(ExecutionContext *ctx) -{ - Value self = ctx->thisObject; - if (ArrayObject *instance = self.asArrayObject()) { - Value v = instance->getValueChecked(ctx, instance->array.back()); - instance->array.pop_back(); - return v; - } - - Value r1 = self.property(ctx, ctx->engine->id_length); - quint32 r2 = !r1.isUndefined() ? r1.toUInt32(ctx) : 0; - if (r2) { - String *r6 = Value::fromDouble(r2 - 1).toString(ctx); - Value r7 = self.property(ctx, r6); - self.objectValue()->__delete__(ctx, r6); - self.objectValue()->__put__(ctx, ctx->engine->id_length, Value::fromDouble(2 - 1)); - return r7; - } - - self.objectValue()->__put__(ctx, ctx->engine->id_length, Value::fromDouble(0)); - return Value::undefinedValue(); -} - -Value ArrayPrototype::method_push(ExecutionContext *ctx) -{ - Value self = ctx->thisObject; - if (ArrayObject *instance = self.asArrayObject()) { - for (unsigned int i = 0; i < ctx->argumentCount; ++i) { - Value val = ctx->argument(i); - instance->array.push_back(val); - } - return Value::fromDouble(instance->array.length()); - } - - Value r1 = self.property(ctx, ctx->engine->id_length); - quint32 n = !r1.isUndefined() ? r1.toUInt32(ctx) : 0; - for (unsigned int index = 0; index < ctx->argumentCount; ++index, ++n) { - Value r3 = ctx->argument(index); - String *name = Value::fromDouble(n).toString(ctx); - self.objectValue()->__put__(ctx, name, r3); - } - Value r = Value::fromDouble(n); - self.objectValue()->__put__(ctx, ctx->engine->id_length, r); - return r; -} - -Value ArrayPrototype::method_reverse(ExecutionContext *ctx) -{ - ArrayObject *instance = ctx->thisObject.asArrayObject(); - if (!instance) - ctx->throwUnimplemented(QStringLiteral("Array.prototype.reverse")); - - int lo = 0, hi = instance->array.length() - 1; - - // ### - for (; lo < hi; ++lo, --hi) { - Value tmp = instance->__get__(ctx, lo); - instance->array.set(lo, instance->__get__(ctx, hi)); - instance->array.set(hi, tmp); - } - return Value::undefinedValue(); -} - -Value ArrayPrototype::method_shift(ExecutionContext *ctx) -{ - ArrayObject *instance = ctx->thisObject.asArrayObject(); - if (!instance) - ctx->throwUnimplemented(QStringLiteral("Array.prototype.shift")); - - Value v = instance->getValueChecked(ctx, instance->array.front()); - instance->array.pop_front(); - return v; -} - -Value ArrayPrototype::method_slice(ExecutionContext *ctx) -{ - Object *o = ctx->thisObject.toObject(ctx).objectValue(); - - Array result; - uint len = o->__get__(ctx, ctx->engine->id_length).toUInt32(ctx); - double s = ctx->argument(0).toInteger(ctx); - uint start; - if (s < 0) - start = (uint)qMax(len + s, 0.); - else if (s > len) - start = len; - else - start = (uint) s; - uint end = len; - if (!ctx->argument(1).isUndefined()) { - double e = ctx->argument(1).toInteger(ctx); - if (e < 0) - end = (uint)qMax(len + e, 0.); - else if (e > len) - end = len; - else - end = (uint) e; - } - - uint n = 0; - for (uint i = start; i < end; ++i) { - bool exists; - Value v = o->__get__(ctx, i, &exists); - if (exists) - result.set(n, v); - ++n; - } - return Value::fromObject(ctx->engine->newArrayObject(ctx, result)); -} - -Value ArrayPrototype::method_sort(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - - uint len = getLength(ctx, instance); - - Value comparefn = ctx->argument(0); - instance->array.sort(ctx, instance, comparefn, len); - return ctx->thisObject; -} - -Value ArrayPrototype::method_splice(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - uint len = getLength(ctx, instance); - - ArrayObject *newArray = ctx->engine->newArrayObject(ctx); - - double rs = ctx->argument(0).toInteger(ctx); - uint start; - if (rs < 0) - start = (uint) qMax(0., len + rs); - else - start = (uint) qMin(rs, (double)len); - - uint deleteCount = (uint)qMin(qMax(ctx->argument(1).toInteger(ctx), 0.), (double)(len - start)); - - newArray->array.values.resize(deleteCount); - PropertyDescriptor *pd = newArray->array.values.data(); - for (uint i = 0; i < deleteCount; ++i) { - pd->type = PropertyDescriptor::Data; - pd->writable = PropertyDescriptor::Enabled; - pd->enumberable = PropertyDescriptor::Enabled; - pd->configurable = PropertyDescriptor::Enabled; - pd->value = instance->__get__(ctx, start + i); - ++pd; - } - newArray->array.setLengthUnchecked(deleteCount); - - uint itemCount = ctx->argumentCount < 2 ? 0 : ctx->argumentCount - 2; - - if (itemCount < deleteCount) { - for (uint k = start; k < len - deleteCount; ++k) { - bool exists; - Value v = instance->__get__(ctx, k + deleteCount, &exists); - if (exists) - instance->array.set(k + itemCount, v); - else - instance->__delete__(ctx, k + itemCount); - } - for (uint k = len; k > len - deleteCount + itemCount; --k) - instance->__delete__(ctx, k - 1); - } else if (itemCount > deleteCount) { - uint k = len - deleteCount; - while (k > start) { - bool exists; - Value v = instance->__get__(ctx, k + deleteCount - 1, &exists); - if (exists) - instance->array.set(k + itemCount - 1, v); - else - instance->__delete__(ctx, k + itemCount - 1); - --k; - } - } - - for (uint i = 0; i < itemCount; ++i) - instance->array.set(start + i, ctx->argument(i + 2)); - - ctx->strictMode = true; - instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(len - deleteCount + itemCount)); - - return Value::fromObject(newArray); -} - -Value ArrayPrototype::method_unshift(ExecutionContext *ctx) -{ - ArrayObject *instance = ctx->thisObject.asArrayObject(); - if (!instance) - ctx->throwUnimplemented(QStringLiteral("Array.prototype.shift")); - - for (int i = ctx->argumentCount - 1; i >= 0; --i) { - Value v = ctx->argument(i); - instance->array.push_front(v); - } - - uint l = instance->array.length(); - if (l < INT_MAX) - return Value::fromInt32(l); - return Value::fromDouble((double)l); -} - -Value ArrayPrototype::method_indexOf(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - uint len = getLength(ctx, instance); - if (!len) - return Value::fromInt32(-1); - - Value searchValue; - uint fromIndex = 0; - - if (ctx->argumentCount >= 1) - searchValue = ctx->argument(0); - else - searchValue = Value::undefinedValue(); - - if (ctx->argumentCount >= 2) { - double f = ctx->argument(1).toInteger(ctx); - if (f >= len) - return Value::fromInt32(-1); - if (f < 0) - f = qMax(len + f, 0.); - fromIndex = (uint) f; - } - - if (instance->isString) { - for (uint k = fromIndex; k < len; ++k) { - bool exists; - Value v = instance->__get__(ctx, k, &exists); - if (exists && __qmljs_strict_equal(v, searchValue)) - return Value::fromDouble(k); - } - return Value::fromInt32(-1); - } - - return instance->array.indexOf(searchValue, fromIndex, len, ctx, instance); -} - -Value ArrayPrototype::method_lastIndexOf(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - uint len = getLength(ctx, instance); - if (!len) - return Value::fromInt32(-1); - - Value searchValue; - uint fromIndex = len - 1; - - if (ctx->argumentCount >= 1) - searchValue = ctx->argument(0); - else - searchValue = Value::undefinedValue(); - - if (ctx->argumentCount >= 2) { - double f = ctx->argument(1).toInteger(ctx); - if (f >= len) - return Value::fromInt32(-1); - if (f < 0) - f = qMax(len + f, 0.); - fromIndex = (uint) f; - } - - for (uint k = fromIndex; k > 0; --k) { - bool exists; - Value v = instance->__get__(ctx, k, &exists); - if (exists && __qmljs_strict_equal(v, searchValue)) - return Value::fromDouble(k); - } - return Value::fromInt32(-1); -} - -Value ArrayPrototype::method_every(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - - uint len = getLength(ctx, instance); - - FunctionObject *callback = ctx->argument(0).asFunctionObject(); - if (!callback) - __qmljs_throw_type_error(ctx); - - Value thisArg = ctx->argument(1); - - bool ok = true; - for (uint k = 0; ok && k < len; ++k) { - bool exists; - Value v = instance->__get__(ctx, k, &exists); - if (!exists) - continue; - - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = ctx->thisObject; - Value r = callback->call(ctx, thisArg, args, 3); - ok = __qmljs_to_boolean(r, ctx); - } - return Value::fromBoolean(ok); -} - -Value ArrayPrototype::method_some(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - - uint len = getLength(ctx, instance); - - FunctionObject *callback = ctx->argument(0).asFunctionObject(); - if (!callback) - __qmljs_throw_type_error(ctx); - - Value thisArg = ctx->argument(1); - - for (uint k = 0; k < len; ++k) { - bool exists; - Value v = instance->__get__(ctx, k, &exists); - if (!exists) - continue; - - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = ctx->thisObject; - Value r = callback->call(ctx, thisArg, args, 3); - if (__qmljs_to_boolean(r, ctx)) - return Value::fromBoolean(true); - } - return Value::fromBoolean(false); -} - -Value ArrayPrototype::method_forEach(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - - uint len = getLength(ctx, instance); - - FunctionObject *callback = ctx->argument(0).asFunctionObject(); - if (!callback) - __qmljs_throw_type_error(ctx); - - Value thisArg = ctx->argument(1); - - for (uint k = 0; k < len; ++k) { - bool exists; - Value v = instance->__get__(ctx, k, &exists); - if (!exists) - continue; - - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = ctx->thisObject; - callback->call(ctx, thisArg, args, 3); - } - return Value::undefinedValue(); -} - -Value ArrayPrototype::method_map(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - - uint len = getLength(ctx, instance); - - FunctionObject *callback = ctx->argument(0).asFunctionObject(); - if (!callback) - __qmljs_throw_type_error(ctx); - - Value thisArg = ctx->argument(1); - - ArrayObject *a = ctx->engine->newArrayObject(ctx); - a->array.setLength(len); - - for (uint k = 0; k < len; ++k) { - bool exists; - Value v = instance->__get__(ctx, k, &exists); - if (!exists) - continue; - - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = ctx->thisObject; - Value mapped = callback->call(ctx, thisArg, args, 3); - a->array.set(k, mapped); - } - return Value::fromObject(a); -} - -Value ArrayPrototype::method_filter(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - - uint len = getLength(ctx, instance); - - FunctionObject *callback = ctx->argument(0).asFunctionObject(); - if (!callback) - __qmljs_throw_type_error(ctx); - - Value thisArg = ctx->argument(1); - - ArrayObject *a = ctx->engine->newArrayObject(ctx); - - uint to = 0; - for (uint k = 0; k < len; ++k) { - bool exists; - Value v = instance->__get__(ctx, k, &exists); - if (!exists) - continue; - - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = ctx->thisObject; - Value selected = callback->call(ctx, thisArg, args, 3); - if (__qmljs_to_boolean(selected, ctx)) { - a->array.set(to, v); - ++to; - } - } - return Value::fromObject(a); -} - -Value ArrayPrototype::method_reduce(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - - uint len = getLength(ctx, instance); - - FunctionObject *callback = ctx->argument(0).asFunctionObject(); - if (!callback) - __qmljs_throw_type_error(ctx); - - uint k = 0; - Value acc; - if (ctx->argumentCount > 1) { - acc = ctx->argument(1); - } else { - bool kPresent = false; - while (k < len && !kPresent) { - Value v = instance->__get__(ctx, k, &kPresent); - if (kPresent) - acc = v; - ++k; - } - if (!kPresent) - __qmljs_throw_type_error(ctx); - } - - while (k < len) { - bool kPresent; - Value v = instance->__get__(ctx, k, &kPresent); - if (kPresent) { - Value args[4]; - args[0] = acc; - args[1] = v; - args[2] = Value::fromDouble(k); - args[3] = ctx->thisObject; - acc = callback->call(ctx, Value::undefinedValue(), args, 4); - } - ++k; - } - return acc; -} - -Value ArrayPrototype::method_reduceRight(ExecutionContext *ctx) -{ - Object *instance = __qmljs_to_object(ctx->thisObject, ctx).objectValue(); - - uint len = getLength(ctx, instance); - - FunctionObject *callback = ctx->argument(0).asFunctionObject(); - if (!callback) - __qmljs_throw_type_error(ctx); - - if (len == 0) { - if (ctx->argumentCount == 1) - __qmljs_throw_type_error(ctx); - return ctx->argument(1); - } - - uint k = len; - Value acc; - if (ctx->argumentCount > 1) { - acc = ctx->argument(1); - } else { - bool kPresent = false; - while (k > 0 && !kPresent) { - Value v = instance->__get__(ctx, k - 1, &kPresent); - if (kPresent) - acc = v; - --k; - } - if (!kPresent) - __qmljs_throw_type_error(ctx); - } - - while (k > 0) { - bool kPresent; - Value v = instance->__get__(ctx, k - 1, &kPresent); - if (kPresent) { - Value args[4]; - args[0] = acc; - args[1] = v; - args[2] = Value::fromDouble(k - 1); - args[3] = ctx->thisObject; - acc = callback->call(ctx, Value::undefinedValue(), args, 4); - } - --k; - } - return acc; -} - diff --git a/qv4ecmaobjects_p.h b/qv4ecmaobjects_p.h index 687601c..12cf99b 100644 --- a/qv4ecmaobjects_p.h +++ b/qv4ecmaobjects_p.h @@ -126,45 +126,6 @@ struct BooleanPrototype: BooleanObject static Value method_valueOf(ExecutionContext *ctx); }; -struct ArrayCtor: FunctionObject -{ - ArrayCtor(ExecutionContext *scope); - - virtual Value call(ExecutionContext *ctx); -}; - -struct ArrayPrototype: ArrayObject -{ - ArrayPrototype(ExecutionContext *context) : ArrayObject(context) {} - - void init(ExecutionContext *ctx, const Value &ctor); - - static uint getLength(ExecutionContext *ctx, Object *o); - - static Value method_isArray(ExecutionContext *ctx); - static Value method_toString(ExecutionContext *ctx); - static Value method_toLocaleString(ExecutionContext *ctx); - static Value method_concat(ExecutionContext *ctx); - static Value method_join(ExecutionContext *ctx); - static Value method_pop(ExecutionContext *ctx); - static Value method_push(ExecutionContext *ctx); - static Value method_reverse(ExecutionContext *ctx); - static Value method_shift(ExecutionContext *ctx); - static Value method_slice(ExecutionContext *ctx); - static Value method_sort(ExecutionContext *ctx); - static Value method_splice(ExecutionContext *ctx); - static Value method_unshift(ExecutionContext *ctx); - static Value method_indexOf(ExecutionContext *ctx); - static Value method_lastIndexOf(ExecutionContext *ctx); - static Value method_every(ExecutionContext *ctx); - static Value method_some(ExecutionContext *ctx); - static Value method_forEach(ExecutionContext *ctx); - static Value method_map(ExecutionContext *ctx); - static Value method_filter(ExecutionContext *ctx); - static Value method_reduce(ExecutionContext *ctx); - static Value method_reduceRight(ExecutionContext *ctx); -}; - } // end of namespace VM } // end of namespace QQmlJS diff --git a/v4.pro b/v4.pro index d181c02..bc54c45 100644 --- a/v4.pro +++ b/v4.pro @@ -26,6 +26,7 @@ SOURCES += main.cpp \ qv4mm.cpp \ qv4managed.cpp \ qv4array.cpp \ + qv4arrayobject.cpp \ qv4argumentsobject.cpp \ qv4dateobject.cpp \ qv4errorobject.cpp \ @@ -57,6 +58,7 @@ HEADERS += \ qv4mm.h \ qv4managed.h \ qv4array.h \ + qv4arrayobject.h \ qv4argumentsobject.h \ qv4dateobject.h \ qv4errorobject.h \ -- 2.7.4