diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-07-28 12:06:43 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-07-28 12:08:43 (GMT) |
commit | c11ddcf4c5f47db78a07123a0d534748c0672b0a (patch) | |
tree | 90ecfeb49f4232671da581e8d02e14ffc5f00608 /src/script | |
parent | 09a9014ded34d58177a782b44d385edf86b61f37 (diff) | |
download | Qt-c11ddcf4c5f47db78a07123a0d534748c0672b0a.zip Qt-c11ddcf4c5f47db78a07123a0d534748c0672b0a.tar.gz Qt-c11ddcf4c5f47db78a07123a0d534748c0672b0a.tar.bz2 |
make more tests pass for QScriptValue::setProperty()
JSC doesn't provide a way of un-defining a getter/setter. If
deleting e.g. only the setter, we remember the getter, delete
the property, then re-establish the getter.
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/api/qscriptvalue.cpp | 76 |
1 files changed, 53 insertions, 23 deletions
diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 59e6729..d410973 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -1857,34 +1857,64 @@ void QScriptValue::setProperty(const QScriptString &name, JSC::ExecState *exec = eng_p->currentFrame; JSC::JSValue jscValue = eng_p->scriptValueToJSCValue(value); JSC::Identifier id = name.d_ptr->identifier; - if (!jscValue) { - JSC::asObject(d->jscValue)->deleteProperty(exec, id); - } else { - if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) { - if (jscValue.isObject()) { - if (flags & QScriptValue::PropertyGetter) - JSC::asObject(d->jscValue)->defineGetter(exec, id, JSC::asObject(jscValue)); - if (flags & QScriptValue::PropertySetter) - JSC::asObject(d->jscValue)->defineSetter(exec, id, JSC::asObject(jscValue)); + JSC::JSObject *thisObject = JSC::asObject(d->jscValue); + JSC::JSValue setter = thisObject->lookupSetter(exec, id); + JSC::JSValue getter = thisObject->lookupGetter(exec, id); + if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) { + if (!jscValue) { + // deleting getter/setter + if ((flags & QScriptValue::PropertyGetter) && (flags & QScriptValue::PropertySetter)) { + // deleting both: just delete the property + thisObject->deleteProperty(exec, id); + } else if (flags & QScriptValue::PropertyGetter) { + // preserve setter, if there is one + thisObject->deleteProperty(exec, id); + if (setter && setter.isObject()) + thisObject->defineSetter(exec, id, JSC::asObject(setter)); + } else { // flags & QScriptValue::PropertySetter + // preserve getter, if there is one + thisObject->deleteProperty(exec, id); + if (getter && getter.isObject()) + thisObject->defineGetter(exec, id, JSC::asObject(getter)); } } else { - if (flags != QScriptValue::KeepExistingFlags) { - if (JSC::asObject(d->jscValue)->hasOwnProperty(exec, id)) - JSC::asObject(d->jscValue)->deleteProperty(exec, id); - unsigned attribs = 0; - if (flags & QScriptValue::ReadOnly) - attribs |= JSC::ReadOnly; - if (flags & QScriptValue::SkipInEnumeration) - attribs |= JSC::DontEnum; - if (flags & QScriptValue::Undeletable) - attribs |= JSC::DontDelete; - attribs |= flags & QScriptValue::UserRange; - JSC::asObject(d->jscValue)->putWithAttributes(exec, id, jscValue, attribs); + if (jscValue.isObject()) { // ### should check if it has callData() + // defining getter/setter + if (flags & QScriptValue::PropertyGetter) + thisObject->defineGetter(exec, id, JSC::asObject(jscValue)); + if (flags & QScriptValue::PropertySetter) + thisObject->defineSetter(exec, id, JSC::asObject(jscValue)); } else { - JSC::PutPropertySlot slot; - JSC::asObject(d->jscValue)->put(exec, id, jscValue, slot); + qWarning("QScriptValue::setProperty(): getter/setter must be a function"); } } + } else { + // setting the value + if (getter && getter.isObject() && !(setter && setter.isObject())) { + qWarning("QScriptValue::setProperty() failed: " + "property '%s' has a getter but no setter", + qPrintable(name.toString())); + return; + } + if (!jscValue) { + // ### check if it's a getter/setter property + thisObject->deleteProperty(exec, id); + } else if (flags != QScriptValue::KeepExistingFlags) { + if (thisObject->hasOwnProperty(exec, id)) + thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes? + unsigned attribs = 0; + if (flags & QScriptValue::ReadOnly) + attribs |= JSC::ReadOnly; + if (flags & QScriptValue::SkipInEnumeration) + attribs |= JSC::DontEnum; + if (flags & QScriptValue::Undeletable) + attribs |= JSC::DontDelete; + attribs |= flags & QScriptValue::UserRange; + thisObject->putWithAttributes(exec, id, jscValue, attribs); + } else { + JSC::PutPropertySlot slot; + thisObject->put(exec, id, jscValue, slot); + } } } |