1// Copyright (C) 2016 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#ifndef QV4PROPERTYDESCRIPTOR_H
4#define QV4PROPERTYDESCRIPTOR_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include "qv4global_p.h"
18#include "qv4value_p.h"
19
20QT_BEGIN_NAMESPACE
21
22namespace QV4 {
23
24struct FunctionObject;
25
26struct Property {
27 Value value;
28 Value set;
29
30 // Section 8.10
31 inline void fullyPopulated(PropertyAttributes *attrs) {
32 if (!attrs->hasType()) {
33 value = Value::undefinedValue();
34 }
35 if (attrs->type() == PropertyAttributes::Accessor) {
36 attrs->clearWritable();
37 if (value.isEmpty())
38 value = Value::undefinedValue();
39 if (set.isEmpty())
40 set = Value::undefinedValue();
41 }
42 attrs->resolve();
43 }
44
45 // ES8: 6.2.5.6
46 void completed(PropertyAttributes *attrs) {
47 if (value.isEmpty())
48 value = Encode::undefined();
49 if (attrs->isGeneric() || attrs->isData()) {
50 attrs->setType(PropertyAttributes::Data);
51 if (!attrs->hasWritable())
52 attrs->setWritable(false);
53 } else {
54 if (set.isEmpty())
55 set = Encode::undefined();
56 }
57 if (!attrs->hasEnumerable())
58 attrs->setEnumerable(false);
59 if (!attrs->hasConfigurable())
60 attrs->setConfigurable(false);
61 }
62
63 inline bool isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const;
64 inline void merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs);
65
66 inline Heap::FunctionObject *getter() const { return reinterpret_cast<Heap::FunctionObject *>(value.heapObject()); }
67 inline Heap::FunctionObject *setter() const { return reinterpret_cast<Heap::FunctionObject *>(set.heapObject()); }
68 inline void setGetter(FunctionObject *g) { value = reinterpret_cast<Managed *>(g); }
69 inline void setSetter(FunctionObject *s) { set = (s ? reinterpret_cast<Managed *>(s) : nullptr); }
70
71 void copy(const Property *other, PropertyAttributes attrs) {
72 value = other->value;
73 if (attrs.isAccessor())
74 set = other->set;
75 }
76
77 // ES8, section 9.1.6.2/9,.1.6.3
78 bool isCompatible(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const {
79 if (otherAttrs.isEmpty())
80 return true;
81 if (!attrs.isConfigurable()) {
82 if (otherAttrs.hasConfigurable() && otherAttrs.isConfigurable())
83 return false;
84 if (otherAttrs.hasEnumerable() && otherAttrs.isEnumerable() != attrs.isEnumerable())
85 return false;
86 }
87 if (otherAttrs.isGeneric())
88 return true;
89 if (attrs.isData() != otherAttrs.isData()) {
90 if (!attrs.isConfigurable())
91 return false;
92 } else if (attrs.isData() && otherAttrs.isData()) {
93 if (!attrs.isConfigurable() && !attrs.isWritable()) {
94 if (otherAttrs.hasWritable() && otherAttrs.isWritable())
95 return false;
96 if (!other->value.isEmpty() && !value.sameValue(other: other->value))
97 return false;
98 }
99 } else if (attrs.isAccessor() && otherAttrs.isAccessor()) {
100 if (!attrs.isConfigurable()) {
101 if (!other->value.isEmpty() && !value.sameValue(other: other->value))
102 return false;
103 if (!other->set.isEmpty() && !set.sameValue(other: other->set))
104 return false;
105 }
106 }
107 return true;
108 }
109
110
111 explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(m: nullptr); }
112 Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
113 value.setM(reinterpret_cast<Heap::Base *>(getter));
114 set.setM(reinterpret_cast<Heap::Base *>(setter));
115 }
116private:
117 Q_DISABLE_COPY(Property)
118};
119
120inline bool Property::isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
121{
122 if (attrs.type() != PropertyAttributes::Generic && attrs.type() != otherAttrs.type())
123 return false;
124 if (attrs.hasEnumerable() && attrs.isEnumerable() != otherAttrs.isEnumerable())
125 return false;
126 if (attrs.hasConfigurable() && attrs.isConfigurable() != otherAttrs.isConfigurable())
127 return false;
128 if (attrs.hasWritable() && attrs.isWritable() != otherAttrs.isWritable())
129 return false;
130 if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other: other->value))
131 return false;
132 if (attrs.type() == PropertyAttributes::Accessor) {
133 if (value.heapObject() != other->value.heapObject())
134 return false;
135 if (set.heapObject() != other->set.heapObject())
136 return false;
137 }
138 return true;
139}
140
141inline void Property::merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs)
142{
143 if (otherAttrs.hasEnumerable())
144 attrs.setEnumerable(otherAttrs.isEnumerable());
145 if (otherAttrs.hasConfigurable())
146 attrs.setConfigurable(otherAttrs.isConfigurable());
147 if (otherAttrs.hasWritable())
148 attrs.setWritable(otherAttrs.isWritable());
149 if (otherAttrs.type() == PropertyAttributes::Accessor) {
150 attrs.setType(PropertyAttributes::Accessor);
151 if (!other->value.isEmpty())
152 value = other->value;
153 if (!other->set.isEmpty())
154 set = other->set;
155 } else if (otherAttrs.type() == PropertyAttributes::Data){
156 attrs.setType(PropertyAttributes::Data);
157 value = other->value;
158 }
159}
160
161struct PropertyIndex {
162 Heap::Base *base;
163 Value *slot;
164
165 void set(EngineBase *e, Value newVal) {
166 WriteBarrier::write(engine: e, base, slot: slot->data_ptr(), value: newVal.asReturnedValue());
167 }
168 const Value *operator->() const { return slot; }
169 const Value &operator*() const { return *slot; }
170 bool isNull() const { return !slot; }
171};
172
173
174}
175
176QT_END_NAMESPACE
177
178#endif
179

source code of qtdeclarative/src/qml/jsruntime/qv4property_p.h