1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include <qv4symbol_p.h>
41 #include <qv4functionobject_p.h>
42 #include <qv4identifiertable_p.h>
43
44 using namespace QV4;
45
46 DEFINE_OBJECT_VTABLE(SymbolCtor);
47 DEFINE_MANAGED_VTABLE(Symbol);
48 DEFINE_OBJECT_VTABLE(SymbolObject);
49
init(const QString & s)50 void Heap::Symbol::init(const QString &s)
51 {
52 Q_ASSERT(s.at(0) == QLatin1Char('@'));
53 identifier = PropertyKey::fromStringOrSymbol(this);
54 QString desc(s);
55 text = desc.data_ptr();
56 text->ref.ref();
57 }
58
init(QV4::ExecutionContext * scope)59 void Heap::SymbolCtor::init(QV4::ExecutionContext *scope)
60 {
61 Heap::FunctionObject::init(scope, QStringLiteral("Symbol"));
62 }
63
init(const QV4::Symbol * s)64 void Heap::SymbolObject::init(const QV4::Symbol *s)
65 {
66 Object::init();
67 symbol.set(internalClass->engine, s->d());
68 }
69
virtualCall(const QV4::FunctionObject * f,const QV4::Value *,const QV4::Value * argv,int argc)70 ReturnedValue QV4::SymbolCtor::virtualCall(const QV4::FunctionObject *f, const QV4::Value *, const QV4::Value *argv, int argc)
71 {
72 Scope scope(f);
73 QString desc = QChar::fromLatin1('@');
74 if (argc && !argv[0].isUndefined()) {
75 ScopedString s(scope, argv[0].toString(scope.engine));
76 if (scope.hasException())
77 return Encode::undefined();
78 desc += s->toQString();
79 }
80 return Symbol::create(scope.engine, desc)->asReturnedValue();
81 }
82
virtualCallAsConstructor(const FunctionObject * f,const Value *,int,const Value *)83 ReturnedValue SymbolCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
84 {
85 return f->engine()->throwTypeError(QStringLiteral("Symbol can't be used together with |new|."));
86 }
87
method_for(const FunctionObject * f,const Value *,const Value * argv,int argc)88 ReturnedValue SymbolCtor::method_for(const FunctionObject *f, const Value *, const Value *argv, int argc)
89 {
90 Scope scope(f);
91 ScopedValue k(scope, argc ? argv[0]: Value::undefinedValue());
92 ScopedString key(scope, k->toString(scope.engine));
93 if (scope.hasException())
94 return Encode::undefined();
95 QString desc = QLatin1Char('@') + key->toQString();
96 return scope.engine->identifierTable->insertSymbol(desc)->asReturnedValue();
97 }
98
method_keyFor(const FunctionObject * f,const Value *,const Value * argv,int argc)99 ReturnedValue SymbolCtor::method_keyFor(const FunctionObject *f, const Value *, const Value *argv, int argc)
100 {
101 ExecutionEngine *e = f->engine();
102 if (!argc || !argv[0].isSymbol())
103 return e->throwTypeError(QLatin1String("Symbol.keyFor: Argument is not a symbol."));
104 const Symbol &arg = static_cast<const Symbol &>(argv[0]);
105 Heap::Symbol *s = e->identifierTable->symbolForId(arg.propertyKey());
106 Q_ASSERT(!s || s == arg.d());
107 if (s)
108 return e->newString(arg.toQString().mid((1)))->asReturnedValue();
109 return Encode::undefined();
110 }
111
init(ExecutionEngine * engine,Object * ctor)112 void SymbolPrototype::init(ExecutionEngine *engine, Object *ctor)
113 {
114 Scope scope(engine);
115 ScopedValue v(scope);
116 ctor->defineReadonlyProperty(engine->id_prototype(), (v = this));
117 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(0));
118
119 ctor->defineDefaultProperty(QStringLiteral("for"), SymbolCtor::method_for, 1);
120 ctor->defineDefaultProperty(QStringLiteral("keyFor"), SymbolCtor::method_keyFor, 1);
121 ctor->defineReadonlyProperty(QStringLiteral("hasInstance"), *engine->symbol_hasInstance());
122 ctor->defineReadonlyProperty(QStringLiteral("isConcatSpreadable"), *engine->symbol_isConcatSpreadable());
123 ctor->defineReadonlyProperty(QStringLiteral("iterator"), *engine->symbol_iterator());
124 ctor->defineReadonlyProperty(QStringLiteral("match"), *engine->symbol_match());
125 ctor->defineReadonlyProperty(QStringLiteral("replace"), *engine->symbol_replace());
126 ctor->defineReadonlyProperty(QStringLiteral("search"), *engine->symbol_search());
127 ctor->defineReadonlyProperty(QStringLiteral("species"), *engine->symbol_species());
128 ctor->defineReadonlyProperty(QStringLiteral("split"), *engine->symbol_split());
129 ctor->defineReadonlyProperty(QStringLiteral("toPrimitive"), *engine->symbol_toPrimitive());
130 ctor->defineReadonlyProperty(QStringLiteral("toStringTag"), *engine->symbol_toStringTag());
131 ctor->defineReadonlyProperty(QStringLiteral("unscopables"), *engine->symbol_unscopables());
132
133 defineDefaultProperty(QStringLiteral("constructor"), (v = ctor));
134 defineDefaultProperty(QStringLiteral("toString"), method_toString);
135 defineDefaultProperty(QStringLiteral("valueOf"), method_valueOf);
136 defineDefaultProperty(engine->symbol_toPrimitive(), method_symbolToPrimitive, 1, Attr_ReadOnly_ButConfigurable);
137
138 v = engine->newString(QStringLiteral("Symbol"));
139 defineReadonlyConfigurableProperty(engine->symbol_toStringTag(), v);
140
141 }
142
method_toString(const FunctionObject * f,const Value * thisObject,const Value *,int)143 ReturnedValue SymbolPrototype::method_toString(const FunctionObject *f, const Value *thisObject, const Value *, int)
144 {
145 Scope scope(f);
146 Scoped<Symbol> s(scope, thisObject->as<Symbol>());
147 if (!s) {
148 if (const SymbolObject *o = thisObject->as<SymbolObject>())
149 s = o->d()->symbol;
150 else
151 return scope.engine->throwTypeError();
152 }
153 return scope.engine->newString(s->descriptiveString())->asReturnedValue();
154 }
155
method_valueOf(const FunctionObject * f,const Value * thisObject,const Value *,int)156 ReturnedValue SymbolPrototype::method_valueOf(const FunctionObject *f, const Value *thisObject, const Value *, int)
157 {
158 Scope scope(f);
159 Scoped<Symbol> s(scope, thisObject->as<Symbol>());
160 if (!s) {
161 if (const SymbolObject *o = thisObject->as<SymbolObject>())
162 s = o->d()->symbol;
163 else
164 return scope.engine->throwTypeError();
165 }
166 return s->asReturnedValue();
167 }
168
method_symbolToPrimitive(const FunctionObject * f,const Value * thisObject,const Value *,int)169 ReturnedValue SymbolPrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *, int)
170 {
171 if (thisObject->isSymbol())
172 return thisObject->asReturnedValue();
173 if (const SymbolObject *o = thisObject->as<SymbolObject>())
174 return o->d()->symbol->asReturnedValue();
175 return f->engine()->throwTypeError();
176 }
177
create(ExecutionEngine * e,const QString & s)178 Heap::Symbol *Symbol::create(ExecutionEngine *e, const QString &s)
179 {
180 Q_ASSERT(s.at(0) == QLatin1Char('@'));
181 return e->memoryManager->alloc<Symbol>(s);
182 }
183
descriptiveString() const184 QString Symbol::descriptiveString() const
185 {
186 return QLatin1String("Symbol(") + toQString().midRef(1) + QLatin1String(")");
187 }
188