diff options
Diffstat (limited to 'src/script/bridge')
-rw-r--r-- | src/script/bridge/qscriptactivationobject.cpp | 18 | ||||
-rw-r--r-- | src/script/bridge/qscriptactivationobject_p.h | 6 | ||||
-rw-r--r-- | src/script/bridge/qscriptclassobject.cpp | 84 | ||||
-rw-r--r-- | src/script/bridge/qscriptclassobject_p.h | 11 | ||||
-rw-r--r-- | src/script/bridge/qscriptdeclarativeclass.cpp | 221 | ||||
-rw-r--r-- | src/script/bridge/qscriptdeclarativeclass_p.h | 41 | ||||
-rw-r--r-- | src/script/bridge/qscriptdeclarativeobject.cpp | 90 | ||||
-rw-r--r-- | src/script/bridge/qscriptdeclarativeobject_p.h | 16 | ||||
-rw-r--r-- | src/script/bridge/qscriptglobalobject.cpp | 38 | ||||
-rw-r--r-- | src/script/bridge/qscriptglobalobject_p.h | 25 | ||||
-rw-r--r-- | src/script/bridge/qscriptobject.cpp | 38 | ||||
-rw-r--r-- | src/script/bridge/qscriptobject_p.h | 18 | ||||
-rw-r--r-- | src/script/bridge/qscriptqobject.cpp | 448 | ||||
-rw-r--r-- | src/script/bridge/qscriptqobject_p.h | 23 | ||||
-rw-r--r-- | src/script/bridge/qscriptvariant.cpp | 9 |
15 files changed, 626 insertions, 460 deletions
diff --git a/src/script/bridge/qscriptactivationobject.cpp b/src/script/bridge/qscriptactivationobject.cpp index 7189f2e..6a8ae56 100644 --- a/src/script/bridge/qscriptactivationobject.cpp +++ b/src/script/bridge/qscriptactivationobject.cpp @@ -63,20 +63,20 @@ bool QScriptActivationObject::getOwnPropertySlot(JSC::ExecState* exec, const JSC return JSC::JSVariableObject::getOwnPropertySlot(exec, propertyName, slot); } -bool QScriptActivationObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, unsigned& attributes) const +bool QScriptActivationObject::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor) { if (d_ptr()->delegate != 0) - return d_ptr()->delegate->getPropertyAttributes(exec, propertyName, attributes); - return JSC::JSVariableObject::getPropertyAttributes(exec, propertyName, attributes); + return d_ptr()->delegate->getOwnPropertyDescriptor(exec, propertyName, descriptor); + return JSC::JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); } -void QScriptActivationObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, bool includeNonEnumerable) +void QScriptActivationObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, JSC::EnumerationMode mode) { if (d_ptr()->delegate != 0) { - d_ptr()->delegate->getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + d_ptr()->delegate->getOwnPropertyNames(exec, propertyNames, mode); return; } - return JSC::JSVariableObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + return JSC::JSVariableObject::getOwnPropertyNames(exec, propertyNames, mode); } void QScriptActivationObject::putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes) @@ -111,11 +111,11 @@ void QScriptActivationObject::put(JSC::ExecState* exec, unsigned propertyName, J JSC::JSVariableObject::put(exec, propertyName, value); } -bool QScriptActivationObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, bool checkDontDelete) +bool QScriptActivationObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName) { if (d_ptr()->delegate != 0) - return d_ptr()->delegate->deleteProperty(exec, propertyName, checkDontDelete); - return JSC::JSVariableObject::deleteProperty(exec, propertyName, checkDontDelete); + return d_ptr()->delegate->deleteProperty(exec, propertyName); + return JSC::JSVariableObject::deleteProperty(exec, propertyName); } void QScriptActivationObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction) diff --git a/src/script/bridge/qscriptactivationobject_p.h b/src/script/bridge/qscriptactivationobject_p.h index 7648a26..72ea11f 100644 --- a/src/script/bridge/qscriptactivationobject_p.h +++ b/src/script/bridge/qscriptactivationobject_p.h @@ -51,14 +51,14 @@ public: virtual bool isDynamicScope() const { return true; } virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); - virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, bool includeNonEnumerable = false); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes); virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot&); virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue value); - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName); virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction); virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction); diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index a4d9cc1..dd229f1 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -84,6 +84,47 @@ bool ClassObjectDelegate::getOwnPropertySlot(QScriptObject* object, return false; } +bool ClassObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, + JSC::ExecState *exec, + const JSC::Identifier &propertyName, + JSC::PropertyDescriptor &descriptor) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScript::SaveFrameHelper saveFrame(engine, exec); + // for compatibility with the old back-end, normal JS properties + // are queried first. + if (QScriptObjectDelegate::getOwnPropertyDescriptor(object, exec, propertyName, descriptor)) + return true; + + QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); + QScriptString scriptName; + QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); + QScriptStringPrivate::init(scriptName, &scriptName_d); + uint id = 0; + QScriptClass::QueryFlags qflags = m_scriptClass->queryProperty( + scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id); + if (qflags & QScriptClass::HandlesReadAccess) { + QScriptValue::PropertyFlags pflags = m_scriptClass->propertyFlags(scriptObject, scriptName, id); + unsigned attribs = 0; + if (pflags & QScriptValue::ReadOnly) + attribs |= JSC::ReadOnly; + if (pflags & QScriptValue::SkipInEnumeration) + attribs |= JSC::DontEnum; + if (pflags & QScriptValue::Undeletable) + attribs |= JSC::DontDelete; + if (pflags & QScriptValue::PropertyGetter) + attribs |= JSC::Getter; + if (pflags & QScriptValue::PropertySetter) + attribs |= JSC::Setter; + attribs |= pflags & QScriptValue::UserRange; + // Rather than calling the getter, we could return an access descriptor here. + QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id); + descriptor.setDescriptor(engine->scriptValueToJSCValue(value), attribs); + return true; + } + return false; +} + void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, JSC::PutPropertySlot &slot) @@ -105,8 +146,7 @@ void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, } bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec, - const JSC::Identifier &propertyName, - bool checkDontDelete) + const JSC::Identifier &propertyName) { // ### avoid duplication of put() QScriptEnginePrivate *engine = scriptEngineFromExec(exec); @@ -124,44 +164,12 @@ bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState * m_scriptClass->setProperty(scriptObject, scriptName, id, QScriptValue()); return true; } - return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete); -} - -bool ClassObjectDelegate::getPropertyAttributes(const QScriptObject* object, JSC::ExecState *exec, - const JSC::Identifier &propertyName, - unsigned &attribs) const -{ - QScriptEnginePrivate *engine = scriptEngineFromExec(exec); - QScript::SaveFrameHelper saveFrame(engine, exec); - QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); - QScriptString scriptName; - QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); - QScriptStringPrivate::init(scriptName, &scriptName_d); - uint id = 0; - QScriptClass::QueryFlags flags = m_scriptClass->queryProperty( - scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id); - if (flags & QScriptClass::HandlesReadAccess) { - QScriptValue::PropertyFlags flags = m_scriptClass->propertyFlags(scriptObject, scriptName, id); - attribs = 0; - if (flags & QScriptValue::ReadOnly) - attribs |= JSC::ReadOnly; - if (flags & QScriptValue::SkipInEnumeration) - attribs |= JSC::DontEnum; - if (flags & QScriptValue::Undeletable) - attribs |= JSC::DontDelete; - if (flags & QScriptValue::PropertyGetter) - attribs |= JSC::Getter; - if (flags & QScriptValue::PropertySetter) - attribs |= JSC::Setter; - attribs |= flags & QScriptValue::UserRange; - return true; - } - return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs); + return QScriptObjectDelegate::deleteProperty(object, exec, propertyName); } void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(engine, exec); @@ -175,7 +183,7 @@ void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecSt } delete it; } - QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); } JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &callData) @@ -206,7 +214,7 @@ JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC:: QVariant result = scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx)); eng_p->popContext(); eng_p->currentFrame = oldFrame; - return eng_p->jscValueFromVariant(result); + return QScriptEnginePrivate::jscValueFromVariant(exec, result); } JSC::ConstructType ClassObjectDelegate::getConstructData(QScriptObject*, JSC::ConstructData &constructData) diff --git a/src/script/bridge/qscriptclassobject_p.h b/src/script/bridge/qscriptclassobject_p.h index 89142ab..83fa61b 100644 --- a/src/script/bridge/qscriptclassobject_p.h +++ b/src/script/bridge/qscriptclassobject_p.h @@ -60,18 +60,17 @@ public: virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(QScriptObject*, JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor&); virtual void put(QScriptObject*, JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, - const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*, diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 24037e1..acfb2a4 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -35,19 +35,128 @@ QT_BEGIN_NAMESPACE +/*! +\class QScriptDeclarativeClass::Value +\internal +\brief The QScriptDeclarativeClass::Value class acts as a container for JavaScript data types. + +QScriptDeclarativeClass::Value class is similar to QScriptValue, but it is slightly faster. +Unlike QScriptValue, however, Value instances cannot be stored as they may not survive garbage +collection. If you need to store a Value, convert it to a QScriptValue and store that. +*/ + +QScriptDeclarativeClass::Value::Value() +{ + new (this) JSC::JSValue(JSC::jsUndefined()); +} + +QScriptDeclarativeClass::Value::Value(const Value &other) +{ + new (this) JSC::JSValue((JSC::JSValue &)other); +} + +static QScriptDeclarativeClass::Value jscToValue(const JSC::JSValue &val) +{ + return QScriptDeclarativeClass::Value((QScriptDeclarativeClass::Value &)val); +} + +QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, int value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value); +} + +QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, uint value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value); +} + +QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, bool value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value); +} + +QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, double value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value); +} + +QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, float value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value); +} + +QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QString &value) +{ + new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::frameForContext(ctxt), value)); +} + +QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, const QScriptValue &value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::get(ctxt->engine())->scriptValueToJSCValue(value)); +} + +QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, int value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value); +} + +QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, uint value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value); +} + +QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, bool value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value); +} + +QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, double value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value); +} + +QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, float value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value); +} + +QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QString &value) +{ + new (this) JSC::JSValue(JSC::jsString(QScriptEnginePrivate::get(eng)->currentFrame, value)); +} + +QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, const QScriptValue &value) +{ + new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->scriptValueToJSCValue(value)); +} + +QScriptDeclarativeClass::Value::~Value() +{ + ((JSC::JSValue *)(this))->~JSValue(); +} + +QScriptValue QScriptDeclarativeClass::Value::toScriptValue(QScriptEngine *engine) const +{ + return QScriptEnginePrivate::get(engine)->scriptValueFromJSCValue((JSC::JSValue &)*this); +} + QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier() + : identifier(0), engine(0) { new (&d) JSC::Identifier(); } QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier() { + if (engine) + JSC::setCurrentIdentifierTable(engine->globalData->identifierTable); ((JSC::Identifier &)d).JSC::Identifier::~Identifier(); } QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other) { identifier = other.identifier; + engine = other.engine; new (&d) JSC::Identifier((JSC::Identifier &)(other.d)); } @@ -55,6 +164,7 @@ QScriptDeclarativeClass::PersistentIdentifier & QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other) { identifier = other.identifier; + engine = other.engine; ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d); return *this; } @@ -82,28 +192,36 @@ QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine, return p->scriptValueFromJSCValue(result); } +QScriptDeclarativeClass::Value +QScriptDeclarativeClass::newObjectValue(QScriptEngine *engine, + QScriptDeclarativeClass *scriptClass, + Object *object) +{ + Q_ASSERT(engine); + Q_ASSERT(scriptClass); + + QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine)); + + JSC::ExecState* exec = p->currentFrame; + QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure); + result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object)); + return jscToValue(JSC::JSValue(result)); +} + QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); - if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) - return 0; - QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - QScriptObjectDelegate *delegate = scriptObject->delegate(); - if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) + if (!d || !d->isJSC()) return 0; - return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass(); + return QScriptEnginePrivate::declarativeClass(d->jscValue); } QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v) { QScriptValuePrivate *d = QScriptValuePrivate::get(v); - if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) + if (!d || !d->isJSC()) return 0; - QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - QScriptObjectDelegate *delegate = scriptObject->delegate(); - if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) - return 0; - return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->object(); + return QScriptEnginePrivate::declarativeObject(d->jscValue); } QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name) @@ -151,6 +269,53 @@ QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Iden return QScriptValue(); } +QScriptDeclarativeClass::Value +QScriptDeclarativeClass::functionValue(const QScriptValue &v, const Identifier &name) +{ + QScriptValuePrivate *d = QScriptValuePrivate::get(v); + + if (!d->isObject()) + return Value(); + + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSObject *object = d->jscValue.getObject(); + JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object)); + JSC::JSValue result; + + JSC::Identifier id(exec, (JSC::UString::Rep *)name); + + if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) { + result = slot.getValue(exec, id); + if (QScript::isFunction(result)) + return jscToValue(result); + } + + return Value(); +} + +QScriptDeclarativeClass::Value +QScriptDeclarativeClass::propertyValue(const QScriptValue &v, const Identifier &name) +{ + QScriptValuePrivate *d = QScriptValuePrivate::get(v); + + if (!d->isObject()) + return Value(); + + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSObject *object = d->jscValue.getObject(); + JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object)); + JSC::JSValue result; + + JSC::Identifier id(exec, (JSC::UString::Rep *)name); + + if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) { + result = slot.getValue(exec, id); + return jscToValue(result); + } + + return Value(); +} + /* Returns the scope chain entry at \a index. If index is less than 0, returns entries starting at the end. For example, scopeChainValue(context, -1) will return @@ -241,6 +406,16 @@ QScriptEngine *QScriptDeclarativeClass::engine() const return d_ptr->engine; } +bool QScriptDeclarativeClass::supportsCall() const +{ + return d_ptr->supportsCall; +} + +void QScriptDeclarativeClass::setSupportsCall(bool c) +{ + d_ptr->supportsCall = c; +} + QScriptDeclarativeClass::PersistentIdentifier QScriptDeclarativeClass::createPersistentIdentifier(const QString &str) { @@ -248,7 +423,7 @@ QScriptDeclarativeClass::createPersistentIdentifier(const QString &str) static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; - PersistentIdentifier rv(true); + PersistentIdentifier rv(p); new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size()); rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep(); return rv; @@ -261,7 +436,7 @@ QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id) static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; - PersistentIdentifier rv(true); + PersistentIdentifier rv(p); new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id); rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep(); return rv; @@ -290,11 +465,12 @@ QScriptDeclarativeClass::queryProperty(Object *object, const Identifier &name, return 0; } -QScriptValue QScriptDeclarativeClass::property(Object *object, const Identifier &name) +QScriptDeclarativeClass::Value +QScriptDeclarativeClass::property(Object *object, const Identifier &name) { Q_UNUSED(object); Q_UNUSED(name); - return QScriptValue(); + return Value(); } void QScriptDeclarativeClass::setProperty(Object *object, const Identifier &name, @@ -313,6 +489,19 @@ QScriptDeclarativeClass::propertyFlags(Object *object, const Identifier &name) return 0; } +QScriptDeclarativeClass::Value QScriptDeclarativeClass::call(Object *object, + QScriptContext *ctxt) +{ + Q_UNUSED(object); + Q_UNUSED(ctxt); + return Value(); +} + +bool QScriptDeclarativeClass::compare(Object *o, Object *o2) +{ + return o == o2; +} + QStringList QScriptDeclarativeClass::propertyNames(Object *object) { Q_UNUSED(object); diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index d28a371..714a67c 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -47,16 +47,47 @@ class QScriptContext; class Q_SCRIPT_EXPORT QScriptDeclarativeClass { public: +#define QT_HAVE_QSCRIPTDECLARATIVECLASS_VALUE + class Q_SCRIPT_EXPORT Value + { + public: + Value(); + Value(const Value &); + + Value(QScriptContext *, int); + Value(QScriptContext *, uint); + Value(QScriptContext *, bool); + Value(QScriptContext *, double); + Value(QScriptContext *, float); + Value(QScriptContext *, const QString &); + Value(QScriptContext *, const QScriptValue &); + Value(QScriptEngine *, int); + Value(QScriptEngine *, uint); + Value(QScriptEngine *, bool); + Value(QScriptEngine *, double); + Value(QScriptEngine *, float); + Value(QScriptEngine *, const QString &); + Value(QScriptEngine *, const QScriptValue &); + ~Value(); + + QScriptValue toScriptValue(QScriptEngine *) const; + private: + char dummy[8]; + }; + typedef void* Identifier; struct Object { virtual ~Object() {} }; static QScriptValue newObject(QScriptEngine *, QScriptDeclarativeClass *, Object *); + static Value newObjectValue(QScriptEngine *, QScriptDeclarativeClass *, Object *); static QScriptDeclarativeClass *scriptClass(const QScriptValue &); static Object *object(const QScriptValue &); static QScriptValue function(const QScriptValue &, const Identifier &); static QScriptValue property(const QScriptValue &, const Identifier &); + static Value functionValue(const QScriptValue &, const Identifier &); + static Value propertyValue(const QScriptValue &, const Identifier &); static QScriptValue scopeChainValue(QScriptContext *, int index); static QScriptContext *pushCleanContext(QScriptEngine *); @@ -73,7 +104,8 @@ public: private: friend class QScriptDeclarativeClass; - PersistentIdentifier(bool) : identifier(0), d(0) {} + PersistentIdentifier(QScriptEnginePrivate *e) : identifier(0), engine(e), d(0) {} + QScriptEnginePrivate *engine; void *d; }; @@ -82,6 +114,9 @@ public: QScriptEngine *engine() const; + bool supportsCall() const; + void setSupportsCall(bool); + PersistentIdentifier createPersistentIdentifier(const QString &); PersistentIdentifier createPersistentIdentifier(const Identifier &); @@ -91,9 +126,11 @@ public: virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); - virtual QScriptValue property(Object *, const Identifier &); + virtual Value property(Object *, const Identifier &); virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); virtual QScriptValue::PropertyFlags propertyFlags(Object *, const Identifier &); + virtual Value call(Object *, QScriptContext *); + virtual bool compare(Object *, Object *); virtual QStringList propertyNames(Object *); diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp index aecb09a..6e08b83 100644 --- a/src/script/bridge/qscriptdeclarativeobject.cpp +++ b/src/script/bridge/qscriptdeclarativeobject.cpp @@ -66,7 +66,6 @@ bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object, const JSC::Identifier &propertyName, JSC::PropertySlot &slot) { - QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class); @@ -74,9 +73,9 @@ bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object, QScriptClass::QueryFlags flags = m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess); if (flags & QScriptClass::HandlesReadAccess) { - QScriptValue value = m_class->property(m_object, identifier); + QScriptDeclarativeClass::Value val = m_class->property(m_object, identifier); p->context = 0; - slot.setValue(engine->scriptValueToJSCValue(value)); + slot.setValue((const JSC::JSValue &)val); return true; } p->context = 0; @@ -106,43 +105,14 @@ void DeclarativeObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, } bool DeclarativeObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec, - const JSC::Identifier &propertyName, - bool checkDontDelete) + const JSC::Identifier &propertyName) { - return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete); -} - -bool DeclarativeObjectDelegate::getPropertyAttributes(const QScriptObject* object, - JSC::ExecState *exec, - const JSC::Identifier &propertyName, - unsigned &attribs) const -{ - QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); - - QScriptClass::QueryFlags flags = - m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess); - if (flags & QScriptClass::HandlesReadAccess) { - QScriptValue::PropertyFlags flags = m_class->propertyFlags(m_object, identifier); - attribs = 0; - if (flags & QScriptValue::ReadOnly) - attribs |= JSC::ReadOnly; - if (flags & QScriptValue::SkipInEnumeration) - attribs |= JSC::DontEnum; - if (flags & QScriptValue::Undeletable) - attribs |= JSC::DontDelete; - if (flags & QScriptValue::PropertyGetter) - attribs |= JSC::Getter; - if (flags & QScriptValue::PropertySetter) - attribs |= JSC::Setter; - attribs |= flags & QScriptValue::UserRange; - return true; - } - return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs); + return QScriptObjectDelegate::deleteProperty(object, exec, propertyName); } void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { QStringList properties = m_class->propertyNames(m_object); for (int ii = 0; ii < properties.count(); ++ii) { @@ -150,12 +120,41 @@ void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC:: propertyNames.add(JSC::Identifier(exec, name)); } - QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); } JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData) { - return QScriptObjectDelegate::getCallData(object, callData); + if (!QScriptDeclarativeClassPrivate::get(m_class)->supportsCall) + return JSC::CallTypeNone; + callData.native.function = call; + return JSC::CallTypeHost; +} + +JSC::JSValue DeclarativeObjectDelegate::call(JSC::ExecState *exec, JSC::JSObject *callee, + JSC::JSValue thisValue, const JSC::ArgList &args) +{ + if (!callee->inherits(&QScriptObject::info)) + return JSC::throwError(exec, JSC::TypeError, "callee is not a DeclarativeObject object"); + QScriptObject *obj = static_cast<QScriptObject*>(callee); + QScriptObjectDelegate *delegate = obj->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) + return JSC::throwError(exec, JSC::TypeError, "callee is not a DeclarativeObject object"); + + QScriptDeclarativeClass *scriptClass = static_cast<DeclarativeObjectDelegate*>(delegate)->m_class; + QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); + + JSC::ExecState *oldFrame = eng_p->currentFrame; + eng_p->pushContext(exec, thisValue, args, callee); + QScriptContext *ctxt = eng_p->contextForFrame(eng_p->currentFrame); + + QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj); + QScriptDeclarativeClass::Value result = + scriptClass->call(static_cast<DeclarativeObjectDelegate*>(delegate)->m_object, ctxt); + + eng_p->popContext(); + eng_p->currentFrame = oldFrame; + return (JSC::JSValue &)(result); } JSC::ConstructType DeclarativeObjectDelegate::getConstructData(QScriptObject* object, JSC::ConstructData &constructData) @@ -169,6 +168,23 @@ bool DeclarativeObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecStat return QScriptObjectDelegate::hasInstance(object, exec, value, proto); } +bool DeclarativeObjectDelegate::compareToObject(QScriptObject *o, JSC::ExecState *exec, JSC::JSObject *o2) +{ + if (!o2->inherits(&QScriptObject::info)) + return false; + + QScriptObject *scriptObject = static_cast<QScriptObject*>(o2); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) + return false; + + DeclarativeObjectDelegate *other = static_cast<DeclarativeObjectDelegate*>(delegate); + if (m_class != other->m_class) + return false; + else + return m_class->compare(m_object, other->m_object); +} + } // namespace QScript QT_END_NAMESPACE diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h index d5bf673..beb5af0 100644 --- a/src/script/bridge/qscriptdeclarativeobject_p.h +++ b/src/script/bridge/qscriptdeclarativeobject_p.h @@ -48,11 +48,12 @@ class QScriptClass; class QScriptDeclarativeClassPrivate { public: - QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0), context(0) {} + QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0), context(0), supportsCall(false) {} QScriptEngine *engine; QScriptDeclarativeClass *q_ptr; QScriptContext *context; + bool supportsCall:1; static QScriptDeclarativeClassPrivate *get(QScriptDeclarativeClass *c) { return c->d_ptr.data(); @@ -80,21 +81,22 @@ public: const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, - const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); + static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*, + JSC::JSValue, const JSC::ArgList&); + virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&); virtual bool hasInstance(QScriptObject*, JSC::ExecState*, JSC::JSValue value, JSC::JSValue proto); + bool compareToObject(QScriptObject *, JSC::ExecState *, JSC::JSObject *); + private: QScriptDeclarativeClass *m_class; QScriptDeclarativeClass::Object *m_object; diff --git a/src/script/bridge/qscriptglobalobject.cpp b/src/script/bridge/qscriptglobalobject.cpp index e7ea0df..4c002b7 100644 --- a/src/script/bridge/qscriptglobalobject.cpp +++ b/src/script/bridge/qscriptglobalobject.cpp @@ -72,6 +72,23 @@ bool GlobalObject::getOwnPropertySlot(JSC::ExecState* exec, return JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); } +bool GlobalObject::getOwnPropertyDescriptor(JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor& descriptor) +{ + // Must match the logic of getOwnPropertySlot(). + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + if (propertyName == exec->propertyNames().arguments && engine->currentFrame->argumentCount() > 0) { + // ### Can we get rid of this special handling of the arguments property? + JSC::JSValue args = engine->scriptValueToJSCValue(engine->contextForFrame(engine->currentFrame)->argumentsObject()); + descriptor.setValue(args); + return true; + } + if (customGlobalObject) + return customGlobalObject->getOwnPropertyDescriptor(exec, propertyName, descriptor); + return JSC::JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + void GlobalObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot) { @@ -90,29 +107,20 @@ void GlobalObject::putWithAttributes(JSC::ExecState* exec, const JSC::Identifier JSC::JSGlobalObject::putWithAttributes(exec, propertyName, value, attributes); } -bool GlobalObject::deleteProperty(JSC::ExecState* exec, - const JSC::Identifier& propertyName, bool checkDontDelete) -{ - if (customGlobalObject) - return customGlobalObject->deleteProperty(exec, propertyName, checkDontDelete); - return JSC::JSGlobalObject::deleteProperty(exec, propertyName, checkDontDelete); -} - -bool GlobalObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, - unsigned& attributes) const +bool GlobalObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName) { if (customGlobalObject) - return customGlobalObject->getPropertyAttributes(exec, propertyName, attributes); - return JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes); + return customGlobalObject->deleteProperty(exec, propertyName); + return JSC::JSGlobalObject::deleteProperty(exec, propertyName); } void GlobalObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { if (customGlobalObject) - customGlobalObject->getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + customGlobalObject->getOwnPropertyNames(exec, propertyNames, mode); else - JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, mode); } void GlobalObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes) diff --git a/src/script/bridge/qscriptglobalobject_p.h b/src/script/bridge/qscriptglobalobject_p.h index b210f78..c0a419f 100644 --- a/src/script/bridge/qscriptglobalobject_p.h +++ b/src/script/bridge/qscriptglobalobject_p.h @@ -54,17 +54,17 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor&); virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual void putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, unsigned attributes); virtual bool deleteProperty(JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes = 0); virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes = 0); virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName); @@ -94,19 +94,20 @@ public: const JSC::Identifier& propertyName, JSC::PropertySlot& slot) { return originalGlobalObject->JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); } + virtual bool getOwnPropertyDescriptor(JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor& descriptor) + { return originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); } virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot) { originalGlobalObject->JSC::JSGlobalObject::put(exec, propertyName, value, slot); } virtual void putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, unsigned attributes) { originalGlobalObject->JSC::JSGlobalObject::putWithAttributes(exec, propertyName, value, attributes); } virtual bool deleteProperty(JSC::ExecState* exec, - const JSC::Identifier& propertyName, bool checkDontDelete = true) - { return originalGlobalObject->JSC::JSGlobalObject::deleteProperty(exec, propertyName, checkDontDelete); } - virtual bool getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, - unsigned& attributes) const - { return originalGlobalObject->JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes); } - virtual void getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, bool includeNonEnumerable = false) - { originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } + const JSC::Identifier& propertyName) + { return originalGlobalObject->JSC::JSGlobalObject::deleteProperty(exec, propertyName); } + virtual void getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties) + { originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, mode); } virtual void defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes) { originalGlobalObject->JSC::JSGlobalObject::defineGetter(exec, propertyName, getterFunction, attributes); } virtual void defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes) diff --git a/src/script/bridge/qscriptobject.cpp b/src/script/bridge/qscriptobject.cpp index 3db109e..9b6910e 100644 --- a/src/script/bridge/qscriptobject.cpp +++ b/src/script/bridge/qscriptobject.cpp @@ -81,30 +81,21 @@ void QScriptObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyNam } bool QScriptObject::deleteProperty(JSC::ExecState* exec, - const JSC::Identifier& propertyName, - bool checkDontDelete) + const JSC::Identifier& propertyName) { if (!d || !d->delegate) - return JSC::JSObject::deleteProperty(exec, propertyName, checkDontDelete); - return d->delegate->deleteProperty(this, exec, propertyName, checkDontDelete); -} - -bool QScriptObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, - unsigned& attributes) const -{ - if (!d || !d->delegate) - return JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); - return d->delegate->getPropertyAttributes(this, exec, propertyName, attributes); + return JSC::JSObject::deleteProperty(exec, propertyName); + return d->delegate->deleteProperty(this, exec, propertyName); } void QScriptObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { if (!d || !d->delegate) { - JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode); return; } - d->delegate->getOwnPropertyNames(this, exec, propertyNames, includeNonEnumerable); + d->delegate->getOwnPropertyNames(this, exec, propertyNames, mode); } bool QScriptObject::compareToObject(JSC::ExecState* exec, JSC::JSObject *other) @@ -189,25 +180,16 @@ void QScriptObjectDelegate::put(QScriptObject* object, JSC::ExecState* exec, } bool QScriptObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState* exec, - const JSC::Identifier& propertyName, - bool checkDontDelete) -{ - return object->JSC::JSObject::deleteProperty(exec, propertyName, checkDontDelete); -} - -bool QScriptObjectDelegate::getPropertyAttributes(const QScriptObject* object, - JSC::ExecState* exec, - const JSC::Identifier& propertyName, - unsigned& attributes) const + const JSC::Identifier& propertyName) { - return object->JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); + return object->JSC::JSObject::deleteProperty(exec, propertyName); } void QScriptObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { - object->JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + object->JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode); } void QScriptObjectDelegate::markChildren(QScriptObject* object, JSC::MarkStack& markStack) diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h index 4d15bee..f6de418 100644 --- a/src/script/bridge/qscriptobject_p.h +++ b/src/script/bridge/qscriptobject_p.h @@ -67,12 +67,9 @@ public: virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void markChildren(JSC::MarkStack& markStack); virtual JSC::CallType getCallData(JSC::CallData&); virtual JSC::ConstructType getConstructData(JSC::ConstructData&); @@ -84,7 +81,7 @@ public: static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, JSC::ImplementsHasInstance | JSC::OverridesHasInstance)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); } inline JSC::JSValue data() const; @@ -94,6 +91,8 @@ public: inline void setDelegate(QScriptObjectDelegate *delegate); protected: + static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesHasInstance | JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSObject::StructureFlags; + Data *d; }; @@ -128,12 +127,9 @@ public: virtual void put(QScriptObject*, JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, - const JSC::Identifier&, unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void markChildren(QScriptObject*, JSC::MarkStack& markStack); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&); diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index db312bc..765e074 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -163,23 +163,51 @@ static bool isEnumerableMetaProperty(const QMetaProperty &prop, && (mo->indexOfProperty(prop.name()) == index); } -static inline QByteArray methodName(const QMetaMethod &method) +/*! \internal + Calculates the length of the name of the given \a method by looking + for the first '(' character. +*/ +static inline int methodNameLength(const QMetaMethod &method) { - QByteArray signature = method.signature(); - return signature.left(signature.indexOf('(')); + const char *signature = method.signature(); + const char *s = signature; + while (*s && (*s != '(')) + ++s; + return s - signature; } -static QVariant variantFromValue(QScriptEnginePrivate *eng, - int targetType, const QScriptValue &value) +/*! \internal + Makes a deep copy of the first \a nameLength characters of the given + method \a signature and returns the copy. +*/ +static inline QByteArray methodName(const char *signature, int nameLength) +{ + return QByteArray(signature, nameLength); +} + +/*! \internal + + Returns true if the name of the given \a method is the same as that + specified by the (signature, nameLength) pair, otherwise returns + false. +*/ +static inline bool methodNameEquals(const QMetaMethod &method, + const char *signature, int nameLength) +{ + const char *otherSignature = method.signature(); + return !qstrncmp(otherSignature, signature, nameLength) + && (otherSignature[nameLength] == '('); +} + +static QVariant variantFromValue(JSC::ExecState *exec, int targetType, JSC::JSValue value) { QVariant v(targetType, (void *)0); - Q_ASSERT(eng); - if (QScriptEnginePrivate::convert(value, targetType, v.data(), eng)) + if (QScriptEnginePrivate::convertValue(exec, value, targetType, v.data())) return v; if (uint(targetType) == QVariant::LastType) - return value.toVariant(); - if (value.isVariant()) { - v = value.toVariant(); + return QScriptEnginePrivate::toVariant(exec, value); + if (QScriptEnginePrivate::isVariant(value)) { + v = QScriptEnginePrivate::variantValue(value); if (v.canConvert(QVariant::Type(targetType))) { v.convert(QVariant::Type(targetType)); return v; @@ -312,25 +340,16 @@ QList<int> QScript::QtFunction::overloadedIndexes() const if (!maybeOverloaded()) return QList<int>(); QList<int> result; - QString name = functionName(); const QMetaObject *meta = metaObject(); + QMetaMethod method = meta->method(initialIndex()); + int nameLength = methodNameLength(method); for (int index = mostGeneralMethod() - 1; index >= 0; --index) { - QString otherName = QString::fromLatin1(methodName(meta->method(index))); - if (otherName == name) + if (methodNameEquals(meta->method(index), method.signature(), nameLength)) result.append(index); } return result; } -QString QtFunction::functionName() const -{ - const QMetaObject *meta = metaObject(); - if (!meta) - return QString(); - QMetaMethod method = meta->method(initialIndex()); - return QLatin1String(methodName(method)); -} - class QScriptMetaType { public: @@ -417,8 +436,8 @@ class QScriptMetaMethod public: inline QScriptMetaMethod() { } - inline QScriptMetaMethod(const QByteArray &name, const QVector<QScriptMetaType> &types) - : m_name(name), m_types(types), m_firstUnresolvedIndex(-1) + inline QScriptMetaMethod(const QVector<QScriptMetaType> &types) + : m_types(types), m_firstUnresolvedIndex(-1) { QVector<QScriptMetaType>::const_iterator it; for (it = m_types.constBegin(); it != m_types.constEnd(); ++it) { @@ -431,9 +450,6 @@ public: inline bool isValid() const { return !m_types.isEmpty(); } - QByteArray name() const - { return m_name; } - inline QScriptMetaType returnType() const { return m_types.at(0); } @@ -462,7 +478,6 @@ public: { return m_types; } private: - QByteArray m_name; QVector<QScriptMetaType> m_types; int m_firstUnresolvedIndex; }; @@ -499,7 +514,6 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c const QMetaObject *meta, int initialIndex, bool maybeOverloaded) { - QByteArray funName; QScriptMetaMethod chosenMethod; int chosenIndex = -1; QVarLengthArray<QVariant, 9> args; @@ -508,65 +522,62 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c QVector<int> tooFewArgs; QVector<int> conversionFailed; int index; + int nameLength = 0; + const char *initialMethodSignature = 0; exec->clearException(); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(exec); for (index = initialIndex; index >= 0; --index) { QMetaMethod method = metaMethod(meta, callType, index); - if (index == initialIndex) - funName = methodName(method); - else { - if (methodName(method) != funName) + if (index == initialIndex) { + initialMethodSignature = method.signature(); + nameLength = methodNameLength(method); + } else { + if (!methodNameEquals(method, initialMethodSignature, nameLength)) continue; } + QList<QByteArray> parameterTypeNames = method.parameterTypes(); + QVector<QScriptMetaType> types; + types.resize(1 + parameterTypeNames.size()); + QScriptMetaType *typesData = types.data(); // resolve return type QByteArray returnTypeName = method.typeName(); int rtype = QMetaType::type(returnTypeName); if ((rtype == 0) && !returnTypeName.isEmpty()) { - if (returnTypeName == "QVariant") { - types.append(QScriptMetaType::variant()); - } else { - int enumIndex = indexOfMetaEnum(meta, returnTypeName); - if (enumIndex != -1) - types.append(QScriptMetaType::metaEnum(enumIndex, returnTypeName)); - else - types.append(QScriptMetaType::unresolved(returnTypeName)); - } + int enumIndex = indexOfMetaEnum(meta, returnTypeName); + if (enumIndex != -1) + typesData[0] = QScriptMetaType::metaEnum(enumIndex, returnTypeName); + else + typesData[0] = QScriptMetaType::unresolved(returnTypeName); } else { if (callType == QMetaMethod::Constructor) - types.append(QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*")); - else if (returnTypeName == "QVariant") - types.append(QScriptMetaType::variant()); + typesData[0] = QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*"); + else if (rtype == QMetaType::QVariant) + typesData[0] = QScriptMetaType::variant(); else - types.append(QScriptMetaType::metaType(rtype, returnTypeName)); + typesData[0] = QScriptMetaType::metaType(rtype, returnTypeName); } // resolve argument types - QList<QByteArray> parameterTypeNames = method.parameterTypes(); for (int i = 0; i < parameterTypeNames.count(); ++i) { QByteArray argTypeName = parameterTypeNames.at(i); int atype = QMetaType::type(argTypeName); if (atype == 0) { - if (argTypeName == "QVariant") { - types.append(QScriptMetaType::variant()); - } else { - int enumIndex = indexOfMetaEnum(meta, argTypeName); - if (enumIndex != -1) - types.append(QScriptMetaType::metaEnum(enumIndex, argTypeName)); - else - types.append(QScriptMetaType::unresolved(argTypeName)); - } - } else { - if (argTypeName == "QVariant") - types.append(QScriptMetaType::variant()); + int enumIndex = indexOfMetaEnum(meta, argTypeName); + if (enumIndex != -1) + typesData[1 + i] = QScriptMetaType::metaEnum(enumIndex, argTypeName); else - types.append(QScriptMetaType::metaType(atype, argTypeName)); + typesData[1 + i] = QScriptMetaType::unresolved(argTypeName); + } else if (atype == QMetaType::QVariant) { + typesData[1 + i] = QScriptMetaType::variant(); + } else { + typesData[1 + i] = QScriptMetaType::metaType(atype, argTypeName); } } - QScriptMetaMethod mtd = QScriptMetaMethod(methodName(method), types); + QScriptMetaMethod mtd = QScriptMetaMethod(types); if (int(scriptArgs.size()) < mtd.argumentCount()) { tooFewArgs.append(index); @@ -591,38 +602,38 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c bool converted = true; int matchDistance = 0; for (int i = 0; converted && i < mtd.argumentCount(); ++i) { - QScriptValue actual; + JSC::JSValue actual; if (i < (int)scriptArgs.size()) - actual = engine->scriptValueFromJSCValue(scriptArgs.at(i)); + actual = scriptArgs.at(i); else - actual = QScriptValue(QScriptValue::UndefinedValue); + actual = JSC::jsUndefined(); QScriptMetaType argType = mtd.argumentType(i); int tid = -1; QVariant v; if (argType.isUnresolved()) { v = QVariant(QMetaType::QObjectStar, (void *)0); - converted = engine->convertToNativeQObject( - actual, argType.name(), reinterpret_cast<void* *>(v.data())); + converted = QScriptEnginePrivate::convertToNativeQObject( + exec, actual, argType.name(), reinterpret_cast<void* *>(v.data())); } else if (argType.isVariant()) { - if (actual.isVariant()) { - v = actual.toVariant(); + if (QScriptEnginePrivate::isVariant(actual)) { + v = QScriptEnginePrivate::variantValue(actual); } else { - v = actual.toVariant(); + v = QScriptEnginePrivate::toVariant(exec, actual); converted = v.isValid() || actual.isUndefined() || actual.isNull(); } } else { tid = argType.typeId(); v = QVariant(tid, (void *)0); - converted = QScriptEnginePrivate::convert(actual, tid, v.data(), engine); + converted = QScriptEnginePrivate::convertValue(exec, actual, tid, v.data()); if (exec->hadException()) return exec->exception(); } if (!converted) { - if (actual.isVariant()) { + if (QScriptEnginePrivate::isVariant(actual)) { if (tid == -1) tid = argType.typeId(); - QVariant vv = actual.toVariant(); + QVariant vv = QScriptEnginePrivate::variantValue(actual); if (vv.canConvert(QVariant::Type(tid))) { v = vv; converted = v.convert(QVariant::Type(tid)); @@ -649,15 +660,15 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c } if (m.isValid()) { if (actual.isNumber()) { - int ival = actual.toInt32(); + int ival = QScriptEnginePrivate::toInt32(exec, actual); if (m.valueToKey(ival) != 0) { qVariantSetValue(v, ival); converted = true; matchDistance += 10; } } else { - QString sval = actual.toString(); - int ival = m.keyToValue(sval.toLatin1()); + JSC::UString sval = QScriptEnginePrivate::toString(exec, actual); + int ival = m.keyToValue(convertToLatin1(sval)); if (ival != -1) { qVariantSetValue(v, ival); converted = true; @@ -718,7 +729,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c matchDistance += 10; break; } - } else if (actual.isDate()) { + } else if (QScriptEnginePrivate::isDate(actual)) { switch (tid) { case QMetaType::QDateTime: // perfect @@ -733,7 +744,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c matchDistance += 10; break; } - } else if (actual.isRegExp()) { + } else if (QScriptEnginePrivate::isRegExp(actual)) { switch (tid) { case QMetaType::QRegExp: // perfect @@ -742,14 +753,14 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c matchDistance += 10; break; } - } else if (actual.isVariant()) { + } else if (QScriptEnginePrivate::isVariant(actual)) { if (argType.isVariant() - || (actual.toVariant().userType() == tid)) { + || (QScriptEnginePrivate::toVariant(exec, actual).userType() == tid)) { // perfect } else { matchDistance += 10; } - } else if (actual.isArray()) { + } else if (QScriptEnginePrivate::isArray(actual)) { switch (tid) { case QMetaType::QStringList: case QMetaType::QVariantList: @@ -759,7 +770,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c matchDistance += 10; break; } - } else if (actual.isQObject()) { + } else if (QScriptEnginePrivate::isQObject(actual)) { switch (tid) { case QMetaType::QObjectStar: case QMetaType::QWidgetStar: @@ -841,9 +852,10 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c //#ifndef Q_SCRIPT_NO_EVENT_NOTIFY // engine->notifyFunctionEntry(context); //#endif + QString funName = QString::fromLatin1(methodName(initialMethodSignature, nameLength)); if (!conversionFailed.isEmpty()) { QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n") - .arg(QLatin1String(funName)); + .arg(funName); for (int i = 0; i < conversionFailed.size(); ++i) { if (i > 0) message += QLatin1String("\n"); @@ -858,7 +870,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c QScriptMetaType unresolvedType = argsInstance.method.type(unresolvedIndex); QString unresolvedTypeName = QString::fromLatin1(unresolvedType.name()); QString message = QString::fromLatin1("cannot call %0(): ") - .arg(QString::fromLatin1(funName)); + .arg(funName); if (unresolvedIndex > 0) { message.append(QString::fromLatin1("argument %0 has unknown type `%1'"). arg(unresolvedIndex).arg(unresolvedTypeName)); @@ -870,7 +882,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c result = JSC::throwError(exec, JSC::TypeError, message); } else { QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n") - .arg(QLatin1String(funName)); + .arg(funName); for (int i = 0; i < tooFewArgs.size(); ++i) { if (i > 0) message += QLatin1String("\n"); @@ -886,6 +898,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c && (metaArgs.args.count() == candidates.at(1).args.count()) && (metaArgs.matchDistance == candidates.at(1).matchDistance)) { // ambiguous call + QByteArray funName = methodName(initialMethodSignature, nameLength); QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n") .arg(QLatin1String(funName)); for (int i = 0; i < candidates.size(); ++i) { @@ -953,13 +966,11 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c } else { QScriptMetaType retType = chosenMethod.returnType(); if (retType.isVariant()) { - result = engine->jscValueFromVariant(*(QVariant *)params[0]); + result = QScriptEnginePrivate::jscValueFromVariant(exec, *(QVariant *)params[0]); } else if (retType.typeId() != 0) { - result = engine->scriptValueToJSCValue(engine->create(retType.typeId(), params[0])); - if (!result) { - QScriptValue sv = QScriptEnginePrivate::get(engine)->newVariant(QVariant(retType.typeId(), params[0])); - result = engine->scriptValueToJSCValue(sv); - } + result = QScriptEnginePrivate::create(exec, retType.typeId(), params[0]); + if (!result) + result = engine->newVariant(QVariant(retType.typeId(), params[0])); } else { result = JSC::jsUndefined(); } @@ -1049,14 +1060,7 @@ JSC::JSValue JSC_HOST_CALL QtPropertyFunction::call( if (!callee->inherits(&QtPropertyFunction::info)) return throwError(exec, JSC::TypeError, "callee is not a QtPropertyFunction object"); QtPropertyFunction *qfun = static_cast<QtPropertyFunction*>(callee); - QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); - JSC::ExecState *previousFrame = eng_p->currentFrame; - eng_p->currentFrame = exec; - eng_p->pushContext(exec, thisValue, args, callee); - JSC::JSValue result = qfun->execute(eng_p->currentFrame, thisValue, args); - eng_p->popContext(); - eng_p->currentFrame = previousFrame; - return result; + return qfun->execute(exec, thisValue, args); } JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec, @@ -1065,15 +1069,16 @@ JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec, { JSC::JSValue result = JSC::jsUndefined(); - // ### don't go via QScriptValue QScriptEnginePrivate *engine = scriptEngineFromExec(exec); - thisValue = engine->toUsableValue(thisValue); - QScriptValue object = engine->scriptValueFromJSCValue(thisValue); - QObject *qobject = object.toQObject(); + JSC::ExecState *previousFrame = engine->currentFrame; + engine->currentFrame = exec; + + JSC::JSValue qobjectValue = engine->toUsableValue(thisValue); + QObject *qobject = QScriptEnginePrivate::toQObject(exec, qobjectValue); while ((!qobject || (qobject->metaObject() != data->meta)) - && object.prototype().isObject()) { - object = object.prototype(); - qobject = object.toQObject(); + && JSC::asObject(qobjectValue)->prototype().isObject()) { + qobjectValue = JSC::asObject(qobjectValue)->prototype(); + qobject = QScriptEnginePrivate::toQObject(exec, qobjectValue); } Q_ASSERT_X(qobject, Q_FUNC_INFO, "this-object must be a QObject"); @@ -1085,16 +1090,19 @@ JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec, QScriptable *scriptable = scriptableFromQObject(qobject); QScriptEngine *oldEngine = 0; if (scriptable) { + engine->pushContext(exec, thisValue, args, this); oldEngine = QScriptablePrivate::get(scriptable)->engine; QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine); } QVariant v = prop.read(qobject); - if (scriptable) + if (scriptable) { QScriptablePrivate::get(scriptable)->engine = oldEngine; + engine->popContext(); + } - result = engine->jscValueFromVariant(v); + result = QScriptEnginePrivate::jscValueFromVariant(exec, v); } } else { // set @@ -1106,25 +1114,27 @@ JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec, // string to enum value v = (QString)arg.toString(exec); } else { - // ### don't go via QScriptValue - QScriptValue tmp = engine->scriptValueFromJSCValue(arg); - v = variantFromValue(engine, prop.userType(), tmp); + v = variantFromValue(exec, prop.userType(), arg); } QScriptable *scriptable = scriptableFromQObject(qobject); QScriptEngine *oldEngine = 0; if (scriptable) { + engine->pushContext(exec, thisValue, args, this); oldEngine = QScriptablePrivate::get(scriptable)->engine; QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine); } prop.write(qobject, v); - if (scriptable) + if (scriptable) { QScriptablePrivate::get(scriptable)->engine = oldEngine; + engine->popContext(); + } result = arg; } + engine->currentFrame = previousFrame; return result; } @@ -1176,7 +1186,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState * { //Note: this has to be kept in sync with getOwnPropertyDescriptor #ifndef QT_NO_PROPERTIES - QByteArray name = QString(propertyName.ustring()).toLatin1(); + QByteArray name = convertToLatin1(propertyName.ustring()); QObject *qobject = data->value; if (!qobject) { QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject") @@ -1237,7 +1247,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState * if (!prop.isValid()) val = JSC::jsUndefined(); else - val = eng->jscValueFromVariant(prop.read(qobject)); + val = QScriptEnginePrivate::jscValueFromVariant(exec, prop.read(qobject)); slot.setValue(val); } return true; @@ -1247,7 +1257,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState * index = qobject->dynamicPropertyNames().indexOf(name); if (index != -1) { - JSC::JSValue val = eng->jscValueFromVariant(qobject->property(name)); + JSC::JSValue val = QScriptEnginePrivate::jscValueFromVariant(exec, qobject->property(name)); slot.setValue(val); return true; } @@ -1257,7 +1267,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState * for (index = meta->methodCount() - 1; index >= offset; --index) { QMetaMethod method = meta->method(index); if (hasMethodAccess(method, index, opt) - && (methodName(method) == name)) { + && methodNameEquals(method, name.constData(), name.length())) { QtFunction *fun = new (exec)QtFunction( object, index, /*maybeOverloaded=*/true, &exec->globalData(), eng->originalGlobalObject()->functionStructure(), @@ -1274,8 +1284,7 @@ bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState * QObject *child = children.at(index); if (child->objectName() == QString(propertyName.ustring())) { QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; - QScriptValue tmp = QScriptEnginePrivate::get(eng)->newQObject(child, QScriptEngine::QtOwnership, opt); - slot.setValue(eng->scriptValueToJSCValue(tmp)); + slot.setValue(eng->newQObject(child, QScriptEngine::QtOwnership, opt)); return true; } } @@ -1292,9 +1301,9 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS const JSC::Identifier &propertyName, JSC::PropertyDescriptor &descriptor) { - //Note: this has to be kept in sync with getOwnPropertySlot abd getPropertyAttributes + //Note: this has to be kept in sync with getOwnPropertySlot #ifndef QT_NO_PROPERTIES - QByteArray name = QString(propertyName.ustring()).toLatin1(); + QByteArray name = convertToLatin1(propertyName.ustring()); QObject *qobject = data->value; if (!qobject) { QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject") @@ -1370,7 +1379,7 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS if (!prop.isValid()) val = JSC::jsUndefined(); else - val = eng->jscValueFromVariant(prop.read(qobject)); + val = QScriptEnginePrivate::jscValueFromVariant(exec, prop.read(qobject)); descriptor.setDescriptor(val, attributes); } return true; @@ -1380,7 +1389,7 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS index = qobject->dynamicPropertyNames().indexOf(name); if (index != -1) { - JSC::JSValue val = eng->jscValueFromVariant(qobject->property(name)); + JSC::JSValue val = QScriptEnginePrivate::jscValueFromVariant(exec, qobject->property(name)); descriptor.setDescriptor(val, QObjectMemberAttribute); return true; } @@ -1390,7 +1399,7 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS for (index = meta->methodCount() - 1; index >= offset; --index) { QMetaMethod method = meta->method(index); if (hasMethodAccess(method, index, opt) - && (methodName(method) == name)) { + && methodNameEquals(method, name.constData(), name.length())) { QtFunction *fun = new (exec)QtFunction( object, index, /*maybeOverloaded=*/true, &exec->globalData(), eng->originalGlobalObject()->functionStructure(), @@ -1410,8 +1419,8 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS QObject *child = children.at(index); if (child->objectName() == QString(propertyName.ustring())) { QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; - QScriptValue tmp = QScriptEnginePrivate::get(eng)->newQObject(child, QScriptEngine::QtOwnership, opt); - descriptor.setDescriptor(eng->scriptValueToJSCValue(tmp), JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum); + descriptor.setDescriptor(eng->newQObject(child, QScriptEngine::QtOwnership, opt), + JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum); return true; } } @@ -1428,7 +1437,7 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, JSC::JSValue value, JSC::PutPropertySlot &slot) { #ifndef QT_NO_PROPERTIES - QByteArray name = ((QString)propertyName.ustring()).toLatin1(); + QByteArray name = convertToLatin1(propertyName.ustring()); QObject *qobject = data->value; if (!qobject) { QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject") @@ -1490,7 +1499,7 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, // string to enum value v = (QString)value.toString(exec); } else { - v = eng->jscValueToVariant(value, prop.userType()); + v = QScriptEnginePrivate::jscValueToVariant(exec, value, prop.userType()); } (void)prop.write(qobject, v); } @@ -1504,7 +1513,7 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, for (index = meta->methodCount() - 1; index >= offset; --index) { QMetaMethod method = meta->method(index); if (hasMethodAccess(method, index, opt) - && (methodName(method) == name)) { + && methodNameEquals(method, name.constData(), name.length())) { data->cachedMembers.insert(name, value); return; } @@ -1512,7 +1521,7 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, index = qobject->dynamicPropertyNames().indexOf(name); if ((index != -1) || (opt & QScriptEngine::AutoCreateDynamicProperties)) { - QVariant v = eng->scriptValueFromJSCValue(value).toVariant(); + QVariant v = QScriptEnginePrivate::toVariant(exec, value); (void)qobject->setProperty(name, v); return; } @@ -1522,11 +1531,10 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, } bool QObjectDelegate::deleteProperty(QScriptObject *object, JSC::ExecState *exec, - const JSC::Identifier& propertyName, - bool checkDontDelete) + const JSC::Identifier& propertyName) { #ifndef QT_NO_PROPERTIES - QByteArray name = ((QString)propertyName.ustring()).toLatin1(); + QByteArray name = convertToLatin1(propertyName.ustring()); QObject *qobject = data->value; if (!qobject) { QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject") @@ -1563,86 +1571,7 @@ bool QObjectDelegate::deleteProperty(QScriptObject *object, JSC::ExecState *exec return true; } - return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete); -#else //QT_NO_PROPERTIES - return false; -#endif //QT_NO_PROPERTIES -} - -bool QObjectDelegate::getPropertyAttributes(const QScriptObject *object, - JSC::ExecState *exec, - const JSC::Identifier &propertyName, - unsigned &attributes) const -{ -#ifndef QT_NO_PROPERTIES - //Note: this has to be kept in sync with getOwnPropertyDescriptor and getOwnPropertySlot - QByteArray name = ((QString)propertyName.ustring()).toLatin1(); - QObject *qobject = data->value; - if (!qobject) - return false; - - const QScriptEngine::QObjectWrapOptions &opt = data->options; - const QMetaObject *meta = qobject->metaObject(); - int index = -1; - if (name.contains('(')) { - QByteArray normalized = QMetaObject::normalizedSignature(name); - if (-1 != (index = meta->indexOfMethod(normalized))) { - QMetaMethod method = meta->method(index); - if (hasMethodAccess(method, index, opt)) { - if (!(opt & QScriptEngine::ExcludeSuperClassMethods) - || (index >= meta->methodOffset())) { - attributes = QObjectMemberAttribute; - if (opt & QScriptEngine::SkipMethodsInEnumeration) - attributes |= JSC::DontEnum; - return true; - } - } - } - } - - index = meta->indexOfProperty(name); - if (index != -1) { - QMetaProperty prop = meta->property(index); - if (prop.isScriptable()) { - if (!(opt & QScriptEngine::ExcludeSuperClassProperties) - || (index >= meta->propertyOffset())) { - attributes = flagsForMetaProperty(prop); - return true; - } - } - } - - index = qobject->dynamicPropertyNames().indexOf(name); - if (index != -1) { - attributes = QObjectMemberAttribute; - return true; - } - - const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods) - ? meta->methodOffset() : 0; - for (index = meta->methodCount() - 1; index >= offset; --index) { - QMetaMethod method = meta->method(index); - if (hasMethodAccess(method, index, opt) - && (methodName(method) == name)) { - attributes = QObjectMemberAttribute; - if (opt & QScriptEngine::SkipMethodsInEnumeration) - attributes |= JSC::DontEnum; - return true; - } - } - - if (!(opt & QScriptEngine::ExcludeChildObjects)) { - QList<QObject*> children = qobject->children(); - for (index = 0; index < children.count(); ++index) { - QObject *child = children.at(index); - if (child->objectName() == (QString)(propertyName.ustring())) { - attributes = JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum; - return true; - } - } - } - - return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attributes); + return QScriptObjectDelegate::deleteProperty(object, exec, propertyName); #else //QT_NO_PROPERTIES return false; #endif //QT_NO_PROPERTIES @@ -1650,7 +1579,7 @@ bool QObjectDelegate::getPropertyAttributes(const QScriptObject *object, void QObjectDelegate::getOwnPropertyNames(QScriptObject *object, JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { #ifndef QT_NO_PROPERTIES QObject *qobject = data->value; @@ -1695,7 +1624,7 @@ void QObjectDelegate::getOwnPropertyNames(QScriptObject *object, JSC::ExecState } } - QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); #endif //QT_NO_PROPERTIES } @@ -1862,7 +1791,7 @@ bool QMetaObjectWrapperObject::getOwnPropertySlot( return true; } - QByteArray name = QString(propertyName.ustring()).toLatin1(); + QByteArray name = convertToLatin1(propertyName.ustring()); for (int i = 0; i < meta->enumeratorCount(); ++i) { QMetaEnum e = meta->enumerator(i); @@ -1878,6 +1807,39 @@ bool QMetaObjectWrapperObject::getOwnPropertySlot( return JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot); } +bool QMetaObjectWrapperObject::getOwnPropertyDescriptor( + JSC::ExecState* exec, const JSC::Identifier& propertyName, + JSC::PropertyDescriptor& descriptor) +{ + const QMetaObject *meta = data->value; + if (!meta) + return false; + + if (propertyName == exec->propertyNames().prototype) { + descriptor.setDescriptor(data->ctor + ? data->ctor.get(exec, propertyName) + : data->prototype, + JSC::DontDelete | JSC::DontEnum); + return true; + } + + QByteArray name = QString(propertyName.ustring()).toLatin1(); + + for (int i = 0; i < meta->enumeratorCount(); ++i) { + QMetaEnum e = meta->enumerator(i); + for (int j = 0; j < e.keyCount(); ++j) { + const char *key = e.key(j); + if (!qstrcmp(key, name.constData())) { + descriptor.setDescriptor(JSC::JSValue(exec, e.value(j)), + JSC::ReadOnly | JSC::DontDelete); + return true; + } + } + } + + return JSC::JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot &slot) { @@ -1890,7 +1852,7 @@ void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& } const QMetaObject *meta = data->value; if (meta) { - QByteArray name = QString(propertyName.ustring()).toLatin1(); + QByteArray name = convertToLatin1(propertyName.ustring()); for (int i = 0; i < meta->enumeratorCount(); ++i) { QMetaEnum e = meta->enumerator(i); for (int j = 0; j < e.keyCount(); ++j) { @@ -1903,14 +1865,13 @@ void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& } bool QMetaObjectWrapperObject::deleteProperty( - JSC::ExecState *exec, const JSC::Identifier& propertyName, - bool checkDontDelete) + JSC::ExecState *exec, const JSC::Identifier& propertyName) { if (propertyName == exec->propertyNames().prototype) return false; const QMetaObject *meta = data->value; if (meta) { - QByteArray name = QString(propertyName.ustring()).toLatin1(); + QByteArray name = convertToLatin1(propertyName.ustring()); for (int i = 0; i < meta->enumeratorCount(); ++i) { QMetaEnum e = meta->enumerator(i); for (int j = 0; j < e.keyCount(); ++j) { @@ -1919,36 +1880,12 @@ bool QMetaObjectWrapperObject::deleteProperty( } } } - return JSC::JSObject::deleteProperty(exec, propertyName, checkDontDelete); -} - -bool QMetaObjectWrapperObject::getPropertyAttributes(JSC::ExecState *exec, - const JSC::Identifier &propertyName, - unsigned &attributes) const -{ - if (propertyName == exec->propertyNames().prototype) { - attributes = JSC::DontDelete; - return true; - } - const QMetaObject *meta = data->value; - if (meta) { - QByteArray name = QString(propertyName.ustring()).toLatin1(); - for (int i = 0; i < meta->enumeratorCount(); ++i) { - QMetaEnum e = meta->enumerator(i); - for (int j = 0; j < e.keyCount(); ++j) { - if (!qstrcmp(e.key(j), name.constData())) { - attributes = JSC::ReadOnly | JSC::DontDelete; - return true; - } - } - } - } - return JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); + return JSC::JSObject::deleteProperty(exec, propertyName); } void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { const QMetaObject *meta = data->value; if (!meta) @@ -1958,7 +1895,7 @@ void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState *exec, for (int j = 0; j < e.keyCount(); ++j) propertyNames.add(JSC::Identifier(exec, e.key(j))); } - JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode); } void QMetaObjectWrapperObject::markChildren(JSC::MarkStack& markStack) @@ -2178,24 +2115,21 @@ void QObjectConnectionManager::execute(int slotIndex, void **argv) JSC::ExecState *exec = engine->currentFrame; QVarLengthArray<JSC::JSValue, 8> argsVector(argc); for (int i = 0; i < argc; ++i) { - // ### optimize -- no need to convert via QScriptValue - QScriptValue actual; + JSC::JSValue actual; void *arg = argv[i + 1]; QByteArray typeName = parameterTypes.at(i); int argType = QMetaType::type(parameterTypes.at(i)); if (!argType) { - if (typeName == "QVariant") { - actual = engine->scriptValueFromVariant(*reinterpret_cast<QVariant*>(arg)); - } else { - qWarning("QScriptEngine: Unable to handle unregistered datatype '%s' " - "when invoking handler of signal %s::%s", - typeName.constData(), meta->className(), method.signature()); - actual = QScriptValue(QScriptValue::UndefinedValue); - } + qWarning("QScriptEngine: Unable to handle unregistered datatype '%s' " + "when invoking handler of signal %s::%s", + typeName.constData(), meta->className(), method.signature()); + actual = JSC::jsUndefined(); + } else if (argType == QMetaType::QVariant) { + actual = QScriptEnginePrivate::jscValueFromVariant(exec, *reinterpret_cast<QVariant*>(arg)); } else { - actual = engine->create(argType, arg); + actual = QScriptEnginePrivate::create(exec, argType, arg); } - argsVector[i] = engine->scriptValueToJSCValue(actual); + argsVector[i] = actual; } JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h index 448fa99..b82bcb7 100644 --- a/src/script/bridge/qscriptqobject_p.h +++ b/src/script/bridge/qscriptqobject_p.h @@ -86,14 +86,10 @@ public: const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, - const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void markChildren(QScriptObject*, JSC::MarkStack& markStack); virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*); @@ -212,7 +208,6 @@ public: bool maybeOverloaded() const; int mostGeneralMethod(QMetaMethod *out = 0) const; QList<int> overloadedIndexes() const; - QString functionName() const; private: Data *data; @@ -276,15 +271,15 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor&); virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void markChildren(JSC::MarkStack& markStack); virtual JSC::CallType getCallData(JSC::CallData&); @@ -304,10 +299,12 @@ public: static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); } protected: + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSObject::StructureFlags; + Data *data; }; diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp index 0287d24..b2dd3b0 100644 --- a/src/script/bridge/qscriptvariant.cpp +++ b/src/script/bridge/qscriptvariant.cpp @@ -119,11 +119,8 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, JSC::JSValue value = variantProtoFuncValueOf(exec, callee, thisValue, args); if (value.isObject()) { result = v.toString(); - if (result.isEmpty() && !v.canConvert(QVariant::String)) { - result = "QVariant("; - result += v.typeName(); - result += ")"; - } + if (result.isEmpty() && !v.canConvert(QVariant::String)) + result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(v.typeName())); } else { result = value.toString(exec); } @@ -133,7 +130,7 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, bool QVariantDelegate::compareToObject(QScriptObject *, JSC::ExecState *exec, JSC::JSObject *o2) { const QVariant &variant1 = value(); - return variant1 == scriptEngineFromExec(exec)->scriptValueFromJSCValue(o2).toVariant(); + return variant1 == QScriptEnginePrivate::toVariant(exec, o2); } QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure, |