diff options
-rw-r--r-- | src/script/api/qscriptcontext.cpp | 17 | ||||
-rw-r--r-- | 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()); |