diff options
Diffstat (limited to 'src/qml/jsruntime/qv4stringobject.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 141 |
1 files changed, 110 insertions, 31 deletions
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index b874766655..829ada0c1a 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -73,15 +73,17 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(StringObject); -Heap::StringObject::StringObject() +void Heap::StringObject::init() { + Object::init(); Q_ASSERT(vtable() == QV4::StringObject::staticVTable()); string = internalClass->engine->id_empty()->d(); *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); } -Heap::StringObject::StringObject(const QV4::String *str) +void Heap::StringObject::init(const QV4::String *str) { + Object::init(); string = str->d(); *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length()); } @@ -152,33 +154,29 @@ void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e) DEFINE_OBJECT_VTABLE(StringCtor); -Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("String")) +void Heap::StringCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("String")); } -ReturnedValue StringCtor::construct(const Managed *m, CallData *callData) +void StringCtor::construct(const Managed *m, Scope &scope, CallData *callData) { ExecutionEngine *v4 = static_cast<const Object *>(m)->engine(); - Scope scope(v4); ScopedString value(scope); if (callData->argc) value = callData->args[0].toString(v4); else value = v4->newString(); - return Encode(v4->newStringObject(value)); + scope.result = Encode(v4->newStringObject(value)); } -ReturnedValue StringCtor::call(const Managed *m, CallData *callData) +void StringCtor::call(const Managed *, Scope &scope, CallData *callData) { - ExecutionEngine *v4 = static_cast<const Object *>(m)->engine(); - Scope scope(v4); - ScopedValue value(scope); + ExecutionEngine *v4 = scope.engine; if (callData->argc) - value = callData->args[0].toString(v4); + scope.result = callData->args[0].toString(v4); else - value = v4->newString(); - return value->asReturnedValue(); + scope.result = v4->newString(); } void StringPrototype::init(ExecutionEngine *engine, Object *ctor) @@ -196,7 +194,9 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("charAt"), method_charAt, 1); defineDefaultProperty(QStringLiteral("charCodeAt"), method_charCodeAt, 1); defineDefaultProperty(QStringLiteral("concat"), method_concat, 1); + defineDefaultProperty(QStringLiteral("endsWith"), method_endsWith, 1); defineDefaultProperty(QStringLiteral("indexOf"), method_indexOf, 1); + defineDefaultProperty(QStringLiteral("includes"), method_includes, 1); defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1); defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare, 1); defineDefaultProperty(QStringLiteral("match"), method_match, 1); @@ -204,6 +204,7 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("search"), method_search, 1); defineDefaultProperty(QStringLiteral("slice"), method_slice, 2); defineDefaultProperty(QStringLiteral("split"), method_split, 2); + defineDefaultProperty(QStringLiteral("startsWith"), method_startsWith, 1); defineDefaultProperty(QStringLiteral("substr"), method_substr, 2); defineDefaultProperty(QStringLiteral("substring"), method_substring, 2); defineDefaultProperty(QStringLiteral("toLowerCase"), method_toLowerCase); @@ -293,6 +294,30 @@ ReturnedValue StringPrototype::method_concat(CallContext *context) return context->d()->engine->newString(value)->asReturnedValue(); } +ReturnedValue StringPrototype::method_endsWith(CallContext *context) +{ + QString value = getThisString(context); + if (context->d()->engine->hasException) + return Encode::undefined(); + + QString searchString; + if (context->argc()) { + if (context->args()[0].as<RegExpObject>()) + return context->engine()->throwTypeError(); + searchString = context->args()[0].toQString(); + } + + int pos = value.length(); + if (context->argc() > 1) + pos = (int) context->args()[1].toInteger(); + + if (pos == value.length()) + return Encode(value.endsWith(searchString)); + + QStringRef stringToSearch = value.leftRef(pos); + return Encode(stringToSearch.endsWith(searchString)); +} + ReturnedValue StringPrototype::method_indexOf(CallContext *context) { QString value = getThisString(context); @@ -314,6 +339,35 @@ ReturnedValue StringPrototype::method_indexOf(CallContext *context) return Encode(index); } +ReturnedValue StringPrototype::method_includes(CallContext *context) +{ + QString value = getThisString(context); + if (context->d()->engine->hasException) + return Encode::undefined(); + + QString searchString; + if (context->argc()) { + if (context->args()[0].as<RegExpObject>()) + return context->engine()->throwTypeError(); + searchString = context->args()[0].toQString(); + } + + int pos = 0; + if (context->argc() > 1) { + Scope scope(context); + ScopedValue posArg(scope, context->argument(1)); + pos = (int) posArg->toInteger(); + if (!posArg->isInteger() && posArg->isNumber() && qIsInf(posArg->toNumber())) + pos = value.length(); + } + + if (pos == 0) + return Encode(value.contains(searchString)); + + QStringRef stringToSearch = value.midRef(pos); + return Encode(stringToSearch.contains(searchString)); +} + ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context) { Scope scope(context); @@ -367,7 +421,8 @@ ReturnedValue StringPrototype::method_match(CallContext *context) if (!rx) { ScopedCallData callData(scope, 1); callData->args[0] = regexp; - rx = context->d()->engine->regExpCtor()->construct(callData); + context->d()->engine->regExpCtor()->construct(scope, callData); + rx = scope.result.asReturnedValue(); } if (!rx) @@ -383,8 +438,10 @@ ReturnedValue StringPrototype::method_match(CallContext *context) ScopedCallData callData(scope, 1); callData->thisObject = rx; callData->args[0] = s; - if (!global) - return exec->call(callData); + if (!global) { + exec->call(scope, callData); + return scope.result.asReturnedValue(); + } ScopedString lastIndex(scope, context->d()->engine->newString(QStringLiteral("lastIndex"))); rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0))); @@ -392,14 +449,13 @@ ReturnedValue StringPrototype::method_match(CallContext *context) double previousLastIndex = 0; uint n = 0; - ScopedValue result(scope); ScopedValue matchStr(scope); ScopedValue index(scope); while (1) { - result = exec->call(callData); - if (result->isNull()) + exec->call(scope, callData); + if (scope.result.isNull()) break; - assert(result->isObject()); + assert(scope.result.isObject()); index = rx->get(lastIndex, 0); double thisIndex = index->toInteger(); if (previousLastIndex == thisIndex) { @@ -408,7 +464,7 @@ ReturnedValue StringPrototype::method_match(CallContext *context) } else { previousLastIndex = thisIndex; } - matchStr = result->objectValue()->getIndexed(0); + matchStr = scope.result.objectValue()->getIndexed(0); a->arraySet(n, matchStr); ++n; } @@ -524,7 +580,6 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) } QString result; - ScopedValue replacement(scope); ScopedValue replaceValue(scope, ctx->argument(1)); ScopedFunctionObject searchCallback(scope, replaceValue); if (!!searchCallback) { @@ -549,9 +604,9 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) callData->args[numCaptures] = Primitive::fromUInt32(matchStart); callData->args[numCaptures + 1] = ctx->d()->engine->newString(string); - replacement = searchCallback->call(callData); + searchCallback->call(scope, callData); result += string.midRef(lastEnd, matchStart - lastEnd); - result += replacement->toQString(); + result += scope.result.toQString(); lastEnd = matchEnd; } result += string.midRef(lastEnd); @@ -584,17 +639,17 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx) { Scope scope(ctx); QString string = getThisString(ctx); - ScopedValue regExpValue(scope, ctx->argument(0)); + scope.result = ctx->argument(0); if (scope.engine->hasException) return Encode::undefined(); - Scoped<RegExpObject> regExp(scope, regExpValue->as<RegExpObject>()); + Scoped<RegExpObject> regExp(scope, scope.result.as<RegExpObject>()); if (!regExp) { ScopedCallData callData(scope, 1); - callData->args[0] = regExpValue; - regExpValue = ctx->d()->engine->regExpCtor()->construct(callData); + callData->args[0] = scope.result; + ctx->d()->engine->regExpCtor()->construct(scope, callData); if (scope.engine->hasException) return Encode::undefined(); - regExp = regExpValue->as<RegExpObject>(); + regExp = scope.result.as<RegExpObject>(); Q_ASSERT(regExp); } Scoped<RegExp> re(scope, regExp->value()); @@ -662,7 +717,7 @@ 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(); } @@ -716,6 +771,30 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) return array.asReturnedValue(); } +ReturnedValue StringPrototype::method_startsWith(CallContext *context) +{ + QString value = getThisString(context); + if (context->d()->engine->hasException) + return Encode::undefined(); + + QString searchString; + if (context->argc()) { + if (context->args()[0].as<RegExpObject>()) + return context->engine()->throwTypeError(); + searchString = context->args()[0].toQString(); + } + + int pos = 0; + if (context->argc() > 1) + pos = (int) context->args()[1].toInteger(); + + if (pos == 0) + return Encode(value.startsWith(searchString)); + + QStringRef stringToSearch = value.midRef(pos); + return Encode(stringToSearch.startsWith(searchString)); +} + ReturnedValue StringPrototype::method_substr(CallContext *context) { const QString value = getThisString(context); |