1/****************************************************************************
2**
3** Copyright (C) 2016 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#ifndef QV4PROPERTYDESCRIPTOR_H
40#define QV4PROPERTYDESCRIPTOR_H
41
42//
43// W A R N I N G
44// -------------
45//
46// This file is not part of the Qt API. It exists purely as an
47// implementation detail. This header file may change from version to
48// version without notice, or even be removed.
49//
50// We mean it.
51//
52
53#include "qv4global_p.h"
54#include "qv4value_p.h"
55
56QT_BEGIN_NAMESPACE
57
58namespace QV4 {
59
60struct FunctionObject;
61
62struct Property {
63 Value value;
64 Value set;
65
66 // Section 8.10
67 inline void fullyPopulated(PropertyAttributes *attrs) {
68 if (!attrs->hasType()) {
69 value = Value::undefinedValue();
70 }
71 if (attrs->type() == PropertyAttributes::Accessor) {
72 attrs->clearWritable();
73 if (value.isEmpty())
74 value = Value::undefinedValue();
75 if (set.isEmpty())
76 set = Value::undefinedValue();
77 }
78 attrs->resolve();
79 }
80
81 // ES8: 6.2.5.6
82 void completed(PropertyAttributes *attrs) {
83 if (value.isEmpty())
84 value = Encode::undefined();
85 if (attrs->isGeneric() || attrs->isData()) {
86 attrs->setType(PropertyAttributes::Data);
87 if (!attrs->hasWritable())
88 attrs->setWritable(false);
89 } else {
90 if (set.isEmpty())
91 set = Encode::undefined();
92 }
93 if (!attrs->hasEnumerable())
94 attrs->setEnumerable(false);
95 if (!attrs->hasConfigurable())
96 attrs->setConfigurable(false);
97 }
98
99 inline bool isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const;
100 inline void merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs);
101
102 inline Heap::FunctionObject *getter() const { return reinterpret_cast<Heap::FunctionObject *>(value.heapObject()); }
103 inline Heap::FunctionObject *setter() const { return reinterpret_cast<Heap::FunctionObject *>(set.heapObject()); }
104 inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); }
105 inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : nullptr); }
106
107 void copy(const Property *other, PropertyAttributes attrs) {
108 value = other->value;
109 if (attrs.isAccessor())
110 set = other->set;
111 }
112
113 // ES8, section 9.1.6.2/9,.1.6.3
114 bool isCompatible(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const {
115 if (otherAttrs.isEmpty())
116 return true;
117 if (!attrs.isConfigurable()) {
118 if (otherAttrs.hasConfigurable() && otherAttrs.isConfigurable())
119 return false;
120 if (otherAttrs.hasEnumerable() && otherAttrs.isEnumerable() != attrs.isEnumerable())
121 return false;
122 }
123 if (otherAttrs.isGeneric())
124 return true;
125 if (attrs.isData() != otherAttrs.isData()) {
126 if (!attrs.isConfigurable())
127 return false;
128 } else if (attrs.isData() && otherAttrs.isData()) {
129 if (!attrs.isConfigurable() && !attrs.isWritable()) {
130 if (otherAttrs.hasWritable() && otherAttrs.isWritable())
131 return false;
132 if (!other->value.isEmpty() && !value.sameValue(other->value))
133 return false;
134 }
135 } else if (attrs.isAccessor() && otherAttrs.isAccessor()) {
136 if (!attrs.isConfigurable()) {
137 if (!other->value.isEmpty() && !value.sameValue(other->value))
138 return false;
139 if (!other->set.isEmpty() && !set.sameValue(other->set))
140 return false;
141 }
142 }
143 return true;
144 }
145
146
147 explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(nullptr); }
148 Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
149 value.setM(reinterpret_cast<Heap::Base *>(getter));
150 set.setM(reinterpret_cast<Heap::Base *>(setter));
151 }
152private:
153 Q_DISABLE_COPY(Property)
154};
155
156inline bool Property::isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
157{
158 if (attrs.type() != PropertyAttributes::Generic && attrs.type() != otherAttrs.type())
159 return false;
160 if (attrs.hasEnumerable() && attrs.isEnumerable() != otherAttrs.isEnumerable())
161 return false;
162 if (attrs.hasConfigurable() && attrs.isConfigurable() != otherAttrs.isConfigurable())
163 return false;
164 if (attrs.hasWritable() && attrs.isWritable() != otherAttrs.isWritable())
165 return false;
166 if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other->value))
167 return false;
168 if (attrs.type() == PropertyAttributes::Accessor) {
169 if (value.heapObject() != other->value.heapObject())
170 return false;
171 if (set.heapObject() != other->set.heapObject())
172 return false;
173 }
174 return true;
175}
176
177inline void Property::merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs)
178{
179 if (otherAttrs.hasEnumerable())
180 attrs.setEnumerable(otherAttrs.isEnumerable());
181 if (otherAttrs.hasConfigurable())
182 attrs.setConfigurable(otherAttrs.isConfigurable());
183 if (otherAttrs.hasWritable())
184 attrs.setWritable(otherAttrs.isWritable());
185 if (otherAttrs.type() == PropertyAttributes::Accessor) {
186 attrs.setType(PropertyAttributes::Accessor);
187 if (!other->value.isEmpty())
188 value = other->value;
189 if (!other->set.isEmpty())
190 set = other->set;
191 } else if (otherAttrs.type() == PropertyAttributes::Data){
192 attrs.setType(PropertyAttributes::Data);
193 value = other->value;
194 }
195}
196
197struct PropertyIndex {
198 Heap::Base *base;
199 Value *slot;
200
201 void set(EngineBase *e, Value newVal) {
202 WriteBarrier::write(e, base, slot->data_ptr(), newVal.asReturnedValue());
203 }
204 const Value *operator->() const { return slot; }
205 const Value &operator*() const { return *slot; }
206 bool isNull() const { return !slot; }
207};
208
209
210}
211
212Q_DECLARE_TYPEINFO(QV4::Property, Q_MOVABLE_TYPE);
213
214QT_END_NAMESPACE
215
216#endif
217