6#include <private/qv4argumentsobject_p.h>
7#include <private/qv4identifiertable_p.h>
8#include <private/qv4jscall_p.h>
9#include <private/qv4lookup_p.h>
10#include <private/qv4memberdata_p.h>
11#include <private/qv4mm_p.h>
12#include <private/qv4proxy_p.h>
13#include <private/qv4scopedvalue_p.h>
14#include <private/qv4stackframe_p.h>
15#include <private/qv4stringobject_p.h>
16#include <private/qv4symbol_p.h>
18#include <QtCore/qloggingcategory.h>
32 Heap::Object *
p =
d();
34 if (ic->numRedundantTransitions <
p->internalClass.get()->numRedundantTransitions) {
40 Scoped<InternalClass> newIC(scope, ic);
45 for (
uint i = 0;
i < ic->size; ++
i) {
51 p->internalClass.set(scope.
engine, ic);
52 const uint nInline =
p->vtable()->nInlineProperties;
54 if (ic->size > nInline)
57 p->memberData.set(scope.
engine,
nullptr);
59 const auto &memberValues = newMembers->d()->values;
60 for (
uint i = 0;
i < ic->size; ++
i)
66 p->internalClass.set(ic->engine, ic);
67 const uint nInline =
p->vtable()->nInlineProperties;
68 if (ic->size > nInline) {
69 const uint requiredSize = ic->size - nInline;
70 if ((
p->memberData ?
p->memberData->values.size : 0) < requiredSize) {
72 ic->engine, requiredSize,
p->memberData));
79 if (ic->engine->isInitialized && ic->isUsedAsProto())
80 ic->updateProtoUsage(
p);
86 p->value = *propertyData(
entry.index);
87 if (
entry.attributes.isAccessor())
88 p->set = *propertyData(
entry.setterIndex);
94 if (
entry.attributes.isAccessor())
98void Heap::Object::setUsedAsProto()
100 internalClass.set(internalClass->engine, internalClass->asProtoClass());
105 if (!
attrs.isAccessor())
106 return v.asReturnedValue();
114 *jsCallData.thisObject = *thisObject;
124 if (
attrs.isAccessor()) {
130 jsCallData.args[0] =
value;
131 *jsCallData.thisObject =
this;
132 setter->call(jsCallData);
138 if (!
attrs.isWritable())
150 defineDefaultProperty(
s,
value, attributes);
160 defineDefaultProperty(
s, function, attributes);
169 defineDefaultProperty(nameOrSymbol, function, attributes);
177 defineAccessorProperty(
s, getter, setter);
186 if (!
n.isEmpty() &&
n.at(0) ==
'@'_L1)
192 p->setGetter(
nullptr);
198 p->setSetter(
nullptr);
210 defineReadonlyProperty(
s,
value);
223 defineReadonlyConfigurableProperty(
s,
value);
231void Object::addSymbolSpecies()
236 p->setSetter(
nullptr);
242 Base::markObjects(
b, stack);
245 o->memberData->mark(stack);
247 o->arrayData->mark(stack);
248 uint nInline =
o->vtable()->nInlineProperties;
249 Value *
v =
reinterpret_cast<Value *
>(
o) +
o->vtable()->inlinePropertyOffset;
268void Object::setPrototypeUnchecked(
const Object *
p)
270 setInternalClass(internalClass()->changePrototype(
p ?
p->d() :
nullptr));
276 if (
id.isArrayIndex()) {
278 Heap::Object *
o =
d();
282 if (idx != UINT_MAX) {
284 return {
o->arrayData ,
o->arrayData->values.values + (
attrs->isAccessor() ? idx + SetterOffset : idx) };
287 if (
o->vtable()->type == Type_StringObject) {
288 if (
index <
static_cast<const Heap::StringObject *
>(
o)->length()) {
292 return {
reinterpret_cast<Heap::ArrayData *
>(0x1),
nullptr };
298 Heap::Object *
o =
d();
300 auto idx =
o->internalClass->findValueOrSetter(
id);
303 return o->writablePropertyData(idx.index);
310 return {
nullptr,
nullptr };
315 return static_cast<const Object *
>(
m)->internalGet(
id, receiver, hasProperty);
320 return static_cast<Object *
>(
m)->internalPut(
id,
value, receiver);
325 return static_cast<Object *
>(
m)->internalDeleteProperty(
id);
332 if (
o->arrayType() == Heap::ArrayData::Sparse) {
339 while (arrayNode !=
o->sparseEnd()) {
341 uint pidx = arrayNode->value;
343 const Property *
p =
reinterpret_cast<const Property *
>(sa->values.data() + pidx);
344 arrayNode = arrayNode->nextNode();
356 while (arrayIndex < o->
d()->arrayData->values.size) {
362 if (!val.isEmpty()) {
374 while (memberIndex < o->internalClass()->
size) {
377 if (!
n.isStringOrSymbol())
415 Heap::Object *
o =
d();
417 if (
id.isArrayIndex()) {
423 if (
o->arrayData &&
o->arrayData->getProperty(
index, pd, &
attrs)) {
434 return str.asReturnedValue();
443 auto idx =
o->internalClass->findValueOrGetter(
id);
470 if (scope.hasException())
474 if (
r &&
r->d() ==
d()) {
483 if (
id.isArrayIndex()) {
485 propertyIndex =
arrayData()->getValueOrSetter(
id.asArrayIndex(), &
attrs);
488 if (member.isValid()) {
489 attrs = member.attrs;
490 propertyIndex =
d()->writablePropertyData(member.index);
494 if (!propertyIndex.isNull() && !
attrs.isAccessor()) {
495 if (!
attrs.isWritable())
497 else if (
isArrayObject() &&
id == scope.engine->id_length()->propertyKey()) {
501 scope.engine->throwRangeError(
value);
508 propertyIndex.set(scope.engine,
value);
521 return p->put(
id,
value, receiver);
525 if (
attrs.isAccessor()) {
530 jsCallData.args[0] =
value;
531 *jsCallData.thisObject = *receiver;
533 return !scope.hasException();
537 if (!
attrs.isWritable())
541 attrs =
r->getOwnProperty(
id,
p);
544 if (
attrs.isAccessor() || !
attrs.isWritable())
547 if (!
r->isExtensible())
554 if (
id.isArrayIndex()) {
555 r->arraySet(
id.asArrayIndex(),
value);
564 return r->defineOwnProperty(
id,
p,
attrs);
573 if (
id.isArrayIndex()) {
576 if (scope.hasException())
579 Scoped<ArrayData> ad(scope,
arrayData());
580 if (!ad || ad->vtable()->del(
this,
index))
587 if (memberIdx.isValid()) {
588 if (memberIdx.attrs.isConfigurable()) {
609 cattrs = memberEntry->attributes;
616 if (
p->isSubset(
attrs, current, cattrs))
620 if (!cattrs.isConfigurable()) {
621 if (
attrs.isConfigurable())
623 if (
attrs.hasEnumerable() &&
attrs.isEnumerable() != cattrs.isEnumerable())
628 if (
attrs.isGeneric() || current->value.isEmpty())
632 if (cattrs.isData() !=
attrs.isData()) {
634 if (!cattrs.isConfigurable())
636 if (cattrs.isData()) {
639 cattrs.clearWritable();
646 current->setGetter(
nullptr);
647 current->setSetter(
nullptr);
651 cattrs.setWritable(
false);
658 }
else if (cattrs.isData() &&
attrs.isData()) {
659 if (!cattrs.isConfigurable() && !cattrs.isWritable()) {
660 if (
attrs.isWritable() || !current->value.sameValue(
p->value))
665 if (!cattrs.isConfigurable()) {
666 if (!
p->value.isEmpty() && current->value.rawValue() !=
p->value.rawValue())
668 if (!
p->set.isEmpty() && current->set.rawValue() !=
p->set.rawValue())
675 current->merge(cattrs,
p,
attrs);
694 (
other->arrayType() == Heap::ArrayData::Sparse &&
other->arrayData()->attrs)) {
702 }
else if (!
other->arrayData()) {
707 other->d()->arrayData->values.alloc,
false);
708 if (
other->arrayType() == Heap::ArrayData::Sparse) {
709 Heap::ArrayData *od =
other->d()->arrayData;
710 Heap::ArrayData *dd =
d()->arrayData;
713 Heap::ArrayData *dd =
d()->arrayData;
714 dd->values.size =
other->d()->arrayData->values.size;
715 dd->offset =
other->d()->arrayData->offset;
718 memcpy(
d()->
arrayData->values.values,
other->d()->arrayData->values.values,
other->d()->arrayData->values.alloc*
sizeof(
Value));
727 return v->toLength();
748 Heap::Object *
obj =
object->d();
750 if (
name.isArrayIndex()) {
756 auto index =
obj->internalClass->findValueOrGetter(
name);
757 if (
index.isValid()) {
759 uint nInline =
obj->vtable()->nInlineProperties;
760 if (
attrs.isData()) {
761 if (
index.index <
obj->vtable()->nInlineProperties) {
762 index.index +=
obj->vtable()->inlinePropertyOffset;
765 index.index -= nInline;
791 auto idx =
c->findValueOrSetter(
key);
797 }
else if (idx.attrs.isData() && idx.attrs.isWritable()) {
800 const auto nInline =
object->d()->vtable()->nInlineProperties;
801 if (idx.index < nInline) {
803 lookup->
objectLookup.offset = idx.index +
object->d()->vtable()->inlinePropertyOffset;
822 if (
object->internalClass() ==
c) {
827 idx =
object->internalClass()->findValueOrSetter(
key);
828 if (!idx.isValid() || idx.attrs.isAccessor()) {
866 if (
f->isBoundFunction()) {
880 return f->engine()->throwTypeError();
882 Heap::Object *
v = lhs->d();
894 else if (
o->d() ==
v)
910 o =
o->getPrototypeOf();
912 return o->hasProperty(
id);
921 if (
id.isArrayIndex()) {
923 if (
o->arrayData()) {
930 auto member =
o->internalClass()->find(
id);
931 if (member.isValid()) {
932 attrs = member.attributes;
934 p->value = *
o->propertyData(member.index);
935 if (
attrs.isAccessor())
936 p->set = *
o->propertyData(member.setterIndex);
950 if (
id.isArrayIndex()) {
955 if (
o->arrayData()) {
958 hasProperty = (index < static_cast<StringObject *>(
o)->length());
962 if (!
o->isExtensible())
967 pp->fullyPopulated(&
attrs);
980 Scoped<InternalClass> ic(scope,
o->internalClass());
981 auto memberIndex = ic->d()->find(
id);
983 if (!memberIndex.isValid()) {
984 if (!
o->isExtensible())
988 if (ic->d()->isLocked()) {
989 while (Heap::Object *prototype = ic->d()->prototype) {
990 ic = prototype->internalClass;
991 const auto entry = ic->d()->find(
id);
992 if (
entry.isValid()) {
993 if (
entry.attributes.isConfigurable())
1003 Scoped<StringOrSymbol>
name(scope,
id.asStringOrSymbol());
1011 return o->internalDefineOwnProperty(scope.
engine, UINT_MAX, &memberIndex,
p,
attrs);
1016 return m->d()->internalClass->isExtensible();
1023 o->setInternalClass(
o->internalClass()->nonExtensible());
1029 return m->internalClass()->prototype;
1038 Heap::Object *protod = proto ? proto->d() :
nullptr;
1039 if (current == protod)
1043 Heap::Object *
p = protod;
1047 if (
p->vtable()->getPrototypeOf != Object::staticVTable()->getPrototypeOf)
1062 if (newLen < oldLen) {
1070 if (newLen >= 0x100000)
1081 if (
arrayType() == Heap::ArrayData::Sparse)
1091 if (!spreadable->isUndefined())
1092 return spreadable->toBoolean();
1100 if (
vtable() == ProxyObject::staticVTable()) {
1103 if (!
p->d()->handler) {
1108 return o->isArray();
1117 return defaultConstructor;
1124 if (S->isNullOrUndefined())
1125 return defaultConstructor;
1127 if (!
f || !
f->isConstructor()) {
1165 a->arrayReserve(
len);
1167 for (
int ii = 0; ii <
len; ++ii)
1169 a->setArrayLengthUnchecked(
len);
1190 result.append(
v->toQStringNoThrow());
1200 if (
id.isArrayIndex()) {
1211 a->setArrayLengthUnchecked(
index + 1);
1222 a->getProperty(e, lp);
1227 bool succeeded =
true;
1230 uint l =
p->value.asArrayLength(&
ok);
1236 succeeded =
a->setArrayLength(l);
1238 if (
attrs.hasWritable() && !
attrs.isWritable()) {
qsizetype size() const noexcept
const_reference at(qsizetype i) const noexcept
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
employee setName("Richard Schmit")
Scoped< FunctionObject > ScopedFunctionObject
ReturnedValue checkedResult(QV4::ExecutionEngine *v4, ReturnedValue result)
Scoped< String > ScopedString
Scoped< StringOrSymbol > ScopedStringOrSymbol
@ Attr_ReadOnly_ButConfigurable
void setter(QUntypedPropertyData *d, const void *value)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
static QDBusError::ErrorType get(const char *name)
static struct AttrInfo attrs[]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
#define QStringLiteral(str)
#define DEFINE_OBJECT_VTABLE(classname)
QFuture< QSet< QChar > > set
[10]
args<< 1<< 2;QJSValue threeAgain=fun.call(args);QString fileName="helloworld.qs";QFile scriptFile(fileName);if(!scriptFile.open(QIODevice::ReadOnly)) QTextStream stream(&scriptFile);QString contents=stream.readAll();scriptFile.close();myEngine.evaluate(contents, fileName);myEngine.globalObject().setProperty("myNumber", 123);...QJSValue myNumberPlusOne=myEngine.evaluate("myNumber + 1");QJSValue result=myEngine.evaluate(...);if(result.isError()) qDebug()<< "Uncaught exception at line"<< result.property("lineNumber").toInt()<< ":"<< result.toString();QPushButton *button=new QPushButton;QJSValue scriptButton=myEngine.newQObject(button);myEngine.globalObject().setProperty("button", scriptButton);myEngine.evaluate("button.checkable = true");qDebug()<< scriptButton.property("checkable").toBool();scriptButton.property("show").call();QJSEngine engine;QObject *myQObject=new QObject();myQObject- setProperty)("dynamicProperty", 3)
static bool isNonStrictArgumentsObject(Managed *m)
static void realloc(Object *o, Type newType, uint alloc, bool enforceAttributes)
Heap::ArrayData::Type Type
QStringList toQStringList() const
static constexpr ReturnedValue undefined()
IdentifierTable * identifierTable
CppStackFrame * currentStackFrame
Symbol * symbol_isConcatSpreadable() const
FunctionObject * getSymbolSpecies() const
ReturnedValue throwRangeError(const Value &value)
String * id_length() const
String * id_constructor() const
Heap::String * newString(char16_t c)
Heap::String * newIdentifier(const QString &text)
Symbol * symbol_species() const
ReturnedValue throwTypeError()
WriteBarrier::HeapObjectWrapper< CompilationUnitRuntimeData, 1 > compilationUnit
static Heap::FunctionObject * createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount)
Pointer< InternalClass *, 0 > internalClass
IndexAndAttribute findValueOrSetter(const PropertyKey id)
static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry)
SharedInternalClassData< PropertyKey > nameMap
IndexAndAttribute findValueOrGetter(const PropertyKey id)
Q_REQUIRED_RESULT InternalClass * changePrototype(Heap::Object *proto)
bool isExtensible() const
Q_REQUIRED_RESULT InternalClass * changeMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry=nullptr)
static void removeMember(QV4::Object *object, PropertyKey identifier)
PropertyKey asPropertyKey(const Heap::String *str)
PropertyAttributes attributes
struct QV4::Lookup::@584::@591 objectLookup
void resolveProtoGetter(PropertyKey name, const Heap::Object *proto)
static bool setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
ReturnedValue(* getter)(Lookup *l, ExecutionEngine *engine, const Value &object)
static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
static bool setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
struct QV4::Lookup::@584::@596 insertionLookup
struct QV4::Lookup::@584::@597 indexedLookup
struct QV4::Lookup::@584::@592 protoLookup
static bool arrayLengthSetter(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
bool(* setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v)
static ReturnedValue getterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object)
static ReturnedValue getter0Inline(Lookup *l, ExecutionEngine *engine, const Value &object)
static bool setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
static ReturnedValue getter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object)
static ReturnedValue getterIndexed(Lookup *l, ExecutionEngine *engine, const Value &object)
Heap::InternalClass * internalClass() const
bool isArrayObject() const
ExecutionEngine * engine() const
static Heap::MemberData * allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old=nullptr)
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
const Value * propertyData(uint index) const
void arraySet(uint index, const Property *p, PropertyAttributes attributes=Attr_Data)
bool setArrayLength(uint newLen)
static ReturnedValue getValue(const Value *thisObject, const Value &v, PropertyAttributes attrs)
void copyArrayData(Object *other)
bool hasProperty(PropertyKey id) const
PropertyAttributes getOwnProperty(PropertyKey id, Property *p=nullptr) const
bool setProtoFromNewTarget(const Value *newTarget)
Heap::ArrayData * arrayData() const
ArrayData::Type arrayType() const
const FunctionObject * speciesConstructor(Scope &scope, const FunctionObject *defaultConstructor) const
void getProperty(const InternalClassEntry &entry, Property *p) const
const VTable * vtable() const
void setArrayAttributes(uint i, PropertyAttributes a)
bool isConcatSpreadable() const
bool setPrototypeOf(const Object *p)
void setArrayLengthUnchecked(uint l)
Heap::Object * getPrototypeOf() const
ReturnedValue get(StringOrSymbol *name, bool *hasProperty=nullptr, const Value *receiver=nullptr) const
static ReturnedValue checkedInstanceOf(ExecutionEngine *engine, const FunctionObject *typeObject, const Value &var)
static PropertyKey invalid()
static PropertyKey fromArrayIndex(uint idx)
void fullyPopulated(PropertyAttributes *attrs)
void copy(const Property *other, PropertyAttributes attrs)
SparseArrayNode * lowerBound(uint key)
const SparseArrayNode * begin() const
QV4_NEARLY_ALWAYS_INLINE constexpr quint32 value() const
PropertyKey propertyKey() const
static constexpr VTable::SetPrototypeOf virtualSetPrototypeOf
static constexpr VTable::DefineOwnProperty virtualDefineOwnProperty
static constexpr VTable::OwnPropertyKeys virtualOwnPropertyKeys
static constexpr VTable::GetOwnProperty virtualGetOwnProperty
static constexpr VTable::PreventExtensions virtualPreventExtensions
static constexpr VTable::GetPrototypeOf virtualGetPrototypeOf
static constexpr VTable::Get virtualGet
static constexpr VTable::Metacall virtualMetacall
static constexpr VTable::GetLength virtualGetLength
static constexpr VTable::InstanceOf virtualInstanceOf
static constexpr VTable::HasProperty virtualHasProperty
static constexpr VTable::ResolveLookupGetter virtualResolveLookupGetter
static constexpr VTable::ResolveLookupSetter virtualResolveLookupSetter
static constexpr VTable::IsExtensible virtualIsExtensible
ReturnedValue(* Call)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
GetOwnProperty getOwnProperty
void mark(MarkStack *markStack)
bool isFunctionObject() const
static constexpr Value undefinedValue()
QML_NEARLY_ALWAYS_INLINE Object * objectValue() const
static Value fromHeapObject(HeapBasePtr m)
static constexpr Value fromReturnedValue(ReturnedValue val)
QString toQString() const