From 04a8406c569d9e9b682cb2e7fcf78d806503f135 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 21 May 2012 13:21:35 +0200 Subject: [PATCH] Improve the Array prototype --- qv4array_p.h | 33 ++++++++++++++++----- qv4ecmaobjects.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 107 insertions(+), 10 deletions(-) diff --git a/qv4array_p.h b/qv4array_p.h index a80c8a6..d820ce5 100644 --- a/qv4array_p.h +++ b/qv4array_p.h @@ -26,6 +26,7 @@ public: inline void resize(uint size); inline void concat(const Array &other); inline Value pop(); + inline Value takeFirst(); inline void sort(Context *context, const Value &comparefn); inline void splice(double start, double deleteCount, const QVector &items, @@ -138,9 +139,9 @@ inline Value Array::at(uint index) const if (m_mode == VectorMode) { if (index < uint(to_vector->size())) return to_vector->at(index); - return Value(); + return Value::undefinedValue(); } else { - return to_map->value(index, Value()); + return to_map->value(index, Value::undefinedValue()); } } @@ -188,7 +189,9 @@ inline void Array::resize(uint s) if (m_mode == VectorMode) { if (s < N) { - to_vector->resize (s); // ### init + to_vector->resize(s); + for (uint i = oldSize; i < s; ++i) + assign(i, Value::undefinedValue()); } else { // switch to MapMode QMap *m = new QMap(); @@ -196,7 +199,7 @@ inline void Array::resize(uint s) if (! to_vector->at(i).isUndefined()) m->insert(i, to_vector->at(i)); } - m->insert(s, Value()); + m->insert(s, Value::undefinedValue()); delete to_vector; to_map = m; m_mode = MapMode; @@ -227,7 +230,7 @@ inline void Array::resize(uint s) to_map->erase(it); } } - to_map->insert(s, Value()); + to_map->insert(s, Value::undefinedValue()); } } } @@ -246,7 +249,7 @@ inline void Array::concat(const Array &other) inline Value Array::pop() { if (isEmpty()) - return Value(); + return Value::undefinedValue(); Value v; @@ -260,6 +263,22 @@ inline Value Array::pop() return v; } +inline Value Array::takeFirst() +{ + if (isEmpty()) + return Value::undefinedValue(); + + Value v; + if (m_mode == VectorMode) { + v = to_vector->first(); + to_vector->remove(0, 1); + } else { + v = *to_map->begin(); + to_map->erase(to_map->begin()); + } + return v; +} + inline void Array::sort(Context *context, const Value &comparefn) { ArrayElementLessThan lessThan(context, comparefn); @@ -296,7 +315,7 @@ inline void Array::splice(double start, double deleteCount, for (uint i = 0; i < dc; ++i) other.assign(i, to_vector->at(st + i)); if (itemsSize > dc) - to_vector->insert(st, itemsSize - dc, Value()); + to_vector->insert(st, itemsSize - dc, Value::undefinedValue()); else if (itemsSize < dc) to_vector->remove(st, dc - itemsSize); for (uint i = 0; i < itemsSize; ++i) diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp index 3b4890c..cb06b46 100644 --- a/qv4ecmaobjects.cpp +++ b/qv4ecmaobjects.cpp @@ -1094,12 +1094,31 @@ ArrayCtor::ArrayCtor(Context *scope) void ArrayCtor::construct(Context *ctx) { - ctx->thisObject = Value::fromObject(ctx->engine->newArrayObject()); + call(ctx); + ctx->thisObject = ctx->result; } void ArrayCtor::call(Context *ctx) { - ctx->result = Value::fromObject(ctx->engine->newArrayObject()); + Array value; + if (ctx->argumentCount == 1 && ctx->argument(0).isNumber()) { + double size = ctx->argument(0).numberValue; + quint32 isize = Value::toUInt32(size); + + if (size != double(isize)) { + assert(!"invlaid array length exception"); + return; + } + + qDebug() << "size:" << isize; + value.resize(isize); + } else { + for (size_t i = 0; i < ctx->argumentCount; ++i) { + value.assign(i, ctx->argument(i)); + } + } + + ctx->result = Value::fromObject(ctx->engine->newArrayObject(value)); } ArrayPrototype::ArrayPrototype(Context *ctx, FunctionObject *ctor) @@ -1184,7 +1203,7 @@ void ArrayPrototype::method_join(Context *ctx) if (ArrayObject *a = self.objectValue->asArrayObject()) { for (uint i = 0; i < a->value.size(); ++i) { - if (! R.isEmpty()) + if (i) R += r4; Value e = a->value.at(i); @@ -1239,30 +1258,89 @@ void ArrayPrototype::method_pop(Context *ctx) void ArrayPrototype::method_push(Context *ctx) { + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + uint pos = instance->value.size(); + for (size_t i = 0; i < ctx->argumentCount; ++i) { + Value val = ctx->argument(i); + instance->value.assign(pos++, val); + } + ctx->result = Value::fromNumber(pos); + } else { + String *id_length = ctx->engine->identifier(QLatin1String("length")); + Value *r1 = self.objectValue->getProperty(id_length); + quint32 n = r1 ? r1->toUInt32(ctx) : 0; + for (int index = 0; index < ctx->argumentCount; ++index, ++n) { + Value r3 = ctx->argument(index); + String *name = Value::fromNumber(n).toString(ctx); + self.objectValue->put(name, r3); + } + Value r = Value::fromNumber(n); + self.objectValue->put(id_length, r); + ctx->result = r; + } } void ArrayPrototype::method_reverse(Context *ctx) { + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + int lo = 0, hi = instance->value.count() - 1; + + for (; lo < hi; ++lo, --hi) { + Value tmp = instance->value.at(lo); + instance->value.assign(lo, instance->value.at(hi)); + instance->value.assign(hi, tmp); + } + } else { + assert(!"generic implementation of Array.prototype.reverse"); + } } void ArrayPrototype::method_shift(Context *ctx) { + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + ctx->result = instance->value.takeFirst(); + } else { + assert(!"generic implementation of Array.prototype.reverse"); + } } void ArrayPrototype::method_slice(Context *ctx) { + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + } else { + assert(!"generic implementation of Array.prototype.slice"); + } } void ArrayPrototype::method_sort(Context *ctx) { + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + } else { + assert(!"generic implementation of Array.prototype.sort"); + } } void ArrayPrototype::method_splice(Context *ctx) { + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + } else { + assert(!"generic implementation of Array.prototype.splice"); + } } void ArrayPrototype::method_unshift(Context *ctx) { + Value self = ctx->thisObject; + if (ArrayObject *instance = self.asArrayObject()) { + } else { + assert(!"generic implementation of Array.prototype.unshift"); + } } // -- 2.7.4