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 | |
20 | QT_BEGIN_NAMESPACE |
21 | |
22 | namespace QV4 { |
23 | |
24 | struct FunctionObject; |
25 | |
26 | struct 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 | } |
116 | private: |
117 | Q_DISABLE_COPY(Property) |
118 | }; |
119 | |
120 | inline 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 | |
141 | inline 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 | |
161 | struct 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 | |
176 | QT_END_NAMESPACE |
177 | |
178 | #endif |
179 | |