diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 20 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 29 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4enginebase_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed.cpp | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 27 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 22 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4objectproto.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtimeapi_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4symbol.cpp | 70 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4symbol_p.h | 22 |
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 |