ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine) { Object *o = engine->globalObject(); PropertyAttributes attrs; ReturnedValue v = l->lookup(o, &attrs); if (v != Primitive::emptyValue().asReturnedValue()) { if (attrs.isData()) { if (l->level == 0) l->globalGetter = globalGetter0; else if (l->level == 1) l->globalGetter = globalGetter1; else if (l->level == 2) l->globalGetter = globalGetter2; return v; } else { if (l->level == 0) l->globalGetter = globalGetterAccessor0; else if (l->level == 1) l->globalGetter = globalGetterAccessor1; else if (l->level == 2) l->globalGetter = globalGetterAccessor2; return v; } } Scope scope(engine); ScopedString n(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]); return engine->throwReferenceError(n); }
ReturnedValue Object::getLookup(Managed *m, Lookup *l) { Object *o = static_cast<Object *>(m); PropertyAttributes attrs; ReturnedValue v = l->lookup(o, &attrs); if (v != Primitive::emptyValue().asReturnedValue()) { if (attrs.isData()) { if (l->level == 0) l->getter = Lookup::getter0; else if (l->level == 1) l->getter = Lookup::getter1; else if (l->level == 2) l->getter = Lookup::getter2; else l->getter = Lookup::getterFallback; return v; } else { if (l->level == 0) l->getter = Lookup::getterAccessor0; else if (l->level == 1) l->getter = Lookup::getterAccessor1; else if (l->level == 2) l->getter = Lookup::getterAccessor2; else l->getter = Lookup::getterFallback; return v; } } return Encode::undefined(); }
ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object) { if (Object *o = object.asObject()) return o->getLookup(l); Object *proto; switch (object.type()) { case Value::Undefined_Type: case Value::Null_Type: return engine->throwTypeError(); case Value::Boolean_Type: proto = engine->booleanPrototype.asObject(); break; case Value::Managed_Type: { Q_ASSERT(object.isString()); proto = engine->stringPrototype.asObject(); Scope scope(engine); ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]); if (name->equals(engine->id_length)) { // special case, as the property is on the object itself l->getter = stringLengthGetter; return stringLengthGetter(l, engine, object); } break; } case Value::Integer_Type: default: // Number proto = engine->numberPrototype.asObject(); } PropertyAttributes attrs; ReturnedValue v = l->lookup(object, proto, &attrs); if (v != Primitive::emptyValue().asReturnedValue()) { l->type = object.type(); l->proto = proto; if (attrs.isData()) { if (l->level == 0) l->getter = Lookup::primitiveGetter0; else if (l->level == 1) l->getter = Lookup::primitiveGetter1; return v; } else { if (l->level == 0) l->getter = Lookup::primitiveGetterAccessor0; else if (l->level == 1) l->getter = Lookup::primitiveGetterAccessor1; return v; } } return Encode::undefined(); }
ReturnedValue Object::getLookup(const Managed *m, Lookup *l) { const Object *o = static_cast<const Object *>(m); PropertyAttributes attrs; ReturnedValue v = l->lookup(o, &attrs); if (v != Primitive::emptyValue().asReturnedValue()) { l->proto = l->classList[0]->prototype; if (attrs.isData()) { Q_ASSERT(l->classList[0] == o->internalClass()); if (l->level == 0) { uint nInline = o->d()->vtable()->nInlineProperties; if (l->index < nInline) l->getter = Lookup::getter0Inline; else { l->index -= nInline; l->getter = Lookup::getter0MemberData; } } else if (l->level == 1) l->getter = Lookup::getter1; else if (l->level == 2) l->getter = Lookup::getter2; else l->getter = Lookup::getterFallback; return v; } else { if (l->level == 0) l->getter = Lookup::getterAccessor0; else if (l->level == 1) l->getter = Lookup::getterAccessor1; else if (l->level == 2) l->getter = Lookup::getterAccessor2; else l->getter = Lookup::getterFallback; return v; } } return Encode::undefined(); }
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; }