diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2009-09-29 04:09:01 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2009-09-29 04:09:01 (GMT) |
commit | 575ad2c60482b279f828cfa87186b5fbb10f76c6 (patch) | |
tree | 101df52cd4b769dc8d10ef60714f25d819636e70 /src/script | |
parent | a913e326409062bbc1cad4d5898181c7b81cba23 (diff) | |
parent | 638f46a96b68d21137c4903c68015752ebdf58dc (diff) | |
download | Qt-575ad2c60482b279f828cfa87186b5fbb10f76c6.zip Qt-575ad2c60482b279f828cfa87186b5fbb10f76c6.tar.gz Qt-575ad2c60482b279f828cfa87186b5fbb10f76c6.tar.bz2 |
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt into kinetic-declarativeui
Conflicts:
configure.exe
mkspecs/features/qt.prf
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/api/qscriptcontext.cpp | 8 | ||||
-rw-r--r-- | src/script/api/qscriptcontextinfo.cpp | 15 | ||||
-rw-r--r-- | src/script/api/qscriptengine.cpp | 170 | ||||
-rw-r--r-- | src/script/api/qscriptengine_p.h | 33 | ||||
-rw-r--r-- | src/script/api/qscriptvalue.cpp | 104 | ||||
-rw-r--r-- | src/script/api/qscriptvalueiterator.cpp | 2 | ||||
-rw-r--r-- | src/script/bridge/qscriptactivationobject.cpp | 8 | ||||
-rw-r--r-- | src/script/bridge/qscriptactivationobject_p.h | 2 | ||||
-rw-r--r-- | src/script/bridge/qscriptclassobject.cpp | 21 | ||||
-rw-r--r-- | src/script/bridge/qscriptclassobject_p.h | 5 | ||||
-rw-r--r-- | src/script/bridge/qscriptfunction.cpp | 4 | ||||
-rw-r--r-- | src/script/bridge/qscriptglobalobject.cpp | 28 | ||||
-rw-r--r-- | src/script/bridge/qscriptglobalobject_p.h | 31 | ||||
-rw-r--r-- | src/script/bridge/qscriptobject.cpp | 49 | ||||
-rw-r--r-- | src/script/bridge/qscriptobject_p.h | 13 | ||||
-rw-r--r-- | src/script/bridge/qscriptqobject.cpp | 123 | ||||
-rw-r--r-- | src/script/bridge/qscriptqobject_p.h | 18 | ||||
-rw-r--r-- | src/script/bridge/qscriptvariant.cpp | 11 | ||||
-rw-r--r-- | src/script/bridge/qscriptvariant_p.h | 2 | ||||
-rw-r--r-- | src/script/script.pro | 33 |
20 files changed, 399 insertions, 281 deletions
diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 2ca6d26..caa4dc2 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -468,7 +468,7 @@ QScriptValue QScriptContext::activationObject() const }*/ } - if (result && result->isObject(&QScript::QScriptActivationObject::info) + if (result && result->inherits(&QScript::QScriptActivationObject::info) && (static_cast<QScript::QScriptActivationObject*>(result)->delegate() != 0)) { // Return the object that property access is being delegated to result = static_cast<QScript::QScriptActivationObject*>(result)->delegate(); @@ -517,7 +517,7 @@ void QScriptContext::setActivationObject(const QScriptValue &activation) while (node != 0) { if (node->object && node->object->isVariableObject()) { if (!object->isVariableObject()) { - if (node->object->isObject(&QScript::QScriptActivationObject::info)) { + if (node->object->inherits(&QScript::QScriptActivationObject::info)) { static_cast<QScript::QScriptActivationObject*>(node->object)->setDelegate(object); } else { // Create a QScriptActivationObject that acts as a proxy @@ -571,7 +571,7 @@ void QScriptContext::setThisObject(const QScriptValue &thisObject) if (cb != 0) { frame[cb->thisRegister()] = jscThisObject; } else { - JSC::Register* thisRegister = frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount(); + JSC::Register* thisRegister = QScriptEnginePrivate::thisRegisterForFrame(frame); thisRegister[0] = jscThisObject; } } @@ -687,7 +687,7 @@ QScriptValueList QScriptContext::scopeChain() const JSC::JSObject *object = *it; if (!object) continue; - if (object->isObject(&QScript::QScriptActivationObject::info) + if (object->inherits(&QScript::QScriptActivationObject::info) && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) { // Return the object that property access is being delegated to object = static_cast<QScript::QScriptActivationObject*>(object)->delegate(); diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index 1be76a9..6c34c5e 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -198,18 +198,17 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte // Get the others informations: JSC::JSObject *callee = frame->callee(); - if (callee && callee->isObject(&JSC::InternalFunction::info)) + if (callee && callee->inherits(&JSC::InternalFunction::info)) functionName = JSC::asInternalFunction(callee)->name(&frame->globalData()); - if (callee && callee->isObject(&JSC::JSFunction::info)) { + if (callee && callee->inherits(&JSC::JSFunction::info)) { functionType = QScriptContextInfo::ScriptFunction; - JSC::FunctionBodyNode *body = JSC::asFunction(callee)->body(); - functionStartLineNumber = body->firstLine(); + JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable(); + functionStartLineNumber = body->lineNo(); functionEndLineNumber = body->lastLine(); - const JSC::Identifier* params = body->parameters(); for (size_t i = 0; i < body->parameterCount(); ++i) - parameterNames.append(params[i].ustring()); + parameterNames.append(body->parameterName(i)); // ### get the function name from the AST - } else if (callee && callee->isObject(&QScript::QtFunction::info)) { + } else if (callee && callee->inherits(&QScript::QtFunction::info)) { functionType = QScriptContextInfo::QtFunction; // ### the slot can be overloaded -- need to get the particular overload from the context functionMetaIndex = static_cast<QScript::QtFunction*>(callee)->initialIndex(); @@ -221,7 +220,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte parameterNames.append(QLatin1String(formals.at(i))); } } - else if (callee && callee->isObject(&QScript::QtPropertyFunction::info)) { + else if (callee && callee->inherits(&QScript::QtPropertyFunction::info)) { functionType = QScriptContextInfo::QtPropertyFunction; functionMetaIndex = static_cast<QScript::QtPropertyFunction*>(callee)->propertyIndex(); } diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index e39e1d1..b27d1be 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -348,7 +348,7 @@ struct GlobalClientData : public JSC::JSGlobalData::ClientData GlobalClientData(QScriptEnginePrivate *e) : engine(e) {} virtual ~GlobalClientData() {} - virtual void mark() { engine->mark(); } + virtual void mark(JSC::MarkStack& markStack) { engine->mark(markStack); } QScriptEnginePrivate *engine; }; @@ -382,6 +382,65 @@ private: bool m_shouldAbortEvaluation; }; +/*Helper class. Main purpose is to give debugger feedback about unloading and loading scripts. + It keeps pointer to JSGlobalObject assuming that it is always the same - there is no way to update + this data. Class is internal and used as an implementation detail in and only in QScriptEngine::evaluate.*/ +class UStringSourceProviderWithFeedback: public JSC::UStringSourceProvider +{ +public: + + static PassRefPtr<UStringSourceProviderWithFeedback> create(const JSC::UString& source, const JSC::UString& url, int lineNumber, QScriptEnginePrivate* engine) + { + return adoptRef(new UStringSourceProviderWithFeedback(source, url, lineNumber, engine)); + } + + /* Destruction means that there is no more copies of script so create scriptUnload event + and unregister script in QScriptEnginePrivate::loadedScripts */ + virtual ~UStringSourceProviderWithFeedback() + { + if (m_ptr) { + if (JSC::Debugger* debugger = this->debugger()) + debugger->scriptUnload(asID()); + m_ptr->loadedScripts.remove(this); + } + } + + /* set internal QScriptEnginePrivate pointer to null and create unloadScript event, should be called + only if QScriptEnginePrivate is about to be destroyed.*/ + void disconnectFromEngine() + { + if (JSC::Debugger* debugger = this->debugger()) + debugger->scriptUnload(asID()); + m_ptr = 0; + } + +protected: + UStringSourceProviderWithFeedback(const JSC::UString& source, const JSC::UString& url, int lineNumber, QScriptEnginePrivate* engine) + : UStringSourceProvider(source, url), + m_ptr(engine) + { + if (JSC::Debugger* debugger = this->debugger()) + debugger->scriptLoad(asID(), source, url, lineNumber); + if (m_ptr) + m_ptr->loadedScripts.insert(this); + } + + JSC::Debugger* debugger() + { + //if m_ptr is null it mean that QScriptEnginePrivate was destroyed and scriptUnload was called + //else m_ptr is stable and we can use it as normal pointer without hesitation + if(!m_ptr) + return 0; //we are in ~QScriptEnginePrivate + else + return m_ptr->originalGlobalObject()->debugger(); //QScriptEnginePrivate is still alive + } + + //trace global object and debugger instance + QScriptEnginePrivate* m_ptr; +}; + + + static int toDigit(char c) { if ((c >= '0') && (c <= '9')) @@ -508,6 +567,7 @@ JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState *exec, JSC::JSObjec slot = arg1; else { // ### don't go via QScriptValue + QScript::SaveFrameHelper saveFrame(engine, exec); QScriptValue tmp = engine->scriptValueFromJSCValue(arg0); QString propertyName(arg1.toString(exec)); slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype)); @@ -591,6 +651,7 @@ JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState *exec, JSC::JSObject * slot = arg1; else { // ### don't go via QScriptValue + QScript::SaveFrameHelper saveFrame(engine, exec); QScriptValue tmp = engine->scriptValueFromJSCValue(arg0); QString propertyName = arg1.toString(exec); slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype)); @@ -803,6 +864,7 @@ QScriptEnginePrivate::QScriptEnginePrivate() JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject(); JSC::ExecState* exec = globalObject->globalExec(); + *thisRegisterForFrame(exec) = JSC::JSValue(); scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype()); @@ -837,8 +899,16 @@ QScriptEnginePrivate::QScriptEnginePrivate() QScriptEnginePrivate::~QScriptEnginePrivate() { + //disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events + QSet<QScript::UStringSourceProviderWithFeedback*>::const_iterator i = loadedScripts.constBegin(); + while(i!=loadedScripts.constEnd()) { + (*i)->disconnectFromEngine(); + i++; + } + while (!ownedAgents.isEmpty()) delete ownedAgents.takeFirst(); + detachAllRegisteredScriptValues(); detachAllRegisteredScriptStrings(); qDeleteAll(m_qobjectData); @@ -1077,11 +1147,17 @@ JSC::JSValue QScriptEnginePrivate::thisForContext(JSC::ExecState *frame) if (frame->codeBlock() != 0) { return frame->thisValue(); } else { - JSC::Register* thisRegister = frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount(); + JSC::Register *thisRegister = thisRegisterForFrame(frame); return thisRegister->jsValue(); } } +JSC::Register* QScriptEnginePrivate::thisRegisterForFrame(JSC::ExecState *frame) +{ + Q_ASSERT(frame->codeBlock() == 0); // only for native calls + return frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount(); +} + /*! \internal For native context, we use the ReturnValueRegister entry in the stackframe header to store flags. We can do that because this header is not used as the native function return their value thought C++ @@ -1106,27 +1182,25 @@ void QScriptEnginePrivate::setContextFlags(JSC::ExecState *exec, uint flags) } -void QScriptEnginePrivate::mark() +void QScriptEnginePrivate::mark(JSC::MarkStack& markStack) { - if (!originalGlobalObject()->marked()) - originalGlobalObject()->mark(); - if (!globalObject()->marked()) - globalObject()->mark(); - if (originalGlobalObjectProxy && !originalGlobalObjectProxy->marked()) - originalGlobalObjectProxy->mark(); + markStack.append(originalGlobalObject()); + markStack.append(globalObject()); + if (originalGlobalObjectProxy) + markStack.append(originalGlobalObjectProxy); - if (qobjectPrototype && !qobjectPrototype->marked()) - qobjectPrototype->mark(); - if (qmetaobjectPrototype && !qmetaobjectPrototype->marked()) - qmetaobjectPrototype->mark(); - if (variantPrototype && !variantPrototype->marked()) - variantPrototype->mark(); + if (qobjectPrototype) + markStack.append(qobjectPrototype); + if (qmetaobjectPrototype) + markStack.append(qmetaobjectPrototype); + if (variantPrototype) + markStack.append(variantPrototype); { QScriptValuePrivate *it; for (it = registeredScriptValues; it != 0; it = it->next) { - if (it->isJSC() && !it->jscValue.marked()) - it->jscValue.mark(); + if (it->isJSC()) + markStack.append(it->jscValue); } } @@ -1135,7 +1209,7 @@ void QScriptEnginePrivate::mark() QHash<QObject*, QScript::QObjectData*>::const_iterator it; for (it = m_qobjectData.constBegin(); it != m_qobjectData.constEnd(); ++it) { QScript::QObjectData *qdata = it.value(); - qdata->mark(); + qdata->mark(markStack); } } #endif @@ -1143,8 +1217,8 @@ void QScriptEnginePrivate::mark() { QHash<int, QScriptTypeInfo*>::const_iterator it; for (it = m_typeInfos.constBegin(); it != m_typeInfos.constEnd(); ++it) { - if ((*it)->prototype && !(*it)->prototype.marked()) - (*it)->prototype.mark(); + if ((*it)->prototype) + markStack.append((*it)->prototype); } } } @@ -1649,7 +1723,7 @@ QScriptValue QScriptEngine::newVariant(const QScriptValue &object, if (!object.isObject()) return newVariant(value); JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue); - if (!jscObject->isObject(&QScriptObject::info)) { + if (!jscObject->inherits(&QScriptObject::info)) { qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported"); return QScriptValue(); } @@ -1726,7 +1800,7 @@ QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject, if (!scriptObject.isObject()) return newQObject(qtObject, ownership, options); JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue); - if (!jscObject->isObject(&QScriptObject::info)) { + if (!jscObject->inherits(&QScriptObject::info)) { qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported"); return QScriptValue(); } @@ -2128,6 +2202,7 @@ QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &progra \sa canEvaluate(), hasUncaughtException(), isEvaluating(), abortEvaluation() */ + QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber) { Q_D(QScriptEngine); @@ -2136,41 +2211,40 @@ QScriptValue QScriptEngine::evaluate(const QString &program, const QString &file QBoolBlocker inEval(d->inEval, true); currentContext()->activationObject(); //force the creation of a context for native function; + JSC::Debugger* debugger = d->originalGlobalObject()->debugger(); + JSC::UString jscProgram = program; JSC::UString jscFileName = fileName; JSC::ExecState* exec = d->currentFrame; - JSC::SourceCode source = JSC::makeSource(jscProgram, jscFileName, lineNumber); + WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider + = QScript::UStringSourceProviderWithFeedback::create(jscProgram, jscFileName, lineNumber, d); + intptr_t sourceId = provider->asID(); + JSC::SourceCode source(provider, lineNumber); //after construction of SourceCode provider variable will be null. - intptr_t sourceId = source.provider()->asID(); - JSC::Debugger* debugger = d->originalGlobalObject()->debugger(); - exec->globalData().scriptpool->startEvaluating(source); if (debugger) debugger->evaluateStart(sourceId); exec->clearException(); JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject()); - int errorLine; - JSC::UString errorMessage; - WTF::RefPtr<JSC::EvalNode> evalNode = exec->globalData().parser->parse<JSC::EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errorLine, &errorMessage); - if (!evalNode) { - JSC::JSValue exceptionValue = JSC::Error::create(exec, JSC::SyntaxError, errorMessage, errorLine, source.provider()->asID(), 0); - exec->setException(exceptionValue); + JSC::EvalExecutable executable(source); + JSC::JSObject* error = executable.compile(exec, exec->scopeChain()); + if (error) { + exec->setException(error); if (debugger) { - debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, exceptionValue), sourceId, false); - debugger->evaluateStop(exceptionValue, sourceId); + debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, error), sourceId, false); + debugger->evaluateStop(error, sourceId); } - exec->globalData().scriptpool->stopEvaluating(source); - return d->scriptValueFromJSCValue(exceptionValue); + return d->scriptValueFromJSCValue(error); } JSC::JSValue thisValue = d->thisForContext(exec); JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); JSC::JSValue exceptionValue; d->timeoutChecker()->setShouldAbort(false); - JSC::JSValue result = exec->interpreter()->execute(evalNode.get(), exec, thisObject, exec->scopeChain(), &exceptionValue); + JSC::JSValue result = exec->interpreter()->execute(&executable, exec, thisObject, exec->scopeChain(), &exceptionValue); if (d->timeoutChecker()->shouldAbort()) { if (d->abortResult.isError()) @@ -2178,7 +2252,6 @@ QScriptValue QScriptEngine::evaluate(const QString &program, const QString &file if (debugger) debugger->evaluateStop(d->scriptValueToJSCValue(d->abortResult), sourceId); - exec->globalData().scriptpool->stopEvaluating(source); return d->abortResult; } @@ -2188,14 +2261,12 @@ QScriptValue QScriptEngine::evaluate(const QString &program, const QString &file if (debugger) debugger->evaluateStop(exceptionValue, sourceId); - exec->globalData().scriptpool->stopEvaluating(source); return d->scriptValueFromJSCValue(exceptionValue); } if (debugger) debugger->evaluateStop(result, sourceId); - exec->globalData().scriptpool->stopEvaluating(source); Q_ASSERT(!exec->hadException()); return d->scriptValueFromJSCValue(result); @@ -2282,23 +2353,25 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV //build a frame JSC::CallFrame *newCallFrame = exec; if (callee == 0 //called from public QScriptEngine::pushContext - || exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call + || exec->returnPC() == 0 || (contextFlags(exec) & NativeContext) //called from native-native call || (exec->codeBlock() && exec->callee() != callee)) { //the interpreter did not build a frame for us. //We need to check if the Interpreter might have already created a frame for function called from JS. JSC::Interpreter *interp = exec->interpreter(); JSC::Register *oldEnd = interp->registerFile().end(); int argc = args.size() + 1; //add "this" JSC::Register *newEnd = oldEnd + argc + JSC::RegisterFile::CallFrameHeaderSize; - if (!interp->registerFile().grow(newEnd)) + //Without + argc + JSC::RegisterFile::CallFrameHeaderSize, it crashes. + //It seems that JSC is not consistant with the way the callframe is crated + if (!interp->registerFile().grow(newEnd + argc + JSC::RegisterFile::CallFrameHeaderSize)) return 0; //### Stack overflow - newCallFrame = JSC::CallFrame::create(oldEnd); + newCallFrame = JSC::CallFrame::create(newEnd); newCallFrame[0] = thisObject; int dst = 0; JSC::ArgList::const_iterator it; for (it = args.begin(); it != args.end(); ++it) newCallFrame[++dst] = *it; newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; - newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags, argc, callee); + newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } else { setContextFlags(newCallFrame, flags); #if ENABLE(JIT) @@ -2306,7 +2379,7 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV #endif if (calledAsConstructor) { //update the new created this - JSC::Register* thisRegister = newCallFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - newCallFrame->argumentCount(); + JSC::Register* thisRegister = thisRegisterForFrame(newCallFrame); *thisRegister = thisObject; } } @@ -2340,18 +2413,19 @@ void QScriptEngine::popContext() */ void QScriptEnginePrivate::popContext() { - bool hasScope = contextFlags(currentFrame) & HasScopeContext; - if (currentFrame->returnPC() == 0) { //normal case + uint flags = contextFlags(currentFrame); + bool hasScope = flags & HasScopeContext; + if (flags & ShouldRestoreCallFrame) { //normal case JSC::RegisterFile ®isterFile = currentFrame->interpreter()->registerFile(); JSC::Register *const newEnd = currentFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - currentFrame->argumentCount(); if (hasScope) currentFrame->scopeChain()->pop()->deref(); - currentFrame = currentFrame->callerFrame(); registerFile.shrink(newEnd); } else if(hasScope) { //the stack frame was created by the Interpreter, we don't need to rewind it. currentFrame->setScopeChain(currentFrame->scopeChain()->pop()); currentFrame->scopeChain()->deref(); } + currentFrame = currentFrame->callerFrame(); } /*! diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index b36787b..b8b805e 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -100,6 +100,8 @@ namespace QScript //some conversion helper functions QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec); bool isFunction(JSC::JSValue value); + + class UStringSourceProviderWithFeedback; } class QScriptEnginePrivate @@ -154,12 +156,13 @@ public: JSC::ExecState *globalExec() const; JSC::JSValue toUsableValue(JSC::JSValue value); static JSC::JSValue thisForContext(JSC::ExecState *frame); + static JSC::Register *thisRegisterForFrame(JSC::ExecState *frame); JSC::CallFrame *pushContext(JSC::CallFrame *exec, JSC::JSValue thisObject, const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor = false); void popContext(); - void mark(); + void mark(JSC::MarkStack& markStack); bool isCollecting() const; void collectGarbage(); @@ -167,7 +170,8 @@ public: enum ContextFlags { NativeContext = 1, CalledAsConstructorContext = 2, - HasScopeContext = 4 + HasScopeContext = 4, // Specifies that the is a QScriptActivationObject + ShouldRestoreCallFrame = 8 }; static uint contextFlags(JSC::ExecState *); static void setContextFlags(JSC::ExecState *, uint); @@ -254,6 +258,8 @@ public: QSet<QString> importedExtensions; QSet<QString> extensionsBeingImported; + + QSet<QScript::UStringSourceProviderWithFeedback*> loadedScripts; #ifndef QT_NO_QOBJECT QHash<QObject*, QScript::QObjectData*> m_qobjectData; @@ -264,6 +270,29 @@ public: #endif }; +namespace QScript +{ + +class SaveFrameHelper +{ +public: + SaveFrameHelper(QScriptEnginePrivate *eng, + JSC::ExecState *newFrame) + : engine(eng), oldFrame(eng->currentFrame) + { + eng->currentFrame = newFrame; + } + ~SaveFrameHelper() + { + engine->currentFrame = oldFrame; + } +private: + QScriptEnginePrivate *engine; + JSC::ExecState *oldFrame; +}; + +} // namespace QScript + inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size) { if (freeScriptValues) { diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 2ca036a..f2716e4 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -399,7 +399,10 @@ QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const JSC::Identi JSC::ExecState *exec = engine->currentFrame; JSC::JSObject *object = JSC::asObject(jscValue); unsigned attribs = 0; - if (!object->getPropertyAttributes(exec, id, attribs)) { + JSC::PropertyDescriptor descriptor; + if (object->getOwnPropertyDescriptor(exec, id, descriptor)) + attribs = descriptor.attributes(); + else if (!object->getPropertyAttributes(exec, id, attribs)) { if ((mode & QScriptValue::ResolvePrototype) && object->prototype() && object->prototype().isObject()) { QScriptValue proto = engine->scriptValueFromJSCValue(object->prototype()); return QScriptValuePrivate::get(proto)->propertyFlags(id, mode); @@ -426,7 +429,7 @@ QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const JSC::Identi QVariant &QScriptValuePrivate::variantValue() const { - Q_ASSERT(jscValue.isObject(&QScriptObject::info)); + Q_ASSERT(jscValue.inherits(&QScriptObject::info)); QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(jscValue))->delegate(); Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant)); return static_cast<QScript::QVariantDelegate*>(delegate)->value(); @@ -434,7 +437,7 @@ QVariant &QScriptValuePrivate::variantValue() const void QScriptValuePrivate::setVariantValue(const QVariant &value) { - Q_ASSERT(jscValue.isObject(&QScriptObject::info)); + Q_ASSERT(jscValue.inherits(&QScriptObject::info)); QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(jscValue))->delegate(); Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant)); static_cast<QScript::QVariantDelegate*>(delegate)->setValue(value); @@ -560,13 +563,8 @@ QScriptValue::QScriptValue(QScriptEngine *engine, int val) if (engine) { JSC::ExecState *exec = d_ptr->engine->currentFrame; d_ptr->initFrom(JSC::jsNumber(exec, val)); - } else { - JSC::JSValue immediate = JSC::JSImmediate::from(val); - if (immediate) - d_ptr->initFrom(immediate); - else - d_ptr->initFrom(val); - } + } else + d_ptr->initFrom(val); } /*! @@ -582,13 +580,8 @@ QScriptValue::QScriptValue(QScriptEngine *engine, uint val) if (engine) { JSC::ExecState *exec = d_ptr->engine->currentFrame; d_ptr->initFrom(JSC::jsNumber(exec, val)); - } else { - JSC::JSValue immediate = JSC::JSImmediate::from(val); - if (immediate) - d_ptr->initFrom(immediate); - else - d_ptr->initFrom(val); - } + } else + d_ptr->initFrom(val); } /*! @@ -604,13 +597,8 @@ QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val) if (engine) { JSC::ExecState *exec = d_ptr->engine->currentFrame; d_ptr->initFrom(JSC::jsNumber(exec, val)); - } else { - JSC::JSValue immediate = JSC::JSImmediate::from(val); - if (immediate) - d_ptr->initFrom(immediate); - else - d_ptr->initFrom(val); - } + } else + d_ptr->initFrom(val); } /*! @@ -689,11 +677,7 @@ QScriptValue::QScriptValue(bool value) QScriptValue::QScriptValue(int value) : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) { - JSC::JSValue immediate = JSC::JSImmediate::from(value); - if (immediate) - d_ptr->initFrom(immediate); - else - d_ptr->initFrom(value); + d_ptr->initFrom(value); } /*! @@ -704,11 +688,7 @@ QScriptValue::QScriptValue(int value) QScriptValue::QScriptValue(uint value) : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) { - JSC::JSValue immediate = JSC::JSImmediate::from(value); - if (immediate) - d_ptr->initFrom(immediate); - else - d_ptr->initFrom(value); + d_ptr->initFrom(value); } /*! @@ -719,11 +699,7 @@ QScriptValue::QScriptValue(uint value) QScriptValue::QScriptValue(qsreal value) : d_ptr(new (/*engine=*/0)QScriptValuePrivate(/*engine=*/0)) { - JSC::JSValue immediate = JSC::JSImmediate::from(value); - if (immediate) - d_ptr->initFrom(immediate); - else - d_ptr->initFrom(value); + d_ptr->initFrom(value); } /*! @@ -786,7 +762,7 @@ bool QScriptValue::isError() const Q_D(const QScriptValue); if (!d || !d->isObject()) return false; - return d->jscValue.isObject(&JSC::ErrorInstance::info); + return d->jscValue.inherits(&JSC::ErrorInstance::info); } /*! @@ -800,7 +776,7 @@ bool QScriptValue::isArray() const Q_D(const QScriptValue); if (!d || !d->isObject()) return false; - return d->jscValue.isObject(&JSC::JSArray::info); + return d->jscValue.inherits(&JSC::JSArray::info); } /*! @@ -814,7 +790,7 @@ bool QScriptValue::isDate() const Q_D(const QScriptValue); if (!d || !d->isObject()) return false; - return d->jscValue.isObject(&JSC::DateInstance::info); + return d->jscValue.inherits(&JSC::DateInstance::info); } /*! @@ -828,7 +804,7 @@ bool QScriptValue::isRegExp() const Q_D(const QScriptValue); if (!d || !d->isObject()) return false; - return d->jscValue.isObject(&JSC::RegExpObject::info); + return d->jscValue.inherits(&JSC::RegExpObject::info); } /*! @@ -1180,11 +1156,6 @@ bool QScriptValue::equals(const QScriptValue &other) const QScriptValuePrivate::saveException(exec, &savedException); bool result = JSC::JSValue::equal(exec, d->jscValue, other.d_ptr->jscValue); QScriptValuePrivate::restoreException(exec, savedException); - // special QtScript rules - if (!result && isQObject() && other.isQObject()) - result = (toQObject() == other.toQObject()); - else if (!result && isVariant() && other.isVariant()) - result = (toVariant() == other.toVariant()); return result; } } @@ -1224,8 +1195,15 @@ bool QScriptValue::strictlyEquals(const QScriptValue &other) const "a different engine"); return false; } - if (d->type != other.d_ptr->type) + + if (d->type != other.d_ptr->type) { + if (d->type == QScriptValuePrivate::JavaScriptCore) + return JSC::JSValue::strictEqual(d->jscValue, d->engine->scriptValueToJSCValue(other)); + else if (other.d_ptr->type == QScriptValuePrivate::JavaScriptCore) + return JSC::JSValue::strictEqual(other.d_ptr->engine->scriptValueToJSCValue(*this), other.d_ptr->jscValue); + return false; + } switch (d->type) { case QScriptValuePrivate::JavaScriptCore: return JSC::JSValue::strictEqual(d->jscValue, other.d_ptr->jscValue); @@ -2284,7 +2262,7 @@ bool QScriptValue::isObject() const bool QScriptValue::isVariant() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) return false; QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = object->delegate(); @@ -2303,7 +2281,7 @@ bool QScriptValue::isVariant() const bool QScriptValue::isQObject() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) return false; QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = object->delegate(); @@ -2321,7 +2299,7 @@ bool QScriptValue::isQMetaObject() const Q_D(const QScriptValue); if (!d || !d->isObject()) return false; - return JSC::asObject(d->jscValue)->isObject(&QScript::QMetaObjectWrapperObject::info); + return JSC::asObject(d->jscValue)->inherits(&QScript::QMetaObjectWrapperObject::info); } /*! @@ -2347,7 +2325,7 @@ QScriptValue QScriptValue::data() const Q_D(const QScriptValue); if (!d || !d->isObject()) return QScriptValue(); - if (d->jscValue.isObject(&QScriptObject::info)) { + if (d->jscValue.inherits(&QScriptObject::info)) { QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); return d->engine->scriptValueFromJSCValue(scriptObject->data()); } else { @@ -2370,7 +2348,7 @@ void QScriptValue::setData(const QScriptValue &data) if (!d || !d->isObject()) return; JSC::JSValue other = d->engine->scriptValueToJSCValue(data); - if (d->jscValue.isObject(&QScriptObject::info)) { + if (d->jscValue.inherits(&QScriptObject::info)) { QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); scriptObject->setData(other); } else { @@ -2396,7 +2374,7 @@ void QScriptValue::setData(const QScriptValue &data) QScriptClass *QScriptValue::scriptClass() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info)) return 0; QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); @@ -2423,18 +2401,22 @@ void QScriptValue::setScriptClass(QScriptClass *scriptClass) Q_D(QScriptValue); if (!d || !d->isObject()) return; - if (!d->jscValue.isObject(&QScriptObject::info)) { + if (!d->jscValue.inherits(&QScriptObject::info)) { qWarning("QScriptValue::setScriptClass() failed: " "cannot change class of non-QScriptObject"); return; } QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); - QScriptObjectDelegate *delegate = scriptObject->delegate(); - if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) { - delegate = new QScript::ClassObjectDelegate(scriptClass); - scriptObject->setDelegate(delegate); + if (!scriptClass) { + scriptObject->setDelegate(0); + } else { + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) { + delegate = new QScript::ClassObjectDelegate(scriptClass); + scriptObject->setDelegate(delegate); + } + static_cast<QScript::ClassObjectDelegate*>(delegate)->setScriptClass(scriptClass); } - static_cast<QScript::ClassObjectDelegate*>(delegate)->setScriptClass(scriptClass); } /*! diff --git a/src/script/api/qscriptvalueiterator.cpp b/src/script/api/qscriptvalueiterator.cpp index 5bba327..cf27af6 100644 --- a/src/script/api/qscriptvalueiterator.cpp +++ b/src/script/api/qscriptvalueiterator.cpp @@ -110,7 +110,7 @@ public: JSC::ExecState *exec = eng_p->globalExec(); JSC::PropertyNameArray propertyNamesArray(exec); propertyNamesArray.setShouldCache(false); - JSC::asObject(QScriptValuePrivate::get(object)->jscValue)->getPropertyNames(exec, propertyNamesArray, JSC::Structure::NonEnumerable); + JSC::asObject(QScriptValuePrivate::get(object)->jscValue)->getOwnPropertyNames(exec, propertyNamesArray, /*includeNonEnumerable=*/true); JSC::PropertyNameArray::const_iterator propertyNamesIt = propertyNamesArray.begin(); for(; propertyNamesIt != propertyNamesArray.end(); ++propertyNamesIt) { diff --git a/src/script/bridge/qscriptactivationobject.cpp b/src/script/bridge/qscriptactivationobject.cpp index fea8f44..edccb3e 100644 --- a/src/script/bridge/qscriptactivationobject.cpp +++ b/src/script/bridge/qscriptactivationobject.cpp @@ -46,7 +46,7 @@ namespace JSC { - ASSERT_CLASS_FITS_IN_CELL(QScript::QScriptActivationObject); + ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScript::QScriptActivationObject)); } QT_BEGIN_NAMESPACE @@ -88,13 +88,13 @@ bool QScriptActivationObject::getPropertyAttributes(JSC::ExecState* exec, const return JSC::JSVariableObject::getPropertyAttributes(exec, propertyName, attributes); } -void QScriptActivationObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, unsigned listedAttributes) +void QScriptActivationObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, bool includeNonEnumerable) { if (d_ptr()->delegate != 0) { - d_ptr()->delegate->getPropertyNames(exec, propertyNames, listedAttributes); + d_ptr()->delegate->getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); return; } - return JSC::JSVariableObject::getPropertyNames(exec, propertyNames, listedAttributes); + return JSC::JSVariableObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } void QScriptActivationObject::putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes) diff --git a/src/script/bridge/qscriptactivationobject_p.h b/src/script/bridge/qscriptactivationobject_p.h index f45845d..f313f90 100644 --- a/src/script/bridge/qscriptactivationobject_p.h +++ b/src/script/bridge/qscriptactivationobject_p.h @@ -70,7 +70,7 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, bool includeNonEnumerable = false); 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&); diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index b85fa5e..0d88532 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -77,6 +77,7 @@ QScriptClass *ClassObjectDelegate::scriptClass() const void ClassObjectDelegate::setScriptClass(QScriptClass *scriptClass) { + Q_ASSERT(scriptClass != 0); m_scriptClass = scriptClass; } @@ -90,12 +91,13 @@ bool ClassObjectDelegate::getOwnPropertySlot(QScriptObject* object, const JSC::Identifier &propertyName, JSC::PropertySlot &slot) { + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScript::SaveFrameHelper saveFrame(engine, exec); // for compatibility with the old back-end, normal JS properties // are queried first. if (QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot)) return true; - QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); QScriptString scriptName; QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); @@ -116,6 +118,7 @@ void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, JSC::JSValue value, JSC::PutPropertySlot &slot) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScript::SaveFrameHelper saveFrame(engine, exec); QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); QScriptString scriptName; QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); @@ -136,6 +139,7 @@ bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState * { // ### avoid duplication of put() QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScript::SaveFrameHelper saveFrame(engine, exec); QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); QScriptString scriptName; QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); @@ -157,6 +161,7 @@ bool ClassObjectDelegate::getPropertyAttributes(const QScriptObject* object, JSC 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); @@ -183,11 +188,12 @@ bool ClassObjectDelegate::getPropertyAttributes(const QScriptObject* object, JSC return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs); } -void ClassObjectDelegate::getPropertyNames(QScriptObject* object, JSC::ExecState *exec, - JSC::PropertyNameArray &propertyNames, - unsigned listedAttributes) +void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec, + JSC::PropertyNameArray &propertyNames, + bool includeNonEnumerable) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScript::SaveFrameHelper saveFrame(engine, exec); QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); QScriptClassPropertyIterator *it = m_scriptClass->newIterator(scriptObject); if (it != 0) { @@ -198,7 +204,7 @@ void ClassObjectDelegate::getPropertyNames(QScriptObject* object, JSC::ExecState } delete it; } - QScriptObjectDelegate::getPropertyNames(object, exec, propertyNames, listedAttributes); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); } JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &callData) @@ -212,7 +218,7 @@ JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &ca JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC::JSObject *callee, JSC::JSValue thisValue, const JSC::ArgList &args) { - if (!callee->isObject(&QScriptObject::info)) + if (!callee->inherits(&QScriptObject::info)) return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object"); QScriptObject *obj = static_cast<QScriptObject*>(callee); QScriptObjectDelegate *delegate = obj->delegate(); @@ -243,7 +249,7 @@ JSC::ConstructType ClassObjectDelegate::getConstructData(QScriptObject*, JSC::Co JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObject *callee, const JSC::ArgList &args) { - Q_ASSERT(callee->isObject(&QScriptObject::info)); + Q_ASSERT(callee->inherits(&QScriptObject::info)); QScriptObject *obj = static_cast<QScriptObject*>(callee); QScriptObjectDelegate *delegate = obj->delegate(); QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass(); @@ -267,6 +273,7 @@ bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exe return QScriptObjectDelegate::hasInstance(object, exec, value, proto); QScriptValueList args; QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); + QScript::SaveFrameHelper saveFrame(eng_p, exec); args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value); QVariant result = scriptClass()->extension(QScriptClass::HasInstance, qVariantFromValue(args)); return result.toBool(); diff --git a/src/script/bridge/qscriptclassobject_p.h b/src/script/bridge/qscriptclassobject_p.h index 253e406..f5cce76 100644 --- a/src/script/bridge/qscriptclassobject_p.h +++ b/src/script/bridge/qscriptclassobject_p.h @@ -87,8 +87,9 @@ public: virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getPropertyNames(QScriptObject*, JSC::ExecState*, - JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); + virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, + JSC::PropertyNameArray&, + bool includeNonEnumerable = false); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*, diff --git a/src/script/bridge/qscriptfunction.cpp b/src/script/bridge/qscriptfunction.cpp index 5f419ff..d3767bf 100644 --- a/src/script/bridge/qscriptfunction.cpp +++ b/src/script/bridge/qscriptfunction.cpp @@ -55,8 +55,8 @@ namespace JSC { -ASSERT_CLASS_FITS_IN_CELL(QScript::FunctionWrapper); -ASSERT_CLASS_FITS_IN_CELL(QScript::FunctionWithArgWrapper); +ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScript::FunctionWrapper)); +ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScript::FunctionWithArgWrapper)); } QT_BEGIN_NAMESPACE diff --git a/src/script/bridge/qscriptglobalobject.cpp b/src/script/bridge/qscriptglobalobject.cpp index 17a96c3..c624a31 100644 --- a/src/script/bridge/qscriptglobalobject.cpp +++ b/src/script/bridge/qscriptglobalobject.cpp @@ -68,12 +68,11 @@ GlobalObject::~GlobalObject() { } -void GlobalObject::mark() +void GlobalObject::markChildren(JSC::MarkStack& markStack) { - Q_ASSERT(!marked()); - JSC::JSGlobalObject::mark(); - if (customGlobalObject && !customGlobalObject->marked()) - customGlobalObject->mark(); + JSC::JSGlobalObject::markChildren(markStack); + if (customGlobalObject) + markStack.append(customGlobalObject); } bool GlobalObject::getOwnPropertySlot(JSC::ExecState* exec, @@ -125,28 +124,29 @@ bool GlobalObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identi return JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes); } -void GlobalObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, unsigned listedAttributes) +void GlobalObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, + bool includeNonEnumerable) { if (customGlobalObject) - customGlobalObject->getPropertyNames(exec, propertyNames, listedAttributes); + customGlobalObject->getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); else - JSC::JSGlobalObject::getPropertyNames(exec, propertyNames, listedAttributes); + JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } -void GlobalObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction) +void GlobalObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes) { if (customGlobalObject) - customGlobalObject->defineGetter(exec, propertyName, getterFunction); + customGlobalObject->defineGetter(exec, propertyName, getterFunction, attributes); else - JSC::JSGlobalObject::defineGetter(exec, propertyName, getterFunction); + JSC::JSGlobalObject::defineGetter(exec, propertyName, getterFunction, attributes); } -void GlobalObject::defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction) +void GlobalObject::defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes) { if (customGlobalObject) - customGlobalObject->defineSetter(exec, propertyName, setterFunction); + customGlobalObject->defineSetter(exec, propertyName, setterFunction, attributes); else - JSC::JSGlobalObject::defineSetter(exec, propertyName, setterFunction); + JSC::JSGlobalObject::defineSetter(exec, propertyName, setterFunction, attributes); } JSC::JSValue GlobalObject::lookupGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName) diff --git a/src/script/bridge/qscriptglobalobject_p.h b/src/script/bridge/qscriptglobalobject_p.h index 70458a7..01784c2 100644 --- a/src/script/bridge/qscriptglobalobject_p.h +++ b/src/script/bridge/qscriptglobalobject_p.h @@ -68,7 +68,7 @@ public: GlobalObject(); virtual ~GlobalObject(); virtual JSC::UString className() const { return "global"; } - virtual void mark(); + virtual void markChildren(JSC::MarkStack&); virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); @@ -81,10 +81,10 @@ public: bool checkDontDelete = true); virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, - unsigned listedAttributes = JSC::Structure::Prototype); - virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction); - virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, + bool includeNonEnumerable = false); + 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); virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName); @@ -103,12 +103,10 @@ public: {} virtual JSC::UString className() const { return originalGlobalObject->className(); } - virtual void mark() + virtual void markChildren(JSC::MarkStack& markStack) { - Q_ASSERT(!marked()); - if (!originalGlobalObject->marked()) - originalGlobalObject->JSC::JSGlobalObject::mark(); - JSC::JSObject::mark(); + markStack.append(originalGlobalObject); + JSC::JSObject::markChildren(markStack); } virtual bool getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, @@ -125,13 +123,12 @@ public: virtual bool getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, unsigned& attributes) const { return originalGlobalObject->JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes); } - virtual void getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, - unsigned listedAttributes = JSC::Structure::Prototype) - { originalGlobalObject->JSC::JSGlobalObject::getPropertyNames(exec, propertyNames, listedAttributes); } - virtual void defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction) - { originalGlobalObject->JSC::JSGlobalObject::defineGetter(exec, propertyName, getterFunction); } - virtual void defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction) - { originalGlobalObject->JSC::JSGlobalObject::defineSetter(exec, propertyName, setterFunction); } + virtual void getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, bool includeNonEnumerable = false) + { originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } + 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) + { originalGlobalObject->JSC::JSGlobalObject::defineSetter(exec, propertyName, setterFunction, attributes); } virtual JSC::JSValue lookupGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName) { return originalGlobalObject->JSC::JSGlobalObject::lookupGetter(exec, propertyName); } virtual JSC::JSValue lookupSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName) diff --git a/src/script/bridge/qscriptobject.cpp b/src/script/bridge/qscriptobject.cpp index d46765a..55644fe 100644 --- a/src/script/bridge/qscriptobject.cpp +++ b/src/script/bridge/qscriptobject.cpp @@ -46,8 +46,8 @@ namespace JSC { //QT_USE_NAMESPACE -ASSERT_CLASS_FITS_IN_CELL(QScriptObject); -ASSERT_CLASS_FITS_IN_CELL(QScriptObjectPrototype); +ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScriptObject)); +ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScriptObjectPrototype)); } QT_BEGIN_NAMESPACE @@ -136,30 +136,38 @@ bool QScriptObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Ident return d->delegate->getPropertyAttributes(this, exec, propertyName, attributes); } -void QScriptObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, unsigned listedAttributes) +void QScriptObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, + bool includeNonEnumerable) { if (!d || !d->delegate) { - JSC::JSObject::getPropertyNames(exec, propertyNames, listedAttributes); + JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); return; } - d->delegate->getPropertyNames(this, exec, propertyNames, listedAttributes); + d->delegate->getOwnPropertyNames(this, exec, propertyNames, includeNonEnumerable); } -void QScriptObject::mark() +bool QScriptObject::compareToObject(JSC::ExecState* exec, JSC::JSObject *other) +{ + if (!d || !d->delegate) { + return JSC::JSObject::compareToObject(exec, other); + } + return d->delegate->compareToObject(this, exec, other); +} + +void QScriptObject::markChildren(JSC::MarkStack& markStack) { - Q_ASSERT(!marked()); if (!d) d = new Data(); if (d->isMarking) return; QBoolBlocker markBlocker(d->isMarking, true); - if (d && d->data && !d->data.marked()) - d->data.mark(); + if (d && d->data) + markStack.append(d->data); if (!d || !d->delegate) { - JSC::JSObject::mark(); + JSC::JSObject::markChildren(markStack); return; } - d->delegate->mark(this); + d->delegate->markChildren(this, markStack); } JSC::CallType QScriptObject::getCallData(JSC::CallData &data) @@ -226,17 +234,17 @@ bool QScriptObjectDelegate::getPropertyAttributes(const QScriptObject* object, return object->JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); } -void QScriptObjectDelegate::getPropertyNames(QScriptObject* object, JSC::ExecState* exec, - JSC::PropertyNameArray& propertyNames, - unsigned listedAttributes) +void QScriptObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState* exec, + JSC::PropertyNameArray& propertyNames, + bool includeNonEnumerable) { - object->JSC::JSObject::getPropertyNames(exec, propertyNames, listedAttributes); + object->JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } -void QScriptObjectDelegate::mark(QScriptObject* object) +void QScriptObjectDelegate::markChildren(QScriptObject* object, JSC::MarkStack& markStack) { - if (!object->marked()) - object->JSC::JSObject::mark(); + // ### should this call the virtual function instead?? + object->JSC::JSObject::markChildren(markStack); } JSC::CallType QScriptObjectDelegate::getCallData(QScriptObject* object, JSC::CallData& data) @@ -255,4 +263,9 @@ bool QScriptObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState* e return object->JSC::JSObject::hasInstance(exec, value, proto); } +bool QScriptObjectDelegate::compareToObject(QScriptObject* object, JSC::ExecState* exec, JSC::JSObject* o) +{ + return object->JSC::JSObject::compareToObject(exec, o); +} + QT_END_NAMESPACE diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h index 8f4113f..c1cee31 100644 --- a/src/script/bridge/qscriptobject_p.h +++ b/src/script/bridge/qscriptobject_p.h @@ -88,11 +88,13 @@ public: bool checkDontDelete = true); virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); - virtual void mark(); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, + bool includeNonEnumerable = false); + virtual void markChildren(JSC::MarkStack& markStack); virtual JSC::CallType getCallData(JSC::CallData&); virtual JSC::ConstructType getConstructData(JSC::ConstructData&); virtual bool hasInstance(JSC::ExecState*, JSC::JSValue value, JSC::JSValue proto); + virtual bool compareToObject(JSC::ExecState*, JSC::JSObject*); virtual const JSC::ClassInfo* classInfo() const { return &info; } static const JSC::ClassInfo info; @@ -143,13 +145,14 @@ public: bool checkDontDelete = true); virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - unsigned listedAttributes = JSC::Structure::Prototype); - virtual void mark(QScriptObject*); + virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, + bool includeNonEnumerable = false); + virtual void markChildren(QScriptObject*, JSC::MarkStack& markStack); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&); virtual bool hasInstance(QScriptObject*, JSC::ExecState*, JSC::JSValue value, JSC::JSValue proto); + virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*); private: Q_DISABLE_COPY(QScriptObjectDelegate) diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index d603e9f..345489f 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -99,11 +99,12 @@ struct QObjectConnection return (s == slot); } - void mark() + void mark(JSC::MarkStack& markStack) { - if (senderWrapper && !senderWrapper.marked()) { + // ### need to find out if senderWrapper is marked + if (senderWrapper) { // see if the sender should be marked or not - Q_ASSERT(senderWrapper.isObject(&QScriptObject::info)); + Q_ASSERT(senderWrapper.inherits(&QScriptObject::info)); QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(senderWrapper)); QScriptObjectDelegate *delegate = scriptObject->delegate(); Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); @@ -111,15 +112,17 @@ struct QObjectConnection if ((inst->ownership() == QScriptEngine::ScriptOwnership) || ((inst->ownership() == QScriptEngine::AutoOwnership) && inst->value() && !inst->value()->parent())) { - senderWrapper = JSC::JSValue(); + // #### don't mark if not marked otherwise + //senderWrapper = JSC::JSValue(); + markStack.append(senderWrapper); } else { - senderWrapper.mark(); + markStack.append(senderWrapper); } } - if (receiver && !receiver.marked()) - receiver.mark(); - if (slot && !slot.marked()) - slot.mark(); + if (receiver) + markStack.append(receiver); + if (slot) + markStack.append(slot); } }; @@ -154,7 +157,7 @@ public: void execute(int slotIndex, void **argv); - void mark(); + void mark(JSC::MarkStack&); private: QScriptEnginePrivate *engine; @@ -264,12 +267,11 @@ JSC::CallType QtFunction::getCallData(JSC::CallData &callData) return JSC::CallTypeHost; } -void QtFunction::mark() +void QtFunction::markChildren(JSC::MarkStack& markStack) { - Q_ASSERT(!marked()); - if (data->object && !data->object.marked()) - data->object.mark(); - JSC::InternalFunction::mark(); + if (data->object) + markStack.append(data->object); + JSC::InternalFunction::markChildren(markStack); } QScriptObject *QtFunction::wrapperObject() const @@ -988,7 +990,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c JSC::JSValue QtFunction::execute(JSC::ExecState *exec, JSC::JSValue thisValue, const JSC::ArgList &scriptArgs) { - Q_ASSERT(data->object.isObject(&QScriptObject::info)); + Q_ASSERT(data->object.inherits(&QScriptObject::info)); QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(data->object)); QScriptObjectDelegate *delegate = scriptObject->delegate(); Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); @@ -999,7 +1001,7 @@ JSC::JSValue QtFunction::execute(JSC::ExecState *exec, JSC::JSValue thisValue, const QMetaObject *meta = qobj->metaObject(); QObject *thisQObject = 0; thisValue = engine->toUsableValue(thisValue); - if (thisValue.isObject(&QScriptObject::info)) { + if (thisValue.inherits(&QScriptObject::info)) { delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate(); if (delegate && (delegate->type() == QScriptObjectDelegate::QtObject)) thisQObject = static_cast<QScript::QObjectDelegate*>(delegate)->value(); @@ -1021,7 +1023,7 @@ const JSC::ClassInfo QtFunction::info = { "QtFunction", &InternalFunction::info, JSC::JSValue JSC_HOST_CALL QtFunction::call(JSC::ExecState *exec, JSC::JSObject *callee, JSC::JSValue thisValue, const JSC::ArgList &args) { - if (!callee->isObject(&QtFunction::info)) + if (!callee->inherits(&QtFunction::info)) return throwError(exec, JSC::TypeError, "callee is not a QtFunction object"); QtFunction *qfun = static_cast<QtFunction*>(callee); QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); @@ -1060,7 +1062,7 @@ JSC::JSValue JSC_HOST_CALL QtPropertyFunction::call( JSC::ExecState *exec, JSC::JSObject *callee, JSC::JSValue thisValue, const JSC::ArgList &args) { - if (!callee->isObject(&QtPropertyFunction::info)) + 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); @@ -1511,9 +1513,9 @@ bool QObjectDelegate::getPropertyAttributes(const QScriptObject *object, return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attributes); } -void QObjectDelegate::getPropertyNames(QScriptObject *object, JSC::ExecState *exec, - JSC::PropertyNameArray &propertyNames, - unsigned listedAttributes) +void QObjectDelegate::getOwnPropertyNames(QScriptObject *object, JSC::ExecState *exec, + JSC::PropertyNameArray &propertyNames, + bool includeNonEnumerable) { QObject *qobject = data->value; if (!qobject) { @@ -1557,19 +1559,30 @@ void QObjectDelegate::getPropertyNames(QScriptObject *object, JSC::ExecState *ex } } - QScriptObjectDelegate::getPropertyNames(object, exec, propertyNames, listedAttributes); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); } -void QObjectDelegate::mark(QScriptObject *object) +void QObjectDelegate::markChildren(QScriptObject *object, JSC::MarkStack& markStack) { QHash<QByteArray, JSC::JSValue>::const_iterator it; for (it = data->cachedMembers.constBegin(); it != data->cachedMembers.constEnd(); ++it) { JSC::JSValue val = it.value(); - if (val && !val.marked()) - val.mark(); + if (val) + markStack.append(val); } - QScriptObjectDelegate::mark(object); + QScriptObjectDelegate::markChildren(object, markStack); +} + +bool QObjectDelegate::compareToObject(QScriptObject *, JSC::ExecState *exec, JSC::JSObject *o2) +{ + if (!o2->inherits(&QScriptObject::info)) + return false; + QScriptObject *object = static_cast<QScriptObject*>(o2); + QScriptObjectDelegate *delegate = object->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject)) + return false; + return value() == static_cast<QObjectDelegate *>(delegate)->value(); } static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec, JSC::JSObject*, @@ -1577,7 +1590,7 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); thisValue = engine->toUsableValue(thisValue); - if (!thisValue.isObject(&QScriptObject::info)) + if (!thisValue.inherits(&QScriptObject::info)) return throwError(exec, JSC::TypeError, "this object is not a QObject"); QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); @@ -1598,7 +1611,7 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *e QScriptEnginePrivate *engine = scriptEngineFromExec(exec); thisValue = engine->toUsableValue(thisValue); // extract the QObject - if (!thisValue.isObject(&QScriptObject::info)) + if (!thisValue.inherits(&QScriptObject::info)) return throwError(exec, JSC::TypeError, "this object is not a QObject"); QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); @@ -1610,7 +1623,7 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *e QList<QObject *> children; if (args.size() != 0) { const JSC::JSValue arg = args.at(0); - if (arg.isObject(&JSC::RegExpObject::info)) { + if (arg.inherits(&JSC::RegExpObject::info)) { const QObjectList allChildren= obj->children(); JSC::RegExpObject *const regexp = JSC::asRegExpObject(arg); @@ -1650,7 +1663,7 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncToString(JSC::ExecState *exec, { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); thisValue = engine->toUsableValue(thisValue); - if (!thisValue.isObject(&QScriptObject::info)) + if (!thisValue.inherits(&QScriptObject::info)) return JSC::jsUndefined(); QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); @@ -1795,7 +1808,9 @@ bool QMetaObjectWrapperObject::getPropertyAttributes(JSC::ExecState *exec, return JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); } -void QMetaObjectWrapperObject::getPropertyNames(JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, unsigned listedAttributes) +void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState *exec, + JSC::PropertyNameArray &propertyNames, + bool includeNonEnumerable) { const QMetaObject *meta = data->value; if (!meta) @@ -1805,17 +1820,16 @@ void QMetaObjectWrapperObject::getPropertyNames(JSC::ExecState *exec, JSC::Prope for (int j = 0; j < e.keyCount(); ++j) propertyNames.add(JSC::Identifier(exec, e.key(j))); } - JSC::JSObject::getPropertyNames(exec, propertyNames, listedAttributes); + JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } -void QMetaObjectWrapperObject::mark() +void QMetaObjectWrapperObject::markChildren(JSC::MarkStack& markStack) { - Q_ASSERT(!marked()); - if (data->ctor && !data->ctor.marked()) - data->ctor.mark(); - if (data->prototype && !data->prototype.marked()) - data->prototype.mark(); - JSC::JSObject::mark(); + if (data->ctor) + markStack.append(data->ctor); + if (data->prototype) + markStack.append(data->prototype); + JSC::JSObject::markChildren(markStack); } JSC::CallType QMetaObjectWrapperObject::getCallData(JSC::CallData& callData) @@ -1836,7 +1850,7 @@ JSC::JSValue JSC_HOST_CALL QMetaObjectWrapperObject::call( { QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); thisValue = eng_p->toUsableValue(thisValue); - if (!callee->isObject(&QMetaObjectWrapperObject::info)) + if (!callee->inherits(&QMetaObjectWrapperObject::info)) return throwError(exec, JSC::TypeError, "callee is not a QMetaObject"); QMetaObjectWrapperObject *self = static_cast<QMetaObjectWrapperObject*>(callee); JSC::ExecState *previousFrame = eng_p->currentFrame; @@ -1871,12 +1885,12 @@ JSC::JSValue QMetaObjectWrapperObject::execute(JSC::ExecState *exec, JSC::CallType callType = data->ctor.getCallData(callData); Q_UNUSED(callType); Q_ASSERT_X(callType == JSC::CallTypeHost, Q_FUNC_INFO, "script constructors not supported"); - if (data->ctor.isObject(&FunctionWithArgWrapper::info)) { + if (data->ctor.inherits(&FunctionWithArgWrapper::info)) { FunctionWithArgWrapper *wrapper = static_cast<FunctionWithArgWrapper*>(JSC::asObject(data->ctor)); QScriptValue result = wrapper->function()(ctx, QScriptEnginePrivate::get(eng_p), wrapper->arg()); return eng_p->scriptValueToJSCValue(result); } else { - Q_ASSERT(data->ctor.isObject(&FunctionWrapper::info)); + Q_ASSERT(data->ctor.inherits(&FunctionWrapper::info)); FunctionWrapper *wrapper = static_cast<FunctionWrapper*>(JSC::asObject(data->ctor)); QScriptValue result = wrapper->function()(ctx, QScriptEnginePrivate::get(eng_p)); return eng_p->scriptValueToJSCValue(result); @@ -1887,7 +1901,7 @@ JSC::JSValue QMetaObjectWrapperObject::execute(JSC::ExecState *exec, JSC::JSValue result = callQtMethod(exec, QMetaMethod::Constructor, /*thisQObject=*/0, args, meta, meta->constructorCount()-1, /*maybeOverloaded=*/true); if (!exec->hadException()) { - Q_ASSERT(result && result.isObject(&QScriptObject::info)); + Q_ASSERT(result && result.inherits(&QScriptObject::info)); QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(result)); QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(object->delegate()); delegate->setOwnership(QScriptEngine::AutoOwnership); @@ -1914,7 +1928,7 @@ static JSC::JSValue JSC_HOST_CALL qmetaobjectProtoFuncClassName( { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); thisValue = engine->toUsableValue(thisValue); - if (!thisValue.isObject(&QMetaObjectWrapperObject::info)) + if (!thisValue.inherits(&QMetaObjectWrapperObject::info)) return throwError(exec, JSC::TypeError, "this object is not a QMetaObject"); const QMetaObject *meta = static_cast<QMetaObjectWrapperObject*>(JSC::asObject(thisValue))->value(); return JSC::jsString(exec, meta->className()); @@ -2048,7 +2062,7 @@ void QObjectConnectionManager::execute(int slotIndex, void **argv) JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); JSC::JSValue senderObject; - if (senderWrapper && senderWrapper.isObject(&QScriptObject::info)) // ### check if it's actually a QObject wrapper + if (senderWrapper && senderWrapper.inherits(&QScriptObject::info)) // ### check if it's actually a QObject wrapper senderObject = senderWrapper; else { QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; @@ -2081,12 +2095,12 @@ QObjectConnectionManager::~QObjectConnectionManager() { } -void QObjectConnectionManager::mark() +void QObjectConnectionManager::mark(JSC::MarkStack& markStack) { for (int i = 0; i < connections.size(); ++i) { QVector<QObjectConnection> &cs = connections[i]; for (int j = 0; j < cs.size(); ++j) - cs[j].mark(); + cs[j].mark(markStack); } } @@ -2150,19 +2164,18 @@ QObjectData::~QObjectData() } } -void QObjectData::mark() +void QObjectData::mark(JSC::MarkStack& markStack) { if (connectionManager) - connectionManager->mark(); + connectionManager->mark(markStack); { QList<QScript::QObjectWrapperInfo>::iterator it; for (it = wrappers.begin(); it != wrappers.end(); ) { const QScript::QObjectWrapperInfo &info = *it; - if (info.object->marked()) { - ++it; - } else { - it = wrappers.erase(it); - } + // ### don't mark if there are no other references. + // we need something like isMarked() + markStack.append(info.object); + ++it; } } } diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h index ef26c7d..2d482cc 100644 --- a/src/script/bridge/qscriptqobject_p.h +++ b/src/script/bridge/qscriptqobject_p.h @@ -105,9 +105,11 @@ public: virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - unsigned listedAttributes = JSC::Structure::Prototype); - virtual void mark(QScriptObject*); + virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, + JSC::PropertyNameArray&, + bool includeNonEnumerable = false); + virtual void markChildren(QScriptObject*, JSC::MarkStack& markStack); + virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*); inline QObject *value() const { return data->value; } inline void setValue(QObject* value) { data->value = value; } @@ -179,7 +181,7 @@ public: QScriptEngine::ValueOwnership ownership, const QScriptEngine::QObjectWrapOptions &options); - void mark(); + void mark(JSC::MarkStack&); private: QScriptEnginePrivate *engine; @@ -206,7 +208,7 @@ public: virtual ~QtFunction(); virtual JSC::CallType getCallData(JSC::CallData&); - virtual void mark(); + virtual void markChildren(JSC::MarkStack&); virtual const JSC::ClassInfo* classInfo() const { return &info; } static const JSC::ClassInfo info; @@ -295,9 +297,9 @@ public: bool checkDontDelete = true); virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, - unsigned listedAttributes = JSC::Structure::Prototype); - virtual void mark(); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, + bool includeNonEnumerable = false); + virtual void markChildren(JSC::MarkStack& markStack); virtual JSC::CallType getCallData(JSC::CallData&); virtual JSC::ConstructType getConstructData(JSC::ConstructData&); diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp index 583b61c..725f4e0 100644 --- a/src/script/bridge/qscriptvariant.cpp +++ b/src/script/bridge/qscriptvariant.cpp @@ -89,7 +89,7 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncValueOf(JSC::ExecState *exec, { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); thisValue = engine->toUsableValue(thisValue); - if (!thisValue.isObject(&QScriptObject::info)) + if (!thisValue.inherits(&QScriptObject::info)) return throwError(exec, JSC::TypeError); QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate(); if (!delegate || (delegate->type() != QScriptObjectDelegate::Variant)) @@ -127,7 +127,7 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); thisValue = engine->toUsableValue(thisValue); - if (!thisValue.isObject(&QScriptObject::info)) + if (!thisValue.inherits(&QScriptObject::info)) return throwError(exec, JSC::TypeError, "This object is not a QVariant"); QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate(); if (!delegate || (delegate->type() != QScriptObjectDelegate::Variant)) @@ -148,6 +148,12 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, return JSC::jsString(exec, result); } +bool QVariantDelegate::compareToObject(QScriptObject *, JSC::ExecState *exec, JSC::JSObject *o2) +{ + const QVariant &variant1 = value(); + return variant1 == scriptEngineFromExec(exec)->scriptValueFromJSCValue(o2).toVariant(); +} + QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure, JSC::Structure* prototypeFunctionStructure) : QScriptObject(structure) @@ -158,6 +164,7 @@ QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC:: putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, variantProtoFuncValueOf), JSC::DontEnum); } + } // namespace QScript QT_END_NAMESPACE diff --git a/src/script/bridge/qscriptvariant_p.h b/src/script/bridge/qscriptvariant_p.h index 9325396..445ca69 100644 --- a/src/script/bridge/qscriptvariant_p.h +++ b/src/script/bridge/qscriptvariant_p.h @@ -68,6 +68,8 @@ public: QVariantDelegate(const QVariant &value); ~QVariantDelegate(); + virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*); + QVariant &value(); void setValue(const QVariant &value); diff --git a/src/script/script.pro b/src/script/script.pro index 66a11b9..e278f59 100644 --- a/src/script/script.pro +++ b/src/script/script.pro @@ -1,7 +1,7 @@ TARGET = QtScript QPRO_PWD = $$PWD QT = core -DEFINES += JSC=QTJSC +DEFINES += JSC=QTJSC jscyyparse=qtjscyyparse jscyylex=qtjscyylex jscyyerror=qtjscyyerror DEFINES += QT_BUILD_SCRIPT_LIB DEFINES += QT_NO_USING_NAMESPACE DEFINES += QLALR_NO_QSCRIPTGRAMMAR_DEBUG_INFO @@ -11,8 +11,7 @@ unix:QMAKE_PKGCONFIG_REQUIRES = QtCore include(../qbase.pri) -# Disable a few warnings on Windows. -win32-msvc*: QMAKE_CXXFLAGS += -wd4291 -wd4344 -wd4503 -wd4800 -wd4819 -wd4996 -wd4396 -wd4099 +CONFIG += building-libs # disable JIT for now DEFINES += ENABLE_JIT=0 @@ -23,25 +22,16 @@ DEFINES += ENABLE_JIT=0 WEBKITDIR = $$(WEBKITDIR) isEmpty(WEBKITDIR) { WEBKITDIR = $$PWD/../3rdparty/javascriptcore - - # FIXME: not needed once JSCBISON works - # TODO: or leave it like this since the generated file is available anyway? - SOURCES += $$WEBKITDIR/JavaScriptCore/generated/Grammar.cpp - - # avoid warnings when parsing JavaScriptCore.pri - # (we don't care about generating files, we already have them generated) - defineTest(addExtraCompiler) { - return(true) - } - defineTest(addExtraCompilerWithHeader) { - return(true) - } + GENERATED_SOURCES_DIR = generated } else { message(using external WebKit from $$WEBKITDIR) - CONFIG += building-libs CONFIG -= QTDIR_build - include($$WEBKITDIR/WebKit.pri) } +include($$WEBKITDIR/WebKit.pri) + +# Disable a few warnings on Windows. +# These are in addition to the ones disabled in WebKit.pri +win32-msvc*: QMAKE_CXXFLAGS += -wd4396 -wd4099 # Windows CE-specific stuff copied from WebCore.pro # ### Should rather be in JavaScriptCore.pri? @@ -69,10 +59,9 @@ INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/bytecode INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/assembler INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/generated -DEFINES += BUILDING_QT__=1 -DEFINES += USE_SYSTEM_MALLOC -DEFINES += WTF_USE_JAVASCRIPTCORE_BINDINGS=1 -DEFINES += WTF_CHANGES=1 +# This line copied from WebCore.pro +DEFINES += WTF_USE_JAVASCRIPTCORE_BINDINGS=1 WTF_CHANGES=1 + DEFINES += NDEBUG INCLUDEPATH += $$PWD |