bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs) { // clause 5 if (attrs.isEmpty()) return true; Scope scope(engine); ScopedProperty current(scope); PropertyAttributes cattrs; if (member) { getProperty(index, current, &cattrs); cattrs = internalClass()->propertyData[index]; } else if (arrayData()) { arrayData()->getProperty(index, current, &cattrs); cattrs = arrayData()->attributes(index); } // clause 6 if (p->isSubset(attrs, current, cattrs)) return true; // clause 7 if (!cattrs.isConfigurable()) { if (attrs.isConfigurable()) goto reject; if (attrs.hasEnumerable() && attrs.isEnumerable() != cattrs.isEnumerable()) goto reject; } // clause 8 if (attrs.isGeneric() || current->value.isEmpty()) goto accept; // clause 9 if (cattrs.isData() != attrs.isData()) { // 9a if (!cattrs.isConfigurable()) goto reject; if (cattrs.isData()) { // 9b cattrs.setType(PropertyAttributes::Accessor); cattrs.clearWritable(); if (!member) { // need to convert the array and the slot initSparseArray(); Q_ASSERT(arrayData()); setArrayAttributes(index, cattrs); } current->setGetter(0); current->setSetter(0); } else { // 9c cattrs.setType(PropertyAttributes::Data); cattrs.setWritable(false); if (!member) { // need to convert the array and the slot setArrayAttributes(index, cattrs); } current->value = Primitive::undefinedValue(); } } else if (cattrs.isData() && attrs.isData()) { // clause 10 if (!cattrs.isConfigurable() && !cattrs.isWritable()) { if (attrs.isWritable() || !current->value.sameValue(p->value)) goto reject; } } else { // clause 10 Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor()); if (!cattrs.isConfigurable()) { if (!p->value.isEmpty() && current->value.rawValue() != p->value.rawValue()) goto reject; if (!p->set.isEmpty() && current->set.rawValue() != p->set.rawValue()) goto reject; } } accept: current->merge(cattrs, p, attrs); if (member) { InternalClass::changeMember(this, member, cattrs); setProperty(index, current); } else { setArrayAttributes(index, cattrs); arrayData()->setProperty(scope.engine, index, current); } return true; reject: if (engine->current->strictMode) engine->throwTypeError(); return false; }
bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs) { // clause 5 if (attrs.isEmpty()) return true; Property *current; PropertyAttributes cattrs; if (!member.isNull()) { current = propertyAt(index); cattrs = internalClass->propertyData[index]; } else { current = arrayData->getProperty(index); cattrs = arrayData->attributes(index); } // clause 6 if (p.isSubset(attrs, *current, cattrs)) return true; // clause 7 if (!cattrs.isConfigurable()) { if (attrs.isConfigurable()) goto reject; if (attrs.hasEnumerable() && attrs.isEnumerable() != cattrs.isEnumerable()) goto reject; } // clause 8 if (attrs.isGeneric() || current->value.isEmpty()) goto accept; // clause 9 if (cattrs.isData() != attrs.isData()) { // 9a if (!cattrs.isConfigurable()) goto reject; if (cattrs.isData()) { // 9b cattrs.setType(PropertyAttributes::Accessor); cattrs.clearWritable(); if (member.isNull()) { // need to convert the array and the slot initSparseArray(); setArrayAttributes(index, cattrs); current = arrayData->getProperty(index); } current->setGetter(0); current->setSetter(0); } else { // 9c cattrs.setType(PropertyAttributes::Data); cattrs.setWritable(false); if (member.isNull()) { // need to convert the array and the slot setArrayAttributes(index, cattrs); current = arrayData->getProperty(index); } current->value = Primitive::undefinedValue(); } } else if (cattrs.isData() && attrs.isData()) { // clause 10 if (!cattrs.isConfigurable() && !cattrs.isWritable()) { if (attrs.isWritable() || !current->value.sameValue(p.value)) goto reject; } } else { // clause 10 Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor()); if (!cattrs.isConfigurable()) { if (!p.value.isEmpty() && current->value.val != p.value.val) goto reject; if (!p.set.isEmpty() && current->set.val != p.set.val) goto reject; } } accept: current->merge(cattrs, p, attrs); if (!member.isNull()) { InternalClass::changeMember(this, member.getPointer(), cattrs); } else { setArrayAttributes(index, cattrs); } if (cattrs.isAccessor()) hasAccessorProperty = 1; return true; reject: if (ctx->strictMode) ctx->throwTypeError(); return false; }