aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4regexpobject.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-08-08 11:56:07 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-08-15 14:24:19 +0000
commit15f56b74dc18c1105c9943f76599dbab5214b8e8 (patch)
tree4701b6c75977f19bce5aec46af8c32b74af33415 /src/qml/jsruntime/qv4regexpobject.cpp
parenta29ab499a4822014d34d6e9e988600fdb6d60a0d (diff)
Partial implementation of RegExp.prototype[Symbol.match]
Change-Id: Id94c3cc25835b53bae08713cdd8f2e384d907690 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4regexpobject.cpp')
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp137
1 files changed, 91 insertions, 46 deletions
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 414ce8e78c..cff8223942 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -44,6 +44,7 @@
#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4jscall_p.h"
+#include "qv4symbol_p.h"
#include "private/qlocale_tools_p.h"
@@ -197,6 +198,58 @@ uint RegExpObject::flags() const
return f;
}
+ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *str)
+{
+ QString s = str->toQString();
+
+ Scope scope(engine);
+ int offset = global() ? lastIndex() : 0;
+ if (offset < 0 || offset > s.length()) {
+ setLastIndex(0);
+ RETURN_RESULT(Encode::null());
+ }
+
+ Q_ALLOCA_VAR(uint, matchOffsets, value()->captureCount() * 2 * sizeof(uint));
+ const int result = Scoped<RegExp>(scope, value())->match(s, offset, matchOffsets);
+
+ RegExpCtor *regExpCtor = static_cast<RegExpCtor *>(scope.engine->regExpCtor());
+ regExpCtor->d()->clearLastMatch();
+
+ if (result == -1) {
+ setLastIndex(0);
+ RETURN_RESULT(Encode::null());
+ }
+
+ // fill in result data
+ ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->internalClasses(EngineBase::Class_RegExpExecArray)));
+ int len = value()->captureCount();
+ array->arrayReserve(len);
+ ScopedValue v(scope);
+ int strlen = s.length();
+ for (int i = 0; i < len; ++i) {
+ int start = matchOffsets[i * 2];
+ int end = matchOffsets[i * 2 + 1];
+ if (end > strlen)
+ end = strlen;
+ v = (start != -1) ? scope.engine->memoryManager->alloc<ComplexString>(str->d(), start, end - start)->asReturnedValue() : Encode::undefined();
+ array->arrayPut(i, v);
+ }
+ array->setArrayLengthUnchecked(len);
+ array->setProperty(Index_ArrayIndex, Primitive::fromInt32(result));
+ array->setProperty(Index_ArrayInput, *str);
+
+ RegExpCtor::Data *dd = regExpCtor->d();
+ dd->lastMatch.set(scope.engine, array);
+ dd->lastInput.set(scope.engine, str->d());
+ dd->lastMatchStart = matchOffsets[0];
+ dd->lastMatchEnd = matchOffsets[1];
+
+ if (global())
+ setLastIndex(matchOffsets[1]);
+
+ return array.asReturnedValue();
+}
+
DEFINE_OBJECT_VTABLE(RegExpCtor);
void Heap::RegExpCtor::init(QV4::ExecutionContext *scope)
@@ -308,6 +361,7 @@ void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor)
defineDefaultProperty(QStringLiteral("test"), method_test, 1);
defineDefaultProperty(engine->id_toString(), method_toString, 0);
defineDefaultProperty(QStringLiteral("compile"), method_compile, 2);
+ defineDefaultProperty(engine->symbol_match(), method_match, 1);
}
/* used by String.match */
@@ -356,6 +410,23 @@ ReturnedValue RegExpPrototype::execFirstMatch(const FunctionObject *b, const Val
return retVal;
}
+ReturnedValue RegExpPrototype::exec(ExecutionEngine *engine, const Object *o, const String *s)
+{
+ Scope scope(engine);
+ ScopedString key(scope, scope.engine->newString(QStringLiteral("exec")));
+ ScopedFunctionObject exec(scope, o->get(key));
+ if (exec) {
+ ScopedValue result(scope, exec->call(o, s, 1));
+ if (!result->isNull() && !result->isObject())
+ return scope.engine->throwTypeError();
+ return result->asReturnedValue();
+ }
+ Scoped<RegExpObject> re(scope, o);
+ if (!re)
+ return scope.engine->throwTypeError();
+ return re->builtinExec(engine, s);
+}
+
ReturnedValue RegExpPrototype::method_exec(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
@@ -367,53 +438,8 @@ ReturnedValue RegExpPrototype::method_exec(const FunctionObject *b, const Value
ScopedString str(scope, arg->toString(scope.engine));
if (scope.hasException())
RETURN_UNDEFINED();
- QString s = str->toQString();
-
- int offset = r->global() ? r->lastIndex() : 0;
- 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());
- }
-
- // fill in result data
- ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->internalClasses(EngineBase::Class_RegExpExecArray)));
- int len = r->value()->captureCount();
- array->arrayReserve(len);
- ScopedValue v(scope);
- int strlen = str->d()->length();
- for (int i = 0; i < len; ++i) {
- int start = matchOffsets[i * 2];
- int end = matchOffsets[i * 2 + 1];
- if (end > strlen)
- end = strlen;
- v = (start != -1) ? scope.engine->memoryManager->alloc<ComplexString>(str->d(), start, end - start)->asReturnedValue() : Encode::undefined();
- array->arrayPut(i, v);
- }
- array->setArrayLengthUnchecked(len);
- array->setProperty(Index_ArrayIndex, Primitive::fromInt32(result));
- array->setProperty(Index_ArrayInput, str);
-
- RegExpCtor::Data *dd = regExpCtor->d();
- dd->lastMatch.set(scope.engine, array);
- dd->lastInput.set(scope.engine, str->d());
- dd->lastMatchStart = matchOffsets[0];
- dd->lastMatchEnd = matchOffsets[1];
-
- if (r->global())
- r->setLastIndex(matchOffsets[1]);
- return array.asReturnedValue();
+ return r->builtinExec(scope.engine, str);
}
ReturnedValue RegExpPrototype::method_test(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
@@ -445,6 +471,25 @@ ReturnedValue RegExpPrototype::method_compile(const FunctionObject *b, const Val
return Encode::undefined();
}
+ReturnedValue RegExpPrototype::method_match(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
+{
+ Scope scope(f);
+ ScopedObject rx(scope, thisObject);
+ if (!rx)
+ return scope.engine->throwTypeError();
+ ScopedString s(scope, (argc ? argv[0] : Primitive::undefinedValue()).toString(scope.engine));
+ if (scope.hasException())
+ return Encode::undefined();
+ ScopedString key(scope, scope.engine->newString(QStringLiteral("global")));
+ bool global = ScopedValue(scope, rx->get(key))->toBoolean();
+
+ if (!global)
+ return exec(scope.engine, rx, s);
+
+ // ####
+ return scope.engine->throwTypeError();
+}
+
template <uint index>
ReturnedValue RegExpPrototype::method_get_lastMatch_n(const FunctionObject *b, const Value *, const Value *, int)
{