1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qv4symbol_p.h>
5#include <qv4functionobject_p.h>
6#include <qv4identifiertable_p.h>
7
8using namespace QV4;
9
10DEFINE_OBJECT_VTABLE(SymbolCtor);
11DEFINE_MANAGED_VTABLE(Symbol);
12DEFINE_OBJECT_VTABLE(SymbolObject);
13
14void Heap::Symbol::init(const QString &s)
15{
16 Q_ASSERT(s.at(0) == QLatin1Char('@'));
17 QString desc(s);
18 StringOrSymbol::init(text: desc.data_ptr());
19 identifier = PropertyKey::fromStringOrSymbol(b: this);
20}
21
22void Heap::SymbolCtor::init(QV4::ExecutionContext *scope)
23{
24 Heap::FunctionObject::init(scope, QStringLiteral("Symbol"));
25}
26
27void Heap::SymbolObject::init(const QV4::Symbol *s)
28{
29 Object::init();
30 symbol.set(e: internalClass->engine, newVal: s->d());
31}
32
33ReturnedValue QV4::SymbolCtor::virtualCall(const QV4::FunctionObject *f, const QV4::Value *, const QV4::Value *argv, int argc)
34{
35 Scope scope(f);
36 QString desc = QChar::fromLatin1(c: '@');
37 if (argc && !argv[0].isUndefined()) {
38 ScopedString s(scope, argv[0].toString(e: scope.engine));
39 if (scope.hasException())
40 return Encode::undefined();
41 desc += s->toQString();
42 }
43 return Symbol::create(e: scope.engine, s: desc)->asReturnedValue();
44}
45
46ReturnedValue SymbolCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
47{
48 return f->engine()->throwTypeError(QStringLiteral("Symbol can't be used together with |new|."));
49}
50
51ReturnedValue SymbolCtor::method_for(const FunctionObject *f, const Value *, const Value *argv, int argc)
52{
53 Scope scope(f);
54 ScopedValue k(scope, argc ? argv[0] : Value::undefinedValue());
55 ScopedString key(scope, k->toString(e: scope.engine));
56 if (scope.hasException())
57 return Encode::undefined();
58 QString desc = QLatin1Char('@') + key->toQString();
59 return scope.engine->identifierTable->insertSymbol(s: desc)->asReturnedValue();
60}
61
62ReturnedValue SymbolCtor::method_keyFor(const FunctionObject *f, const Value *, const Value *argv, int argc)
63{
64 ExecutionEngine *e = f->engine();
65 if (!argc || !argv[0].isSymbol())
66 return e->throwTypeError(message: QLatin1String("Symbol.keyFor: Argument is not a symbol."));
67 const Symbol &arg = static_cast<const Symbol &>(argv[0]);
68 Heap::Symbol *s = e->identifierTable->symbolForId(i: arg.propertyKey());
69 Q_ASSERT(!s || s == arg.d());
70 if (s)
71 return e->newString(s: arg.toQString().mid(position: (1)))->asReturnedValue();
72 return Encode::undefined();
73}
74
75void SymbolPrototype::init(ExecutionEngine *engine, Object *ctor)
76{
77 Scope scope(engine);
78 ScopedValue v(scope);
79 ctor->defineReadonlyProperty(name: engine->id_prototype(), value: (v = this));
80 ctor->defineReadonlyConfigurableProperty(name: engine->id_length(), value: Value::fromInt32(i: 0));
81
82 ctor->defineDefaultProperty(QStringLiteral("for"), code: SymbolCtor::method_for, argumentCount: 1);
83 ctor->defineDefaultProperty(QStringLiteral("keyFor"), code: SymbolCtor::method_keyFor, argumentCount: 1);
84 ctor->defineReadonlyProperty(QStringLiteral("hasInstance"), value: *engine->symbol_hasInstance());
85 ctor->defineReadonlyProperty(QStringLiteral("isConcatSpreadable"), value: *engine->symbol_isConcatSpreadable());
86 ctor->defineReadonlyProperty(QStringLiteral("iterator"), value: *engine->symbol_iterator());
87 ctor->defineReadonlyProperty(QStringLiteral("match"), value: *engine->symbol_match());
88 ctor->defineReadonlyProperty(QStringLiteral("replace"), value: *engine->symbol_replace());
89 ctor->defineReadonlyProperty(QStringLiteral("search"), value: *engine->symbol_search());
90 ctor->defineReadonlyProperty(QStringLiteral("species"), value: *engine->symbol_species());
91 ctor->defineReadonlyProperty(QStringLiteral("split"), value: *engine->symbol_split());
92 ctor->defineReadonlyProperty(QStringLiteral("toPrimitive"), value: *engine->symbol_toPrimitive());
93 ctor->defineReadonlyProperty(QStringLiteral("toStringTag"), value: *engine->symbol_toStringTag());
94 ctor->defineReadonlyProperty(QStringLiteral("unscopables"), value: *engine->symbol_unscopables());
95
96 defineDefaultProperty(QStringLiteral("constructor"), value: (v = ctor));
97 defineDefaultProperty(QStringLiteral("toString"), code: method_toString);
98 defineDefaultProperty(QStringLiteral("valueOf"), code: method_valueOf);
99 defineDefaultProperty(name: engine->symbol_toPrimitive(), code: method_symbolToPrimitive, argumentCount: 1, attributes: Attr_ReadOnly_ButConfigurable);
100
101 v = engine->newString(QStringLiteral("Symbol"));
102 defineReadonlyConfigurableProperty(name: engine->symbol_toStringTag(), value: v);
103
104}
105
106ReturnedValue SymbolPrototype::method_toString(const FunctionObject *f, const Value *thisObject, const Value *, int)
107{
108 Scope scope(f);
109 Scoped<Symbol> s(scope, thisObject->as<Symbol>());
110 if (!s) {
111 if (const SymbolObject *o = thisObject->as<SymbolObject>())
112 s = o->d()->symbol;
113 else
114 return scope.engine->throwTypeError();
115 }
116 return scope.engine->newString(s: s->descriptiveString())->asReturnedValue();
117}
118
119ReturnedValue SymbolPrototype::method_valueOf(const FunctionObject *f, const Value *thisObject, const Value *, int)
120{
121 Scope scope(f);
122 Scoped<Symbol> s(scope, thisObject->as<Symbol>());
123 if (!s) {
124 if (const SymbolObject *o = thisObject->as<SymbolObject>())
125 s = o->d()->symbol;
126 else
127 return scope.engine->throwTypeError();
128 }
129 return s->asReturnedValue();
130}
131
132ReturnedValue SymbolPrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *, int)
133{
134 if (thisObject->isSymbol())
135 return thisObject->asReturnedValue();
136 if (const SymbolObject *o = thisObject->as<SymbolObject>())
137 return o->d()->symbol->asReturnedValue();
138 return f->engine()->throwTypeError();
139}
140
141Heap::Symbol *Symbol::create(ExecutionEngine *e, const QString &s)
142{
143 Q_ASSERT(s.at(0) == QLatin1Char('@'));
144 return e->memoryManager->alloc<Symbol>(args: s);
145}
146
147QString Symbol::descriptiveString() const
148{
149 return QLatin1String("Symbol(") + QStringView{toQString()}.mid(pos: 1) + QLatin1String(")");
150}
151

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