From 55d54a125e61dd31b7035c492ca8223a04e565f4 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 22 Jan 2013 15:13:15 +0100 Subject: [PATCH] Add URI handling methods Change-Id: Ieee66aa1f95e6676316c4504b4874d307f5b3564 Reviewed-by: Simon Hausmann --- qmljs_engine.cpp | 9 ++ qmljs_engine.h | 1 + qmljs_environment.cpp | 5 + qmljs_environment.h | 1 + qv4errorobject.cpp | 7 ++ qv4errorobject.h | 1 + qv4globalobject.cpp | 330 +++++++++++++++++++++++++++++++++++++++++++++++-- qv4globalobject.h | 80 +++++------- tests/TestExpectations | 99 +-------------- 9 files changed, 375 insertions(+), 158 deletions(-) diff --git a/qmljs_engine.cpp b/qmljs_engine.cpp index e3ce0b4..0f6823d 100644 --- a/qmljs_engine.cpp +++ b/qmljs_engine.cpp @@ -224,6 +224,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) glo->defineDefaultProperty(rootContext, QStringLiteral("parseFloat"), Value::fromObject(new (memoryManager) ParseFloatFunction(rootContext))); glo->defineDefaultProperty(rootContext, QStringLiteral("isNaN"), Value::fromObject(new (memoryManager) IsNaNFunction(rootContext))); glo->defineDefaultProperty(rootContext, QStringLiteral("isFinite"), Value::fromObject(new (memoryManager) IsFiniteFunction(rootContext))); + glo->defineDefaultProperty(rootContext, QStringLiteral("decodeURI"), Value::fromObject(new (memoryManager) DecodeUriFunction(rootContext))); + glo->defineDefaultProperty(rootContext, QStringLiteral("decodeURIComponent"), Value::fromObject(new (memoryManager) DecodeUriComponentFunction(rootContext))); + glo->defineDefaultProperty(rootContext, QStringLiteral("encodeURI"), Value::fromObject(new (memoryManager) EncodeUriFunction(rootContext))); + glo->defineDefaultProperty(rootContext, QStringLiteral("encodeURIComponent"), Value::fromObject(new (memoryManager) EncodeUriComponentFunction(rootContext))); } ExecutionEngine::~ExecutionEngine() @@ -419,6 +423,11 @@ Object *ExecutionEngine::newRangeErrorObject(ExecutionContext *ctx, const QStrin return new (memoryManager) RangeErrorObject(ctx, message); } +Object *ExecutionEngine::newURIErrorObject(ExecutionContext *ctx, Value message) +{ + return new (memoryManager) URIErrorObject(ctx, message); +} + Object *ExecutionEngine::newMathObject(ExecutionContext *ctx) { MathObject *object = new (memoryManager) MathObject(ctx); diff --git a/qmljs_engine.h b/qmljs_engine.h index fbb6e48..afc0b3b 100644 --- a/qmljs_engine.h +++ b/qmljs_engine.h @@ -211,6 +211,7 @@ struct ExecutionEngine Object *newReferenceErrorObject(ExecutionContext *ctx, const QString &message); Object *newTypeErrorObject(ExecutionContext *ctx, const QString &message); Object *newRangeErrorObject(ExecutionContext *ctx, const QString &message); + Object *newURIErrorObject(ExecutionContext *ctx, Value message); Object *newMathObject(ExecutionContext *ctx); Object *newActivationObject(); diff --git a/qmljs_environment.cpp b/qmljs_environment.cpp index 89ba600..d01b038 100644 --- a/qmljs_environment.cpp +++ b/qmljs_environment.cpp @@ -440,6 +440,11 @@ void ExecutionContext::throwRangeError(Value value) throwError(Value::fromObject(engine->newRangeErrorObject(this, msg))); } +void ExecutionContext::throwURIError(Value msg) +{ + throwError(Value::fromObject(engine->newURIErrorObject(this, msg))); +} + void ExecutionContext::initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc) { MemoryManager::GCBlocker blockGC(parent->engine->memoryManager); diff --git a/qmljs_environment.h b/qmljs_environment.h index f043b06..b5f6802 100644 --- a/qmljs_environment.h +++ b/qmljs_environment.h @@ -119,6 +119,7 @@ struct ExecutionContext void throwTypeError(); void throwReferenceError(Value value); void throwRangeError(Value value); + void throwURIError(Value msg); void throwUnimplemented(const QString &message); void setProperty(String *name, Value value); diff --git a/qv4errorobject.cpp b/qv4errorobject.cpp index b5005cb..8e10a90 100644 --- a/qv4errorobject.cpp +++ b/qv4errorobject.cpp @@ -150,6 +150,13 @@ URIErrorObject::URIErrorObject(ExecutionContext *ctx) prototype = ctx->engine->uRIErrorPrototype; } +URIErrorObject::URIErrorObject(ExecutionContext *ctx, Value msg) + : ErrorObject(ctx->engine, msg) +{ + setNameProperty(ctx); + prototype = ctx->engine->uRIErrorPrototype; +} + ErrorCtor::ErrorCtor(ExecutionContext *scope) : FunctionObject(scope) diff --git a/qv4errorobject.h b/qv4errorobject.h index 66f2676..5c31f33 100644 --- a/qv4errorobject.h +++ b/qv4errorobject.h @@ -95,6 +95,7 @@ struct TypeErrorObject: ErrorObject { struct URIErrorObject: ErrorObject { URIErrorObject(ExecutionContext *ctx); + URIErrorObject(ExecutionContext *ctx, Value); virtual QString className() { return QStringLiteral("URIError"); } }; diff --git a/qv4globalobject.cpp b/qv4globalobject.cpp index f87ad70..f928b0d 100644 --- a/qv4globalobject.cpp +++ b/qv4globalobject.cpp @@ -40,11 +40,9 @@ ****************************************************************************/ #include "qv4globalobject.h" -#include "qv4ir_p.h" -#include "qv4isel_p.h" -#include "qv4objectproto.h" -#include "qv4stringobject.h" #include "qv4mm.h" +#include "qmljs_value.h" +#include "qmljs_environment.h" #include #include @@ -54,15 +52,244 @@ #include #include "private/qlocale_tools_p.h" -#include #include -#include -#include +#include #include -#include using namespace QQmlJS::VM; +static inline char toHex(char c) +{ + static const char hexnumbers[] = "0123456789ABCDEF"; + return hexnumbers[c & 0xf]; +} + +static int fromHex(QChar ch) +{ + ushort c = ch.unicode(); + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + return -1; +} + +static QString escape(const QString &input) +{ + QString output; + output.reserve(input.size() * 3); + const int length = input.length(); + for (int i = 0; i < length; ++i) { + ushort uc = input.at(i).unicode(); + if (uc < 0x100) { + if ( (uc > 0x60 && uc < 0x7B) + || (uc > 0x3F && uc < 0x5B) + || (uc > 0x2C && uc < 0x3A) + || (uc == 0x2A) + || (uc == 0x2B) + || (uc == 0x5F)) { + output.append(QChar(uc)); + } else { + output.append('%'); + output.append(QChar(toHex(uc >> 4))); + output.append(QChar(toHex(uc))); + } + } else { + output.append('%'); + output.append('u'); + output.append(QChar(toHex(uc >> 12))); + output.append(QChar(toHex(uc >> 8))); + output.append(QChar(toHex(uc >> 4))); + output.append(QChar(toHex(uc))); + } + } + return output; +} + +static QString unescape(const QString &input) +{ + QString result; + result.reserve(input.length()); + int i = 0; + const int length = input.length(); + while (i < length) { + QChar c = input.at(i++); + if ((c == '%') && (i + 1 < length)) { + QChar a = input.at(i); + if ((a == 'u') && (i + 4 < length)) { + int d3 = fromHex(input.at(i+1)); + int d2 = fromHex(input.at(i+2)); + int d1 = fromHex(input.at(i+3)); + int d0 = fromHex(input.at(i+4)); + if ((d3 != -1) && (d2 != -1) && (d1 != -1) && (d0 != -1)) { + ushort uc = ushort((d3 << 12) | (d2 << 8) | (d1 << 4) | d0); + result.append(QChar(uc)); + i += 5; + } else { + result.append(c); + } + } else { + int d1 = fromHex(a); + int d0 = fromHex(input.at(i+1)); + if ((d1 != -1) && (d0 != -1)) { + c = (d1 << 4) | d0; + i += 2; + } + result.append(c); + } + } else { + result.append(c); + } + } + return result; +} + +static const char uriReserved[] = ";/?:@&=+$,"; +static const char uriUnescaped[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"; + +static QString encode(const QString &input, const QString &unescapedSet, bool *ok) +{ + *ok = true; + QString output; + const int length = input.length(); + int i = 0; + while (i < length) { + const QChar c = input.at(i); + if (!unescapedSet.contains(c)) { + ushort uc = c.unicode(); + if ((uc >= 0xDC00) && (uc <= 0xDFFF)) { + *ok = false; + break; + } + if (!((uc < 0xD800) || (uc > 0xDBFF))) { + ++i; + if (i == length) { + *ok = false; + break; + } + const ushort uc2 = input.at(i).unicode(); + if ((uc < 0xDC00) || (uc > 0xDFFF)) { + *ok = false; + break; + } + uc = ((uc - 0xD800) * 0x400) + (uc2 - 0xDC00) + 0x10000; + } + QString tmp(1, QChar(uc)); + QByteArray octets = tmp.toUtf8(); + for (int j = 0; j < octets.length(); ++j) { + output.append(QLatin1Char('%')); + output.append(QLatin1Char(toHex(octets.at(j) >> 4))); + output.append(QLatin1Char(toHex(octets.at(j)))); + } + } else { + output.append(c); + } + ++i; + } + if (i != length) + *ok = false; + return output; +} + +static QString decode(const QString &input, const QString &reservedSet, bool *ok) +{ + *ok = true; + QString output; + const int length = input.length(); + int i = 0; + const QChar percent = QLatin1Char('%'); + while (i < length) { + const QChar ch = input.at(i); + if (ch == percent) { + int start = i; + if (i + 2 >= length) + goto error; + + int d1 = fromHex(input.at(i+1)); + int d0 = fromHex(input.at(i+2)); + if ((d1 == -1) || (d0 == -1)) + goto error; + + int b = (d1 << 4) | d0; + i += 2; + if (b & 0x80) { + int uc; + int min_uc; + int need; + if ((b & 0xe0) == 0xc0) { + uc = b & 0x1f; + need = 1; + min_uc = 0x80; + } else if ((b & 0xf0) == 0xe0) { + uc = b & 0x0f; + need = 2; + min_uc = 0x800; + } else if ((b & 0xf8) == 0xf0) { + uc = b & 0x07; + need = 3; + min_uc = 0x10000; + } else { + goto error; + } + + if (i + (3 * need) >= length) + goto error; + + for (int j = 0; j < need; ++j) { + ++i; + if (input.at(i) != percent) + goto error; + + d1 = fromHex(input.at(i+1)); + d0 = fromHex(input.at(i+2)); + if ((d1 == -1) || (d0 == -1)) + goto error; + + b = (d1 << 4) | d0; + if ((b & 0xC0) != 0x80) + goto error; + + i += 2; + uc = (uc << 6) + b; + } + if (uc < min_uc) + goto error; + + if (uc < 0x10000) { + output.append(QChar(uc)); + } else { + if (uc > 0x10FFFF) + goto error; + + ushort l = ushort(((uc - 0x10000) & 0x3FF) + 0xDC00); + ushort h = ushort((((uc - 0x10000) >> 10) & 0x3FF) + 0xD800); + output.append(QChar(l)); + output.append(QChar(h)); + } + } else { + QChar z(b); + if (!reservedSet.contains(z)) { + output.append(z); + } else { + output.append(input.mid(start, i - start + 1)); + } + } + } else { + output.append(ch); + } + ++i; + } + if (i != length) + *ok = false; + return output; + error: + *ok = false; + return QString(); +} + + Value EvalFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int argc) { @@ -349,3 +576,90 @@ Value IsFiniteFunction::call(ExecutionContext *context, Value /*thisObject*/, Va double d = v.toNumber(context); return Value::fromBoolean(std::isfinite(d)); } + + +/// decodeURI [15.1.3.1] +DecodeUriFunction::DecodeUriFunction(ExecutionContext *scope) + : FunctionObject(scope) +{ + name = scope->engine->newString(QLatin1String("decodeURI")); +} + +Value DecodeUriFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int argc) +{ + if (argc == 0) + return Value::undefinedValue(); + + QString uriString = args[0].toString(context)->toQString(); + bool ok; + QString out = decode(uriString, QString::fromUtf8(uriReserved) + QString::fromUtf8("#"), &ok); + if (!ok) + context->throwURIError(Value::fromString(context, QStringLiteral("malformed URI sequence"))); + + return Value::fromString(context, out); +} + +/// decodeURIComponent [15.1.3.2] +DecodeUriComponentFunction::DecodeUriComponentFunction(ExecutionContext *scope) + : FunctionObject(scope) +{ + name = scope->engine->newString(QLatin1String("decodeURIComponent")); +} + +Value DecodeUriComponentFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int argc) +{ + if (argc == 0) + return Value::undefinedValue(); + + QString uriString = args[0].toString(context)->toQString(); + bool ok; + QString out = decode(uriString, QString(), &ok); + if (!ok) + context->throwURIError(Value::fromString(context, QStringLiteral("malformed URI sequence"))); + + return Value::fromString(context, out); +} + +/// encodeURI [15.1.3.3] +EncodeUriFunction::EncodeUriFunction(ExecutionContext *scope) + : FunctionObject(scope) +{ + name = scope->engine->newString(QLatin1String("encodeURI")); +} + +Value EncodeUriFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int argc) +{ + if (argc == 0) + return Value::undefinedValue(); + + QString uriString = args[0].toString(context)->toQString(); + bool ok; + QString out = encode(uriString, QLatin1String(uriReserved) + QLatin1String(uriUnescaped) + QString::fromUtf8("#"), &ok); + if (!ok) + context->throwURIError(Value::fromString(context, QStringLiteral("malformed URI sequence"))); + + return Value::fromString(context, out); +} + + +/// encodeURIComponent [15.1.3.4] +EncodeUriComponentFunction::EncodeUriComponentFunction(ExecutionContext *scope) + : FunctionObject(scope) +{ + name = scope->engine->newString(QLatin1String("encodeURIComponent")); +} + +Value EncodeUriComponentFunction::call(ExecutionContext *context, Value /*thisObject*/, Value *args, int argc) +{ + if (argc == 0) + return Value::undefinedValue(); + + QString uriString = args[0].toString(context)->toQString(); + bool ok; + QString out = encode(uriString, QString(), &ok); + if (!ok) + context->throwURIError(Value::fromString(context, QStringLiteral("malformed URI sequence"))); + + return Value::fromString(context, out); +} + diff --git a/qv4globalobject.h b/qv4globalobject.h index 822ec97..fbbeac6 100644 --- a/qv4globalobject.h +++ b/qv4globalobject.h @@ -41,64 +41,12 @@ #ifndef QV4GLOBALOBJECT_H #define QV4GLOBALOBJECT_H -#include "qmljs_runtime.h" -#include "qmljs_engine.h" -#include "qmljs_environment.h" #include "qv4functionobject.h" -#include "qv4array.h" -#include "qv4string.h" -#include "qv4codegen_p.h" -#include "qv4isel_p.h" -#include "qv4managed.h" -#include "qv4propertydescriptor.h" -#include "qv4propertytable.h" -#include "qv4objectiterator.h" -#include "qv4regexp.h" - -#include -#include -#include -#include -#include namespace QQmlJS { namespace VM { -struct Value; -struct Function; -struct Object; -struct ObjectIterator; -struct BooleanObject; -struct NumberObject; -struct StringObject; -struct ArrayObject; -struct DateObject; -struct FunctionObject; -struct RegExpObject; -struct ErrorObject; -struct ArgumentsObject; -struct ExecutionContext; -struct ExecutionEngine; -class MemoryManager; - -struct ObjectPrototype; -struct StringPrototype; -struct NumberPrototype; -struct BooleanPrototype; -struct ArrayPrototype; -struct FunctionPrototype; -struct DatePrototype; -struct RegExpPrototype; -struct ErrorPrototype; -struct EvalErrorPrototype; -struct RangeErrorPrototype; -struct ReferenceErrorPrototype; -struct SyntaxErrorPrototype; -struct TypeErrorPrototype; -struct URIErrorPrototype; - - struct EvalFunction : FunctionObject { EvalFunction(ExecutionContext *scope); @@ -139,6 +87,34 @@ struct IsFiniteFunction: FunctionObject virtual Value call(ExecutionContext *context, Value thisObject, Value *args, int argc); }; +struct DecodeUriFunction: FunctionObject +{ + DecodeUriFunction(ExecutionContext *scope); + + virtual Value call(ExecutionContext *context, Value thisObject, Value *args, int argc); +}; + +struct DecodeUriComponentFunction: FunctionObject +{ + DecodeUriComponentFunction(ExecutionContext *scope); + + virtual Value call(ExecutionContext *context, Value thisObject, Value *args, int argc); +}; + +struct EncodeUriFunction: FunctionObject +{ + EncodeUriFunction(ExecutionContext *scope); + + virtual Value call(ExecutionContext *context, Value thisObject, Value *args, int argc); +}; + +struct EncodeUriComponentFunction: FunctionObject +{ + EncodeUriComponentFunction(ExecutionContext *scope); + + virtual Value call(ExecutionContext *context, Value thisObject, Value *args, int argc); +}; + } // namespace VM } // namespace QQmlJS diff --git a/tests/TestExpectations b/tests/TestExpectations index 2fd3077..5da4805 100644 --- a/tests/TestExpectations +++ b/tests/TestExpectations @@ -3,9 +3,6 @@ S15.1.3.1_A2.5_T1 S15.1.3.2_A2.5_T1 # Tests failing that are supposed to pass. -S10.2.3_A1.1_T2 failing -S10.2.3_A1.2_T2 failing -S10.2.3_A1.3_T2 failing 10.4.2-1-1 failing 10.4.2-1-2 failing 10.4.2-1-3 failing @@ -307,12 +304,6 @@ S15.1.2.5_A2.2 failing S15.1.2.5_A2.3 failing S15.1.2.5_A2.4 failing S15.1.2.5_A2.7 failing -S15.1.3.1_A1.10_T1 failing -S15.1.3.1_A1.11_T1 failing -S15.1.3.1_A1.11_T2 failing -S15.1.3.1_A1.12_T1 failing -S15.1.3.1_A1.12_T2 failing -S15.1.3.1_A1.12_T3 failing S15.1.3.1_A1.13_T1 failing S15.1.3.1_A1.13_T2 failing S15.1.3.1_A1.14_T1 failing @@ -325,21 +316,6 @@ S15.1.3.1_A1.15_T3 failing S15.1.3.1_A1.15_T4 failing S15.1.3.1_A1.15_T5 failing S15.1.3.1_A1.15_T6 failing -S15.1.3.1_A1.1_T1 failing -S15.1.3.1_A1.2_T1 failing -S15.1.3.1_A1.2_T2 failing -S15.1.3.1_A1.3_T1 failing -S15.1.3.1_A1.3_T2 failing -S15.1.3.1_A1.4_T1 failing -S15.1.3.1_A1.5_T1 failing -S15.1.3.1_A1.6_T1 failing -S15.1.3.1_A1.7_T1 failing -S15.1.3.1_A1.8_T1 failing -S15.1.3.1_A1.8_T2 failing -S15.1.3.1_A1.9_T1 failing -S15.1.3.1_A1.9_T2 failing -S15.1.3.1_A1.9_T3 failing -S15.1.3.1_A2.1_T1 failing 15.12.3-11-2 failing 15.12.3-11-26 failing 15.12.3-11-3 failing @@ -372,52 +348,21 @@ S15.1.3.1_A2.1_T1 failing 15.12.3_2-3-a-3 failing 15.12.3_4-1-2 failing S15.1.3.2_A5.4 failing -S15.1.3.2_A5.6 failing S15.1.3.2_A5.7 failing -S15.1.3.2_A6_T1 failing -S15.1.3.3_A1.1_T1 failing -S15.1.3.3_A1.1_T2 failing -S15.1.3.3_A1.2_T1 failing -S15.1.3.3_A1.2_T2 failing -S15.1.3.3_A1.3_T1 failing -S15.1.3.3_A2.1_T1 failing -S15.1.3.3_A2.2_T1 failing -S15.1.3.3_A2.3_T1 failing S15.1.3.3_A2.4_T1 failing S15.1.3.3_A2.4_T2 failing S15.1.3.3_A2.5_T1 failing -S15.1.3.3_A3.1_T1 failing -S15.1.3.3_A3.2_T1 failing -S15.1.3.3_A3.2_T2 failing -S15.1.3.3_A3.2_T3 failing -S15.1.3.3_A3.3_T1 failing -S15.1.3.3_A4_T1 failing -S15.1.3.3_A4_T2 failing -S15.1.3.3_A4_T3 failing -S15.1.3.3_A4_T4 failing S15.1.3.3_A5.1 failing S15.1.3.3_A5.2 failing S15.1.3.3_A5.3 failing S15.1.3.3_A5.4 failing -S15.1.3.3_A5.6 failing S15.1.3.3_A5.7 failing -S15.1.3.3_A6_T1 failing -S15.1.3.4_A1.1_T1 failing -S15.1.3.4_A1.1_T2 failing -S15.1.3.4_A1.2_T1 failing -S15.1.3.4_A1.2_T2 failing -S15.1.3.4_A1.3_T1 failing -S15.1.3.4_A2.1_T1 failing -S15.1.3.4_A2.2_T1 failing -S15.1.3.4_A2.3_T1 failing S15.1.3.4_A2.4_T1 failing S15.1.3.4_A2.4_T2 failing S15.1.3.4_A2.5_T1 failing -S15.1.3.4_A3.1_T1 failing S15.1.3.4_A3.2_T1 failing S15.1.3.4_A3.2_T2 failing S15.1.3.4_A3.2_T3 failing -S15.1.3.4_A3.3_T1 failing S15.1.3.4_A4_T1 failing S15.1.3.4_A4_T2 failing S15.1.3.4_A4_T3 failing @@ -426,32 +371,16 @@ S15.1.3.4_A5.1 failing S15.1.3.4_A5.2 failing S15.1.3.4_A5.3 failing S15.1.3.4_A5.4 failing -S15.1.3.4_A5.6 failing S15.1.3.4_A5.7 failing S15.1.3.4_A6_T1 failing -S15.1.3.1_A2.2_T1 failing S15.1.3.1_A2.3_T1 failing S15.1.3.1_A2.4_T1 failing -S15.1.3.1_A3_T1 failing -S15.1.3.1_A3_T2 failing -S15.1.3.1_A3_T3 failing -S15.1.3.1_A4_T1 failing S15.1.3.1_A4_T2 failing -S15.1.3.1_A4_T3 failing -S15.1.3.1_A4_T4 failing S15.1.3.1_A5.1 failing S15.1.3.1_A5.2 failing S15.1.3.1_A5.3 failing S15.1.3.1_A5.4 failing -S15.1.3.1_A5.6 failing S15.1.3.1_A5.7 failing -S15.1.3.1_A6_T1 failing -S15.1.3.2_A1.10_T1 failing -S15.1.3.2_A1.11_T1 failing -S15.1.3.2_A1.11_T2 failing -S15.1.3.2_A1.12_T1 failing -S15.1.3.2_A1.12_T2 failing -S15.1.3.2_A1.12_T3 failing S15.1.3.2_A1.13_T1 failing S15.1.3.2_A1.13_T2 failing S15.1.3.2_A1.14_T1 failing @@ -464,39 +393,14 @@ S15.1.3.2_A1.15_T3 failing S15.1.3.2_A1.15_T4 failing S15.1.3.2_A1.15_T5 failing S15.1.3.2_A1.15_T6 failing -S15.1.3.2_A1.1_T1 failing -S15.1.3.2_A1.2_T1 failing -S15.1.3.2_A1.2_T2 failing -S15.1.3.2_A1.3_T1 failing -S15.1.3.2_A1.3_T2 failing -S15.1.3.2_A1.4_T1 failing -S15.1.3.2_A1.5_T1 failing -S15.1.3.2_A1.6_T1 failing -S15.1.3.2_A1.7_T1 failing -S15.1.3.2_A1.8_T1 failing -S15.1.3.2_A1.8_T2 failing -S15.1.3.2_A1.9_T1 failing -S15.1.3.2_A1.9_T2 failing -S15.1.3.2_A1.9_T3 failing -S15.1.3.2_A2.1_T1 failing -S15.1.3.2_A2.2_T1 failing S15.1.3.2_A2.3_T1 failing S15.1.3.2_A2.4_T1 failing -S15.1.3.2_A3_T1 failing -S15.1.3.2_A3_T2 failing -S15.1.3.2_A3_T3 failing -S15.1.3.2_A4_T1 failing S15.1.3.2_A4_T2 failing -S15.1.3.2_A4_T3 failing -S15.1.3.2_A4_T4 failing S15.1.3.2_A5.1 failing S15.1.3.2_A5.2 failing S15.1.3.2_A5.3 failing -15.2.3.3-4-10 failing -15.2.3.3-4-11 failing 15.2.3.3-4-12 failing 15.2.3.3-4-13 failing -15.2.3.3-4-9 failing 15.2.3.6-2-17-1 failing 15.2.3.6-4-291-1 failing 15.2.3.6-4-292-1 failing @@ -711,7 +615,6 @@ S15.4.4.4_A1_T2 failing 15.12.3-11-23 failing 15.12.3-11-24 failing 15.12.3-11-25 failing -15.2.3.4-4-1 failing 15.4.4.18-7-c-i-6 failing 15.4.4.19-8-c-i-6 failing 15.4.4.20-9-c-i-6 failing @@ -724,4 +627,4 @@ S15.4.4.4_A1_T2 failing 15.4.4.21-8-b-iii-1-6 failing 15.12.3_4-1-1 -15.12.3_4-1-3 \ No newline at end of file +15.12.3_4-1-3 -- 2.7.4