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
44using namespace QV4;
45
46DEFINE_OBJECT_VTABLE(SymbolCtor);
47DEFINE_MANAGED_VTABLE(Symbol);
48DEFINE_OBJECT_VTABLE(SymbolObject);
49
50void Heap::Symbol::init(const QString &s)
51{
52 Q_ASSERT(s.at(0) == QLatin1Char('@'));
53 identifier = PropertyKey::fromStringOrSymbol(b: this);
54 QString desc(s);
55 text = desc.data_ptr();
56 text->ref.ref();
57}
58
59void Heap::SymbolCtor::init(QV4::ExecutionContext *scope)
60{
61 Heap::FunctionObject::init(scope, QStringLiteral("Symbol"));
62}
63
64void Heap::SymbolObject::init(const QV4::Symbol *s)
65{
66 Object::init();
67 symbol.set(e: internalClass->engine, newVal: s->d());
68}
69
70ReturnedValue 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(c: '@');
74 if (argc && !argv[0].isUndefined()) {
75 ScopedString s(scope, argv[0].toString(e: scope.engine));
76 if (scope.hasException())
77 return Encode::undefined();
78 desc += s->toQString();
79 }
80 return Symbol::create(e: scope.engine, s: desc)->asReturnedValue();
81}
82
83ReturnedValue 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
88ReturnedValue 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(e: scope.engine));
93 if (scope.hasException())
94 return Encode::undefined();
95 QString desc = QLatin1Char('@') + key->toQString();
96 return scope.engine->identifierTable->insertSymbol(s: desc)->asReturnedValue();
97}
98
99ReturnedValue 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(message: 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(i: arg.propertyKey());
106 Q_ASSERT(!s || s == arg.d());
107 if (s)
108 return e->newString(s: arg.toQString().mid(position: (1)))->asReturnedValue();
109 return Encode::undefined();
110}
111
112void SymbolPrototype::init(ExecutionEngine *engine, Object *ctor)
113{
114 Scope scope(engine);
115 ScopedValue v(scope);
116 ctor->defineReadonlyProperty(name: engine->id_prototype(), value: (v = this));
117 ctor->defineReadonlyConfigurableProperty(name: engine->id_length(), value: Value::fromInt32(i: 0));
118
119 ctor->defineDefaultProperty(QStringLiteral("for"), code: SymbolCtor::method_for, argumentCount: 1);
120 ctor->defineDefaultProperty(QStringLiteral("keyFor"), code: SymbolCtor::method_keyFor, argumentCount: 1);
121 ctor->defineReadonlyProperty(QStringLiteral("hasInstance"), value: *engine->symbol_hasInstance());
122 ctor->defineReadonlyProperty(QStringLiteral("isConcatSpreadable"), value: *engine->symbol_isConcatSpreadable());
123 ctor->defineReadonlyProperty(QStringLiteral("iterator"), value: *engine->symbol_iterator());
124 ctor->defineReadonlyProperty(QStringLiteral("match"), value: *engine->symbol_match());
125 ctor->defineReadonlyProperty(QStringLiteral("replace"), value: *engine->symbol_replace());
126 ctor->defineReadonlyProperty(QStringLiteral("search"), value: *engine->symbol_search());
127 ctor->defineReadonlyProperty(QStringLiteral("species"), value: *engine->symbol_species());
128 ctor->defineReadonlyProperty(QStringLiteral("split"), value: *engine->symbol_split());
129 ctor->defineReadonlyProperty(QStringLiteral("toPrimitive"), value: *engine->symbol_toPrimitive());
130 ctor->defineReadonlyProperty(QStringLiteral("toStringTag"), value: *engine->symbol_toStringTag());
131 ctor->defineReadonlyProperty(QStringLiteral("unscopables"), value: *engine->symbol_unscopables());
132
133 defineDefaultProperty(QStringLiteral("constructor"), value: (v = ctor));
134 defineDefaultProperty(QStringLiteral("toString"), code: method_toString);
135 defineDefaultProperty(QStringLiteral("valueOf"), code: method_valueOf);
136 defineDefaultProperty(name: engine->symbol_toPrimitive(), code: method_symbolToPrimitive, argumentCount: 1, attributes: Attr_ReadOnly_ButConfigurable);
137
138 v = engine->newString(QStringLiteral("Symbol"));
139 defineReadonlyConfigurableProperty(name: engine->symbol_toStringTag(), value: v);
140
141}
142
143ReturnedValue 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: s->descriptiveString())->asReturnedValue();
154}
155
156ReturnedValue 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
169ReturnedValue 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
178Heap::Symbol *Symbol::create(ExecutionEngine *e, const QString &s)
179{
180 Q_ASSERT(s.at(0) == QLatin1Char('@'));
181 return e->memoryManager->alloc<Symbol>(args: s);
182}
183
184QString Symbol::descriptiveString() const
185{
186 return QLatin1String("Symbol(") + toQString().midRef(position: 1) + QLatin1String(")");
187}
188

source code of qtdeclarative/src/qml/jsruntime/qv4symbol.cpp