diff options
-rw-r--r-- | src/qml/jsruntime/qv4dateobject.cpp | 18 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4dateobject_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 49 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 10 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 33 |
8 files changed, 68 insertions, 47 deletions
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index e9a2056a61..092c36e52a 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -44,6 +44,7 @@ #include "qv4runtime_p.h" #include "qv4string_p.h" #include "qv4jscall_p.h" +#include "qv4symbol_p.h" #include <QtCore/QDebug> #include <QtCore/QDateTime> @@ -859,6 +860,7 @@ void DatePrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("toISOString"), method_toISOString, 0); defineDefaultProperty(QStringLiteral("toJSON"), method_toJSON, 1); + defineDefaultProperty(engine->symbol_toPrimitive(), method_symbolToPrimitive, 1, Attr_ReadOnly_ButConfigurable); } double DatePrototype::getThisDate(ExecutionEngine *v4, const Value *thisObject) @@ -1515,6 +1517,22 @@ ReturnedValue DatePrototype::method_toJSON(const FunctionObject *b, const Value return toIso->call(O, nullptr, 0); } +ReturnedValue DatePrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) +{ + ExecutionEngine *e = f->engine(); + if (!thisObject->isObject() || !argc || !argv->isString()) + return e->throwTypeError(); + + String *hint = argv->stringValue(); + Identifier id = hint->identifier(); + if (id == e->id_default()->identifier()) + hint = e->id_string(); + else if (id != e->id_string()->identifier() && id != e->id_number()->identifier()) + return e->throwTypeError(); + + return RuntimeHelpers::ordinaryToPrimitive(e, static_cast<const Object *>(thisObject), hint); +} + void DatePrototype::timezoneUpdated(ExecutionEngine *e) { e->localTZA = getLocalTZA(); diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index 1ee514f599..0a5a3954d1 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -169,6 +169,7 @@ struct DatePrototype: Object static ReturnedValue method_toUTCString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_toISOString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); static ReturnedValue method_toJSON(const FunctionObject *, const Value *thisObject, const Value *argv, int argc); + static ReturnedValue method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *, int); static void timezoneUpdated(ExecutionEngine *e); }; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index fbe9db7075..87132f64bb 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -240,6 +240,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) jsStrings[String_boolean] = newIdentifier(QStringLiteral("boolean")); jsStrings[String_number] = newIdentifier(QStringLiteral("number")); jsStrings[String_string] = newIdentifier(QStringLiteral("string")); + jsStrings[String_default] = newIdentifier(QStringLiteral("default")); jsStrings[String_symbol] = newIdentifier(QStringLiteral("symbol")); jsStrings[String_object] = newIdentifier(QStringLiteral("object")); jsStrings[String_function] = newIdentifier(QStringLiteral("function")); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 9206fdc0bb..155383c55d 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -304,6 +304,7 @@ public: String_boolean, String_number, String_string, + String_default, String_symbol, String_object, String_function, @@ -365,6 +366,7 @@ public: String *id_boolean() const { return reinterpret_cast<String *>(jsStrings + String_boolean); } String *id_number() const { return reinterpret_cast<String *>(jsStrings + String_number); } String *id_string() const { return reinterpret_cast<String *>(jsStrings + String_string); } + String *id_default() const { return reinterpret_cast<String *>(jsStrings + String_default); } String *id_symbol() const { return reinterpret_cast<String *>(jsStrings + String_symbol); } String *id_object() const { return reinterpret_cast<String *>(jsStrings + String_object); } String *id_function() const { return reinterpret_cast<String *>(jsStrings + String_function); } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 6eff9c50db..3cc1943427 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -420,27 +420,59 @@ Heap::String *RuntimeHelpers::stringFromNumber(ExecutionEngine *engine, double n ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeHint) { - if (typeHint == PREFERREDTYPE_HINT) { - if (object->as<DateObject>()) - typeHint = STRING_HINT; - else - typeHint = NUMBER_HINT; + ExecutionEngine *engine = object->internalClass()->engine; + if (engine->hasException) + return Encode::undefined(); + + String *hint; + switch (typeHint) { + case STRING_HINT: + hint = engine->id_string(); + break; + case NUMBER_HINT: + hint = engine->id_number(); + break; + default: + hint = engine->id_default(); + break; } - ExecutionEngine *engine = object->internalClass()->engine; + Scope scope(engine); + ScopedFunctionObject toPrimitive(scope, object->get(engine->symbol_toPrimitive())); if (engine->hasException) return Encode::undefined(); + if (toPrimitive) { + ScopedValue result(scope, toPrimitive->call(object, hint, 1)); + if (engine->hasException) + return Encode::undefined(); + if (!result->isPrimitive()) + return engine->throwTypeError(); + return result->asReturnedValue(); + } + + if (hint == engine->id_default()) + hint = engine->id_number(); + return ordinaryToPrimitive(engine, object, hint); +} + + +ReturnedValue RuntimeHelpers::ordinaryToPrimitive(ExecutionEngine *engine, const Object *object, String *typeHint) +{ + Q_ASSERT(!engine->hasException); String *meth1 = engine->id_toString(); String *meth2 = engine->id_valueOf(); - if (typeHint == NUMBER_HINT) + if (typeHint->identifier() == engine->id_number()->identifier()) { qSwap(meth1, meth2); + } else { + Q_ASSERT(typeHint->identifier() == engine->id_string()->identifier()); + } Scope scope(engine); ScopedValue result(scope); - ScopedValue conv(scope, object->get(meth1)); + ScopedValue conv(scope, object->get(meth1)); if (FunctionObject *o = conv->as<FunctionObject>()) { result = o->call(object, nullptr, 0); if (result->isPrimitive()) @@ -461,7 +493,6 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH } - Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const Value &value) { Q_ASSERT(!value.isObject()); diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 3a26c23990..72af90d1dc 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -100,6 +100,7 @@ enum TypeHint { struct Q_QML_PRIVATE_EXPORT RuntimeHelpers { static ReturnedValue objectDefaultValue(const Object *object, int typeHint); static ReturnedValue toPrimitive(const Value &value, TypeHint typeHint); + static ReturnedValue ordinaryToPrimitive(ExecutionEngine *engine, const Object *object, String *typeHint); static double stringToNumber(const QString &s); static Heap::String *stringFromNumber(ExecutionEngine *engine, double number); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index d89d314942..bf07faca2a 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -398,13 +398,13 @@ static bool compareEqual(QV4::Value lhs, QV4::Value rhs) Heap::Base *r = rhs.m(); Q_ASSERT(l); Q_ASSERT(r); - if (l->internalClass->vtable->isString == r->internalClass->vtable->isString) + if (l->internalClass->vtable->isStringOrSymbol == r->internalClass->vtable->isStringOrSymbol) return static_cast<QV4::Managed &>(lhs).isEqualTo(&static_cast<QV4::Managed &>(rhs)); - if (l->internalClass->vtable->isString) { + if (l->internalClass->vtable->isStringOrSymbol) { rhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(rhs), PREFERREDTYPE_HINT)); break; } else { - Q_ASSERT(r->internalClass->vtable->isString); + Q_ASSERT(r->internalClass->vtable->isStringOrSymbol); lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT)); break; } @@ -419,8 +419,8 @@ static bool compareEqual(QV4::Value lhs, QV4::Value rhs) rhs = Primitive::fromDouble(rhs.int_32()); // fall through default: // double - if (lhs.m()->internalClass->vtable->isString) - return RuntimeHelpers::toNumber(lhs) == rhs.doubleValue(); + if (lhs.m()->internalClass->vtable->isStringOrSymbol) + return lhs.m()->internalClass->vtable->isString ? (RuntimeHelpers::toNumber(lhs) == rhs.doubleValue()) : false; else lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT)); } diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index 6724b90663..f5dbf20864 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -477,17 +477,12 @@ built-ins/Date/proto-from-ctor-realm-zero.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-default-first-invalid.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-default-first-non-callable.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-default-first-valid.js fails -built-ins/Date/prototype/Symbol.toPrimitive/hint-invalid.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-number-first-invalid.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-number-first-non-callable.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-number-first-valid.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-string-first-invalid.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-string-first-non-callable.js fails built-ins/Date/prototype/Symbol.toPrimitive/hint-string-first-valid.js fails -built-ins/Date/prototype/Symbol.toPrimitive/length.js fails -built-ins/Date/prototype/Symbol.toPrimitive/name.js fails -built-ins/Date/prototype/Symbol.toPrimitive/prop-desc.js fails -built-ins/Date/prototype/Symbol.toPrimitive/this-val-non-obj.js fails built-ins/Date/prototype/toDateString/format.js fails built-ins/Date/prototype/toDateString/invalid-date.js fails built-ins/Date/prototype/toString/format.js fails @@ -497,13 +492,6 @@ built-ins/Date/prototype/toUTCString/day-names.js fails built-ins/Date/prototype/toUTCString/format.js fails built-ins/Date/prototype/toUTCString/month-names.js fails built-ins/Date/subclassing.js fails -built-ins/Date/value-symbol-to-prim-invocation.js fails -built-ins/Date/value-symbol-to-prim-return-obj.js fails -built-ins/Date/value-symbol-to-prim-return-prim.js fails -built-ins/Date/value-to-primitive-call.js fails -built-ins/Date/value-to-primitive-result-faulty.js fails -built-ins/Date/value-to-primitive-result-non-string-prim.js fails -built-ins/Date/value-to-primitive-result-string.js fails built-ins/Error/proto-from-ctor-realm.js fails built-ins/Error/prototype/S15.11.4_A2.js fails built-ins/Function/call-bind-this-realm-undef.js fails @@ -1974,13 +1962,9 @@ built-ins/SharedArrayBuffer/zero-length.js fails built-ins/String/proto-from-ctor-realm.js fails built-ins/String/prototype/endsWith/return-abrupt-from-searchstring-regexp-test.js fails built-ins/String/prototype/includes/return-abrupt-from-searchstring-regexp-test.js fails -built-ins/String/prototype/indexOf/position-tointeger-errors.js fails built-ins/String/prototype/indexOf/position-tointeger-toprimitive.js fails -built-ins/String/prototype/indexOf/position-tointeger-wrapped-values.js fails built-ins/String/prototype/indexOf/position-tointeger.js fails -built-ins/String/prototype/indexOf/searchstring-tostring-errors.js fails built-ins/String/prototype/indexOf/searchstring-tostring-toprimitive.js fails -built-ins/String/prototype/indexOf/searchstring-tostring-wrapped-values.js fails built-ins/String/prototype/match/cstm-matcher-invocation.js fails built-ins/String/prototype/replace/cstm-replace-invocation.js fails built-ins/String/prototype/replace/this-value-not-obj-coercible.js fails @@ -2479,8 +2463,6 @@ built-ins/TypedArrays/ctors/object-arg/as-generator-iterable-returns.js fails built-ins/TypedArrays/ctors/object-arg/custom-proto-access-throws.js fails built-ins/TypedArrays/ctors/object-arg/iterator-not-callable-throws.js fails built-ins/TypedArrays/ctors/object-arg/proto-from-ctor-realm.js fails -built-ins/TypedArrays/ctors/object-arg/throws-setting-obj-to-primitive-typeerror.js fails -built-ins/TypedArrays/ctors/object-arg/throws-setting-obj-to-primitive.js fails built-ins/TypedArrays/ctors/object-arg/use-custom-proto-if-object.js fails built-ins/TypedArrays/ctors/object-arg/use-default-proto-if-custom-proto-is-not-object.js fails built-ins/TypedArrays/ctors/typedarray-arg/custom-proto-access-throws.js fails @@ -2764,13 +2746,7 @@ built-ins/eval/length-non-configurable.js fails built-ins/global/global-object.js fails built-ins/global/property-descriptor.js fails built-ins/isFinite/toprimitive-not-callable-throws.js fails -built-ins/isFinite/toprimitive-result-is-object-throws.js fails -built-ins/isFinite/toprimitive-result-is-symbol-throws.js fails -built-ins/isFinite/toprimitive-valid-result.js fails built-ins/isNaN/toprimitive-not-callable-throws.js fails -built-ins/isNaN/toprimitive-result-is-object-throws.js fails -built-ins/isNaN/toprimitive-result-is-symbol-throws.js fails -built-ins/isNaN/toprimitive-valid-result.js fails language/arguments-object/cls-decl-gen-meth-args-trailing-comma-multiple.js fails language/arguments-object/cls-decl-gen-meth-args-trailing-comma-null.js fails language/arguments-object/cls-decl-gen-meth-args-trailing-comma-single-args.js fails @@ -2901,11 +2877,6 @@ language/eval-code/indirect/var-env-global-lex-non-strict.js fails language/eval-code/indirect/var-env-var-init-global-exstng.js strictFails language/eval-code/indirect/var-env-var-init-global-new.js strictFails language/eval-code/indirect/var-env-var-non-strict.js strictFails -language/expressions/addition/coerce-symbol-to-prim-err.js fails -language/expressions/addition/coerce-symbol-to-prim-invocation.js fails -language/expressions/addition/coerce-symbol-to-prim-return-obj.js fails -language/expressions/addition/coerce-symbol-to-prim-return-prim.js fails -language/expressions/addition/get-symbol-to-prim-err.js fails language/expressions/array/spread-err-mult-err-expr-throws.js fails language/expressions/array/spread-err-mult-err-iter-get-value.js fails language/expressions/array/spread-err-mult-err-itr-get-call.js fails @@ -3996,10 +3967,6 @@ language/expressions/conditional/tco-cond.js strictFails language/expressions/conditional/tco-pos.js strictFails language/expressions/delete/11.4.1-5-a-28-s.js strictFails language/expressions/delete/super-property.js fails -language/expressions/equals/coerce-symbol-to-prim-invocation.js fails -language/expressions/equals/coerce-symbol-to-prim-return-obj.js fails -language/expressions/equals/coerce-symbol-to-prim-return-prim.js fails -language/expressions/equals/to-prim-hint.js fails language/expressions/exponentiation/applying-the-exp-operator_A7.js fails language/expressions/exponentiation/applying-the-exp-operator_A8.js fails language/expressions/function/arguments-with-arguments-fn.js sloppyFails |