aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-05-30 14:55:34 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-04 13:02:28 +0000
commit502678a183e68a837a5b2ddee2978a3be5e9e008 (patch)
treeacfd88d08ce3c9f3dc1f6867d136e0dcd14fdee0
parent9a0a074452c6534f25a878047398eea77a8c7e0e (diff)
Implement ToPropertyKey() from the ES7 spec
and use it where required. Change-Id: I309ca61e0360b26428fc2ea5a2eea47c8e0632a0 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp8
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp14
-rw-r--r--src/qml/jsruntime/qv4value.cpp11
-rw-r--r--src/qml/jsruntime/qv4value_p.h7
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations6
5 files changed, 26 insertions, 20 deletions
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 478e2e5915..fa9cae970d 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -163,7 +163,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(const FunctionObj
static_cast<ArgumentsObject *>(O.getPointer())->fullyCreate();
ScopedValue v(scope, argc > 1 ? argv[1] : Primitive::undefinedValue());
- ScopedStringOrSymbol name(scope, v->toStringOrSymbol(scope.engine));
+ ScopedStringOrSymbol name(scope, v->toPropertyKey(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
@@ -284,7 +284,7 @@ ReturnedValue ObjectPrototype::method_defineProperty(const FunctionObject *b, co
return scope.engine->throwTypeError();
ScopedObject O(scope, argv[0]);
- ScopedStringOrSymbol name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toStringOrSymbol(scope.engine));
+ ScopedStringOrSymbol name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toPropertyKey(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
@@ -584,7 +584,7 @@ ReturnedValue ObjectPrototype::method_valueOf(const FunctionObject *b, const Val
ReturnedValue ObjectPrototype::method_hasOwnProperty(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
- ScopedStringOrSymbol P(scope, (argc ? argv[0] : Primitive::undefinedValue()).toStringOrSymbol(scope.engine));
+ ScopedStringOrSymbol P(scope, (argc ? argv[0] : Primitive::undefinedValue()).toPropertyKey(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
ScopedObject O(scope, thisObject->toObject(scope.engine));
@@ -618,7 +618,7 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(const FunctionObject *b, con
ReturnedValue ObjectPrototype::method_propertyIsEnumerable(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
{
Scope scope(b);
- ScopedStringOrSymbol p(scope, (argc ? argv[0] : Primitive::undefinedValue()).toStringOrSymbol(scope.engine));
+ ScopedStringOrSymbol p(scope, (argc ? argv[0] : Primitive::undefinedValue()).toPropertyKey(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 477ecb37e9..b712b40897 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -331,7 +331,9 @@ bool Runtime::method_deleteElement(ExecutionEngine *engine, const Value &base, c
return o->deleteIndexedProperty(n);
}
- ScopedStringOrSymbol name(scope, index.toStringOrSymbol(engine));
+ ScopedStringOrSymbol name(scope, index.toPropertyKey(engine));
+ if (engine->hasException)
+ return false;
return method_deleteMemberString(engine, base, name);
}
@@ -383,7 +385,7 @@ QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left
if (!ro)
return engine->throwTypeError();
Scope scope(engine);
- ScopedStringOrSymbol s(scope, left.toStringOrSymbol(engine));
+ ScopedStringOrSymbol s(scope, left.toPropertyKey(engine));
if (scope.hasException())
return Encode::undefined();
bool r = ro->hasProperty(s);
@@ -647,7 +649,7 @@ static Q_NEVER_INLINE ReturnedValue getElementFallback(ExecutionEngine *engine,
Q_ASSERT(!!o); // can't fail as null/undefined is covered above
}
- ScopedStringOrSymbol name(scope, index.toStringOrSymbol(engine));
+ ScopedStringOrSymbol name(scope, index.toPropertyKey(engine));
if (scope.hasException())
return Encode::undefined();
return o->get(name);
@@ -701,7 +703,9 @@ static Q_NEVER_INLINE bool setElementFallback(ExecutionEngine *engine, const Val
return o->putIndexed(idx, value);
}
- ScopedStringOrSymbol name(scope, index.toStringOrSymbol(engine));
+ ScopedStringOrSymbol name(scope, index.toPropertyKey(engine));
+ if (engine->hasException)
+ return false;
return o->put(name, value);
}
@@ -1213,7 +1217,7 @@ ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base,
ScopedValue thisObject(scope, base->toObject(engine));
base = thisObject;
- ScopedStringOrSymbol str(scope, index.toStringOrSymbol(engine));
+ ScopedStringOrSymbol str(scope, index.toPropertyKey(engine));
if (engine->hasException)
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index be406db325..9febd41a00 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -228,6 +228,17 @@ QString Value::toQString() const
}
} // switch
}
+
+Heap::StringOrSymbol *Value::toPropertyKey(ExecutionEngine *e) const
+{
+ Scope scope(e);
+ ScopedValue v(scope, RuntimeHelpers::toPrimitive(*this, STRING_HINT));
+ if (!v->isStringOrSymbol())
+ v = v->toString(e);
+ if (e->hasException)
+ return nullptr;
+ return static_cast<Heap::StringOrSymbol *>(v->m());
+}
#endif // V4_BOOTSTRAP
bool Value::sameValue(Value other) const {
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index af956e84e1..59a8adca8f 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -415,11 +415,8 @@ public:
return reinterpret_cast<Heap::String *>(m());
return toString(e, *this);
}
- Heap::StringOrSymbol *toStringOrSymbol(ExecutionEngine *e) const {
- if (isStringOrSymbol())
- return reinterpret_cast<Heap::StringOrSymbol *>(m());
- return reinterpret_cast<Heap::StringOrSymbol *>(toString(e, *this));
- }
+ Heap::StringOrSymbol *toPropertyKey(ExecutionEngine *e) const;
+
static Heap::String *toString(ExecutionEngine *e, Value val);
Heap::Object *toObject(ExecutionEngine *e) const {
if (isObject())
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 45d05dcf0c..0c27620fcc 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -707,12 +707,6 @@ built-ins/Object/keys/proxy-keys.js fails
built-ins/Object/preventExtensions/15.2.3.10-1-1.js fails
built-ins/Object/preventExtensions/15.2.3.10-1-2.js fails
built-ins/Object/proto-from-ctor.js fails
-built-ins/Object/prototype/hasOwnProperty/symbol_property_toPrimitive.js fails
-built-ins/Object/prototype/hasOwnProperty/symbol_property_toString.js fails
-built-ins/Object/prototype/hasOwnProperty/symbol_property_valueOf.js fails
-built-ins/Object/prototype/propertyIsEnumerable/symbol_property_toPrimitive.js fails
-built-ins/Object/prototype/propertyIsEnumerable/symbol_property_toString.js fails
-built-ins/Object/prototype/propertyIsEnumerable/symbol_property_valueOf.js fails
built-ins/Object/prototype/setPrototypeOf-with-different-values.js fails
built-ins/Object/prototype/setPrototypeOf-with-same-value.js fails
built-ins/Object/prototype/toLocaleString/primitive_this_value_getter.js strictFails