aboutsummaryrefslogtreecommitdiffstats
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
parent4bfd94c35e5099557cafcc9ae9b7d7a970089c9f (diff)
Fix some details in RegExp handling
Change-Id: If9f7c07ea657ba8503b9188a7b77e301f23423ef Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-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
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations28
6 files changed, 52 insertions, 46 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 {
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 06856ba80f..cacd6f3787 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -707,22 +707,7 @@ built-ins/RegExp/from-regexp-like-get-source-err.js fails
built-ins/RegExp/from-regexp-like-short-circuit.js fails
built-ins/RegExp/from-regexp-like.js fails
built-ins/RegExp/proto-from-ctor-realm.js fails
-built-ins/RegExp/prototype/15.10.6.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-coerce-lastindex.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-failure-g-set-lastindex-err.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-success-g-set-lastindex-err.js fails
built-ins/RegExp/prototype/Symbol.match/builtin-success-u-return-val-groups.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-failure-y-set-lastindex-err.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-failure-y-set-lastindex.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-success-y-set-lastindex-err.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-success-y-set-lastindex.js fails
-built-ins/RegExp/prototype/Symbol.match/g-init-lastindex-err.js fails
-built-ins/RegExp/prototype/Symbol.match/y-fail-lastindex-no-write.js fails
-built-ins/RegExp/prototype/Symbol.match/y-init-lastindex.js fails
-built-ins/RegExp/prototype/Symbol.match/y-set-lastindex.js fails
-built-ins/RegExp/prototype/Symbol.replace/y-fail-lastindex-no-write.js fails
-built-ins/RegExp/prototype/Symbol.replace/y-init-lastindex.js fails
-built-ins/RegExp/prototype/Symbol.replace/y-set-lastindex.js fails
built-ins/RegExp/prototype/Symbol.split/coerce-flags-err.js fails
built-ins/RegExp/prototype/Symbol.split/coerce-flags.js fails
built-ins/RegExp/prototype/Symbol.split/coerce-limit-err.js fails
@@ -768,20 +753,8 @@ built-ins/RegExp/prototype/Symbol.split/u-lastindex-adv-thru-match.js fails
built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3.js fails
built-ins/RegExp/prototype/exec/failure-lastindex-access.js fails
built-ins/RegExp/prototype/exec/success-lastindex-access.js fails
-built-ins/RegExp/prototype/exec/y-fail-lastindex-no-write.js fails
-built-ins/RegExp/prototype/exec/y-init-lastindex.js fails
-built-ins/RegExp/prototype/exec/y-set-lastindex.js fails
-built-ins/RegExp/prototype/global/this-val-regexp-prototype.js fails
-built-ins/RegExp/prototype/ignoreCase/this-val-regexp-prototype.js fails
-built-ins/RegExp/prototype/multiline/this-val-regexp-prototype.js fails
-built-ins/RegExp/prototype/no-regexp-matcher.js fails
built-ins/RegExp/prototype/source/value-line-terminator.js fails
-built-ins/RegExp/prototype/sticky/this-val-regexp-prototype.js fails
built-ins/RegExp/prototype/test/S15.10.6.3_A1_T22.js fails
-built-ins/RegExp/prototype/test/y-fail-lastindex-no-write.js fails
-built-ins/RegExp/prototype/test/y-init-lastindex.js fails
-built-ins/RegExp/prototype/test/y-set-lastindex.js fails
-built-ins/RegExp/prototype/unicode/this-val-regexp-prototype.js fails
built-ins/RegExp/unicode_restricted_brackets.js fails
built-ins/RegExp/unicode_restricted_character_class_escape.js fails
built-ins/RegExp/unicode_restricted_identity_escape.js fails
@@ -2014,7 +1987,6 @@ language/global-code/script-decl-var.js fails
language/identifiers/other_id_continue.js fails
language/identifiers/other_id_start-escaped.js fails
language/identifiers/other_id_start.js fails
-language/literals/regexp/y-assertion-start.js fails
language/module-code/eval-export-dflt-cls-anon.js strictFails
language/module-code/eval-gtbndng-indirect-update-dflt.js strictFails
language/module-code/instn-iee-bndng-cls.js strictFails