bool QScriptValueImpl::hasInstance(const QScriptValueImpl &value) const { Q_ASSERT(isObject()); if (QScriptClassData *odata = classInfo()->data()) { if (odata->implementsHasInstance(*this)) return odata->hasInstance(*this, value); } if (!isFunction()) return false; // [[HasInstance] for function objects if (!value.isObject()) return false; QScriptEnginePrivate *eng = engine(); QScriptValueImpl proto = property(eng->idTable()->id_prototype); if (!proto.isObject()) { QScriptContextPrivate *ctx = eng->currentContext(); ctx->throwTypeError(QLatin1String("instanceof: 'prototype' property is not an object")); return false; } QScriptObject *target = proto.m_object_value; QScriptValueImpl v = value; while (true) { v = v.prototype(); if (!v.isObject()) break; if (target == v.m_object_value) return true; } return false; }
/*! If this QScriptValue is an object, sets the internal prototype (\c{__proto__} property) of this object to be \a prototype; otherwise does nothing. The internal prototype should not be confused with the public property with name "prototype"; the public prototype is usually only set on functions that act as constructors. \sa prototype(), isObject() */ void QScriptValue::setPrototype(const QScriptValue &prototype) { if (!isObject()) return; if (prototype.isValid() && (prototype.engine() != engine())) { qWarning("QScriptValue::setPrototype() failed: " "cannot set a prototype created in " "a different engine"); return; } QScriptValueImpl self = QScriptValuePrivate::valueOf(*this); QScriptValueImpl was = self.prototype(); self.setPrototype(QScriptValuePrivate::valueOf(prototype)); if (self.detectedCycle()) { qWarning("QScriptValue::setPrototype() failed: " "cyclic prototype value"); self.setPrototype(was); } }
QScriptValueImpl Object::method_isPrototypeOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *) { bool result = false; if (context->thisObject().isObject() && (context->argumentCount() > 0)) { QScriptValueImpl arg = context->argument(0); if (arg.isObject()) { QScriptValueImpl proto = arg.prototype(); if (proto.isObject()) { QScriptValueImpl self = context->thisObject(); result = self.objectValue() == proto.objectValue(); } } } return (QScriptValueImpl(result)); }
/*! \internal \since 4.5 Returns the scope chain of this QScriptContext. */ QScriptValueList QScriptContext::scopeChain() const { Q_D(const QScriptContext); // make sure arguments properties are initialized const QScriptContextPrivate *ctx = d; while (ctx) { (void)ctx->activationObject(); ctx = ctx->previous; } QScriptValueList result; QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine()); QScriptValueImpl scope = d->m_scopeChain; while (scope.isObject()) { if (scope.classInfo() == eng_p->m_class_with) result.append(eng_p->toPublic(scope.prototype())); else result.append(eng_p->toPublic(scope)); scope = scope.scope(); } return result; }
bool QScriptValueIteratorImpl::hasNext() { if (m_foundMember.isValid() && m_foundForward) { // we have the information about the next element already return true; } int idx, count; QScriptValueImpl obj = m_object; if (m_searchClassDataIterator) { Q_ASSERT(m_classDataIterator != 0); if (m_foundMember.isValid()) { // undo effect of hasPrevious() m_foundMember.invalidate(); QScript::Member dummy; m_classDataIterator->next(&dummy); } goto LSearchClassData; } idx = m_searchIndex; if (m_foundMember.isValid()) { // undo effect of hasPrevious() m_foundMember.invalidate(); ++idx; } LSearchObjectData: count = obj.memberCount(); for (int i = idx; i < count; ++i) { QScript::Member m; obj.member(i, &m); if (acceptsMember(obj, m)) { m_foundObject = obj; m_foundMember = m; m_foundForward = true; m_searchIndex = i + 1; return true; } } if (!m_classDataIterator) { QScriptClassData *data = obj.classInfo()->data(); if (!data) goto LNext; m_classDataIterator = data->newIterator(obj); if (!m_classDataIterator) goto LNext; } m_searchClassDataIterator = true; LSearchClassData: Q_ASSERT(m_classDataIterator != 0); while (m_classDataIterator->hasNext()) { QScript::Member m; m_classDataIterator->next(&m); if (acceptsMember(obj, m)) { m_foundObject = obj; m_foundMember = m; m_foundForward = true; return true; } } LNext: if (!m_enumerateProto || !obj.prototype().isObject()) return false; // look in prototype obj = obj.prototype(); idx = 0; if (m_classDataIterator) { delete m_classDataIterator; m_classDataIterator = 0; m_searchClassDataIterator = false; } goto LSearchObjectData; }