diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-08-08 21:33:18 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-08-15 14:24:41 +0000 |
commit | b862d429b1010fecf2e29d0e781b012a4b07cad6 (patch) | |
tree | d0040a21dd8d55cbf42f9724e67f2deb3e470b41 | |
parent | 4bfd94c35e5099557cafcc9ae9b7d7a970089c9f (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.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexp_p.h | 17 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject.cpp | 37 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject_p.h | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 5 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 28 |
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 |