diff options
Diffstat (limited to 'src/qml/jsruntime/qv4stringobject.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 200 |
1 files changed, 97 insertions, 103 deletions
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 8bf9a096c5..e0b84f6da3 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** @@ -10,9 +10,9 @@ ** 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. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -23,8 +23,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** 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 +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ @@ -33,20 +33,15 @@ #include "qv4stringobject_p.h" +#include "qv4regexp_p.h" #include "qv4regexpobject_p.h" #include "qv4objectproto_p.h" #include "qv4mm_p.h" #include "qv4scopedvalue_p.h" #include "qv4alloca_p.h" -#include <QtCore/qnumeric.h> -#include <QtCore/qmath.h> #include <QtCore/QDateTime> -#include <QtCore/QStringList> #include <QtCore/QDebug> -#include <cmath> -#include <qmath.h> -#include <qnumeric.h> -#include <cassert> +#include <QtCore/QStringList> #include <private/qqmljsengine_p.h> #include <private/qqmljslexer_p.h> @@ -55,6 +50,8 @@ #include <qv4jsir_p.h> #include <qv4codegen_p.h> +#include <cassert> + #ifndef Q_OS_WIN # include <time.h> # ifndef Q_OS_VXWORKS @@ -70,11 +67,11 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(StringObject); -StringObject::Data::Data(InternalClass *ic) - : Object::Data(ic) +Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype) + : Heap::Object(ic, prototype) { - Q_ASSERT(internalClass->vtable == staticVTable()); - value = ic->engine->newString(QStringLiteral(""))->asReturnedValue(); + Q_ASSERT(vtable == QV4::StringObject::staticVTable()); + value = ic->engine->newString()->asReturnedValue(); tmpProperty.value = Primitive::undefinedValue(); Scope scope(ic->engine); @@ -82,49 +79,45 @@ StringObject::Data::Data(InternalClass *ic) s->defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0)); } -StringObject::Data::Data(ExecutionEngine *engine, const ValueRef val) - : Object::Data(engine->stringObjectClass) +Heap::StringObject::StringObject(ExecutionEngine *engine, const Value &val) + : Heap::Object(engine->emptyClass, engine->stringPrototype.asObject()) { value = val; Q_ASSERT(value.isString()); tmpProperty.value = Primitive::undefinedValue(); - setVTable(staticVTable()); Scope scope(engine); ScopedObject s(scope, this); s->defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length())); } -Property *StringObject::getIndex(uint index) const +Property *Heap::StringObject::getIndex(uint index) const { - QString str = d()->value.stringValue()->toQString(); + QString str = value.stringValue()->toQString(); if (index >= (uint)str.length()) return 0; - d()->tmpProperty.value = Encode(internalClass()->engine->newString(str.mid(index, 1))); - return &d()->tmpProperty; + tmpProperty.value = Encode(internalClass->engine->newString(str.mid(index, 1))); + return &tmpProperty; } bool StringObject::deleteIndexedProperty(Managed *m, uint index) { - ExecutionEngine *v4 = m->engine(); + ExecutionEngine *v4 = static_cast<StringObject *>(m)->engine(); Scope scope(v4); Scoped<StringObject> o(scope, m->asStringObject()); - if (!o) { - v4->currentContext()->throwTypeError(); - return false; - } + Q_ASSERT(!!o); if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) { - if (v4->currentContext()->d()->strictMode) - v4->currentContext()->throwTypeError(); + if (v4->currentContext()->strictMode) + v4->throwTypeError(); return false; } return true; } -void StringObject::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs) +void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs) { - name = (String *)0; + *name = (Heap::String *)0; StringObject *s = static_cast<StringObject *>(m); uint slen = s->d()->value.stringValue()->toQString().length(); if (it->arrayIndex <= slen) { @@ -135,7 +128,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, String *&name Property *pd = s->__getOwnProperty__(*index, &a); if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { *attrs = a; - p->copy(*pd, a); + p->copy(pd, a); return; } } @@ -150,44 +143,43 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, String *&name return Object::advanceIterator(m, it, name, index, p, attrs); } -void StringObject::markObjects(Managed *that, ExecutionEngine *e) +void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e) { - StringObject *o = static_cast<StringObject *>(that); - o->d()->value.stringValue()->mark(e); - o->d()->tmpProperty.value.mark(e); + StringObject::Data *o = static_cast<StringObject::Data *>(that); + o->value.stringValue()->mark(e); + o->tmpProperty.value.mark(e); Object::markObjects(that, e); } DEFINE_OBJECT_VTABLE(StringCtor); -StringCtor::Data::Data(ExecutionContext *scope) - : FunctionObject::Data(scope, QStringLiteral("String")) +Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope) + : Heap::FunctionObject(scope, QStringLiteral("String")) { - setVTable(staticVTable()); } ReturnedValue StringCtor::construct(Managed *m, CallData *callData) { - ExecutionEngine *v4 = m->engine(); + ExecutionEngine *v4 = static_cast<Object *>(m)->engine(); Scope scope(v4); ScopedValue value(scope); if (callData->argc) - value = callData->args[0].toString(v4->currentContext()); + value = callData->args[0].toString(v4); else - value = v4->newString(QString()); + value = v4->newString(); return Encode(v4->newStringObject(value)); } ReturnedValue StringCtor::call(Managed *m, CallData *callData) { - ExecutionEngine *v4 = m->engine(); + ExecutionEngine *v4 = static_cast<Object *>(m)->engine(); Scope scope(v4); ScopedValue value(scope); if (callData->argc) - value = callData->args[0].toString(v4->currentContext()); + value = callData->args[0].toString(v4); else - value = v4->newString(QString()); - return value.asReturnedValue(); + value = v4->newString(); + return value->asReturnedValue(); } void StringPrototype::init(ExecutionEngine *engine, Object *ctor) @@ -225,13 +217,13 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) static QString getThisString(ExecutionContext *ctx) { Scope scope(ctx); - ScopedValue t(scope, ctx->d()->callData->thisObject); + ScopedValue t(scope, ctx->thisObject()); if (t->isString()) return t->stringValue()->toQString(); if (StringObject *thisString = t->asStringObject()) return thisString->d()->value.stringValue()->toQString(); if (t->isUndefined() || t->isNull()) { - ctx->throwTypeError(); + scope.engine->throwTypeError(); return QString(); } return t->toQString(); @@ -239,12 +231,12 @@ static QString getThisString(ExecutionContext *ctx) ReturnedValue StringPrototype::method_toString(CallContext *context) { - if (context->d()->callData->thisObject.isString()) - return context->d()->callData->thisObject.asReturnedValue(); + if (context->thisObject().isString()) + return context->thisObject().asReturnedValue(); - StringObject *o = context->d()->callData->thisObject.asStringObject(); + StringObject *o = context->thisObject().asStringObject(); if (!o) - return context->throwTypeError(); + return context->engine()->throwTypeError(); return o->d()->value.asReturnedValue(); } @@ -255,8 +247,8 @@ ReturnedValue StringPrototype::method_charAt(CallContext *context) return Encode::undefined(); int pos = 0; - if (context->d()->callData->argc > 0) - pos = (int) context->d()->callData->args[0].toInteger(); + if (context->argc() > 0) + pos = (int) context->args()[0].toInteger(); QString result; if (pos >= 0 && pos < str.length()) @@ -272,8 +264,8 @@ ReturnedValue StringPrototype::method_charCodeAt(CallContext *context) return Encode::undefined(); int pos = 0; - if (context->d()->callData->argc > 0) - pos = (int) context->d()->callData->args[0].toInteger(); + if (context->argc() > 0) + pos = (int) context->args()[0].toInteger(); if (pos >= 0 && pos < str.length()) @@ -291,8 +283,8 @@ ReturnedValue StringPrototype::method_concat(CallContext *context) return Encode::undefined(); ScopedValue v(scope); - for (int i = 0; i < context->d()->callData->argc; ++i) { - v = RuntimeHelpers::toString(context, ValueRef(&context->d()->callData->args[i])); + for (int i = 0; i < context->argc(); ++i) { + v = RuntimeHelpers::toString(scope.engine, context->args()[i]); if (scope.hasException()) return Encode::undefined(); Q_ASSERT(v->isString()); @@ -309,12 +301,12 @@ ReturnedValue StringPrototype::method_indexOf(CallContext *context) return Encode::undefined(); QString searchString; - if (context->d()->callData->argc) - searchString = context->d()->callData->args[0].toString(context)->toQString(); + if (context->argc()) + searchString = context->args()[0].toQString(); int pos = 0; - if (context->d()->callData->argc > 1) - pos = (int) context->d()->callData->args[1].toInteger(); + if (context->argc() > 1) + pos = (int) context->args()[1].toInteger(); int index = -1; if (! value.isEmpty()) @@ -332,8 +324,8 @@ ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context) return Encode::undefined(); QString searchString; - if (context->d()->callData->argc) - searchString = context->d()->callData->args[0].toQString(); + if (context->argc()) + searchString = context->args()[0].toQString(); ScopedValue posArg(scope, context->argument(1)); double position = RuntimeHelpers::toNumber(posArg); @@ -358,20 +350,20 @@ ReturnedValue StringPrototype::method_localeCompare(CallContext *context) if (scope.engine->hasException) return Encode::undefined(); - ScopedValue v(scope, context->d()->callData->argument(0)); + ScopedValue v(scope, context->argument(0)); const QString that = v->toQString(); return Encode(QString::localeAwareCompare(value, that)); } ReturnedValue StringPrototype::method_match(CallContext *context) { - if (context->d()->callData->thisObject.isUndefined() || context->d()->callData->thisObject.isNull()) - return context->throwTypeError(); + if (context->thisObject().isUndefined() || context->thisObject().isNull()) + return context->engine()->throwTypeError(); Scope scope(context); - ScopedString s(scope, context->d()->callData->thisObject.toString(context)); + ScopedString s(scope, context->thisObject().toString(scope.engine)); - ScopedValue regexp(scope, context->d()->callData->argument(0)); + ScopedValue regexp(scope, context->argument(0)); Scoped<RegExpObject> rx(scope, regexp); if (!rx) { ScopedCallData callData(scope, 1); @@ -381,13 +373,13 @@ ReturnedValue StringPrototype::method_match(CallContext *context) if (!rx) // ### CHECK - return context->throwTypeError(); + return context->engine()->throwTypeError(); bool global = rx->global(); // ### use the standard builtin function, not the one that might be redefined in the proto - ScopedString execString(scope, context->d()->engine->newString(QStringLiteral("exec"))); - Scoped<FunctionObject> exec(scope, context->d()->engine->regExpClass->prototype->get(execString.getPointer())); + ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec"))); + ScopedFunctionObject exec(scope, scope.engine->regExpPrototype.asObject()->get(execString)); ScopedCallData callData(scope, 1); callData->thisObject = rx; @@ -396,8 +388,8 @@ ReturnedValue StringPrototype::method_match(CallContext *context) return exec->call(callData); ScopedString lastIndex(scope, context->d()->engine->newString(QStringLiteral("lastIndex"))); - rx->put(lastIndex.getPointer(), ScopedValue(scope, Primitive::fromInt32(0))); - Scoped<ArrayObject> a(scope, context->d()->engine->newArrayObject()); + rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0))); + ScopedArrayObject a(scope, context->d()->engine->newArrayObject()); double previousLastIndex = 0; uint n = 0; @@ -409,11 +401,11 @@ ReturnedValue StringPrototype::method_match(CallContext *context) if (result->isNull()) break; assert(result->isObject()); - index = rx->get(lastIndex.getPointer(), 0); + index = rx->get(lastIndex, 0); double thisIndex = index->toInteger(); if (previousLastIndex == thisIndex) { previousLastIndex = thisIndex + 1; - rx->put(lastIndex.getPointer(), ScopedValue(scope, Primitive::fromDouble(previousLastIndex))); + rx->put(lastIndex, ScopedValue(scope, Primitive::fromDouble(previousLastIndex))); } else { previousLastIndex = thisIndex; } @@ -478,10 +470,10 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) { Scope scope(ctx); QString string; - if (StringObject *thisString = ctx->d()->callData->thisObject.asStringObject()) + if (StringObject *thisString = ctx->thisObject().asStringObject()) string = thisString->d()->value.stringValue()->toQString(); else - string = ctx->d()->callData->thisObject.toString(ctx)->toQString(); + string = ctx->thisObject().toQString(); int numCaptures = 0; int numStringMatches = 0; @@ -518,12 +510,12 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) offset = qMax(offset + 1, matchOffsets[oldSize + 1]); } if (regExp->global()) - regExp->lastIndexProperty(ctx)->value = Primitive::fromUInt32(0); + regExp->lastIndexProperty()->value = Primitive::fromUInt32(0); numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2); numCaptures = regExp->value()->captureCount(); } else { numCaptures = 1; - QString searchString = searchValue->toString(ctx)->toQString(); + QString searchString = searchValue->toQString(); int idx = string.indexOf(searchString); if (idx != -1) { numStringMatches = 1; @@ -536,7 +528,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) QString result; ScopedValue replacement(scope); ScopedValue replaceValue(scope, ctx->argument(1)); - Scoped<FunctionObject> searchCallback(scope, replaceValue); + ScopedFunctionObject searchCallback(scope, replaceValue); if (!!searchCallback) { result.reserve(string.length() + 10*numStringMatches); ScopedCallData callData(scope, numCaptures + 2); @@ -561,12 +553,12 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) replacement = searchCallback->call(callData); result += string.midRef(lastEnd, matchStart - lastEnd); - result += replacement->toString(ctx)->toQString(); + result += replacement->toQString(); lastEnd = matchEnd; } result += string.midRef(lastEnd); } else { - QString newString = replaceValue->toString(ctx)->toQString(); + QString newString = replaceValue->toQString(); result.reserve(string.length() + numStringMatches*newString.size()); int lastEnd = 0; @@ -607,8 +599,9 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx) regExp = regExpValue->as<RegExpObject>(); Q_ASSERT(regExp); } + Scoped<RegExp> re(scope, regExp->value()); uint* matchOffsets = (uint*)alloca(regExp->value()->captureCount() * 2 * sizeof(uint)); - uint result = regExp->value()->match(string, /*offset*/0, matchOffsets); + uint result = re->match(string, /*offset*/0, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) return Encode(-1); return Encode(result); @@ -622,9 +615,9 @@ ReturnedValue StringPrototype::method_slice(CallContext *ctx) const double length = text.length(); - double start = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toInteger() : 0; - double end = (ctx->d()->callData->argc < 2 || ctx->d()->callData->args[1].isUndefined()) - ? length : ctx->d()->callData->args[1].toInteger(); + double start = ctx->argc() ? ctx->args()[0].toInteger() : 0; + double end = (ctx->argc() < 2 || ctx->args()[1].isUndefined()) + ? length : ctx->args()[1].toInteger(); if (start < 0) start = qMax(length + start, 0.); @@ -671,9 +664,9 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) Scoped<RegExpObject> re(scope, separatorValue); if (re) { - if (re->value()->pattern().isEmpty()) { + if (re->value()->pattern.isEmpty()) { re = (RegExpObject *)0; - separatorValue = ctx->d()->engine->newString(QString()); + separatorValue = ctx->d()->engine->newString(); } } @@ -682,7 +675,8 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) uint offset = 0; uint* matchOffsets = (uint*)alloca(re->value()->captureCount() * 2 * sizeof(uint)); while (true) { - uint result = re->value()->match(text, offset, matchOffsets); + Scoped<RegExp> regexp(scope, re->value()); + uint result = regexp->match(text, offset, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) break; @@ -703,7 +697,7 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) if (array->getLength() < limit) array->push_back((s = ctx->d()->engine->newString(text.mid(offset)))); } else { - QString separator = separatorValue->toString(ctx)->toQString(); + QString separator = separatorValue->toQString(); if (separator.isEmpty()) { for (uint i = 0; i < qMin(limit, uint(text.length())); ++i) array->push_back((s = ctx->d()->engine->newString(text.mid(i, 1)))); @@ -731,12 +725,12 @@ ReturnedValue StringPrototype::method_substr(CallContext *context) return Encode::undefined(); double start = 0; - if (context->d()->callData->argc > 0) - start = context->d()->callData->args[0].toInteger(); + if (context->argc() > 0) + start = context->args()[0].toInteger(); double length = +qInf(); - if (context->d()->callData->argc > 1) - length = context->d()->callData->args[1].toInteger(); + if (context->argc() > 1) + length = context->args()[1].toInteger(); double count = value.length(); if (start < 0) @@ -759,8 +753,8 @@ ReturnedValue StringPrototype::method_substring(CallContext *context) double start = 0; double end = length; - if (context->d()->callData->argc > 0) - start = context->d()->callData->args[0].toInteger(); + if (context->argc() > 0) + start = context->args()[0].toInteger(); Scope scope(context); ScopedValue endValue(scope, context->argument(1)); @@ -818,10 +812,10 @@ ReturnedValue StringPrototype::method_toLocaleUpperCase(CallContext *ctx) ReturnedValue StringPrototype::method_fromCharCode(CallContext *context) { - QString str(context->d()->callData->argc, Qt::Uninitialized); + QString str(context->argc(), Qt::Uninitialized); QChar *ch = str.data(); - for (int i = 0; i < context->d()->callData->argc; ++i) { - *ch = QChar(context->d()->callData->args[i].toUInt16()); + for (int i = 0; i < context->argc(); ++i) { + *ch = QChar(context->args()[i].toUInt16()); ++ch; } return context->d()->engine->newString(str)->asReturnedValue(); |
