From 034d7d1c0893fe2b25379b109a82325fac96f0d1 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 14 Aug 2009 17:01:42 +0200 Subject: push the right object when the argument is the Global Object Since the internal Global Object is never exposed to the public, we need to do like we do in setActivationObject(): if the object passed is the Global Object proxy, use the internal Global Object as the "real" argument. (JSC requires that the initial object pushed onto the scope chain is an instance of JSC::JSGlobalObject, and the Global Object proxy is not; hence, we can't push the proxy.) --- src/script/api/qscriptcontext.cpp | 17 +++++++++++++---- tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 21 +++++++++------------ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 75ad505..e213f3b 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -711,13 +711,22 @@ void QScriptContext::pushScope(const QScriptValue &object) return; } JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); - JSC::JSValue jscObject = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(object); + QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); + JSC::JSObject *jscObject = JSC::asObject(engine->scriptValueToJSCValue(object)); + if (jscObject == engine->originalGlobalObjectProxy) + jscObject = engine->originalGlobalObject(); JSC::ScopeChainNode *scope = frame->scopeChain(); Q_ASSERT(scope != 0); - if (!scope->object) // pushing to an "empty" chain - scope->object = JSC::asObject(jscObject); + if (!scope->object) { + // pushing to an "empty" chain + if (!jscObject->isGlobalObject()) { + qWarning("QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object"); + return; + } + scope->object = jscObject; + } else - frame->setScopeChain(scope->push(JSC::asObject(jscObject))); + frame->setScopeChain(scope->push(jscObject)); } /*! diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index 2f96ea0..17d57a3 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -709,6 +709,11 @@ void tst_QScriptContext::pushAndPopScope() QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); + QVERIFY(ctx->popScope().strictlyEquals(eng.globalObject())); + ctx->pushScope(eng.globalObject()); + QCOMPARE(ctx->scopeChain().size(), 1); + QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); + QScriptValue obj = eng.newObject(); ctx->pushScope(obj); QCOMPARE(ctx->scopeChain().size(), 2); @@ -758,24 +763,16 @@ void tst_QScriptContext::pushAndPopScope() QVERIFY(ctx->popScope().strictlyEquals(eng.globalObject())); QVERIFY(ctx->scopeChain().isEmpty()); + // Used to work with old back-end, doesn't with new one because JSC requires that the last object in + // a scope chain is the Global Object. + QTest::ignoreMessage(QtWarningMsg, "QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object"); ctx->pushScope(obj); - QCOMPARE(ctx->scopeChain().size(), 1); - QVERIFY(ctx->scopeChain().at(0).strictlyEquals(obj)); - QVERIFY(!obj.property("foo").isValid()); -#if 0 // ### CRASHES, JSC expects last scope object to always be the Global Object - eng.evaluate("function foo() {}"); - // function declarations should always end up in the activation object (ECMA-262, chapter 13) - QVERIFY(!obj.property("foo").isValid()); -#endif - QEXPECT_FAIL("", "JSC requires last object in scope chain to be the Global Object", Continue); - QVERIFY(ctx->activationObject().property("foo").isFunction()); + QCOMPARE(ctx->scopeChain().size(), 0); QScriptEngine eng2; QScriptValue obj2 = eng2.newObject(); QTest::ignoreMessage(QtWarningMsg, "QScriptContext::pushScope() failed: cannot push an object created in a different engine"); ctx->pushScope(obj2); - - QVERIFY(ctx->popScope().strictlyEquals(obj)); QVERIFY(ctx->scopeChain().isEmpty()); QVERIFY(!ctx->popScope().isValid()); -- cgit v0.12