aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4regexpobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4regexpobject.cpp')
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp175
1 files changed, 107 insertions, 68 deletions
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 83bfe21c67..f95719b25f 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -38,20 +38,17 @@
****************************************************************************/
#include "qv4regexpobject_p.h"
-#include "qv4jsir_p.h"
-#include "qv4isel_p.h"
#include "qv4objectproto_p.h"
#include "qv4regexp_p.h"
#include "qv4stringobject_p.h"
#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
+#include "qv4jscall_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
-#include <qv4jsir_p.h>
-#include <qv4codegen_p.h>
#include "private/qlocale_tools_p.h"
#include <QtCore/QDebug>
@@ -217,39 +214,33 @@ void Heap::RegExpCtor::clearLastMatch()
lastMatchEnd = 0;
}
-void RegExpCtor::construct(const Managed *, Scope &scope, CallData *callData)
+ReturnedValue RegExpCtor::callAsConstructor(const FunctionObject *fo, const Value *argv, int argc)
{
- ScopedValue r(scope, callData->argument(0));
- ScopedValue f(scope, callData->argument(1));
+ Scope scope(fo->engine());
+ ScopedValue r(scope, argc ? argv[0] : Primitive::undefinedValue());
+ ScopedValue f(scope, argc > 1 ? argv[1] : Primitive::undefinedValue());
Scoped<RegExpObject> re(scope, r);
if (re) {
- if (!f->isUndefined()) {
- scope.result = scope.engine->throwTypeError();
- return;
- }
+ if (!f->isUndefined())
+ return scope.engine->throwTypeError();
Scoped<RegExp> regexp(scope, re->value());
- scope.result = Encode(scope.engine->newRegExpObject(regexp));
- return;
+ return Encode(scope.engine->newRegExpObject(regexp));
}
QString pattern;
if (!r->isUndefined())
pattern = r->toQString();
- if (scope.hasException()) {
- scope.result = Encode::undefined();
- return;
- }
+ if (scope.hasException())
+ return Encode::undefined();
bool global = false;
bool ignoreCase = false;
bool multiLine = false;
if (!f->isUndefined()) {
ScopedString s(scope, f->toString(scope.engine));
- if (scope.hasException()) {
- scope.result = Encode::undefined();
- return;
- }
+ if (scope.hasException())
+ return Encode::undefined();
QString str = s->toQString();
for (int i = 0; i < str.length(); ++i) {
if (str.at(i) == QLatin1Char('g') && !global) {
@@ -259,31 +250,27 @@ void RegExpCtor::construct(const Managed *, Scope &scope, CallData *callData)
} else if (str.at(i) == QLatin1Char('m') && !multiLine) {
multiLine = true;
} else {
- scope.result = scope.engine->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
- return;
+ return scope.engine->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
}
}
}
Scoped<RegExp> regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine, global));
if (!regexp->isValid()) {
- scope.result = scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression"));
- return;
+ return scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression"));
}
- scope.result = Encode(scope.engine->newRegExpObject(regexp));
+ return Encode(scope.engine->newRegExpObject(regexp));
}
-void RegExpCtor::call(const Managed *that, Scope &scope, CallData *callData)
+ReturnedValue RegExpCtor::call(const FunctionObject *f, const Value *, const Value *argv, int argc)
{
- if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) {
- if (callData->argc == 1 || callData->args[1].isUndefined()) {
- scope.result = callData->args[0];
- return;
- }
+ if (argc > 0 && argv[0].as<RegExpObject>()) {
+ if (argc == 1 || argv[1].isUndefined())
+ return Encode(argv[0]);
}
- construct(that, scope, callData);
+ return callAsConstructor(f, argv, argc);
}
void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
@@ -323,13 +310,60 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
defineDefaultProperty(QStringLiteral("compile"), method_compile, 2);
}
-void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallData *callData)
+/* used by String.match */
+ReturnedValue RegExpPrototype::execFirstMatch(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(b);
+ Scoped<RegExpObject> r(scope, thisObject->as<RegExpObject>());
+ Q_ASSERT(r && r->global());
+
+ ScopedString str(scope, argc ? argv[0] : Primitive::undefinedValue());
+ Q_ASSERT(str);
+ QString s = str->toQString();
+
+ int offset = r->lastIndex();
+ if (offset < 0 || offset > s.length()) {
+ r->setLastIndex(0);
+ RETURN_RESULT(Encode::null());
+ }
+
+ Q_ALLOCA_VAR(uint, matchOffsets, r->value()->captureCount() * 2 * sizeof(uint));
+ const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets);
+
+ RegExpCtor *regExpCtor = static_cast<RegExpCtor *>(scope.engine->regExpCtor());
+ regExpCtor->d()->clearLastMatch();
+
+ if (result == -1) {
+ r->setLastIndex(0);
+ RETURN_RESULT(Encode::null());
+ }
+
+ ReturnedValue retVal = Encode::undefined();
+ // return first match
+ if (r->value()->captureCount()) {
+ int start = matchOffsets[0];
+ int end = matchOffsets[1];
+ retVal = (start != -1) ? scope.engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
+ }
+
+ RegExpCtor::Data *dd = regExpCtor->d();
+ dd->lastInput.set(scope.engine, str->d());
+ dd->lastMatchStart = matchOffsets[0];
+ dd->lastMatchEnd = matchOffsets[1];
+
+ r->setLastIndex(matchOffsets[1]);
+
+ return retVal;
+}
+
+ReturnedValue RegExpPrototype::method_exec(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
- Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>());
+ Scope scope(b);
+ Scoped<RegExpObject> r(scope, thisObject->as<RegExpObject>());
if (!r)
- THROW_TYPE_ERROR();
+ return scope.engine->throwTypeError();
- ScopedValue arg(scope, callData->argument(0));
+ ScopedValue arg(scope, argc ? argv[0]: Primitive::undefinedValue());
ScopedString str(scope, arg->toString(scope.engine));
if (scope.hasException())
RETURN_UNDEFINED();
@@ -344,7 +378,7 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
Q_ALLOCA_VAR(uint, matchOffsets, r->value()->captureCount() * 2 * sizeof(uint));
const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets);
- Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor());
+ RegExpCtor *regExpCtor = static_cast<RegExpCtor *>(scope.engine->regExpCtor());
regExpCtor->d()->clearLastMatch();
if (result == -1) {
@@ -376,73 +410,78 @@ void RegExpPrototype::method_exec(const BuiltinFunction *, Scope &scope, CallDat
if (r->global())
r->setLastIndex(matchOffsets[1]);
- scope.result = array;
+ return array.asReturnedValue();
}
-void RegExpPrototype::method_test(const BuiltinFunction *b, Scope &scope, CallData *callData)
+ReturnedValue RegExpPrototype::method_test(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
- method_exec(b, scope, callData);
- scope.result = Encode(!scope.result.isNull());
+ Value res = Value::fromReturnedValue(method_exec(b, thisObject, argv, argc));
+ return Encode(!res.isNull());
}
-void RegExpPrototype::method_toString(const BuiltinFunction *, Scope &scope, CallData *callData)
+ReturnedValue RegExpPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
- Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>());
+ ExecutionEngine *v4 = b->engine();
+ const RegExpObject *r = thisObject->as<RegExpObject>();
if (!r)
- THROW_TYPE_ERROR();
+ return v4->throwTypeError();
- scope.result = scope.engine->newString(r->toString());
+ return Encode(v4->newString(r->toString()));
}
-void RegExpPrototype::method_compile(const BuiltinFunction *, Scope &scope, CallData *callData)
+ReturnedValue RegExpPrototype::method_compile(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
- Scoped<RegExpObject> r(scope, callData->thisObject.as<RegExpObject>());
+ Scope scope(b);
+ Scoped<RegExpObject> r(scope, thisObject->as<RegExpObject>());
if (!r)
- THROW_TYPE_ERROR();
-
- ScopedCallData cData(scope, callData->argc);
- memcpy(cData->args, callData->args, callData->argc*sizeof(Value));
+ return scope.engine->throwTypeError();
- scope.engine->regExpCtor()->as<FunctionObject>()->construct(scope, cData);
- Scoped<RegExpObject> re(scope, scope.result.asReturnedValue());
+ Scoped<RegExpObject> re(scope, scope.engine->regExpCtor()->callAsConstructor(argv, argc));
r->d()->value.set(scope.engine, re->value());
+ return Encode::undefined();
}
template <int index>
-void RegExpPrototype::method_get_lastMatch_n(const BuiltinFunction *, Scope &scope, CallData *)
+ReturnedValue RegExpPrototype::method_get_lastMatch_n(const FunctionObject *b, const Value *, const Value *, int)
{
+ Scope scope(b);
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch());
- scope.result = lastMatch ? lastMatch->getIndexed(index) : Encode::undefined();
- if (scope.result.isUndefined())
- scope.result = scope.engine->newString();
+ ScopedValue res(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
+ if (res->isUndefined())
+ res = scope.engine->newString();
+ return res->asReturnedValue();
}
-void RegExpPrototype::method_get_lastParen(const BuiltinFunction *, Scope &scope, CallData *)
+ReturnedValue RegExpPrototype::method_get_lastParen(const FunctionObject *b, const Value *, const Value *, int)
{
+ Scope scope(b);
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch());
- scope.result = lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined();
- if (scope.result.isUndefined())
- scope.result = scope.engine->newString();
+ ScopedValue res(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
+ if (res->isUndefined())
+ res = scope.engine->newString();
+ return res->asReturnedValue();
}
-void RegExpPrototype::method_get_input(const BuiltinFunction *, Scope &scope, CallData *)
+ReturnedValue RegExpPrototype::method_get_input(const FunctionObject *b, const Value *, const Value *, int)
{
- scope.result = static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastInput();
+ return static_cast<RegExpCtor*>(b->engine()->regExpCtor())->lastInput()->asReturnedValue();
}
-void RegExpPrototype::method_get_leftContext(const BuiltinFunction *, Scope &scope, CallData *)
+ReturnedValue RegExpPrototype::method_get_leftContext(const FunctionObject *b, const Value *, const Value *, int)
{
+ Scope scope(b);
Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
- scope.result = scope.engine->newString(lastInput.left(regExpCtor->lastMatchStart()));
+ return Encode(scope.engine->newString(lastInput.left(regExpCtor->lastMatchStart())));
}
-void RegExpPrototype::method_get_rightContext(const BuiltinFunction *, Scope &scope, CallData *)
+ReturnedValue RegExpPrototype::method_get_rightContext(const FunctionObject *b, const Value *, const Value *, int)
{
+ Scope scope(b);
Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor());
QString lastInput = regExpCtor->lastInput()->toQString();
- scope.result = scope.engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()));
+ return Encode(scope.engine->newString(lastInput.mid(regExpCtor->lastMatchEnd())));
}
QT_END_NAMESPACE