aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4regexpobject.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-01-20 14:32:26 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-20 16:10:33 +0100
commit19025ab3422658ab27415cee99336d88a4ae19fa (patch)
tree48be7ca9b74b73ce5f68b265ac4bdb485dc827c3 /src/qml/jsruntime/qv4regexpobject.cpp
parent46ffd0e470b66e8cc501d5caf4ba92022d1ee474 (diff)
Add support for deprecated RegExp (constructor) properties
These were apparently part of ancient EcmaScript specs, aren't even listed anymore in any recent spec (not even as deprecated), but apparently they are part of what the web supports as well as previous versions of Qml. So this patch implements them. Task-number: QTBUG-36244 Change-Id: I1b9ea7ea09fceb6a486f615837a71e41aae12de4 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/jsruntime/qv4regexpobject.cpp')
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp93
1 files changed, 91 insertions, 2 deletions
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 468fb34d76..0ebad2f781 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -238,6 +238,15 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("RegExp"))
{
setVTable(&static_vtbl);
+ clearLastMatch();
+}
+
+void RegExpCtor::clearLastMatch()
+{
+ lastMatch = Primitive::nullValue();
+ lastInput = engine()->newIdentifier(QString());
+ lastMatchStart = 0;
+ lastMatchEnd = 0;
}
ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
@@ -300,6 +309,14 @@ ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
return construct(that, callData);
}
+void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e)
+{
+ RegExpCtor *This = static_cast<RegExpCtor*>(that);
+ This->lastMatch.mark(e);
+ This->lastInput.mark(e);
+ FunctionObject::markObjects(that, e);
+}
+
void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
{
Scope scope(engine);
@@ -307,6 +324,28 @@ void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2));
+
+ // Properties deprecated in the spec but required by "the web" :(
+ ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$&"), method_get_lastMatch_n<0>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$1"), method_get_lastMatch_n<1>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$2"), method_get_lastMatch_n<2>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$3"), method_get_lastMatch_n<3>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$4"), method_get_lastMatch_n<4>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$5"), method_get_lastMatch_n<5>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$6"), method_get_lastMatch_n<6>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$7"), method_get_lastMatch_n<7>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$8"), method_get_lastMatch_n<8>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$9"), method_get_lastMatch_n<9>, 0);
+ ctor->defineAccessorProperty(QStringLiteral("lastParen"), method_get_lastParen, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$+"), method_get_lastParen, 0);
+ ctor->defineAccessorProperty(QStringLiteral("input"), method_get_input, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$_"), method_get_input, 0);
+ ctor->defineAccessorProperty(QStringLiteral("leftContext"), method_get_leftContext, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$`"), method_get_leftContext, 0);
+ ctor->defineAccessorProperty(QStringLiteral("rightContext"), method_get_rightContext, 0);
+ ctor->defineAccessorProperty(QStringLiteral("$'"), method_get_rightContext, 0);
+
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(QStringLiteral("exec"), method_exec, 1);
defineDefaultProperty(QStringLiteral("test"), method_test, 1);
@@ -334,7 +373,11 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
}
uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint));
- int result = r->value->match(s, offset, matchOffsets);
+ const int result = r->value->match(s, offset, matchOffsets);
+
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
+ regExpCtor->clearLastMatch();
+
if (result == -1) {
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0);
return Encode::null();
@@ -351,10 +394,14 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
array->arrayDataLen = i + 1;
}
array->setArrayLengthUnchecked(len);
-
array->memberData[Index_ArrayIndex].value = Primitive::fromInt32(result);
array->memberData[Index_ArrayInput].value = arg.asReturnedValue();
+ regExpCtor->lastMatch = array;
+ regExpCtor->lastInput = arg->stringValue();
+ regExpCtor->lastMatchStart = matchOffsets[0];
+ regExpCtor->lastMatchEnd = matchOffsets[1];
+
if (r->global)
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]);
@@ -395,4 +442,46 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
return Encode::undefined();
}
+template <int index>
+ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
+{
+ Scope scope(ctx);
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
+ ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
+ if (result->isUndefined())
+ return ctx->engine->newString(QString())->asReturnedValue();
+ return result.asReturnedValue();
+}
+
+ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
+{
+ Scope scope(ctx);
+ ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
+ ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->arrayLength() - 1) : Encode::undefined());
+ if (result->isUndefined())
+ return ctx->engine->newString(QString())->asReturnedValue();
+ return result.asReturnedValue();
+}
+
+ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
+{
+ return static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastInput.asReturnedValue();
+}
+
+ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
+ QString lastInput = regExpCtor->lastInput->toQString();
+ return ctx->engine->newString(lastInput.left(regExpCtor->lastMatchStart))->asReturnedValue();
+}
+
+ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
+ QString lastInput = regExpCtor->lastInput->toQString();
+ return ctx->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd))->asReturnedValue();
+}
+
QT_END_NAMESPACE