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
56 QT_BEGIN_NAMESPACE
57
58 namespace QV4 {
59
60 struct FunctionObject;
61
62 struct Property {
63 Value value;
64 Value set;
65
66 // Section 8.10
fullyPopulatedProperty67 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
completedProperty82 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
getterProperty102 inline Heap::FunctionObject *getter() const { return reinterpret_cast<Heap::FunctionObject *>(value.heapObject()); }
setterProperty103 inline Heap::FunctionObject *setter() const { return reinterpret_cast<Heap::FunctionObject *>(set.heapObject()); }
setGetterProperty104 inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); }
setSetterProperty105 inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : nullptr); }
106
copyProperty107 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
isCompatibleProperty114 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
PropertyProperty147 explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(nullptr); }
PropertyProperty148 Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
149 value.setM(reinterpret_cast<Heap::Base *>(getter));
150 set.setM(reinterpret_cast<Heap::Base *>(setter));
151 }
152 private:
153 Q_DISABLE_COPY(Property)
154 };
155
isSubset(const PropertyAttributes & attrs,const Property * other,PropertyAttributes otherAttrs)156 inline 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
merge(PropertyAttributes & attrs,const Property * other,PropertyAttributes otherAttrs)177 inline 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
197 struct PropertyIndex {
198 Heap::Base *base;
199 Value *slot;
200
setPropertyIndex201 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; }
isNullPropertyIndex206 bool isNull() const { return !slot; }
207 };
208
209
210 }
211
212 Q_DECLARE_TYPEINFO(QV4::Property, Q_MOVABLE_TYPE);
213
214 QT_END_NAMESPACE
215
216 #endif
217