From e7729e28f0c4c27bcbc780938bf47385877c2d60 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 17 Jan 2013 15:24:58 +0100 Subject: [PATCH] Fix values of RegExp.lastIndex property The property should be writable and also set to 0 if no match is found. Change-Id: I4288ad239980260c7610c5de0061cc42ac38bb7a Reviewed-by: Lars Knoll --- qmljs_engine.cpp | 4 ++-- qmljs_objects.cpp | 16 ++++++++++++++-- qmljs_objects.h | 4 ++-- qv4ecmaobjects.cpp | 12 ++++++++---- qv4ecmaobjects_p.h | 2 +- tests/TestExpectations | 18 ------------------ 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/qmljs_engine.cpp b/qmljs_engine.cpp index a1f99f5..b58ff12 100644 --- a/qmljs_engine.cpp +++ b/qmljs_engine.cpp @@ -104,7 +104,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) arrayPrototype = new (memoryManager) ArrayPrototype(rootContext); datePrototype = new (memoryManager) DatePrototype(); functionPrototype = new (memoryManager) FunctionPrototype(rootContext); - regExpPrototype = new (memoryManager) RegExpPrototype(); + regExpPrototype = new (memoryManager) RegExpPrototype(this); errorPrototype = new (memoryManager) ErrorPrototype(); evalErrorPrototype = new (memoryManager) EvalErrorPrototype(rootContext); rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(rootContext); @@ -369,7 +369,7 @@ RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags RegExpObject *ExecutionEngine::newRegExpObject(PassRefPtr re, bool global) { - RegExpObject *object = new (memoryManager) RegExpObject(re, global); + RegExpObject *object = new (memoryManager) RegExpObject(this, re, global); object->prototype = regExpPrototype; return object; } diff --git a/qmljs_objects.cpp b/qmljs_objects.cpp index 3a700e2..5e3e0ef 100644 --- a/qmljs_objects.cpp +++ b/qmljs_objects.cpp @@ -1105,6 +1105,20 @@ Value IsFiniteFunction::call(ExecutionContext *context, Value /*thisObject*/, Va } +RegExpObject::RegExpObject(ExecutionEngine *engine, PassRefPtr value, bool global) + : value(value) + , global(global) +{ + if (!members) + members.reset(new PropertyTable()); + lastIndexProperty = members->insert(engine->identifier("lastIndex")); + lastIndexProperty->type = PropertyDescriptor::Data; + lastIndexProperty->writable = PropertyDescriptor::Enabled; + lastIndexProperty->enumberable = PropertyDescriptor::Disabled; + lastIndexProperty->configurable = PropertyDescriptor::Disabled; + lastIndexProperty->value = Value::fromInt32(0); +} + Value RegExpObject::__get__(ExecutionContext *ctx, String *name, bool *hasProperty) { QString n = name->toQString(); @@ -1117,8 +1131,6 @@ Value RegExpObject::__get__(ExecutionContext *ctx, String *name, bool *hasProper v = Value::fromBoolean(value->ignoreCase()); else if (n == QLatin1String("multiline")) v = Value::fromBoolean(value->multiLine()); - else if (n == QLatin1String("lastIndex")) - v = lastIndex; if (v.type() != Value::Undefined_Type) { if (hasProperty) *hasProperty = true; diff --git a/qmljs_objects.h b/qmljs_objects.h index 362fe70..01773ee 100644 --- a/qmljs_objects.h +++ b/qmljs_objects.h @@ -361,9 +361,9 @@ struct IsFiniteFunction: FunctionObject struct RegExpObject: Object { RefPtr value; - Value lastIndex; + PropertyDescriptor *lastIndexProperty; bool global; - RegExpObject(PassRefPtr value, bool global): value(value), lastIndex(Value::fromInt32(0)), global(global) {} + RegExpObject(ExecutionEngine *engine, PassRefPtr value, bool global); virtual QString className() { return QStringLiteral("RegExp"); } virtual RegExpObject *asRegExpObject() { return this; } virtual Value __get__(ExecutionContext *ctx, String *name, bool *hasProperty); diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp index 84b536d..7cf5f52 100644 --- a/qv4ecmaobjects.cpp +++ b/qv4ecmaobjects.cpp @@ -2985,14 +2985,18 @@ Value RegExpPrototype::method_exec(ExecutionContext *ctx) arg = __qmljs_to_string(arg, ctx); QString s = arg.stringValue()->toQString(); - int offset = r->global ? r->lastIndex.toInt32(ctx) : 0; - if (offset < 0 || offset > s.length()) + int offset = r->global ? r->lastIndexProperty->value.toInt32(ctx) : 0; + if (offset < 0 || offset > s.length()) { + r->lastIndexProperty->value = Value::fromInt32(0); return Value::nullValue(); + } uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint)); int result = r->value->match(s, offset, matchOffsets); - if (result == -1) + if (result == -1) { + r->lastIndexProperty->value = Value::fromInt32(0); return Value::nullValue(); + } // fill in result data ArrayObject *array = ctx->engine->newArrayObject(ctx)->asArrayObject(); @@ -3009,7 +3013,7 @@ Value RegExpPrototype::method_exec(ExecutionContext *ctx) array->__put__(ctx, QLatin1String("input"), arg); if (r->global) - r->lastIndex = Value::fromInt32(matchOffsets[1]); + r->lastIndexProperty->value = Value::fromInt32(matchOffsets[1]); return Value::fromObject(array); } diff --git a/qv4ecmaobjects_p.h b/qv4ecmaobjects_p.h index 0576eb4..55890ef 100644 --- a/qv4ecmaobjects_p.h +++ b/qv4ecmaobjects_p.h @@ -295,7 +295,7 @@ struct RegExpCtor: FunctionObject struct RegExpPrototype: RegExpObject { - RegExpPrototype(): RegExpObject(RegExp::create(0, QString()), false) {} + RegExpPrototype(ExecutionEngine* engine): RegExpObject(engine, RegExp::create(0, QString()), false) {} void init(ExecutionContext *ctx, const Value &ctor); static Value method_exec(ExecutionContext *ctx); diff --git a/tests/TestExpectations b/tests/TestExpectations index 7d90fd6..4319e5b 100644 --- a/tests/TestExpectations +++ b/tests/TestExpectations @@ -312,21 +312,6 @@ S15.10.2.12_A4_T1 failing S15.10.2.12_A5_T1 failing S15.10.2.8_A3_T18 failing S15.10.6.2_A1_T2 failing -S15.10.6.2_A4_T1 failing -S15.10.6.2_A4_T10 failing -S15.10.6.2_A4_T11 failing -S15.10.6.2_A4_T12 failing -S15.10.6.2_A4_T2 failing -S15.10.6.2_A4_T3 failing -S15.10.6.2_A4_T4 failing -S15.10.6.2_A4_T5 failing -S15.10.6.2_A4_T6 failing -S15.10.6.2_A4_T7 failing -S15.10.6.2_A4_T8 failing -S15.10.6.2_A4_T9 failing -S15.10.6.2_A5_T1 failing -S15.10.6.2_A5_T2 failing -S15.10.6.2_A5_T3 failing S15.10.7_A2_T1 failing 15.10.7.1-2 failing S15.10.7.1_A10 failing @@ -344,9 +329,6 @@ S15.10.7.3_A9 failing S15.10.7.4_A10 failing S15.10.7.4_A8 failing S15.10.7.4_A9 failing -15.10.7.5-2 failing -S15.10.7.5_A8 failing -S15.10.7.5_A9 failing S15.11.4.2_A1 failing S15.11.4.2_A2 failing S15.11.4.3_A1 failing -- 2.7.4