aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
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
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')
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp93
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h14
2 files changed, 105 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
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 0129f8d396..f112ad804d 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -106,8 +106,15 @@ struct RegExpCtor: FunctionObject
Q_MANAGED
RegExpCtor(ExecutionContext *scope);
+ SafeValue lastMatch;
+ SafeString lastInput;
+ int lastMatchStart;
+ int lastMatchEnd;
+ void clearLastMatch();
+
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
+ static void markObjects(Managed *that, ExecutionEngine *e);
};
struct RegExpPrototype: RegExpObject
@@ -119,6 +126,13 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_test(CallContext *ctx);
static ReturnedValue method_toString(CallContext *ctx);
static ReturnedValue method_compile(CallContext *ctx);
+
+ template <int index>
+ static ReturnedValue method_get_lastMatch_n(CallContext *ctx);
+ static ReturnedValue method_get_lastParen(CallContext *ctx);
+ static ReturnedValue method_get_input(CallContext *ctx);
+ static ReturnedValue method_get_leftContext(CallContext *ctx);
+ static ReturnedValue method_get_rightContext(CallContext *ctx);
};
}