summaryrefslogtreecommitdiffstats
path: root/src/script/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/bridge')
-rw-r--r--src/script/bridge/qscriptactivationobject.cpp18
-rw-r--r--src/script/bridge/qscriptactivationobject_p.h6
-rw-r--r--src/script/bridge/qscriptclassobject.cpp84
-rw-r--r--src/script/bridge/qscriptclassobject_p.h11
-rw-r--r--src/script/bridge/qscriptdeclarativeclass.cpp221
-rw-r--r--src/script/bridge/qscriptdeclarativeclass_p.h41
-rw-r--r--src/script/bridge/qscriptdeclarativeobject.cpp90
-rw-r--r--src/script/bridge/qscriptdeclarativeobject_p.h16
-rw-r--r--src/script/bridge/qscriptglobalobject.cpp38
-rw-r--r--src/script/bridge/qscriptglobalobject_p.h25
-rw-r--r--src/script/bridge/qscriptobject.cpp38
-rw-r--r--src/script/bridge/qscriptobject_p.h18
-rw-r--r--src/script/bridge/qscriptqobject.cpp448
-rw-r--r--src/script/bridge/qscriptqobject_p.h23
-rw-r--r--src/script/bridge/qscriptvariant.cpp9
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,