Implement String.prototype.match
authorLars Knoll <lars.knoll@digia.com>
Thu, 17 Jan 2013 22:03:07 +0000 (23:03 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Fri, 18 Jan 2013 12:38:34 +0000 (13:38 +0100)
The implementation is not very performant, as it simply
is a straight implementation of the standard using
RegExpObject. In the long term this should probably
use a RegExp directly instead.

Change-Id: I532909b3fa8555bf1c16378e2650ca4debedd4b2
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qv4ecmaobjects.cpp
tests/TestExpectations

index 0ef0d2a..462678f 100644 (file)
@@ -1186,9 +1186,55 @@ Value StringPrototype::method_localeCompare(ExecutionContext *ctx)
 
 Value StringPrototype::method_match(ExecutionContext *ctx)
 {
-    // requires Regexp
-    ctx->throwUnimplemented(QStringLiteral("String.prototype.match"));
-    return Value::undefinedValue();
+    if (ctx->thisObject.isUndefined() || ctx->thisObject.isNull())
+        __qmljs_throw_type_error(ctx);
+
+    String *s = ctx->thisObject.toString(ctx);
+
+    Value regexp = ctx->argument(0);
+    RegExpObject *rx = regexp.asRegExpObject();
+    if (!rx)
+        rx = ctx->engine->regExpCtor.asFunctionObject()->construct(ctx, &regexp, 1).asRegExpObject();
+
+    if (!rx)
+        // ### CHECK
+        __qmljs_throw_type_error(ctx);
+
+    bool global = rx->global;
+
+    FunctionObject *exec = ctx->engine->regExpPrototype->__get__(ctx, ctx->engine->identifier(QStringLiteral("exec")), 0).asFunctionObject();
+
+    Value arg = Value::fromString(s);
+    if (!global)
+        return exec->call(ctx, Value::fromObject(rx), &arg, 1);
+
+    String *lastIndex = ctx->engine->identifier(QStringLiteral("lastIndex"));
+    rx->__put__(ctx, lastIndex, Value::fromDouble(0.));
+    ArrayObject *a = ctx->engine->newArrayObject(ctx);
+
+    double previousLastIndex = 0;
+    uint n = 0;
+    while (1) {
+        Value result = exec->call(ctx, Value::fromObject(rx), &arg, 1);
+        if (result.isNull())
+            break;
+        assert(result.isObject());
+        double thisIndex = rx->__get__(ctx, lastIndex, 0).toInteger(ctx);
+        if (previousLastIndex == thisIndex) {
+            previousLastIndex = thisIndex + 1;
+            rx->__put__(ctx, lastIndex, Value::fromDouble(previousLastIndex));
+        } else {
+            previousLastIndex = thisIndex;
+        }
+        Value matchStr = result.objectValue()->__get__(ctx, (uint)0, (bool *)0);
+        a->array.set(n, matchStr);
+        ++n;
+    }
+    if (!n)
+        return Value::nullValue();
+
+    return Value::fromObject(a);
+
 }
 
 Value StringPrototype::method_replace(ExecutionContext *ctx)
index 7f29ea9..4c1938b 100644 (file)
@@ -760,38 +760,7 @@ S15.4.4.6_A4_T2 failing
 S15.4.4.7_A3 failing
 S15.4.4.7_A4_T2 failing
 S15.4.4.7_A4_T3 failing
-S15.5.4.10_A1_T1 failing
 S15.5.4.10_A1_T10 failing
-S15.5.4.10_A1_T11 failing
-S15.5.4.10_A1_T12 failing
-S15.5.4.10_A1_T13 failing
-S15.5.4.10_A1_T14 failing
-S15.5.4.10_A1_T2 failing
-S15.5.4.10_A1_T3 failing
-S15.5.4.10_A1_T4 failing
-S15.5.4.10_A1_T5 failing
-S15.5.4.10_A1_T6 failing
-S15.5.4.10_A1_T7 failing
-S15.5.4.10_A1_T8 failing
-S15.5.4.10_A1_T9 failing
-S15.5.4.10_A2_T1 failing
-S15.5.4.10_A2_T10 failing
-S15.5.4.10_A2_T11 failing
-S15.5.4.10_A2_T12 failing
-S15.5.4.10_A2_T13 failing
-S15.5.4.10_A2_T14 failing
-S15.5.4.10_A2_T15 failing
-S15.5.4.10_A2_T16 failing
-S15.5.4.10_A2_T17 failing
-S15.5.4.10_A2_T18 failing
-S15.5.4.10_A2_T2 failing
-S15.5.4.10_A2_T3 failing
-S15.5.4.10_A2_T4 failing
-S15.5.4.10_A2_T5 failing
-S15.5.4.10_A2_T6 failing
-S15.5.4.10_A2_T7 failing
-S15.5.4.10_A2_T8 failing
-S15.5.4.10_A2_T9 failing
 15.5.4.11-1 failing
 S15.5.4.11_A12 failing
 S15.5.4.11_A1_T1 failing