aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-08-08 21:33:18 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-08-15 14:24:41 +0000
commitb862d429b1010fecf2e29d0e781b012a4b07cad6 (patch)
treed0040a21dd8d55cbf42f9724e67f2deb3e470b41 /src/qml/jsruntime
parent4bfd94c35e5099557cafcc9ae9b7d7a970089c9f (diff)
Fix some details in RegExp handling
Change-Id: If9f7c07ea657ba8503b9188a7b77e301f23423ef Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp2
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h17
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp37
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp5
5 files changed, 52 insertions, 18 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 444d12d118..5db26857e4 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -374,7 +374,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
ic = newInternalClass(QV4::RegExpObject::staticVTable(), objectPrototype());
ic = ic->addMember(id_lastIndex()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
Q_ASSERT(index == RegExpObject::Index_LastIndex);
- jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(ic->d());
+ jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(classes[Class_Object]);
classes[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d());
ic = classes[Class_ArrayObject]->addMember(id_index()->propertyKey(), Attr_Data, &index);
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index b027ba7659..6afb10ea95 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -91,6 +91,13 @@ struct RegExp : Base {
return false;
#endif
}
+
+ bool ignoreCase() const { return flags & CompiledData::RegExp::RegExp_IgnoreCase; }
+ bool multiLine() const { return flags & CompiledData::RegExp::RegExp_Multiline; }
+ bool global() const { return flags & CompiledData::RegExp::RegExp_Global; }
+ bool unicode() const { return flags & CompiledData::RegExp::RegExp_Unicode; }
+ bool sticky() const { return flags & CompiledData::RegExp::RegExp_Sticky; }
+
RegExpCache *cache;
int subPatternCount;
uint flags;
@@ -117,11 +124,11 @@ struct RegExp : public Managed
#endif
RegExpCache *cache() const { return d()->cache; }
int subPatternCount() const { return d()->subPatternCount; }
- bool ignoreCase() const { return d()->flags & CompiledData::RegExp::RegExp_IgnoreCase; }
- bool multiLine() const { return d()->flags & CompiledData::RegExp::RegExp_Multiline; }
- bool global() const { return d()->flags & CompiledData::RegExp::RegExp_Global; }
- bool unicode() const { return d()->flags & CompiledData::RegExp::RegExp_Unicode; }
- bool sticky() const { return d()->flags & CompiledData::RegExp::RegExp_Sticky; }
+ bool ignoreCase() const { return d()->ignoreCase(); }
+ bool multiLine() const { return d()->multiLine(); }
+ bool global() const { return d()->global(); }
+ bool unicode() const { return d()->unicode(); }
+ bool sticky() const { return d()->sticky(); }
static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, uint flags = CompiledData::RegExp::RegExp_NoFlags);
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index d157350e00..0acefc26d2 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -180,7 +180,7 @@ ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *s
QString s = str->toQString();
Scope scope(engine);
- int offset = global() ? lastIndex() : 0;
+ int offset = (global() || sticky()) ? lastIndex() : 0;
if (offset < 0 || offset > s.length()) {
setLastIndex(0);
RETURN_RESULT(Encode::null());
@@ -193,7 +193,8 @@ ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *s
regExpCtor->d()->clearLastMatch();
if (result == -1) {
- setLastIndex(0);
+ if (global() || sticky())
+ setLastIndex(0);
RETURN_RESULT(Encode::null());
}
@@ -221,7 +222,7 @@ ReturnedValue RegExpObject::builtinExec(ExecutionEngine *engine, const String *s
dd->lastMatchStart = matchOffsets[0];
dd->lastMatchEnd = matchOffsets[1];
- if (global())
+ if (global() || sticky())
setLastIndex(matchOffsets[1]);
return array.asReturnedValue();
@@ -473,8 +474,11 @@ ReturnedValue RegExpPrototype::method_get_global(const FunctionObject *f, const
{
Scope scope(f);
Scoped<RegExpObject> re(scope, thisObject);
- if (!re)
+ if (!re) {
+ if (thisObject->sameValue(*scope.engine->regExpPrototype()))
+ return Encode::undefined();
return scope.engine->throwTypeError();
+ }
bool b = re->value()->flags & CompiledData::RegExp::RegExp_Global;
return Encode(b);
@@ -484,8 +488,11 @@ ReturnedValue RegExpPrototype::method_get_ignoreCase(const FunctionObject *f, co
{
Scope scope(f);
Scoped<RegExpObject> re(scope, thisObject);
- if (!re)
+ if (!re) {
+ if (thisObject->sameValue(*scope.engine->regExpPrototype()))
+ return Encode::undefined();
return scope.engine->throwTypeError();
+ }
bool b = re->value()->flags & CompiledData::RegExp::RegExp_IgnoreCase;
return Encode(b);
@@ -557,8 +564,11 @@ ReturnedValue RegExpPrototype::method_get_multiline(const FunctionObject *f, con
{
Scope scope(f);
Scoped<RegExpObject> re(scope, thisObject);
- if (!re)
+ if (!re) {
+ if (thisObject->sameValue(*scope.engine->regExpPrototype()))
+ return Encode::undefined();
return scope.engine->throwTypeError();
+ }
bool b = re->value()->flags & CompiledData::RegExp::RegExp_Multiline;
return Encode(b);
@@ -705,8 +715,11 @@ ReturnedValue RegExpPrototype::method_get_source(const FunctionObject *f, const
{
Scope scope(f);
Scoped<RegExpObject> re(scope, thisObject);
- if (!re)
+ if (!re) {
+ if (thisObject->sameValue(*scope.engine->regExpPrototype()))
+ return scope.engine->newString(QStringLiteral("(?:)"))->asReturnedValue();
return scope.engine->throwTypeError();
+ }
return scope.engine->newString(re->toString())->asReturnedValue();
}
@@ -715,8 +728,11 @@ ReturnedValue RegExpPrototype::method_get_sticky(const FunctionObject *f, const
{
Scope scope(f);
Scoped<RegExpObject> re(scope, thisObject);
- if (!re)
+ if (!re) {
+ if (thisObject->sameValue(*scope.engine->regExpPrototype()))
+ return Encode::undefined();
return scope.engine->throwTypeError();
+ }
bool b = re->value()->flags & CompiledData::RegExp::RegExp_Sticky;
return Encode(b);
@@ -754,8 +770,11 @@ ReturnedValue RegExpPrototype::method_get_unicode(const FunctionObject *f, const
{
Scope scope(f);
Scoped<RegExpObject> re(scope, thisObject);
- if (!re)
+ if (!re) {
+ if (thisObject->sameValue(*scope.engine->regExpPrototype()))
+ return Encode::undefined();
return scope.engine->throwTypeError();
+ }
bool b = re->value()->flags & CompiledData::RegExp::RegExp_Unicode;
return Encode(b);
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 2173981b66..ba5a106c6b 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -122,7 +122,8 @@ struct RegExpObject: Object {
enum { NInlineProperties = 5 };
Heap::RegExp *value() const { return d()->value; }
- bool global() const { return d()->value->flags & CompiledData::RegExp::RegExp_Global; }
+ bool global() const { return d()->value->global(); }
+ bool sticky() const { return d()->value->sticky(); }
void initProperties();
@@ -132,6 +133,10 @@ struct RegExpObject: Object {
}
void setLastIndex(int index) {
Q_ASSERT(Index_LastIndex == internalClass()->find(engine()->id_lastIndex()->propertyKey()));
+ if (!internalClass()->propertyData[Index_LastIndex].isWritable()) {
+ engine()->throwTypeError();
+ return;
+ }
return setProperty(Index_LastIndex, Primitive::fromInt32(index));
}
@@ -156,7 +161,7 @@ struct RegExpCtor: FunctionObject
static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
-struct RegExpPrototype: RegExpObject
+struct RegExpPrototype: Object
{
void init(ExecutionEngine *engine, Object *ctor);
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index de8fa0c2ee..e13accd4ea 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -799,8 +799,11 @@ ReturnedValue StringPrototype::method_replace(const FunctionObject *b, const Val
break;
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
- if (regExp->global())
+ if (regExp->global()) {
regExp->setLastIndex(0);
+ if (scope.hasException())
+ return Encode::undefined();
+ }
numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
numCaptures = regExp->value()->captureCount();
} else {