aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp20
-rw-r--r--src/qml/jsruntime/qv4engine_p.h29
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h1
-rw-r--r--src/qml/jsruntime/qv4managed.cpp3
-rw-r--r--src/qml/jsruntime/qv4managed_p.h2
-rw-r--r--src/qml/jsruntime/qv4object.cpp27
-rw-r--r--src/qml/jsruntime/qv4object_p.h22
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp10
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp9
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h2
-rw-r--r--src/qml/jsruntime/qv4symbol.cpp70
-rw-r--r--src/qml/jsruntime/qv4symbol_p.h22
12 files changed, 171 insertions, 46 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 87ae0e09d7..22dc984b4a 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -194,6 +194,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
typedArrayPrototype = static_cast<Object *>(jsAlloca(NTypedArrayTypes));
typedArrayCtors = static_cast<FunctionObject *>(jsAlloca(NTypedArrayTypes));
jsStrings = jsAlloca(NJSStrings);
+ jsSymbols = jsAlloca(NJSSymbols);
// set up stack limits
jsStackLimit = jsStackBase + JSStackLimit/sizeof(Value);
@@ -264,6 +265,18 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
jsStrings[String_buffer] = newIdentifier(QStringLiteral("buffer"));
jsStrings[String_lastIndex] = newIdentifier(QStringLiteral("lastIndex"));
+ jsSymbols[Symbol_hasInstance] = Symbol::create(this, QStringLiteral("@Symbol.hasInstance"));
+ jsSymbols[Symbol_isConcatSpreadable] = Symbol::create(this, QStringLiteral("@Symbol.isConcatSpreadable"));
+ jsSymbols[Symbol_iterator] = Symbol::create(this, QStringLiteral("@Symbol.iterator"));
+ jsSymbols[Symbol_match] = Symbol::create(this, QStringLiteral("@Symbol.match"));
+ jsSymbols[Symbol_replace] = Symbol::create(this, QStringLiteral("@Symbol.replace"));
+ jsSymbols[Symbol_search] = Symbol::create(this, QStringLiteral("@Symbol.search"));
+ jsSymbols[Symbol_species] = Symbol::create(this, QStringLiteral("@Symbol.species"));
+ jsSymbols[Symbol_split] = Symbol::create(this, QStringLiteral("@Symbol.split"));
+ jsSymbols[Symbol_toPrimitive] = Symbol::create(this, QStringLiteral("@Symbol.toPrimitive"));
+ jsSymbols[Symbol_toStringTag] = Symbol::create(this, QStringLiteral("@Symbol.toStringTag"));
+ jsSymbols[Symbol_unscopables] = Symbol::create(this, QStringLiteral("@Symbol.unscopables"));
+
ic = newInternalClass(ArrayPrototype::staticVTable(), objectPrototype());
Q_ASSERT(ic->d()->prototype);
ic = ic->addMember(id_length()->identifier(), Attr_NotConfigurable|Attr_NotEnumerable);
@@ -289,6 +302,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
classes[Class_StringObject] = ic->changePrototype(stringPrototype()->d());
Q_ASSERT(classes[Class_StringObject]->find(id_length()->identifier()) == Heap::StringObject::LengthPropertyIndex);
+ classes[Class_SymbolObject] = newInternalClass(QV4::SymbolObject::staticVTable(), symbolPrototype());
+
jsObjects[NumberProto] = memoryManager->allocate<NumberPrototype>();
jsObjects[BooleanProto] = memoryManager->allocate<BooleanPrototype>();
jsObjects[DateProto] = memoryManager->allocate<DatePrototype>();
@@ -593,6 +608,11 @@ Heap::Object *ExecutionEngine::newStringObject(const String *string)
return memoryManager->allocate<StringObject>(string);
}
+Heap::Object *ExecutionEngine::newSymbolObject(const Symbol *symbol)
+{
+ return memoryManager->allocObject<SymbolObject>(classes[Class_SymbolObject], symbol);
+}
+
Heap::Object *ExecutionEngine::newNumberObject(double value)
{
return memoryManager->allocate<NumberObject>(value);
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 362d95b56a..30e589919c 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -312,6 +312,22 @@ public:
};
Value *jsStrings;
+ enum JSSymbols {
+ Symbol_hasInstance,
+ Symbol_isConcatSpreadable,
+ Symbol_iterator,
+ Symbol_match,
+ Symbol_replace,
+ Symbol_search,
+ Symbol_species,
+ Symbol_split,
+ Symbol_toPrimitive,
+ Symbol_toStringTag,
+ Symbol_unscopables,
+ NJSSymbols
+ };
+ Value *jsSymbols;
+
String *id_empty() const { return reinterpret_cast<String *>(jsStrings + String_Empty); }
String *id_undefined() const { return reinterpret_cast<String *>(jsStrings + String_undefined); }
String *id_null() const { return reinterpret_cast<String *>(jsStrings + String_null); }
@@ -350,6 +366,18 @@ public:
String *id_buffer() const { return reinterpret_cast<String *>(jsStrings + String_buffer); }
String *id_lastIndex() const { return reinterpret_cast<String *>(jsStrings + String_lastIndex); }
+ Symbol *symbol_hasInstance() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_hasInstance); }
+ Symbol *symbol_isConcatSpreadable() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_isConcatSpreadable); }
+ Symbol *symbol_iterator() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_iterator); }
+ Symbol *symbol_match() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_match); }
+ Symbol *symbol_replace() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_replace); }
+ Symbol *symbol_search() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_search); }
+ Symbol *symbol_species() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_species); }
+ Symbol *symbol_split() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_split); }
+ Symbol *symbol_toPrimitive() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toPrimitive); }
+ Symbol *symbol_toStringTag() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_toStringTag); }
+ Symbol *symbol_unscopables() const { return reinterpret_cast<Symbol *>(jsSymbols + Symbol_unscopables); }
+
#ifndef V4_BOOTSTRAP
QIntrusiveList<CompiledData::CompilationUnit, &CompiledData::CompilationUnit::nextCompilationUnit> compilationUnits;
#endif
@@ -416,6 +444,7 @@ public:
Heap::String *newIdentifier(const QString &text);
Heap::Object *newStringObject(const String *string);
+ Heap::Object *newSymbolObject(const Symbol *symbol);
Heap::Object *newNumberObject(double value);
Heap::Object *newBooleanObject(bool b);
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index 085e44a913..d1257b6248 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -101,6 +101,7 @@ struct Q_QML_EXPORT EngineBase {
Class_ArrayObject,
Class_FunctionObject,
Class_StringObject,
+ Class_SymbolObject,
Class_ScriptFunction,
Class_ObjectProto,
Class_RegExp,
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 6ed2a9d716..a2e9deb854 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -97,6 +97,9 @@ QString Managed::className() const
case Type_StringObject:
s = "String";
break;
+ case Type_SymbolObject:
+ s = "Symbol";
+ break;
case Type_DateObject:
s = "Date";
break;
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 7ef5fd4ab8..5a032ba401 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -188,6 +188,7 @@ public:
Type_BooleanObject,
Type_NumberObject,
Type_StringObject,
+ Type_SymbolObject,
Type_DateObject,
Type_RegExpObject,
Type_ErrorObject,
@@ -212,6 +213,7 @@ public:
bool isArrayObject() const { return d()->internalClass->vtable->type == Type_ArrayObject; }
bool isStringObject() const { return d()->internalClass->vtable->type == Type_StringObject; }
+ bool isSymbolObject() const { return d()->internalClass->vtable->type == Type_SymbolObject; }
QString className() const;
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index a896caaecb..261e99b168 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -156,7 +156,8 @@ void Object::defineDefaultProperty(const QString &name, const Value &value)
defineDefaultProperty(s, value);
}
-void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount)
+void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc),
+ int argumentCount, PropertyAttributes attributes)
{
ExecutionEngine *e = engine();
Scope scope(e);
@@ -164,17 +165,21 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(co
ExecutionContext *global = e->rootContext();
ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, s, code));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
- defineDefaultProperty(s, function);
+ defineDefaultProperty(s, function, attributes);
}
-void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount)
+void Object::defineDefaultProperty(StringOrSymbol *nameOrSymbol, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc),
+ int argumentCount, PropertyAttributes attributes)
{
ExecutionEngine *e = engine();
Scope scope(e);
ExecutionContext *global = e->rootContext();
+ ScopedString name(scope, nameOrSymbol);
+ if (!name)
+ name = e->newString(QChar::fromLatin1('[') + nameOrSymbol->toQString().midRef(1) + QChar::fromLatin1(']'));
ScopedFunctionObject function(scope, FunctionObject::createBuiltinFunction(global, name, code));
function->defineReadonlyConfigurableProperty(e->id_length(), Primitive::fromInt32(argumentCount));
- defineDefaultProperty(name, function);
+ defineDefaultProperty(nameOrSymbol, function, attributes);
}
void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
@@ -221,7 +226,7 @@ void Object::defineReadonlyConfigurableProperty(const QString &name, const Value
defineReadonlyConfigurableProperty(s, value);
}
-void Object::defineReadonlyConfigurableProperty(String *name, const Value &value)
+void Object::defineReadonlyConfigurableProperty(StringOrSymbol *name, const Value &value)
{
insertMember(name, value, Attr_ReadOnly_ButConfigurable);
}
@@ -261,7 +266,7 @@ void Object::insertMember(StringOrSymbol *s, const Property *p, PropertyAttribut
}
// Section 8.12.1
-void Object::getOwnProperty(String *name, PropertyAttributes *attrs, Property *p)
+void Object::getOwnProperty(StringOrSymbol *name, PropertyAttributes *attrs, Property *p)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -351,7 +356,7 @@ PropertyIndex Object::getValueOrSetter(uint index, PropertyAttributes *attrs)
return { nullptr, 0 };
}
-bool Object::hasProperty(String *name) const
+bool Object::hasProperty(StringOrSymbol *name) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -383,7 +388,7 @@ bool Object::hasProperty(uint index) const
return false;
}
-bool Object::hasOwnProperty(String *name) const
+bool Object::hasOwnProperty(StringOrSymbol *name) const
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -802,7 +807,7 @@ bool Object::internalDeleteIndexedProperty(uint index)
}
// Section 8.12.9
-bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionEngine *engine, StringOrSymbol *name, const Property *p, PropertyAttributes attrs)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -813,7 +818,7 @@ bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const
uint memberIndex;
- if (isArrayObject() && name->equals(engine->id_length())) {
+ if (isArrayObject() && name->identifier() == engine->id_length()->identifier()) {
Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length()->identifier()));
ScopedProperty lp(scope);
PropertyAttributes cattrs;
@@ -904,7 +909,7 @@ bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Prope
return __defineOwnProperty__(engine, index, nullptr, p, attrs);
}
-bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs)
{
// clause 5
if (attrs.isEmpty())
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 5d46e0e74b..2f8a73de68 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -240,20 +240,20 @@ struct Q_QML_EXPORT Object: Managed {
Heap::Object *prototype() const { return d()->prototype(); }
bool setPrototype(Object *proto);
- void getOwnProperty(String *name, PropertyAttributes *attrs, Property *p = nullptr);
+ void getOwnProperty(StringOrSymbol *name, PropertyAttributes *attrs, Property *p = nullptr);
void getOwnProperty(uint index, PropertyAttributes *attrs, Property *p = nullptr);
PropertyIndex getValueOrSetter(StringOrSymbol *name, PropertyAttributes *attrs);
PropertyIndex getValueOrSetter(uint index, PropertyAttributes *attrs);
- bool hasProperty(String *name) const;
+ bool hasProperty(StringOrSymbol *name) const;
bool hasProperty(uint index) const;
- bool hasOwnProperty(String *name) const;
+ bool hasOwnProperty(StringOrSymbol *name) const;
bool hasOwnProperty(uint index) const;
- bool __defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs);
- bool __defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs);
+ bool __defineOwnProperty__(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs);
+ bool __defineOwnProperty__(ExecutionEngine *engine, StringOrSymbol *name, const Property *p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
bool __defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs);
bool defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
@@ -271,12 +271,14 @@ struct Q_QML_EXPORT Object: Managed {
bool putValue(uint memberIndex, const Value &value);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
- void defineDefaultProperty(String *name, const Value &value) {
- insertMember(name, value, Attr_Data|Attr_NotEnumerable);
+ void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes = Attr_Data|Attr_NotEnumerable) {
+ insertMember(name, value, attributes);
}
void defineDefaultProperty(const QString &name, const Value &value);
- void defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount = 0);
- void defineDefaultProperty(String *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc), int argumentCount = 0);
+ void defineDefaultProperty(const QString &name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc),
+ int argumentCount = 0, PropertyAttributes attributes = Attr_Data|Attr_NotEnumerable);
+ void defineDefaultProperty(StringOrSymbol *name, ReturnedValue (*code)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc),
+ int argumentCount = 0, PropertyAttributes attributes = Attr_Data|Attr_NotEnumerable);
void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
ReturnedValue (*setter)(const FunctionObject *, const Value *, const Value *, int));
void defineAccessorProperty(String *name, ReturnedValue (*getter)(const FunctionObject *, const Value *, const Value *, int),
@@ -287,7 +289,7 @@ struct Q_QML_EXPORT Object: Managed {
/* Fixed: Writable: false, Enumerable: false, Configurable: true */
void defineReadonlyConfigurableProperty(const QString &name, const Value &value);
- void defineReadonlyConfigurableProperty(String *name, const Value &value);
+ void defineReadonlyConfigurableProperty(StringOrSymbol *name, const Value &value);
void insertMember(StringOrSymbol *s, const Value &v, PropertyAttributes attributes = Attr_Data) {
Scope scope(engine());
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 94917a45f6..1cf6ff4ed8 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -154,7 +154,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(const FunctionObj
static_cast<ArgumentsObject *>(O.getPointer())->fullyCreate();
ScopedValue v(scope, argc > 1 ? argv[1] : Primitive::undefinedValue());
- ScopedString name(scope, v->toString(scope.engine));
+ ScopedStringOrSymbol name(scope, v->toStringOrSymbol(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
@@ -255,7 +255,7 @@ ReturnedValue ObjectPrototype::method_defineProperty(const FunctionObject *b, co
return scope.engine->throwTypeError();
ScopedObject O(scope, argv[0]);
- ScopedString name(scope, argc > 1 ? argv[1] : Primitive::undefinedValue(), ScopedString::Convert);
+ ScopedStringOrSymbol name(scope, (argc > 1 ? argv[1] : Primitive::undefinedValue()).toStringOrSymbol(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
@@ -287,7 +287,7 @@ ReturnedValue ObjectPrototype::method_defineProperties(const FunctionObject *b,
ScopedValue val(scope);
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
- ScopedString name(scope);
+ ScopedStringOrSymbol name(scope);
ScopedProperty pd(scope);
ScopedProperty n(scope);
while (1) {
@@ -518,7 +518,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);
- ScopedString P(scope, argc ? argv[0] : Primitive::undefinedValue(), ScopedString::Convert);
+ ScopedStringOrSymbol P(scope, (argc ? argv[0] : Primitive::undefinedValue()).toStringOrSymbol(scope.engine));
if (scope.engine->hasException)
return QV4::Encode::undefined();
ScopedObject O(scope, thisObject->toObject(scope.engine));
@@ -552,7 +552,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);
- ScopedString p(scope, argc ? argv[0] : Primitive::undefinedValue(), ScopedString::Convert);
+ ScopedStringOrSymbol p(scope, (argc ? argv[0] : Primitive::undefinedValue()).toStringOrSymbol(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 18e5f29c09..1237edcdc6 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -327,7 +327,7 @@ bool Runtime::method_deleteElement(ExecutionEngine *engine, const Value &base, c
return o->deleteIndexedProperty(n);
}
- ScopedString name(scope, index.toString(engine));
+ ScopedStringOrSymbol name(scope, index.toStringOrSymbol(engine));
return method_deleteMemberString(engine, base, name);
}
@@ -338,7 +338,7 @@ bool Runtime::method_deleteMember(ExecutionEngine *engine, const Value &base, in
return method_deleteMemberString(engine, base, name);
}
-bool Runtime::method_deleteMemberString(ExecutionEngine *engine, const Value &base, String *name)
+bool Runtime::method_deleteMemberString(ExecutionEngine *engine, const Value &base, StringOrSymbol *name)
{
Scope scope(engine);
ScopedObject obj(scope, base.toObject(engine));
@@ -371,7 +371,7 @@ QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left
if (!ro)
return engine->throwTypeError();
Scope scope(engine);
- ScopedString s(scope, left.toString(engine));
+ ScopedStringOrSymbol s(scope, left.toStringOrSymbol(engine));
if (scope.hasException())
return Encode::undefined();
bool r = ro->hasProperty(s);
@@ -463,8 +463,7 @@ Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const Val
case Value::Managed_Type:
Q_ASSERT(value.isStringOrSymbol());
if (!value.isString())
- // ### this is a symbol, which is an immutable object according to spec
- return nullptr;
+ return engine->newSymbolObject(value.symbolValue());
return engine->newStringObject(value.stringValue());
case Value::Integer_Type:
default: // double
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index a1a7bd9ed0..ac456283cb 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -119,7 +119,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
/* delete */ \
F(bool, deleteElement, (ExecutionEngine *engine, const Value &base, const Value &index)) \
F(bool, deleteMember, (ExecutionEngine *engine, const Value &base, int nameIndex)) \
- F(bool, deleteMemberString, (ExecutionEngine *engine, const Value &base, String *name)) \
+ F(bool, deleteMemberString, (ExecutionEngine *engine, const Value &base, StringOrSymbol *name)) \
F(bool, deleteName, (ExecutionEngine *engine, int nameIndex)) \
\
/* exceptions & scopes */ \
diff --git a/src/qml/jsruntime/qv4symbol.cpp b/src/qml/jsruntime/qv4symbol.cpp
index 86d727ba07..7bb33dce69 100644
--- a/src/qml/jsruntime/qv4symbol.cpp
+++ b/src/qml/jsruntime/qv4symbol.cpp
@@ -45,6 +45,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(SymbolCtor);
DEFINE_MANAGED_VTABLE(Symbol);
+DEFINE_OBJECT_VTABLE(SymbolObject);
void Heap::Symbol::init(const QString &s)
{
@@ -60,15 +61,22 @@ void Heap::SymbolCtor::init(QV4::ExecutionContext *scope)
Heap::FunctionObject::init(scope, QStringLiteral("Symbol"));
}
+void Heap::SymbolObject::init(const QV4::Symbol *s)
+{
+ Object::init();
+ symbol.set(internalClass->engine, s->d());
+}
+
ReturnedValue QV4::SymbolCtor::call(const QV4::FunctionObject *f, const QV4::Value *, const QV4::Value *argv, int argc)
{
Scope scope(f);
- ScopedString s(scope);
- if (argc)
- s = argv[0].toString(scope.engine);
- if (scope.hasException())
- return Encode::undefined();
- QString desc = QLatin1Char('@') + s->toQString();
+ QString desc = QChar::fromLatin1('@');
+ if (argc && !argv[0].isUndefined()) {
+ ScopedString s(scope, argv[0].toString(scope.engine));
+ if (scope.hasException())
+ return Encode::undefined();
+ desc += s->toQString();
+ }
return Symbol::create(scope.engine, desc)->asReturnedValue();
}
@@ -101,33 +109,67 @@ void SymbolPrototype::init(ExecutionEngine *engine, Object *ctor)
Scope scope(engine);
ScopedValue v(scope);
ctor->defineReadonlyProperty(engine->id_prototype(), (v = this));
+ ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0));
ctor->defineDefaultProperty(QStringLiteral("for"), SymbolCtor::method_for, 1);
ctor->defineDefaultProperty(QStringLiteral("keyFor"), SymbolCtor::method_keyFor, 1);
+ ctor->defineReadonlyProperty(QStringLiteral("hasInstance"), *engine->symbol_hasInstance());
+ ctor->defineReadonlyProperty(QStringLiteral("isConcatSpreadable"), *engine->symbol_isConcatSpreadable());
+ ctor->defineReadonlyProperty(QStringLiteral("iterator"), *engine->symbol_iterator());
+ ctor->defineReadonlyProperty(QStringLiteral("match"), *engine->symbol_match());
+ ctor->defineReadonlyProperty(QStringLiteral("replace"), *engine->symbol_replace());
+ ctor->defineReadonlyProperty(QStringLiteral("search"), *engine->symbol_search());
+ ctor->defineReadonlyProperty(QStringLiteral("species"), *engine->symbol_species());
+ ctor->defineReadonlyProperty(QStringLiteral("split"), *engine->symbol_split());
+ ctor->defineReadonlyProperty(QStringLiteral("toPrimitive"), *engine->symbol_toPrimitive());
+ ctor->defineReadonlyProperty(QStringLiteral("toStringTag"), *engine->symbol_toStringTag());
+ ctor->defineReadonlyProperty(QStringLiteral("unscopables"), *engine->symbol_unscopables());
+ defineDefaultProperty(QStringLiteral("constructor"), (v = ctor));
defineDefaultProperty(QStringLiteral("toString"), method_toString);
defineDefaultProperty(QStringLiteral("valueOf"), method_valueOf);
+ defineDefaultProperty(engine->symbol_toPrimitive(), method_symbolToPrimitive, 1, Attr_ReadOnly_ButConfigurable);
+
+ v = engine->newString(QStringLiteral("Symbol"));
+ defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), v);
+
}
ReturnedValue SymbolPrototype::method_toString(const FunctionObject *f, const Value *thisObject, const Value *, int)
{
- ExecutionEngine *e = f->engine();
- const Symbol *s = thisObject->as<Symbol>();
- if (!s)
- return e->throwTypeError();
- return e->newString(s->descriptiveString())->asReturnedValue();
+ Scope scope(f);
+ Scoped<Symbol> s(scope, thisObject->as<Symbol>());
+ if (!s) {
+ if (const SymbolObject *o = thisObject->as<SymbolObject>())
+ s = o->d()->symbol;
+ else
+ return scope.engine->throwTypeError();
+ }
+ return scope.engine->newString(s->descriptiveString())->asReturnedValue();
}
ReturnedValue SymbolPrototype::method_valueOf(const FunctionObject *f, const Value *thisObject, const Value *, int)
{
- const Symbol *s = thisObject->as<Symbol>();
+ Scope scope(f);
+ Scoped<Symbol> s(scope, thisObject->as<Symbol>());
if (!s) {
- ExecutionEngine *e = f->engine();
- return e->throwTypeError();
+ if (const SymbolObject *o = thisObject->as<SymbolObject>())
+ s = o->d()->symbol;
+ else
+ return scope.engine->throwTypeError();
}
return s->asReturnedValue();
}
+ReturnedValue SymbolPrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *, int)
+{
+ if (thisObject->isSymbol())
+ return thisObject->asReturnedValue();
+ if (const SymbolObject *o = thisObject->as<SymbolObject>())
+ return o->d()->symbol->asReturnedValue();
+ return f->engine()->throwTypeError();
+}
+
Heap::Symbol *Symbol::create(ExecutionEngine *e, const QString &s)
{
Q_ASSERT(s.at(0) == QLatin1Char('@'));
diff --git a/src/qml/jsruntime/qv4symbol_p.h b/src/qml/jsruntime/qv4symbol_p.h
index 6ff60d22db..3cf6bc5dde 100644
--- a/src/qml/jsruntime/qv4symbol_p.h
+++ b/src/qml/jsruntime/qv4symbol_p.h
@@ -68,6 +68,14 @@ struct Symbol : StringOrSymbol {
void init(const QString &s);
};
+#define SymbolObjectMembers(class, Member) \
+ Member(class, Pointer, Symbol *, symbol)
+
+DECLARE_HEAP_OBJECT(SymbolObject, Object) {
+ DECLARE_MARKOBJECTS(SymbolObject);
+ void init(const QV4::Symbol *s);
+};
+
}
struct SymbolCtor : FunctionObject
@@ -86,6 +94,8 @@ struct SymbolPrototype : Object
static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_valueOf(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+
+ static ReturnedValue method_symbolToPrimitive(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
};
struct Symbol : StringOrSymbol
@@ -100,6 +110,18 @@ struct Symbol : StringOrSymbol
QString descriptiveString() const;
};
+struct SymbolObject : Object
+{
+ V4_OBJECT2(SymbolObject, Object)
+ Q_MANAGED_TYPE(SymbolObject)
+ V4_INTERNALCLASS(SymbolObject)
+ V4_PROTOTYPE(symbolPrototype)
+
+ static bool put(Managed *, StringOrSymbol *, const Value &) { return false; }
+ static bool putIndexed(Managed *, uint, const Value &) { return false; }
+
+};
+
}
QT_END_NAMESPACE