diff options
Diffstat (limited to 'src')
405 files changed, 20159 insertions, 36080 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/API/JSCallbackObject.h b/src/3rdparty/webkit/JavaScriptCore/API/JSCallbackObject.h index 9d22ad9..4360baa 100644 --- a/src/3rdparty/webkit/JavaScriptCore/API/JSCallbackObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/API/JSCallbackObject.h @@ -61,12 +61,12 @@ private: virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier&); - virtual bool deleteProperty(ExecState*, unsigned); + virtual bool deleteProperty(ExecState*, const Identifier&, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, unsigned, bool checkDontDelete = true); virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; diff --git a/src/3rdparty/webkit/JavaScriptCore/API/JSCallbackObjectFunctions.h b/src/3rdparty/webkit/JavaScriptCore/API/JSCallbackObjectFunctions.h index 987c59f..669b3cd 100644 --- a/src/3rdparty/webkit/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/src/3rdparty/webkit/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -224,7 +224,7 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName } template <class Base> -bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { JSContextRef ctx = toRef(exec); JSObjectRef thisRef = toRef(this); @@ -262,13 +262,13 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p } } - return Base::deleteProperty(exec, propertyName); + return Base::deleteProperty(exec, propertyName, checkDontDelete); } template <class Base> -bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, unsigned propertyName) +bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, unsigned propertyName, bool checkDontDelete) { - return deleteProperty(exec, Identifier::from(exec, propertyName)); + return deleteProperty(exec, Identifier::from(exec, propertyName), checkDontDelete); } template <class Base> @@ -372,7 +372,7 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, } template <class Base> -void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { JSContextRef execRef = toRef(exec); JSObjectRef thisRef = toRef(this); @@ -380,7 +380,7 @@ void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) { JSLock::DropAllLocks dropAllLocks(exec); - getPropertyNames(execRef, thisRef, toRef(&propertyNames)); + getPropertyNames(execRef, thisRef, toRef(&propertyNames), listedAttributes); } if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { @@ -406,7 +406,7 @@ void JSCallbackObject<Base>::getPropertyNames(ExecState* exec, PropertyNameArray } } - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } template <class Base> diff --git a/src/3rdparty/webkit/JavaScriptCore/API/JSObjectRef.h b/src/3rdparty/webkit/JavaScriptCore/API/JSObjectRef.h index 3e8b0eb..86921bd 100644 --- a/src/3rdparty/webkit/JavaScriptCore/API/JSObjectRef.h +++ b/src/3rdparty/webkit/JavaScriptCore/API/JSObjectRef.h @@ -187,6 +187,7 @@ typedef bool @param ctx The execution context to use. @param object The JSObject whose property names are being collected. @param accumulator A JavaScript property name accumulator in which to accumulate the names of object's properties. +@param flag Specify which property should be included @discussion If you named your function GetPropertyNames, you would declare it like this: void GetPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames); @@ -196,7 +197,7 @@ Property name accumulators are used by JSObjectCopyPropertyNames and JavaScript Use JSPropertyNameAccumulatorAddName to add property names to accumulator. A class's getPropertyNames callback only needs to provide the names of properties that the class vends through a custom getProperty or setProperty callback. Other properties, including statically declared properties, properties vended by other classes, and properties belonging to object's prototype, are added independently. */ typedef void -(*JSObjectGetPropertyNamesCallback) (JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames); +(*JSObjectGetPropertyNamesCallback) (JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames, unsigned flag); /*! @typedef JSObjectCallAsFunctionCallback diff --git a/src/3rdparty/webkit/JavaScriptCore/JavaScriptCore.pri b/src/3rdparty/webkit/JavaScriptCore/JavaScriptCore.pri index b43602e..85645be 100644 --- a/src/3rdparty/webkit/JavaScriptCore/JavaScriptCore.pri +++ b/src/3rdparty/webkit/JavaScriptCore/JavaScriptCore.pri @@ -128,7 +128,7 @@ SOURCES += \ yarr/RegexJIT.cpp \ interpreter/RegisterFile.cpp -win32-*: SOURCES += jit/ExecutableAllocatorWin.cpp +win32-*|wince*: SOURCES += jit/ExecutableAllocatorWin.cpp else: SOURCES += jit/ExecutableAllocatorPosix.cpp # AllInOneFile.cpp helps gcc analize and optimize code @@ -216,7 +216,8 @@ SOURCES += \ wtf/DateMath.cpp \ wtf/FastMalloc.cpp \ wtf/Threading.cpp \ - wtf/qt/MainThreadQt.cpp + wtf/qt/MainThreadQt.cpp \ + parser/SourcePoolQt.cpp !contains(DEFINES, ENABLE_SINGLE_THREADED=1) { SOURCES += wtf/qt/ThreadingQt.cpp diff --git a/src/3rdparty/webkit/JavaScriptCore/bytecode/CodeBlock.cpp b/src/3rdparty/webkit/JavaScriptCore/bytecode/CodeBlock.cpp index 0cb3813..4b943c2 100644 --- a/src/3rdparty/webkit/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/bytecode/CodeBlock.cpp @@ -1087,7 +1087,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int debugHookID = (++it)->u.operand; int firstLine = (++it)->u.operand; int lastLine = (++it)->u.operand; - printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine); + int column = (++it)->u.operand; + printf("[%4d] debug\t\t %s, %d, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine, column); break; } case op_profile_will_call: { diff --git a/src/3rdparty/webkit/JavaScriptCore/bytecode/Opcode.h b/src/3rdparty/webkit/JavaScriptCore/bytecode/Opcode.h index 2d1ca98..4baa0be 100644 --- a/src/3rdparty/webkit/JavaScriptCore/bytecode/Opcode.h +++ b/src/3rdparty/webkit/JavaScriptCore/bytecode/Opcode.h @@ -167,7 +167,7 @@ namespace JSC { macro(op_jsr, 3) \ macro(op_sret, 2) \ \ - macro(op_debug, 4) \ + macro(op_debug, 5) \ macro(op_profile_will_call, 2) \ macro(op_profile_did_call, 2) \ \ diff --git a/src/3rdparty/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/src/3rdparty/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 15261ee..ce5518f 100644 --- a/src/3rdparty/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -1602,7 +1602,7 @@ void BytecodeGenerator::emitPopScope() m_dynamicScopeDepth--; } -void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine) +void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine, int column) { if (!m_shouldEmitDebugHooks) return; @@ -1610,6 +1610,7 @@ void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, in instructions().append(debugHookID); instructions().append(firstLine); instructions().append(lastLine); + instructions().append(column); } void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst) diff --git a/src/3rdparty/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/src/3rdparty/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.h index 54d0289..f7f7e1c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/src/3rdparty/webkit/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -324,7 +324,7 @@ namespace JSC { RegisterID* emitPushScope(RegisterID* scope); void emitPopScope(); - void emitDebugHook(DebugHookID, int firstLine, int lastLine); + void emitDebugHook(DebugHookID, int firstLine, int lastLine, int column ); int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; } bool hasFinaliser() { return m_finallyDepth != 0; } diff --git a/src/3rdparty/webkit/JavaScriptCore/debugger/Debugger.h b/src/3rdparty/webkit/JavaScriptCore/debugger/Debugger.h index 98d0935..1ed39ec 100644 --- a/src/3rdparty/webkit/JavaScriptCore/debugger/Debugger.h +++ b/src/3rdparty/webkit/JavaScriptCore/debugger/Debugger.h @@ -22,11 +22,11 @@ #ifndef Debugger_h #define Debugger_h +#include <debugger/DebuggerCallFrame.h> #include "Protect.h" namespace JSC { - class DebuggerCallFrame; class ExecState; class JSGlobalObject; class SourceCode; @@ -40,15 +40,62 @@ namespace JSC { void attach(JSGlobalObject*); virtual void detach(JSGlobalObject*); +#if PLATFORM(QT) +#ifdef QT_BUILD_SCRIPT_LIB + virtual void scriptUnload(qint64 id) + { + UNUSED_PARAM(id); + }; + virtual void scriptLoad(qint64 id, const UString &program, + const UString &fileName, int baseLineNumber) + { + UNUSED_PARAM(id); + UNUSED_PARAM(program); + UNUSED_PARAM(fileName); + UNUSED_PARAM(baseLineNumber); + }; + virtual void contextPush() {}; + virtual void contextPop() {}; + + virtual void evaluateStart(intptr_t sourceID) + { + UNUSED_PARAM(sourceID); + } + virtual void evaluateStop(const JSC::JSValue& returnValue, intptr_t sourceID) + { + UNUSED_PARAM(sourceID); + UNUSED_PARAM(returnValue); + } + + virtual void exceptionThrow(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, bool hasHandler) + { + UNUSED_PARAM(frame); + UNUSED_PARAM(sourceID); + UNUSED_PARAM(hasHandler); + }; + virtual void exceptionCatch(const JSC::DebuggerCallFrame& frame, intptr_t sourceID) + { + UNUSED_PARAM(frame); + UNUSED_PARAM(sourceID); + }; + + virtual void functionExit(const JSC::JSValue& returnValue, intptr_t sourceID) + { + UNUSED_PARAM(returnValue); + UNUSED_PARAM(sourceID); + }; +#endif +#endif + virtual void sourceParsed(ExecState*, const SourceCode&, int errorLine, const UString& errorMsg) = 0; virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0; - virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0; + virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineno, int column) = 0; virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0; virtual void returnEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0; virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0; virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0; - virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineno) = 0; + virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineno, int column) = 0; private: HashSet<JSGlobalObject*> m_globalObjects; diff --git a/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerActivation.cpp b/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerActivation.cpp index 4b2568f..c1815c8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerActivation.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerActivation.cpp @@ -65,14 +65,14 @@ void DebuggerActivation::putWithAttributes(ExecState* exec, const Identifier& pr m_activation->putWithAttributes(exec, propertyName, value, attributes); } -bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { - return m_activation->deleteProperty(exec, propertyName); + return m_activation->deleteProperty(exec, propertyName, checkDontDelete); } -void DebuggerActivation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void DebuggerActivation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { - m_activation->getPropertyNames(exec, propertyNames); + m_activation->getPropertyNames(exec, propertyNames, listedAttributes); } bool DebuggerActivation::getPropertyAttributes(JSC::ExecState* exec, const Identifier& propertyName, unsigned& attributes) const diff --git a/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerActivation.h b/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerActivation.h index 9e1f9f5..7c9f7d1 100644 --- a/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerActivation.h +++ b/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerActivation.h @@ -41,8 +41,8 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction); virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction); diff --git a/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerCallFrame.h b/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerCallFrame.h index 9d377ef..5984fab 100644 --- a/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerCallFrame.h +++ b/src/3rdparty/webkit/JavaScriptCore/debugger/DebuggerCallFrame.h @@ -56,6 +56,9 @@ namespace JSC { JSObject* thisObject() const; JSValue evaluate(const UString&, JSValue& exception) const; JSValue exception() const { return m_exception; } +#if QT_BUILD_SCRIPT_LIB + CallFrame* callFrame() const { return m_callFrame; } +#endif private: CallFrame* m_callFrame; diff --git a/src/3rdparty/webkit/JavaScriptCore/generated/Grammar.cpp b/src/3rdparty/webkit/JavaScriptCore/generated/Grammar.cpp index 94b9654..06c6e38 100644 --- a/src/3rdparty/webkit/JavaScriptCore/generated/Grammar.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/generated/Grammar.cpp @@ -139,7 +139,7 @@ static inline bool allowAutomaticSemicolon(JSC::Lexer&, int); #define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*LEXER, yychar)) YYABORT; } while (0) #define SET_EXCEPTION_LOCATION(node, start, divot, end) node->setExceptionSourceCode((divot), (divot) - (start), (end) - (divot)) -#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line) +#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line, (s).first_column + 1) using namespace JSC; using namespace std; diff --git a/src/3rdparty/webkit/JavaScriptCore/interpreter/CallFrame.h b/src/3rdparty/webkit/JavaScriptCore/interpreter/CallFrame.h index 2d677ce..75de082 100644 --- a/src/3rdparty/webkit/JavaScriptCore/interpreter/CallFrame.h +++ b/src/3rdparty/webkit/JavaScriptCore/interpreter/CallFrame.h @@ -37,7 +37,7 @@ namespace JSC { // Passed as the first argument to most functions. class ExecState : private Register { public: - JSFunction* callee() const { return this[RegisterFile::Callee].function(); } + JSObject* callee() const { return this[RegisterFile::Callee].object(); } CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); } ScopeChainNode* scopeChain() const { return this[RegisterFile::ScopeChain].Register::scopeChain(); } int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); } @@ -110,7 +110,7 @@ namespace JSC { void setScopeChain(ScopeChainNode* scopeChain) { this[RegisterFile::ScopeChain] = scopeChain; } ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, - CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function) + CallFrame* callerFrame, int returnValueRegister, int argc, JSObject* callee) { ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller. @@ -120,7 +120,7 @@ namespace JSC { this[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. this[RegisterFile::ReturnValueRegister] = returnValueRegister; setArgumentCount(argc); // original argument count (for the sake of the "arguments" object) - setCallee(function); + setCallee(callee); setCalleeArguments(0); } @@ -136,7 +136,7 @@ namespace JSC { private: void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = count; } - void setCallee(JSFunction* callee) { this[RegisterFile::Callee] = callee; } + void setCallee(JSObject* callee) { this[RegisterFile::Callee] = callee; } void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; } static const intptr_t HostCallFrameFlag = 1; diff --git a/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp b/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp index e4eebb2..3af4a29 100644 --- a/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.cpp @@ -65,6 +65,14 @@ #include "JIT.h" #endif +#if ENABLE(ASSEMBLER) +#include "AssemblerBuffer.h" +#endif + +#ifdef QT_BUILD_SCRIPT_LIB +#include "bridge/qscriptobject_p.h" +#endif + using namespace std; namespace JSC { @@ -463,9 +471,12 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); - if (callFrame->callee()) + if (callFrame->callee()) { debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine()); - else +#ifdef QT_BUILD_SCRIPT_LIB + debugger->functionExit(exceptionValue, codeBlock->ownerNode()->sourceID()); +#endif + } else debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->lastLine()); } @@ -510,9 +521,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock); exceptionValue = exception; } else { - if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) && + if (!exception->hasProperty(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME)) && !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) && - !exception->hasProperty(callFrame, Identifier(callFrame, "sourceURL")) && + !exception->hasProperty(callFrame, Identifier(callFrame, JSC_ERROR_FILENAME_PROPERTYNAME)) && !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) && !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) && !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) { @@ -521,16 +532,16 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV int endOffset = 0; int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset); - exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, line), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME), jsNumber(callFrame, line), ReadOnly | DontDelete); // We only hit this path for error messages and throw statements, which don't have a specific failure position // So we just give the full range of the error/throw statement. exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete); } else - exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_LINENUMBER_PROPERTYNAME), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete); exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerNode()->sourceID()), ReadOnly | DontDelete); - exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete); + exception->putWithAttributes(callFrame, Identifier(callFrame, JSC_ERROR_FILENAME_PROPERTYNAME), jsOwnedString(callFrame, codeBlock->ownerNode()->sourceURL()), ReadOnly | DontDelete); } if (exception->isWatchdogException()) { @@ -542,7 +553,8 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV } } - if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) { + Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); + if (debugger) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); debugger->exception(debuggerCallFrame, codeBlock->ownerNode()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)); } @@ -566,11 +578,32 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV // Calculate an exception handler vPC, unwinding call frames as necessary. HandlerInfo* handler = 0; + +#ifdef QT_BUILD_SCRIPT_LIB + //try to find handler + bool hasHandler = true; + CallFrame *callFrameTemp = callFrame; + unsigned bytecodeOffsetTemp = bytecodeOffset; + CodeBlock *codeBlockTemp = codeBlock; + while (!(handler = codeBlockTemp->handlerForBytecodeOffset(bytecodeOffsetTemp))) { + callFrameTemp = callFrameTemp->callerFrame(); + if (callFrameTemp->hasHostCallFrameFlag()) { + hasHandler = false; + break; + } else { + codeBlockTemp = callFrameTemp->codeBlock(); + bytecodeOffsetTemp = bytecodeOffsetForPC(callFrameTemp, codeBlockTemp, callFrameTemp->returnPC()); + } + } + if (debugger) + debugger->exceptionThrow(DebuggerCallFrame(callFrame, exceptionValue), codeBlock->ownerNode()->sourceID(), hasHandler); +#endif + while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) { - if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) + if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) { return 0; + } } - // Now unwind the scope chain within the exception handler's call frame. ScopeChainNode* scopeChain = callFrame->scopeChain(); @@ -870,7 +903,7 @@ JSValue Interpreter::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* return result; } -NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine) +NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine, int column) { Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); if (!debugger) @@ -884,7 +917,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine); return; case WillExecuteStatement: - debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine); + debugger->atStatement(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine, column); return; case WillExecuteProgram: debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), firstLine); @@ -893,7 +926,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine); return; case DidReachBreakpoint: - debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine); + debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerNode()->sourceID(), lastLine, column); return; } } @@ -1127,7 +1160,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Instruction* vPC = callFrame->codeBlock()->instructions().begin(); Profiler** enabledProfilerReference = Profiler::enabledProfilerReference(); - unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); + unsigned tickCount = globalData->timeoutChecker->ticksUntilNextCheck(); #define CHECK_FOR_EXCEPTION() \ do { \ @@ -1143,11 +1176,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #define CHECK_FOR_TIMEOUT() \ if (!--tickCount) { \ - if (globalData->timeoutChecker.didTimeOut(callFrame)) { \ + if (globalData->timeoutChecker->didTimeOut(callFrame)) { \ exceptionValue = jsNull(); \ goto vm_throw; \ } \ - tickCount = globalData->timeoutChecker.ticksUntilNextCheck(); \ + tickCount = globalData->timeoutChecker->ticksUntilNextCheck(); \ } #if ENABLE(OPCODE_SAMPLING) @@ -3062,7 +3095,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callType == CallTypeHost) { ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0); + newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v)); Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList args(thisRegister + 1, argCount - 1); @@ -3104,7 +3137,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi exceptionValue = createStackOverflowError(callFrame); goto vm_throw; } - int32_t expectedParams = callFrame->callee()->body()->parameterCount(); + int32_t expectedParams = static_cast<JSFunction*>(callFrame->callee())->body()->parameterCount(); int32_t inplaceArgs = min(argCount, expectedParams); int32_t i = 0; Register* argStore = callFrame->registers() + argsOffset; @@ -3216,7 +3249,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callType == CallTypeHost) { ScopeChainNode* scopeChain = callFrame->scopeChain(); CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0); + newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v)); Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList args(thisRegister + 1, argCount - 1); @@ -3295,17 +3328,27 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi register base to those of the calling function. */ +#ifdef QT_BUILD_SCRIPT_LIB + Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); + intptr_t sourceId = callFrame->codeBlock()->source()->asID(); +#endif + int result = (++vPC)->u.operand; if (callFrame->codeBlock()->needsFullScopeChain()) callFrame->scopeChain()->deref(); JSValue returnValue = callFrame->r(result).jsValue(); +#ifdef QT_BUILD_SCRIPT_LIB + if (debugger) { + debugger->functionExit(returnValue, sourceId); + } +#endif vPC = callFrame->returnPC(); int dst = callFrame->returnValueRegister(); callFrame = callFrame->callerFrame(); - + if (callFrame->hasHostCallFrameFlag()) return returnValue; @@ -3448,8 +3491,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi structure = asObject(prototype)->inheritorID(); else structure = callDataScopeChain->globalObject()->emptyObjectStructure(); +#ifdef QT_BUILD_SCRIPT_LIB + // ### world-class hack + QScriptObject* newObject = new (globalData) QScriptObject(structure); +#else JSObject* newObject = new (globalData) JSObject(structure); - +#endif callFrame->r(thisRegister) = JSValue(newObject); // "this" value CallFrame* previousCallFrame = callFrame; @@ -3475,8 +3522,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1); ScopeChainNode* scopeChain = callFrame->scopeChain(); + CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0); + newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, asObject(v)); JSValue returnValue; { @@ -3647,6 +3695,16 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ ASSERT(exceptionValue); ASSERT(!globalData->exception); + +#ifdef QT_BUILD_SCRIPT_LIB + CodeBlock* codeBlock = callFrame->codeBlock(); + Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); + if (debugger) { + DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); + debugger->exceptionCatch(debuggerCallFrame, codeBlock->ownerNode()->sourceID()); + } +#endif + int ex = (++vPC)->u.operand; callFrame->r(ex) = exceptionValue; exceptionValue = JSValue(); @@ -3787,7 +3845,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_debug) { - /* debug debugHookID(n) firstLine(n) lastLine(n) + /* debug debugHookID(n) firstLine(n) lastLine(n) columnNumber(n) Notifies the debugger of the current state of execution. This opcode is only generated while the debugger is attached. @@ -3795,8 +3853,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int debugHookID = (++vPC)->u.operand; int firstLine = (++vPC)->u.operand; int lastLine = (++vPC)->u.operand; + int column = (++vPC)->u.operand; - debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); + debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); ++vPC; NEXT_INSTRUCTION(); diff --git a/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.h b/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.h index 5331d92..69f83cf 100644 --- a/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.h +++ b/src/3rdparty/webkit/JavaScriptCore/interpreter/Interpreter.h @@ -110,7 +110,7 @@ namespace JSC { NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue& exceptionValue); NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset, bool); - NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); + NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine, int column); private: enum ExecutionFlag { Normal, InitializeAndReturn }; diff --git a/src/3rdparty/webkit/JavaScriptCore/interpreter/Register.h b/src/3rdparty/webkit/JavaScriptCore/interpreter/Register.h index 31f0c8b..6d01eb7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/interpreter/Register.h +++ b/src/3rdparty/webkit/JavaScriptCore/interpreter/Register.h @@ -40,7 +40,6 @@ namespace JSC { class CodeBlock; class ExecState; class JSActivation; - class JSFunction; class JSPropertyNameIterator; class ScopeChainNode; @@ -73,7 +72,7 @@ namespace JSC { Register(JSActivation*); Register(CallFrame*); Register(CodeBlock*); - Register(JSFunction*); + Register(JSObject*); Register(JSPropertyNameIterator*); Register(ScopeChainNode*); Register(Instruction*); @@ -82,7 +81,7 @@ namespace JSC { Arguments* arguments() const; CallFrame* callFrame() const; CodeBlock* codeBlock() const; - JSFunction* function() const; + JSObject* object() const; JSPropertyNameIterator* propertyNameIterator() const; ScopeChainNode* scopeChain() const; Instruction* vPC() const; @@ -96,7 +95,7 @@ namespace JSC { Arguments* arguments; CallFrame* callFrame; CodeBlock* codeBlock; - JSFunction* function; + JSObject* object; JSPropertyNameIterator* propertyNameIterator; ScopeChainNode* scopeChain; Instruction* vPC; @@ -152,9 +151,9 @@ namespace JSC { u.codeBlock = codeBlock; } - ALWAYS_INLINE Register::Register(JSFunction* function) + ALWAYS_INLINE Register::Register(JSObject* object) { - u.function = function; + u.object = object; } ALWAYS_INLINE Register::Register(Instruction* vPC) @@ -211,9 +210,9 @@ namespace JSC { return u.codeBlock; } - ALWAYS_INLINE JSFunction* Register::function() const + ALWAYS_INLINE JSObject* Register::object() const { - return u.function; + return u.object; } ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const diff --git a/src/3rdparty/webkit/JavaScriptCore/interpreter/RegisterFile.cpp b/src/3rdparty/webkit/JavaScriptCore/interpreter/RegisterFile.cpp index cfcf1d3..06ddefc 100644 --- a/src/3rdparty/webkit/JavaScriptCore/interpreter/RegisterFile.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/interpreter/RegisterFile.cpp @@ -38,7 +38,7 @@ RegisterFile::~RegisterFile() #elif HAVE(VIRTUALALLOC) VirtualFree(m_buffer, 0, MEM_RELEASE); #else - #error "Don't know how to release virtual memory on this platform." + fastFree(m_buffer); #endif } diff --git a/src/3rdparty/webkit/JavaScriptCore/interpreter/RegisterFile.h b/src/3rdparty/webkit/JavaScriptCore/interpreter/RegisterFile.h index d46bdc9..5a34d11 100644 --- a/src/3rdparty/webkit/JavaScriptCore/interpreter/RegisterFile.h +++ b/src/3rdparty/webkit/JavaScriptCore/interpreter/RegisterFile.h @@ -204,8 +204,8 @@ namespace JSC { CRASH(); } m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + committedSize); - #else - #error "Don't know how to reserve virtual memory on this platform." + #else // Neither MMAP nor VIRTUALALLOC - use fastMalloc instead + m_buffer = static_cast<Register*>(fastMalloc(bufferLength)); #endif m_start = m_buffer + maxGlobals; m_end = m_start; diff --git a/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp b/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp index 5049477..40d2182 100644 --- a/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp @@ -684,14 +684,14 @@ DEFINE_STUB_FUNCTION(int, timeout_check) STUB_INIT_STACK_FRAME(stackFrame); JSGlobalData* globalData = stackFrame.globalData; - TimeoutChecker& timeoutChecker = globalData->timeoutChecker; + TimeoutChecker* timeoutChecker = globalData->timeoutChecker; - if (timeoutChecker.didTimeOut(stackFrame.callFrame)) { + if (timeoutChecker->didTimeOut(stackFrame.callFrame)) { globalData->exception = createInterruptedExecutionException(globalData); VM_THROW_EXCEPTION_AT_END(); } - return timeoutChecker.ticksUntilNextCheck(); + return timeoutChecker->ticksUntilNextCheck(); } DEFINE_STUB_FUNCTION(void, register_file_check) @@ -2705,8 +2705,13 @@ DEFINE_STUB_FUNCTION(void, op_debug) int debugHookID = stackFrame.args[0].int32(); int firstLine = stackFrame.args[1].int32(); int lastLine = stackFrame.args[2].int32(); +#ifdef QT_BUILD_SCRIPT_LIB + int column = stackFrame.args[3].int32(); +#else + int column = -1; +#endif - stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); + stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); } DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw) diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Grammar.y b/src/3rdparty/webkit/JavaScriptCore/parser/Grammar.y index 354c786..a3bf1fe 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/Grammar.y +++ b/src/3rdparty/webkit/JavaScriptCore/parser/Grammar.y @@ -62,7 +62,7 @@ static inline bool allowAutomaticSemicolon(JSC::Lexer&, int); #define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*LEXER, yychar)) YYABORT; } while (0) #define SET_EXCEPTION_LOCATION(node, start, divot, end) node->setExceptionSourceCode((divot), (divot) - (start), (end) - (divot)) -#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line) +#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line, (s).first_column + 1) using namespace JSC; using namespace std; diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.cpp b/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.cpp index 8e89c18..c36763c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.cpp @@ -59,6 +59,7 @@ static const UChar byteOrderMark = 0xFEFF; Lexer::Lexer(JSGlobalData* globalData) : m_isReparsing(false) , m_globalData(globalData) + , m_startColumnNumberCorrection(0) , m_keywordTable(JSC::mainTable) { m_buffer8.reserveInitialCapacity(initialReadBufferCapacity); @@ -201,6 +202,7 @@ void Lexer::shiftLineTerminator() else shift1(); + m_startColumnNumberCorrection = currentOffset(); ++m_lineNumber; } @@ -293,11 +295,15 @@ start: int startOffset = currentOffset(); if (m_current == -1) { +#ifndef QT_BUILD_SCRIPT_LIB /* the parser takes cate about automatic semicolon. + this might add incorrect semicolons */ + //m_delimited and m_isReparsing are now useless if (!m_terminator && !m_delimited && !m_isReparsing) { // automatic semicolon insertion if program incomplete token = ';'; goto doneSemicolon; } +#endif return 0; } @@ -893,11 +899,11 @@ doneString: // Fall through into returnToken. returnToken: { - int lineNumber = m_lineNumber; - llocp->first_line = lineNumber; - llocp->last_line = lineNumber; - llocp->first_column = startOffset; - llocp->last_column = currentOffset(); + llocp->first_line = m_lineNumber; + llocp->last_line = m_lineNumber; + + llocp->first_column = startOffset - m_startColumnNumberCorrection; + llocp->last_column = currentOffset() - m_startColumnNumberCorrection; m_lastToken = token; return token; diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.h b/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.h index 2583162..0ef6dd4 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.h +++ b/src/3rdparty/webkit/JavaScriptCore/parser/Lexer.h @@ -87,6 +87,10 @@ namespace JSC { static const size_t initialIdentifierTableCapacity = 64; int m_lineNumber; + // this variable is supposed to keep index of last new line character ('\n' or '\r\n'or '\n\r'...) + // it is importent to calculate correct first_column in parser + int m_startColumnNumberCorrection; + Vector<char> m_buffer8; Vector<UChar> m_buffer16; diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/NodeConstructors.h b/src/3rdparty/webkit/JavaScriptCore/parser/NodeConstructors.h index 780a624..c256190 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/NodeConstructors.h +++ b/src/3rdparty/webkit/JavaScriptCore/parser/NodeConstructors.h @@ -63,6 +63,7 @@ namespace JSC { inline StatementNode::StatementNode(JSGlobalData* globalData) : Node(globalData) , m_lastLine(-1) + , m_column(-1) { } diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp index 6c0d1af..9d9fe72 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.cpp @@ -83,10 +83,11 @@ RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator // ------------------------------ StatementNode -------------------------------- -void StatementNode::setLoc(int firstLine, int lastLine) +void StatementNode::setLoc(int firstLine, int lastLine, int column) { m_line = firstLine; m_lastLine = lastLine; + m_column = column; } // ------------------------------ SourceElements -------------------------------- @@ -1225,7 +1226,7 @@ RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); return generator.emitNode(m_next); } @@ -1250,7 +1251,7 @@ RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); return dst; } @@ -1258,7 +1259,7 @@ RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, Regis RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine()); + generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine(), column()); return dst; } @@ -1267,7 +1268,7 @@ RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, Re RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { ASSERT(m_expr); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); return generator.emitNode(dst, m_expr); } @@ -1276,7 +1277,7 @@ RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, Regist RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { ASSERT(m_expr); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); return generator.emitNode(m_expr); } @@ -1284,7 +1285,7 @@ RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, Registe RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<Label> afterThen = generator.newLabel(); @@ -1302,7 +1303,7 @@ RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<Label> beforeElse = generator.newLabel(); RefPtr<Label> afterElse = generator.newLabel(); @@ -1332,12 +1333,14 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); - generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column()); +#endif RegisterID* cond = generator.emitNode(m_expr); generator.emitJumpIfTrue(cond, topOfLoop.get()); @@ -1350,7 +1353,9 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); - +#ifdef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column()); +#endif generator.emitJump(scope->continueTarget()); RefPtr<Label> topOfLoop = generator.newLabel(); @@ -1359,7 +1364,9 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); - generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column()); +#endif RegisterID* cond = generator.emitNode(m_expr); generator.emitJumpIfTrue(cond, topOfLoop.get()); @@ -1378,7 +1385,7 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (m_expr1) generator.emitNode(generator.ignoredResult(), m_expr1); @@ -1392,7 +1399,9 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); +#endif if (m_expr3) generator.emitNode(generator.ignoredResult(), m_expr3); @@ -1418,7 +1427,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RefPtr<Label> continueTarget = generator.newLabel(); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (m_init) generator.emitNode(generator.ignoredResult(), m_init); @@ -1466,7 +1475,9 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitLabel(scope->continueTarget()); generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get()); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); +#endif generator.emitLabel(scope->breakTarget()); return dst; } @@ -1476,7 +1487,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ECMA 12.7 RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); LabelScope* scope = generator.continueTarget(m_ident); @@ -1494,7 +1505,7 @@ RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* // ECMA 12.8 RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); LabelScope* scope = generator.breakTarget(m_ident); @@ -1511,7 +1522,7 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (generator.codeType() != FunctionCode) return emitThrowError(generator, SyntaxError, "Invalid return statement."); @@ -1528,7 +1539,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d generator.emitJumpScopes(l0.get(), 0); generator.emitLabel(l0.get()); } - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), column()); return generator.emitReturn(r0); } @@ -1536,7 +1547,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<RegisterID> scope = generator.newTemporary(); generator.emitNode(scope.get(), m_expr); // scope must be protected until popped @@ -1695,7 +1706,7 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); @@ -1710,7 +1721,7 @@ RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (generator.breakTarget(m_name)) return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name); @@ -1726,7 +1737,7 @@ RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); if (dst == generator.ignoredResult()) dst = 0; @@ -1740,7 +1751,9 @@ RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); +#endif RefPtr<Label> tryStartLabel = generator.newLabel(); RefPtr<Label> tryEndLabel = generator.newLabel(); @@ -1875,13 +1888,13 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElem RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine(), column()); RefPtr<RegisterID> dstRegister = generator.newTemporary(); generator.emitLoad(dstRegister.get(), jsUndefined()); statementListEmitCode(children(), generator, dstRegister.get()); - generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); + generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine(), column()); generator.emitEnd(dstRegister.get()); return 0; } @@ -1930,13 +1943,13 @@ PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); + generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine(), column()); RefPtr<RegisterID> dstRegister = generator.newTemporary(); generator.emitLoad(dstRegister.get(), jsUndefined()); statementListEmitCode(children(), generator, dstRegister.get()); - generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); + generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine(), column()); generator.emitEnd(dstRegister.get()); return 0; } @@ -1996,6 +2009,9 @@ inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) , m_parameters(0) , m_parameterCount(0) { +#ifdef QT_BUILD_SCRIPT_LIB + sourceToken = globalData->scriptpool->objectRegister(); +#endif } inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) @@ -2003,10 +2019,16 @@ inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElemen , m_parameters(0) , m_parameterCount(0) { +#ifdef QT_BUILD_SCRIPT_LIB + sourceToken = globalData->scriptpool->objectRegister(); +#endif } FunctionBodyNode::~FunctionBodyNode() { +#ifdef QT_BUILD_SCRIPT_LIB + if (sourceToken) delete sourceToken; +#endif for (size_t i = 0; i < m_parameterCount; ++i) m_parameters[i].~Identifier(); fastFree(m_parameters); @@ -2116,7 +2138,7 @@ CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* sco RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); + generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine(), column()); statementListEmitCode(children(), generator, generator.ignoredResult()); if (children().size() && children().last()->isBlock()) { BlockNode* blockNode = static_cast<BlockNode*>(children().last()); @@ -2125,7 +2147,7 @@ RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, Registe } RegisterID* r0 = generator.emitLoad(0, jsUndefined()); - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), column()); generator.emitReturn(r0); return 0; } diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.h b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.h index 84e8b95..185cede 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.h +++ b/src/3rdparty/webkit/JavaScriptCore/parser/Nodes.h @@ -36,6 +36,10 @@ #include <wtf/MathExtras.h> #include <wtf/OwnPtr.h> +#ifdef QT_BUILD_SCRIPT_LIB +#include "SourcePoolQt.h" +#endif + namespace JSC { class ArgumentListNode; @@ -191,9 +195,10 @@ namespace JSC { public: StatementNode(JSGlobalData*); - void setLoc(int line0, int line1); + void setLoc(int line0, int line1, int column); int firstLine() const { return lineNo(); } int lastLine() const { return m_lastLine; } + int column() const { return m_column; } virtual bool isEmptyStatement() const { return false; } virtual bool isReturnNode() const { return false; } @@ -203,6 +208,7 @@ namespace JSC { private: int m_lastLine; + int m_column; }; class NullNode : public ExpressionNode { @@ -1605,6 +1611,9 @@ namespace JSC { Identifier* m_parameters; size_t m_parameterCount; OwnPtr<CodeBlock> m_code; +#ifdef QT_BUILD_SCRIPT_LIB + SourcePool::SourcePoolToken* sourceToken; +#endif }; class FuncExprNode : public ExpressionNode, public ParserArenaRefCounted { diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/Parser.h b/src/3rdparty/webkit/JavaScriptCore/parser/Parser.h index 373dc00..5a182a6 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/Parser.h +++ b/src/3rdparty/webkit/JavaScriptCore/parser/Parser.h @@ -76,7 +76,8 @@ namespace JSC { *m_source, m_features, m_numConstants); - result->setLoc(m_source->firstLine(), m_lastLine); + int column = m_source->startOffset(); //is it good way to find column number? + result->setLoc(m_source->firstLine(), m_lastLine, column); } m_arena.reset(); @@ -103,7 +104,8 @@ namespace JSC { *m_source, oldParsedNode->features(), m_numConstants); - result->setLoc(m_source->firstLine(), m_lastLine); + int column = m_source->startOffset(); //is it good way to find column number? + result->setLoc(m_source->firstLine(), m_lastLine, column); } m_arena.reset(); diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/SourceCode.h b/src/3rdparty/webkit/JavaScriptCore/parser/SourceCode.h index 84360b8..305b804 100644 --- a/src/3rdparty/webkit/JavaScriptCore/parser/SourceCode.h +++ b/src/3rdparty/webkit/JavaScriptCore/parser/SourceCode.h @@ -47,7 +47,11 @@ namespace JSC { : m_provider(provider) , m_startChar(0) , m_endChar(m_provider->length()) +#ifdef QT_BUILD_SCRIPT_LIB + , m_firstLine(firstLine) +#else , m_firstLine(std::max(firstLine, 1)) +#endif { } @@ -55,7 +59,11 @@ namespace JSC { : m_provider(provider) , m_startChar(start) , m_endChar(end) +#ifdef QT_BUILD_SCRIPT_LIB + , m_firstLine(firstLine) +#else , m_firstLine(std::max(firstLine, 1)) +#endif { } diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/SourcePoolQt.cpp b/src/3rdparty/webkit/JavaScriptCore/parser/SourcePoolQt.cpp new file mode 100644 index 0000000..4fc859f --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/parser/SourcePoolQt.cpp @@ -0,0 +1,109 @@ +/* + Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "SourcePoolQt.h" + + +#ifdef QT_BUILD_SCRIPT_LIB + +#include "SourceCode.h" +#include "Debugger.h" + + +namespace JSC { + + void SourcePool::startEvaluating(const SourceCode& source) + { + int id = source.provider()->asID(); + + codes.insert(id,source.toString()); + + currentScript.push(id); + scriptRef.insert(id,ScriptActivCount()); + + if (debug) + debug->scriptLoad(id,source.toString(),source.provider()->url(),source.firstLine()); + } + + + void SourcePool::stopEvaluating(const SourceCode& source) + { + int id = source.provider()->asID(); + currentScript.pop(); + + if (scriptRef.contains(id)) { + ScriptActivCount info = scriptRef.take(id); + if (info.getCount()) { + //we can't remove info from scriptRef + info.isActive = false; + scriptRef.insert(id,info); + } else { + //we are unloading source code + if (debug) + debug->scriptUnload(id); + } + } + } + + SourcePool::SourcePoolToken* SourcePool::objectRegister() + { + if (currentScript.isEmpty()) { + return 0; + } + + int id = currentScript.top(); + + SourcePoolToken* token = new SourcePoolToken(id,this); + + ScriptActivCount info = scriptRef.take(id); + + info.incCount(); + scriptRef.insert(id,info); + return token; + } + + void SourcePool::objectUnregister(const SourcePool::SourcePoolToken *token) + { + int id = token->id; + + ScriptActivCount info = scriptRef.take(id); + info.decCount(); + if (info.isActive) { + scriptRef.insert(id,info); + } else { + if (info.getCount() == 0) { + //remove from scriptRef (script is not active and there is no objects connected) + if(debug) + debug->scriptUnload(id); + } else { + scriptRef.insert(id,info); + } + } + + } + + + void SourcePool::setDebugger(JSC::Debugger *debugger) { this->debug = debugger; } + Debugger* SourcePool::debugger() { return debug; } + +} //namespace JSC + + +#endif //QT_BUILD_SCRIPT_LIB diff --git a/src/3rdparty/webkit/JavaScriptCore/parser/SourcePoolQt.h b/src/3rdparty/webkit/JavaScriptCore/parser/SourcePoolQt.h new file mode 100644 index 0000000..baed3ba --- /dev/null +++ b/src/3rdparty/webkit/JavaScriptCore/parser/SourcePoolQt.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2008, 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef SOURCEPOOL_H +#define SOURCEPOOL_H + +#ifdef QT_BUILD_SCRIPT_LIB + +#include "qhash.h" +#include "qstack.h" +#include "qdebug.h" +#include <stdint.h> + +namespace JSC { + + class SourceCode; + class Debugger; + + class SourcePool + { + class ScriptActivCount + { + int count; + public: + void incCount() + { + count++; + }; + void decCount() + { + count--; + }; + int getCount() const + { + return count; + }; + bool isActive; + ScriptActivCount() : count(0), isActive(true) {} + }; + QStack<intptr_t> currentScript; + QHash<unsigned, ScriptActivCount> scriptRef; + QHash<int, QString> codes; //debug + Debugger *debug; + + friend class SourcePoolToken; + public: + class SourcePoolToken + { + unsigned id; + SourcePool *ptr; + SourcePoolToken(unsigned scriptId, SourcePool *scriptPool) : id(scriptId),ptr(scriptPool) {} + SourcePoolToken(const SourcePoolToken&) : id(0), ptr(0) {} //private - do not use - will crash + public: + ~SourcePoolToken() { ptr->objectUnregister(this); } + friend class SourcePool; + }; + + SourcePool() : debug(0) {} + + void startEvaluating(const SourceCode& source); + void stopEvaluating(const SourceCode& source); + SourcePoolToken* objectRegister(); + + void setDebugger(Debugger *debugger); + Debugger* debugger(); + + private: + void objectUnregister(const SourcePoolToken *token); + }; + +} //namespace JSC + + +#endif //QT_BUILD_SCRIPT_LIB + +#endif // SOURCEPOOL_H diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.cpp index f867fe8..7cb4fe9 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.cpp @@ -227,7 +227,7 @@ void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue val JSObject::put(exec, propertyName, value, slot); } -bool Arguments::deleteProperty(ExecState* exec, unsigned i) +bool Arguments::deleteProperty(ExecState* exec, unsigned i, bool checkDontDelete) { if (i < d->numArguments) { if (!d->deletedArguments) { @@ -240,10 +240,10 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i) } } - return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i))); + return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)), checkDontDelete); } -bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); @@ -268,7 +268,17 @@ bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) return true; } - return JSObject::deleteProperty(exec, propertyName); + return JSObject::deleteProperty(exec, propertyName, checkDontDelete); +} + +bool Arguments::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const +{ + if ((propertyName == exec->propertyNames().length) + || (propertyName == exec->propertyNames().callee)) { + attributes = DontEnum; + return true; + } + return JSObject::getPropertyAttributes(exec, propertyName, attributes); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.h index 72697eb..dc54dac 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Arguments.h @@ -45,7 +45,7 @@ namespace JSC { OwnArrayPtr<bool> deletedArguments; Register extraArgumentsFixedBuffer[4]; - JSFunction* callee; + JSObject* callee; bool overrodeLength : 1; bool overrodeCallee : 1; }; @@ -87,13 +87,14 @@ namespace JSC { } private: - void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); + void getArgumentsData(CallFrame*, JSObject*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); - virtual bool deleteProperty(ExecState*, unsigned propertyName); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); + virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; virtual const ClassInfo* classInfo() const { return &info; } @@ -110,12 +111,17 @@ namespace JSC { return static_cast<Arguments*>(asObject(value)); } - ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc) + ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSObject*& callee, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc) { - function = callFrame->callee(); - - CodeBlock* codeBlock = &function->body()->generatedBytecode(); - int numParameters = codeBlock->m_numParameters; + callee = callFrame->callee(); + + int numParameters; + if (callee->isObject(&JSFunction::info)) { + CodeBlock* codeBlock = &JSC::asFunction(callee)->body()->generatedBytecode(); + numParameters = codeBlock->m_numParameters; + } else { + numParameters = 0; + } argc = callFrame->argumentCount(); if (argc <= numParameters) @@ -131,13 +137,16 @@ namespace JSC { : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) , d(new ArgumentsData) { - JSFunction* callee; + JSObject* callee; ptrdiff_t firstParameterIndex; Register* argv; int numArguments; getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments); - d->numParameters = callee->body()->parameterCount(); + if (callee->isObject(&JSFunction::info)) + d->numParameters = JSC::asFunction(callee)->body()->parameterCount(); + else + d->numParameters = 0; d->firstParameterIndex = firstParameterIndex; d->numArguments = numArguments; @@ -168,7 +177,8 @@ namespace JSC { : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) , d(new ArgumentsData) { - ASSERT(!callFrame->callee()->body()->parameterCount()); + if (callFrame->callee() && callFrame->callee()->isObject(&JSC::JSFunction::info)) + ASSERT(!asFunction(callFrame->callee())->body()->parameterCount()); unsigned numArguments = callFrame->argumentCount() - 1; @@ -183,6 +193,8 @@ namespace JSC { extraArguments = d->extraArgumentsFixedBuffer; Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1; + if (callFrame->callee() && !callFrame->callee()->isObject(&JSC::JSFunction::info)) + ++argv; // ### off-by-one issue with native functions for (unsigned i = 0; i < numArguments; ++i) extraArguments[i] = argv[i]; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp index 62e42fe..c89ebf8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp @@ -27,9 +27,32 @@ #include "CallData.h" #include "JSFunction.h" +#include "JSGlobalObject.h" + +#ifdef QT_BUILD_SCRIPT_LIB +#include "Debugger.h" +#include "DebuggerCallFrame.h" +#endif namespace JSC { +#ifdef QT_BUILD_SCRIPT_LIB +JSValue JSC::NativeFuncWrapper::operator() (ExecState* exec, JSObject* jsobj, JSValue thisValue, const ArgList& argList) const +{ + Debugger* debugger = exec->lexicalGlobalObject()->debugger(); + if (debugger) + debugger->callEvent(DebuggerCallFrame(exec), -1, -1); + + JSValue returnValue = ptr(exec, jsobj, thisValue, argList); + + if (debugger) + debugger->functionExit(returnValue, -1); + + return returnValue; +} +#endif + + JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args) { if (callType == CallTypeHost) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.h b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.h index d5b0172..541779c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.h @@ -48,9 +48,35 @@ namespace JSC { typedef JSValue (JSC_HOST_CALL *NativeFunction)(ExecState*, JSObject*, JSValue thisValue, const ArgList&); - union CallData { +#ifdef QT_BUILD_SCRIPT_LIB + class NativeFuncWrapper + { + NativeFunction ptr; + public: + inline NativeFuncWrapper& operator=(NativeFunction func) + { + ptr = func; + return *this; + } + inline operator NativeFunction() const {return ptr;} + inline operator bool() const {return ptr;} + + JSValue operator()(ExecState* exec, JSObject* jsobj, JSValue thisValue, const ArgList& argList) const; + }; +#endif + +#if defined(QT_BUILD_SCRIPT_LIB) && PLATFORM(SOLARIS) + struct +#else + union +#endif + CallData { struct { +#ifndef QT_BUILD_SCRIPT_LIB NativeFunction function; +#else + NativeFuncWrapper function; +#endif } native; struct { FunctionBodyNode* functionBody; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.cpp index bc5582c..dddd83d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Collector.cpp @@ -1167,6 +1167,10 @@ bool Heap::collect() markStackObjectsConservatively(); markProtectedObjects(); +#if QT_BUILD_SCRIPT_LIB + if (m_globalData->clientData) + m_globalData->clientData->mark(); +#endif if (m_markListSet && m_markListSet->size()) MarkedArgumentBuffer::markLists(*m_markListSet); if (m_globalData->exception && !m_globalData->exception.marked()) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp index b8b1581..04c9a2e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Completion.cpp @@ -31,6 +31,11 @@ #include "Debugger.h" #include <stdio.h> +#ifdef QT_BUILD_SCRIPT_LIB +#include "DebuggerCallFrame.h" +#include "SourcePoolQt.h" +#endif + #if !PLATFORM(WIN_OS) #include <unistd.h> #endif @@ -54,12 +59,15 @@ Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& s { JSLock lock(exec); + intptr_t sourceId = source.provider()->asID(); int errLine; UString errMsg; RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - if (!programNode) - return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url())); + if (!programNode) { + JSValue error = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, source.provider()->url()); + return Completion(Throw, error); + } JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); @@ -71,6 +79,7 @@ Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& s return Completion(Interrupted, exception); return Completion(Throw, exception); } + return Completion(Normal, result); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.cpp index 7ee59d7..3dfc918 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.cpp @@ -28,15 +28,38 @@ #include "JSFunction.h" + +#ifdef QT_BUILD_SCRIPT_LIB +#include "Debugger.h" +#include "DebuggerCallFrame.h" +#include "JSGlobalObject.h" +#endif + namespace JSC { -JSObject* construct(ExecState* exec, JSValue object, ConstructType constructType, const ConstructData& constructData, const ArgList& args) +#ifdef QT_BUILD_SCRIPT_LIB +JSObject* JSC::NativeConstrWrapper::operator() (ExecState* exec, JSObject* jsobj, const ArgList& argList) const +{ + Debugger* debugger = exec->lexicalGlobalObject()->debugger(); + if (debugger) + debugger->callEvent(DebuggerCallFrame(exec), -1, -1); + + JSObject* returnValue = ptr(exec, jsobj, argList); + + if ((debugger) && (callDebuggerFunctionExit)) + debugger->functionExit(JSValue(returnValue), -1); + + return returnValue; +} +#endif + +JSObject* construct(ExecState* exec, JSValue callee, ConstructType constructType, const ConstructData& constructData, const ArgList& args) { if (constructType == ConstructTypeHost) - return constructData.native.function(exec, asObject(object), args); + return constructData.native.function(exec, asObject(callee), args); ASSERT(constructType == ConstructTypeJS); // FIXME: Can this be done more efficiently using the constructData? - return asFunction(object)->construct(exec, args); + return asFunction(callee)->construct(exec, args); } } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.h b/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.h index 9d580d5..477399c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/ConstructData.h @@ -46,9 +46,42 @@ namespace JSC { typedef JSObject* (*NativeConstructor)(ExecState*, JSObject*, const ArgList&); - union ConstructData { +#ifdef QT_BUILD_SCRIPT_LIB + class NativeConstrWrapper + { + NativeConstructor ptr; + //Hack. If this variable is true and if debugger is attached at the end of + //operator() execution functionExit event will be created (in most cases it will be default) + //This variable was created because of FunctionWrapper::proxyCall method that change result + //on fly. Event shuld be created with original value so the method should call it itself. + bool callDebuggerFunctionExit; + public: + inline NativeConstrWrapper& operator=(NativeConstructor func) + { + callDebuggerFunctionExit = true; + ptr = func; + return *this; + } + inline operator NativeConstructor() const {return ptr;} + inline operator bool() const {return ptr;} + + inline void doNotCallDebuggerFunctionExit() {callDebuggerFunctionExit = false;} + JSObject* operator()(ExecState*, JSObject*, const ArgList&) const; + }; +#endif + +#if defined(QT_BUILD_SCRIPT_LIB) && PLATFORM(SOLARIS) + struct +#else + union +#endif + ConstructData { struct { +#ifndef QT_BUILD_SCRIPT_LIB NativeConstructor function; +#else + NativeConstrWrapper function; +#endif } native; struct { FunctionBodyNode* functionBody; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Error.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Error.cpp index db1d8cc..1aa9034 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Error.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Error.cpp @@ -83,11 +83,11 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message, JSObject* error = construct(exec, constructor, constructType, constructData, args); if (lineNumber != -1) - error->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, lineNumber), ReadOnly | DontDelete); + error->putWithAttributes(exec, Identifier(exec, JSC_ERROR_LINENUMBER_PROPERTYNAME), jsNumber(exec, lineNumber), ReadOnly | DontDelete); if (sourceID != -1) error->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, sourceID), ReadOnly | DontDelete); if (!sourceURL.isNull()) - error->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsString(exec, sourceURL), ReadOnly | DontDelete); + error->putWithAttributes(exec, Identifier(exec, JSC_ERROR_FILENAME_PROPERTYNAME), jsString(exec, sourceURL), ReadOnly | DontDelete); return error; } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Error.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Error.h index adf7fdf..fb864ee 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Error.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Error.h @@ -60,6 +60,14 @@ namespace JSC { JSObject* throwError(ExecState*, ErrorType, const char* message); JSObject* throwError(ExecState*, ErrorType); +#ifdef QT_BUILD_SCRIPT_LIB +# define JSC_ERROR_FILENAME_PROPERTYNAME "fileName" +# define JSC_ERROR_LINENUMBER_PROPERTYNAME "lineNumber" +#else +# define JSC_ERROR_FILENAME_PROPERTYNAME "sourceURL" +# define JSC_ERROR_LINENUMBER_PROPERTYNAME "line" +#endif + } // namespace JSC #endif // Error_h diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.cpp index 9ba2144..ff8e57b 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -98,7 +98,11 @@ JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSVa return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}"); } +#ifdef QT_BUILD_SCRIPT_LIB //same error message as in the old engine, and in mozilla + return throwError(exec, TypeError, "Function.prototype.toString called on incompatible object"); +#else return throwError(exec, TypeError); +#endif } JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.cpp index 3bef263..184a9cb 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.cpp @@ -133,12 +133,12 @@ void JSActivation::putWithAttributes(ExecState* exec, const Identifier& property JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot); } -bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { if (propertyName == exec->propertyNames().arguments) return false; - return Base::deleteProperty(exec, propertyName); + return Base::deleteProperty(exec, propertyName, checkDontDelete); } JSObject* JSActivation::toThisObject(ExecState* exec) const diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.h index c183dac..b48ef25 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSActivation.h @@ -57,7 +57,7 @@ namespace JSC { virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); virtual JSObject* toThisObject(ExecState*) const; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp index 296ac9d..a8207e3 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.cpp @@ -375,20 +375,20 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu checkConsistency(); } -bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex) - return deleteProperty(exec, i); + return deleteProperty(exec, i, checkDontDelete); if (propertyName == exec->propertyNames().length) return false; - return JSObject::deleteProperty(exec, propertyName); + return JSObject::deleteProperty(exec, propertyName, checkDontDelete); } -bool JSArray::deleteProperty(ExecState* exec, unsigned i) +bool JSArray::deleteProperty(ExecState* exec, unsigned i, bool checkDontDelete) { checkConsistency(); @@ -422,12 +422,12 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i) checkConsistency(); if (i > MAX_ARRAY_INDEX) - return deleteProperty(exec, Identifier::from(exec, i)); + return deleteProperty(exec, Identifier::from(exec, i), checkDontDelete); return false; } -void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { // FIXME: Filling PropertyNameArray with an identifier for every integer // is incredibly inefficient for large arrays. We need a different approach, @@ -447,7 +447,7 @@ void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames propertyNames.add(Identifier::from(exec, it->first)); } - JSObject::getPropertyNames(exec, propertyNames); + JSObject::getPropertyNames(exec, propertyNames, listedAttributes); } bool JSArray::increaseVectorLength(unsigned newLength) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.h index ea490d8..73e1711 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSArray.h @@ -85,9 +85,9 @@ namespace JSC { protected: virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); - virtual bool deleteProperty(ExecState*, unsigned propertyName); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); virtual void mark(); void* lazyCreationData(); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.cpp index 2a5e72f..d00b69c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.cpp @@ -85,12 +85,12 @@ void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value) setIndex(exec, propertyName, value); } -void JSByteArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSByteArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { unsigned length = m_storage->length(); for (unsigned i = 0; i < length; ++i) propertyNames.add(Identifier::from(exec, i)); - JSObject::getPropertyNames(exec, propertyNames); + JSObject::getPropertyNames(exec, propertyNames, listedAttributes); } } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.h index 57374e0..c43c3ea 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSByteArray.h @@ -81,7 +81,7 @@ namespace JSC { virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); virtual const ClassInfo* classInfo() const { return m_classInfo; } static const ClassInfo s_defaultInfo; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.cpp index 8cf7943..10a91f7 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.cpp @@ -167,14 +167,14 @@ void JSCell::put(ExecState* exec, unsigned identifier, JSValue value) toObject(exec)->put(exec, identifier, value); } -bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier) +bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier, bool checkDontDelete) { - return toObject(exec)->deleteProperty(exec, identifier); + return toObject(exec)->deleteProperty(exec, identifier, checkDontDelete); } -bool JSCell::deleteProperty(ExecState* exec, unsigned identifier) +bool JSCell::deleteProperty(ExecState* exec, unsigned identifier, bool checkDontDelete) { - return toObject(exec)->deleteProperty(exec, identifier); + return toObject(exec)->deleteProperty(exec, identifier, checkDontDelete); } JSObject* JSCell::toThisObject(ExecState* exec) const diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.h index 32aa22b..4743baf 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSCell.h @@ -90,8 +90,8 @@ namespace JSC { virtual const ClassInfo* classInfo() const; virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); - virtual bool deleteProperty(ExecState*, unsigned propertyName); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); virtual JSObject* toThisObject(ExecState*) const; virtual UString toThisString(ExecState*) const; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.cpp index b79074f..c8e137e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.cpp @@ -176,13 +176,13 @@ void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue va Base::put(exec, propertyName, value, slot); } -bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { if (isHostFunction()) - return Base::deleteProperty(exec, propertyName); + return Base::deleteProperty(exec, propertyName, checkDontDelete); if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return false; - return Base::deleteProperty(exec, propertyName); + return Base::deleteProperty(exec, propertyName, checkDontDelete); } // ECMA 13.2.2 [[Construct]] diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.h index b27e515..5ddd97c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSFunction.h @@ -56,7 +56,7 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); JSObject* construct(ExecState*, const ArgList&); JSValue call(ExecState*, JSValue thisValue, const ArgList&); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.cpp index ff728e8..85d881e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.cpp @@ -134,6 +134,7 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) #if ENABLE(JIT) , jitStubs(this) #endif + , timeoutChecker(new TimeoutChecker) , heap(this) , initializingLazyNumericCompareFunction(false) , head(0) @@ -141,6 +142,9 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) , scopeNodeBeingReparsed(0) , firstStringifierToMark(0) { +#ifdef QT_BUILD_SCRIPT_LIB + scriptpool = new SourcePool(); +#endif #if PLATFORM(MAC) startProfilerServerIfNeeded(); #endif @@ -176,6 +180,7 @@ JSGlobalData::~JSGlobalData() delete parser; delete lexer; + delete timeoutChecker; deleteAllValues(opaqueJSClassData); @@ -185,6 +190,10 @@ JSGlobalData::~JSGlobalData() deleteIdentifierTable(identifierTable); delete clientData; +#ifdef QT_BUILD_SCRIPT_LIB + if (scriptpool) + delete scriptpool; +#endif } PassRefPtr<JSGlobalData> JSGlobalData::create(bool isShared) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.h index 96a3c2c..fb557af 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalData.h @@ -39,6 +39,10 @@ #include <wtf/HashMap.h> #include <wtf/RefCounted.h> +#ifdef QT_BUILD_SCRIPT_LIB +#include "SourcePoolQt.h" +#endif + struct OpaqueJSClass; struct OpaqueJSClassContextData; @@ -65,6 +69,9 @@ namespace JSC { public: struct ClientData { virtual ~ClientData() = 0; +#ifdef QT_BUILD_SCRIPT_LIB + virtual void mark() {} +#endif }; static bool sharedInstanceExists(); @@ -118,10 +125,13 @@ namespace JSC { Lexer* lexer; Parser* parser; Interpreter* interpreter; +#ifdef QT_BUILD_SCRIPT_LIB + SourcePool* scriptpool; +#endif #if ENABLE(JIT) JITThunks jitStubs; #endif - TimeoutChecker timeoutChecker; + TimeoutChecker* timeoutChecker; Heap heap; JSValue exception; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp index c56b84b..55286d3 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -307,12 +307,12 @@ void JSGlobalObject::reset(JSValue prototype) putDirectFunctionWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum); putDirectFunctionWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum); putDirectFunctionWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor); - putDirectFunctionWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor); - putDirectFunctionWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor); - putDirectFunctionWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor); - putDirectFunctionWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor); - putDirectFunctionWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor); + putDirectFunctionWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor, DontEnum); + putDirectFunctionWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor, DontEnum); // Set global values. GlobalPropertyInfo staticGlobals[] = { @@ -340,8 +340,10 @@ void JSGlobalObject::reset(JSValue prototype) putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum); #ifndef NDEBUG +#ifndef QT_BUILD_SCRIPT_LIB putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); #endif +#endif resetPrototype(prototype); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h index 7ab759d..dc11fee 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSGlobalObject.h @@ -30,6 +30,10 @@ #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> +#ifdef QT_BUILD_SCRIPT_LIB +#include "SourcePoolQt.h" +#endif + namespace JSC { class ArrayPrototype; @@ -226,7 +230,13 @@ namespace JSC { unsigned profileGroup() const { return d()->profileGroup; } Debugger* debugger() const { return d()->debugger; } - void setDebugger(Debugger* debugger) { d()->debugger = debugger; } + void setDebugger(Debugger* debugger) + { +#ifdef QT_BUILD_SCRIPT_LIB + globalData()->scriptpool->setDebugger(debugger); +#endif + d()->debugger = debugger; + } virtual bool supportsProfiling() const { return false; } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.h index 706396e..e7d7847 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSImmediate.h @@ -130,7 +130,11 @@ namespace JSC { */ class JSImmediate { +#ifdef QT_BUILD_SCRIPT_LIB + public: // QtScript needs isImmediate() and from() functions +#else private: +#endif friend class JIT; friend class JSValue; friend class JSFastMath; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.cpp index 937dc2b..fb9cfe8 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.cpp @@ -116,7 +116,7 @@ bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned) return false; } -void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&) +void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&, unsigned) { ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.h index a8e36bd..0aca63b 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSNotAnObject.h @@ -87,7 +87,7 @@ namespace JSC { virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); JSNotAnObjectErrorStub* m_exception; }; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSONObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSONObject.cpp index 2f02b1d..bbbe3af 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSONObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSONObject.cpp @@ -394,7 +394,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& return StringifySucceeded; // If this is the outermost call, then loop to handle everything on the holder stack. - TimeoutChecker localTimeoutChecker(m_exec->globalData().timeoutChecker); + TimeoutChecker localTimeoutChecker(*m_exec->globalData().timeoutChecker); localTimeoutChecker.reset(); unsigned tickCount = localTimeoutChecker.ticksUntilNextCheck(); do { diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp index 415c25d..ded842d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.cpp @@ -204,12 +204,12 @@ bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const } // ECMA 8.6.2.5 -bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { unsigned attributes; JSCell* specificValue; if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) { - if ((attributes & DontDelete)) + if ((attributes & DontDelete) && checkDontDelete) return false; removeDirect(propertyName); return true; @@ -217,7 +217,7 @@ bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName) // Look in the static hashtable of properties const HashEntry* entry = findPropertyHashEntry(exec, propertyName); - if (entry && entry->attributes() & DontDelete) + if (entry && (entry->attributes() & DontDelete) && checkDontDelete) return false; // this builtin property can't be deleted // FIXME: Should the code here actually do some deletion? @@ -230,9 +230,9 @@ bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) c return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot); } -bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName) +bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName, bool checkDontDelete) { - return deleteProperty(exec, Identifier::from(exec, propertyName)); + return deleteProperty(exec, Identifier::from(exec, propertyName), checkDontDelete); } static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName) @@ -447,9 +447,9 @@ bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyNa return false; } -void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { - m_structure->getEnumerablePropertyNames(exec, propertyNames, this); + m_structure->getPropertyNames(exec, propertyNames, this, listedAttributes); } bool JSObject::toBoolean(ExecState*) const @@ -524,7 +524,12 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* Structure* JSObject::createInheritorID() { +#ifdef QT_BUILD_SCRIPT_LIB + // ### QtScript needs the hasOwnProperty() calls etc. for QScriptObject + m_inheritorID = Structure::create(this, TypeInfo(ObjectType, ImplementsHasInstance)); +#else m_inheritorID = JSObject::createStructure(this); +#endif return m_inheritorID.get(); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h index db47ac7..15b7957 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSObject.h @@ -110,14 +110,13 @@ namespace JSC { bool hasProperty(ExecState*, unsigned propertyName) const; bool hasOwnProperty(ExecState*, const Identifier& propertyName) const; - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); - virtual bool deleteProperty(ExecState*, unsigned propertyName); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const; virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty); - - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.cpp index 86f95e0..e1fc66d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.cpp @@ -112,6 +112,21 @@ bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Proper return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); } +bool JSString::getStringPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const +{ + if (propertyName == exec->propertyNames().length) { + attributes = DontEnum | DontDelete | ReadOnly; + return true; + } + bool isStrictUInt32; + unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); + if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) { + attributes = DontDelete | ReadOnly; + return true; + } + return false; +} + JSString* jsString(JSGlobalData* globalData, const UString& s) { int size = s.size(); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.h index 900c565..6db9322 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSString.h @@ -87,6 +87,8 @@ namespace JSC { bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + bool getStringPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned&) const; + bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); } JSString* getIndex(JSGlobalData*, unsigned); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.cpp index a36cefa..78993b6 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.cpp @@ -33,23 +33,23 @@ namespace JSC { -bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { if (symbolTable().contains(propertyName.ustring().rep())) return false; - return JSObject::deleteProperty(exec, propertyName); + return JSObject::deleteProperty(exec, propertyName, checkDontDelete); } -void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { SymbolTable::const_iterator end = symbolTable().end(); for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) { - if (!(it->second.getAttributes() & DontEnum)) + if ((listedAttributes & Structure::NonEnumerable) || !(it->second.getAttributes() & DontEnum)) propertyNames.add(Identifier(exec, it->first.get())); } - JSObject::getPropertyNames(exec, propertyNames); + JSObject::getPropertyNames(exec, propertyNames, listedAttributes); } bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.h index b969da5..310efb1 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/JSVariableObject.h @@ -48,8 +48,8 @@ namespace JSC { virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0; - virtual bool deleteProperty(ExecState*, const Identifier&); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual bool deleteProperty(ExecState*, const Identifier&, bool checkDontDelete = true); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); virtual bool isVariableObject() const; virtual bool isDynamicScope() const = 0; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorPrototype.cpp index 84190a0..650a0fd 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorPrototype.cpp @@ -30,7 +30,11 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype); NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, const UString& name, const UString& message) +#ifdef QT_BUILD_SCRIPT_LIB + : ErrorInstance(structure) +#else : JSObject(structure) +#endif { putDirect(exec->propertyNames().name, jsString(exec, name), 0); putDirect(exec->propertyNames().message, jsString(exec, message), 0); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorPrototype.h b/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorPrototype.h index 77bfe8a..48a9d7e 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorPrototype.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/NativeErrorPrototype.h @@ -22,10 +22,19 @@ #define NativeErrorPrototype_h #include "JSObject.h" +#ifdef QT_BUILD_SCRIPT_LIB +#include "ErrorInstance.h" +#endif namespace JSC { - class NativeErrorPrototype : public JSObject { + class NativeErrorPrototype : +#ifdef QT_BUILD_SCRIPT_LIB //According to ECMAScript Specification 15.11.7, errors must have the "Error" class + public ErrorInstance +#else + public JSObject +#endif + { public: NativeErrorPrototype(ExecState*, PassRefPtr<Structure>, const UString& name, const UString& message); }; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.cpp index 7dd4a8f..b366b58 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExp.cpp @@ -72,12 +72,35 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const US { // NOTE: The global flag is handled on a case-by-case basis by functions like // String::match and RegExpObject::match. +#ifndef QT_BUILD_SCRIPT_LIB if (flags.find('g') != -1) m_flagBits |= Global; if (flags.find('i') != -1) m_flagBits |= IgnoreCase; if (flags.find('m') != -1) m_flagBits |= Multiline; +#else //Invalid flags should throw a SyntaxError (ECMA Script 15.10.4.1) + static const char flagError[] = "invalid regular expression flag"; + for (int i = 0; i < flags.size(); i++) { + switch (flags.data()[i]) { + case 'g': + m_flagBits |= Global; + break; + case 'i': + m_flagBits |= IgnoreCase; + break; + case 'm': + m_flagBits |= Multiline; + break; + default: + m_constructionError = flagError; +#if !ENABLE(YARR) + m_regExp = 0; +#endif + return; + } + } +#endif compile(globalData); } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpMatchesArray.h b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpMatchesArray.h index 9ae18b9..cbba85a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -58,25 +58,25 @@ namespace JSC { JSArray::put(exec, propertyName, v); } - virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName) + virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete = true) { if (lazyCreationData()) fillArrayInstance(exec); - return JSArray::deleteProperty(exec, propertyName); + return JSArray::deleteProperty(exec, propertyName, checkDontDelete); } - virtual bool deleteProperty(ExecState* exec, unsigned propertyName) + virtual bool deleteProperty(ExecState* exec, unsigned propertyName, bool checkDontDelete = true) { if (lazyCreationData()) fillArrayInstance(exec); - return JSArray::deleteProperty(exec, propertyName); + return JSArray::deleteProperty(exec, propertyName, checkDontDelete); } - virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr) + virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr, unsigned listedAttributes) { if (lazyCreationData()) fillArrayInstance(exec); - JSArray::getPropertyNames(exec, arr); + JSArray::getPropertyNames(exec, arr, listedAttributes); } void fillArrayInstance(ExecState*); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpPrototype.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpPrototype.cpp index b1ab889..e507016 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -106,6 +106,10 @@ JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValu } UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec); +#ifdef QT_BUILD_SCRIPT_LIB + if (result.size() == 1) + result.append("(?:)"); +#endif result.append('/'); if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec)) result.append('g'); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.cpp index fb44498..4745a98 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.cpp @@ -68,19 +68,30 @@ void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue JSObject::put(exec, propertyName, value, slot); } -bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { if (propertyName == exec->propertyNames().length) return false; - return JSObject::deleteProperty(exec, propertyName); + bool isStrictUInt32; + unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); + if (isStrictUInt32 && internalValue()->canGetIndex(i)) + return false; + return JSObject::deleteProperty(exec, propertyName, checkDontDelete); } -void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { int size = internalValue()->value().size(); for (int i = 0; i < size; ++i) propertyNames.add(Identifier(exec, UString::from(i))); - return JSObject::getPropertyNames(exec, propertyNames); + return JSObject::getPropertyNames(exec, propertyNames, listedAttributes); +} + +bool StringObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const +{ + if (internalValue()->getStringPropertyAttributes(exec, propertyName, attributes)) + return true; + return JSObject::getPropertyAttributes(exec, propertyName, attributes); } UString StringObject::toString(ExecState*) const diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.h b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.h index ea3a045..fdeb2c1 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/StringObject.h @@ -37,8 +37,9 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); + virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; virtual const ClassInfo* classInfo() const { return &info; } static const JS_EXPORTDATA ClassInfo info; diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp index 5dfd919..9f6b0c3 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp @@ -285,9 +285,9 @@ void Structure::materializePropertyMap() } } -void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject) +void Structure::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject, unsigned listedAttributes) { - bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary); + bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary) && (listedAttributes & Prototype); if (shouldCache && m_cachedPropertyNameArrayData) { if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) { @@ -296,11 +296,13 @@ void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& p } clearEnumerationCache(); } + bool includeNonEnumerable = false; + if (listedAttributes & NonEnumerable) + includeNonEnumerable = true; + getNamesFromPropertyTable(propertyNames, includeNonEnumerable); + getNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames, includeNonEnumerable); - getEnumerableNamesFromPropertyTable(propertyNames); - getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames); - - if (m_prototype.isObject()) { + if ((listedAttributes & Prototype) && m_prototype.isObject()) { propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly. asObject(m_prototype)->getPropertyNames(exec, propertyNames); } @@ -1008,7 +1010,7 @@ static int comparePropertyMapEntryIndices(const void* a, const void* b) return 0; } -void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyNames) +void Structure::getNamesFromPropertyTable(PropertyNameArray& propertyNames, bool includeNonEnumerable) { materializePropertyMapIfNecessary(); if (!m_propertyTable) @@ -1019,7 +1021,8 @@ void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyN int i = 0; unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned k = 1; k <= entryCount; k++) { - if (m_propertyTable->entries()[k].key && !(m_propertyTable->entries()[k].attributes & DontEnum)) { + if (m_propertyTable->entries()[k].key + && (includeNonEnumerable || !(m_propertyTable->entries()[k].attributes & DontEnum))) { PropertyMapEntry* value = &m_propertyTable->entries()[k]; int j; for (j = i - 1; j >= 0 && a[j]->index > value->index; --j) @@ -1046,7 +1049,8 @@ void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyN PropertyMapEntry** p = sortedEnumerables.data(); unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned i = 1; i <= entryCount; i++) { - if (m_propertyTable->entries()[i].key && !(m_propertyTable->entries()[i].attributes & DontEnum)) + if (m_propertyTable->entries()[i].key + && (includeNonEnumerable || !(m_propertyTable->entries()[i].attributes & DontEnum))) *p++ = &m_propertyTable->entries()[i]; } @@ -1065,7 +1069,7 @@ void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyN } } -void Structure::getEnumerableNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames) +void Structure::getNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, bool includeNonEnumerable) { // Add properties from the static hashtables of properties for (; classInfo; classInfo = classInfo->parentClass) { @@ -1078,7 +1082,7 @@ void Structure::getEnumerableNamesFromClassInfoTable(ExecState* exec, const Clas int hashSizeMask = table->compactSize - 1; const HashEntry* entry = table->table; for (int i = 0; i <= hashSizeMask; ++i, ++entry) { - if (entry->key() && !(entry->attributes() & DontEnum)) + if (entry->key() && (includeNonEnumerable || !(entry->attributes() & DontEnum))) propertyNames.add(entry->key()); } } diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h index 866999d..0de03a3 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.h @@ -50,6 +50,11 @@ namespace JSC { class Structure : public RefCounted<Structure> { public: + enum ListedAttribute { + NonEnumerable = 1 << 1, + Prototype = 1 << 2 + }; + friend class JIT; static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo) { @@ -106,7 +111,7 @@ namespace JSC { return get(propertyName._ustring.rep(), attributes, specificValue); } - void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*); + void getPropertyNames(ExecState*, PropertyNameArray&, JSObject*, unsigned listedAttributes = Prototype); bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; } @@ -121,8 +126,8 @@ namespace JSC { size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); size_t remove(const Identifier& propertyName); - void getEnumerableNamesFromPropertyTable(PropertyNameArray&); - void getEnumerableNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&); + void getNamesFromPropertyTable(PropertyNameArray&, bool includeNonEnumerable = false); + void getNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&, bool includeNonEnumerable = false); void expandPropertyMapHashTable(); void rehashPropertyMapHashTable(); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.cpp index 30ba6e9..045a33a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -56,8 +56,8 @@ namespace JSC { // Number of ticks before the first timeout check is done. static const int ticksUntilFirstCheck = 1024; -// Number of milliseconds between each timeout check. -static const int intervalBetweenChecks = 1000; +// Default number of milliseconds between each timeout check. +static const int defaultIntervalBetweenChecks = 1000; // Returns the time the current thread has spent executing, in milliseconds. static inline unsigned getCPUTime() @@ -104,10 +104,15 @@ static inline unsigned getCPUTime() TimeoutChecker::TimeoutChecker() : m_timeoutInterval(0) , m_startCount(0) + , m_intervalBetweenChecks(defaultIntervalBetweenChecks) { reset(); } +TimeoutChecker::~TimeoutChecker() +{ +} + void TimeoutChecker::reset() { m_ticksUntilNextCheck = ticksUntilFirstCheck; @@ -135,7 +140,7 @@ bool TimeoutChecker::didTimeOut(ExecState* exec) // Adjust the tick threshold so we get the next checkTimeout call in the // interval specified in intervalBetweenChecks. - m_ticksUntilNextCheck = static_cast<unsigned>((static_cast<float>(intervalBetweenChecks) / timeDiff) * m_ticksUntilNextCheck); + m_ticksUntilNextCheck = static_cast<unsigned>((static_cast<float>(m_intervalBetweenChecks) / timeDiff) * m_ticksUntilNextCheck); // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the // preferred script check time interval. if (m_ticksUntilNextCheck == 0) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.h b/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.h index 7bfa6d0..1680d6d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/TimeoutChecker.h @@ -38,8 +38,10 @@ namespace JSC { class TimeoutChecker { public: TimeoutChecker(); + virtual ~TimeoutChecker(); void setTimeoutInterval(unsigned timeoutInterval) { m_timeoutInterval = timeoutInterval; } + void setCheckInterval(unsigned checkInterval) { if (checkInterval) m_intervalBetweenChecks = checkInterval; } unsigned ticksUntilNextCheck() { return m_ticksUntilNextCheck; } @@ -58,7 +60,7 @@ namespace JSC { void reset(); - bool didTimeOut(ExecState*); + virtual bool didTimeOut(ExecState*); private: unsigned m_timeoutInterval; @@ -66,6 +68,7 @@ namespace JSC { unsigned m_timeExecuting; unsigned m_startCount; unsigned m_ticksUntilNextCheck; + unsigned m_intervalBetweenChecks; }; } // namespace JSC diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/UString.h b/src/3rdparty/webkit/JavaScriptCore/runtime/UString.h index f2572a9..0a53c50 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/UString.h +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/UString.h @@ -77,6 +77,7 @@ namespace JSC { friend class JIT; public: + typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; struct BaseString; struct Rep : Noncopyable { @@ -364,6 +365,19 @@ namespace JSC { return m_rep->reserveCapacity(capacity); } +#if PLATFORM(QT) + operator QString() const + { + return QString(reinterpret_cast<const QChar*>(this->data()), this->size()); + } + + UString(const QString& str) + { + *this = JSC::UString(reinterpret_cast<const UChar*>(str.constData()), str.length()); + } +#endif + + private: void expandCapacity(int requiredLength); void expandPreCapacity(int requiredPreCap); @@ -531,6 +545,20 @@ namespace JSC { return capacityDelta; } +#if PLATFORM(QT) + + inline UString operator+(const char* s1, const UString& s2) + { + return operator+(UString(s1), s2); + } + + inline UString operator+(const UString& s1, const char* s2) + { + return operator+(s1, UString(s2)); + } + +#endif + struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > { static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->computedHash(); } static unsigned hash(JSC::UString::Rep* key) { return key->computedHash(); } diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.cpp b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.cpp index 819ed9a..54daf23 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.cpp @@ -72,7 +72,10 @@ static void vprintf_stderr_common(const char* format, va_list args) CFRelease(cfFormat); } else #elif COMPILER(MSVC) && !defined(WINCEBASIC) - if (IsDebuggerPresent()) { +# if !defined(_WIN32_WCE) || (_WIN32_WCE >= 0x600) + if (IsDebuggerPresent()) +# endif + { size_t size = 1024; do { diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h index 59efd84..1be7455 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h @@ -144,7 +144,11 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann #if ASSERT_DISABLED #define ASSERT(assertion) ((void)0) +#if COMPILER(MSVC7) +#define ASSERT_WITH_MESSAGE(assertion) ((void)0) +#else #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) +#endif /* COMPILER(MSVC7) */ #define ASSERT_NOT_REACHED() ((void)0) #define ASSERT_UNUSED(variable, assertion) ((void)variable) @@ -199,7 +203,7 @@ while (0) /* FATAL */ -#if FATAL_DISABLED +#if FATAL_DISABLED && !COMPILER(MSVC7) #define FATAL(...) ((void)0) #elif COMPILER(MSVC7) #define FATAL() ((void)0) @@ -212,7 +216,7 @@ while (0) /* LOG_ERROR */ -#if ERROR_DISABLED +#if ERROR_DISABLED && !COMPILER(MSVC7) #define LOG_ERROR(...) ((void)0) #elif COMPILER(MSVC7) #define LOG_ERROR() ((void)0) @@ -222,7 +226,7 @@ while (0) /* LOG */ -#if LOG_DISABLED +#if LOG_DISABLED && !COMPILER(MSVC7) #define LOG(channel, ...) ((void)0) #elif COMPILER(MSVC7) #define LOG() ((void)0) @@ -234,7 +238,7 @@ while (0) /* LOG_VERBOSE */ -#if LOG_DISABLED +#if LOG_DISABLED && !COMPILER(MSVC7) #define LOG_VERBOSE(channel, ...) ((void)0) #elif COMPILER(MSVC7) #define LOG_VERBOSE(channel) ((void)0) diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Platform.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Platform.h index c7a5be9..e531a63 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Platform.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Platform.h @@ -94,6 +94,20 @@ #define WTF_PLATFORM_SOLARIS 1 #endif +/* PLATFORM(AIX) */ +/* Operating system level dependencies for AIX that should be used */ +/* regardless of operating environment */ +#if defined(_AIX) +#define WTF_PLATFORM_AIX 1 +#endif + +/* PLATFORM(HPUX) */ +/* Operating system level dependencies for HP-UX that should be used */ +/* regardless of operating environment */ +#if defined(hpux) || defined(__hpux) +#define WTF_PLATFORM_HPUX 1 +#endif + #if defined (__SYMBIAN32__) /* we are cross-compiling, it is not really windows */ #undef WTF_PLATFORM_WIN_OS @@ -123,10 +137,12 @@ || PLATFORM(FREEBSD) \ || PLATFORM(SYMBIAN) \ || PLATFORM(NETBSD) \ + || PLATFORM(SOLARIS) \ + || PLATFORM(HPUX) \ || defined(unix) \ || defined(__unix) \ || defined(__unix__) \ - || defined(_AIX) \ + || PLATFORM(AIX) \ || defined(__QNXNTO__) #define WTF_PLATFORM_UNIX 1 #endif @@ -343,6 +359,24 @@ #define WTF_COMPILER_WINSCW 1 #endif +/* COMPILER(SUNCC) */ +/* This is the Sun CC compiler, also known as Sun Studio or Sun Pro */ +#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) +#define WTF_COMPILER_SUNCC 1 +#endif + +/* COMPILER(XLC) */ +/* IBM Visual Age C/C++ compiler, a.k.a. xlC */ +#if defined(__xlC__) +#define WTF_COMPILER_XLC 1 +#endif + +/* COMPILER(ACC) */ +/* HP's aC++/ANSI C compiler, a.k.a. aCC */ +#if defined(__HP_aCC) +#define WTF_COMPILER_ACC +#endif + #if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS) #define ENABLE_JSC_MULTIPLE_THREADS 1 #endif diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Vector.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Vector.h index 7cba4e4..bff770c 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Vector.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Vector.h @@ -45,7 +45,7 @@ namespace WTF { #define WTF_ALIGN_OF(type) __alignof(type) #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable #else - #error WTF_ALIGN macros need alignment control. + #define WTF_ALIGN_OF(type) 0 #endif #if COMPILER(GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303) @@ -54,6 +54,7 @@ namespace WTF { typedef char AlignedBufferChar; #endif + #ifdef WTF_ALIGNED template <size_t size, size_t alignment> struct AlignedBuffer; template <size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; }; template <size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2); }; @@ -62,6 +63,17 @@ namespace WTF { template <size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); }; template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); }; template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); }; + #else + template <size_t size, size_t> struct AlignedBuffer + { + AlignedBufferChar oversizebuffer[size + 64]; + AlignedBufferChar *buffer; + inline AlignedBuffer() : buffer(oversizebuffer) + { + buffer += 64 - (reinterpret_cast<size_t>(buffer) & 0x3f); + } + }; + #endif template <bool needsDestruction, typename T> class VectorDestructor; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSClipboardCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSClipboardCustom.cpp index 78dca49..73946c8 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSClipboardCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSClipboardCustom.cpp @@ -59,7 +59,7 @@ JSValue JSClipboard::types(ExecState* exec) const MarkedArgumentBuffer list; HashSet<String>::const_iterator end = types.end(); for (HashSet<String>::const_iterator it = types.begin(); it != end; ++it) - list.append(jsString(exec, UString(*it))); + list.append(jsString(exec, it->operator UString())); return constructArray(exec, list); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomPositionCallback.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomPositionCallback.cpp index 6abed99..e28fd8f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomPositionCallback.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomPositionCallback.cpp @@ -72,9 +72,9 @@ void JSCustomPositionCallback::handleEvent(Geoposition* geoposition, bool& raise MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), geoposition)); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); call(exec, function, callType, callData, m_callback, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); if (exec->hadException()) { reportCurrentException(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp index cda5738..dbe46e2 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp @@ -72,9 +72,9 @@ void JSCustomPositionErrorCallback::handleEvent(PositionError* positionError) MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), positionError)); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); call(exec, function, callType, callData, m_callback, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); if (exec->hadException()) reportCurrentException(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp index d0943de..a2b5c83 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp @@ -78,9 +78,9 @@ void JSCustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLR args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), resultSet)); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); call(exec, function, callType, callData, m_callback, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); if (exec->hadException()) { reportCurrentException(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp index 6c831ac..c7c467f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp @@ -82,12 +82,12 @@ bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error)); JSValue result; - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); if (handleEventCallType != CallTypeNone) result = call(exec, handleEventFunction, handleEventCallType, handleEventCallData, m_callback, args); else result = call(exec, m_callback, callbackCallType, callbackCallData, m_callback, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); if (exec->hadException()) { reportCurrentException(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp index 3d42f81..ca7f069 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp @@ -120,12 +120,12 @@ void JSCustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bo MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction)); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); if (handleEventCallType != CallTypeNone) call(exec, handleEventFunction, handleEventCallType, handleEventCallData, m_data->callback(), args); else call(exec, m_data->callback(), callbackCallType, callbackCallData, m_data->callback(), args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); if (exec->hadException()) { reportCurrentException(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp index 2d41bb8..1c6de7f 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp @@ -77,9 +77,9 @@ void JSCustomSQLTransactionErrorCallback::handleEvent(SQLError* error) MarkedArgumentBuffer args; args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error)); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); call(exec, function, callType, callData, m_callback, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); if (exec->hadException()) reportCurrentException(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomVoidCallback.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomVoidCallback.cpp index b4e525b..2273ff0 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomVoidCallback.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomVoidCallback.cpp @@ -73,9 +73,9 @@ void JSCustomVoidCallback::handleEvent() MarkedArgumentBuffer args; - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); call(exec, function, callType, callData, m_callback, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); if (exec->hadException()) reportCurrentException(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomXPathNSResolver.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomXPathNSResolver.cpp index 4476be5..55e6481 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSCustomXPathNSResolver.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSCustomXPathNSResolver.cpp @@ -95,9 +95,9 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix) MarkedArgumentBuffer args; args.append(jsString(exec, prefix)); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); JSValue retval = call(exec, function, callType, callData, m_customResolver, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); String result; if (exec->hadException()) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp index df6068a..cf81f54 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -166,7 +166,7 @@ JSGlobalData* JSDOMWindowBase::commonJSGlobalData() static JSGlobalData* globalData; if (!globalData) { globalData = JSGlobalData::createLeaked().releaseRef(); - globalData->timeoutChecker.setTimeoutInterval(10000); // 10 seconds + globalData->timeoutChecker->setTimeoutInterval(10000); // 10 seconds } return globalData; diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp index 33ac7bb..93eae74 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -290,20 +290,20 @@ void JSDOMWindow::put(ExecState* exec, const Identifier& propertyName, JSValue v Base::put(exec, propertyName, value, slot); } -bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { // Only allow deleting properties by frames in the same origin. if (!allowsAccessFrom(exec)) return false; - return Base::deleteProperty(exec, propertyName); + return Base::deleteProperty(exec, propertyName, checkDontDelete); } -void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { // Only allow the window to enumerated by frames in the same origin. if (!allowsAccessFrom(exec)) return; - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } bool JSDOMWindow::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.cpp index 1bf478b..ec31721 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -98,14 +98,14 @@ void JSDOMWindowShell::putWithAttributes(ExecState* exec, const Identifier& prop m_window->putWithAttributes(exec, propertyName, value, attributes); } -bool JSDOMWindowShell::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSDOMWindowShell::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { - return m_window->deleteProperty(exec, propertyName); + return m_window->deleteProperty(exec, propertyName, checkDontDelete); } -void JSDOMWindowShell::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindowShell::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { - m_window->getPropertyNames(exec, propertyNames); + m_window->getPropertyNames(exec, propertyNames, listedAttributes); } bool JSDOMWindowShell::getPropertyAttributes(JSC::ExecState* exec, const Identifier& propertyName, unsigned& attributes) const diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.h index 6f21892..87b63fc 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMWindowShell.h @@ -69,8 +69,8 @@ namespace WebCore { virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual void putWithAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, unsigned attributes); - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName, bool checkDontDelete = true); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, unsigned& attributes) const; 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/3rdparty/webkit/WebCore/bindings/js/JSEventListener.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.cpp index a659d3e..c7797be 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSEventListener.cpp @@ -121,7 +121,7 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent) JSValue retval; if (handleEventFunction) { - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); retval = call(exec, handleEventFunction, callType, callData, jsFunction, args); } else { JSValue thisValue; @@ -129,10 +129,10 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent) thisValue = globalObject->toThisObject(exec); else thisValue = toJS(exec, globalObject, event->currentTarget()); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); retval = call(exec, jsFunction, callType, callData, thisValue, args); } - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); globalObject->setCurrentEvent(savedEvent); @@ -187,9 +187,9 @@ bool JSEventListener::reportError(const String& message, const String& url, int JSValue thisValue = globalObject->toThisObject(exec); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); JSValue returnValue = call(exec, jsFunction, callType, callData, thisValue, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); // If an error occurs while handling the script error, it should be bubbled up. if (exec->hadException()) { diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSHistoryCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSHistoryCustom.cpp index a3b15e1..86b7df7 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSHistoryCustom.cpp @@ -100,20 +100,20 @@ bool JSHistory::putDelegate(ExecState* exec, const Identifier&, JSValue, PutProp return false; } -bool JSHistory::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSHistory::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { // Only allow deleting by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) return false; - return Base::deleteProperty(exec, propertyName); + return Base::deleteProperty(exec, propertyName, checkDontDelete); } -void JSHistory::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSHistory::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { // Only allow the history object to enumerated by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) return; - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.cpp index 7caff2b..f4758e4 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSLazyEventListener.cpp @@ -97,7 +97,7 @@ void JSLazyEventListener::parseCode() const ExecState* exec = m_globalObject->globalExec(); MarkedArgumentBuffer args; - UString sourceURL(executionContext->url().string()); + UString sourceURL(executionContext->url().string().operator UString()); args.append(jsNontrivialString(exec, m_eventParameterName)); args.append(jsString(exec, m_code)); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSLocationCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSLocationCustom.cpp index e4f1653..4fcf548 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSLocationCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSLocationCustom.cpp @@ -120,20 +120,20 @@ bool JSLocation::putDelegate(ExecState* exec, const Identifier& propertyName, JS return false; } -bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) { // Only allow deleting by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) return false; - return Base::deleteProperty(exec, propertyName); + return Base::deleteProperty(exec, propertyName, checkDontDelete); } -void JSLocation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSLocation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { // Only allow the location object to enumerated by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) return; - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp index ad1e556..3ca0dd4 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp @@ -160,12 +160,12 @@ void JSQuarantinedObjectWrapper::put(ExecState* exec, unsigned identifier, JSVal transferExceptionToExecState(exec); } -bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, const Identifier& identifier) +bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, const Identifier& identifier, bool checkDontDelete) { if (!allowsDeleteProperty()) return false; - bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier); + bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier, checkDontDelete); transferExceptionToExecState(exec); @@ -268,12 +268,12 @@ CallType JSQuarantinedObjectWrapper::getCallData(CallData& callData) return CallTypeHost; } -void JSQuarantinedObjectWrapper::getPropertyNames(ExecState*, PropertyNameArray& array) +void JSQuarantinedObjectWrapper::getPropertyNames(ExecState*, PropertyNameArray& array, unsigned listedAttributes) { if (!allowsGetPropertyNames()) return; - m_unwrappedObject->getPropertyNames(unwrappedExecState(), array); + m_unwrappedObject->getPropertyNames(unwrappedExecState(), array, listedAttributes); } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.h b/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.h index bf8fddb..95e42f6 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSQuarantinedObjectWrapper.h @@ -62,7 +62,7 @@ namespace WebCore { virtual void put(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&); virtual void put(JSC::ExecState*, unsigned, JSC::JSValue); - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&); + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&, bool checkDontDelete = true); virtual bool deleteProperty(JSC::ExecState*, unsigned); virtual JSC::CallType getCallData(JSC::CallData&); @@ -70,7 +70,7 @@ namespace WebCore { virtual bool hasInstance(JSC::ExecState*, JSC::JSValue, JSC::JSValue proto); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); virtual JSC::UString className() const { return m_unwrappedObject->className(); } diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSStorageCustom.cpp b/src/3rdparty/webkit/WebCore/bindings/js/JSStorageCustom.cpp index 2d2d0f8..4af5ddd 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSStorageCustom.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSStorageCustom.cpp @@ -47,7 +47,7 @@ JSValue JSStorage::nameGetter(ExecState* exec, const Identifier& propertyName, c return jsStringOrNull(exec, thisObj->impl()->getItem(propertyName)); } -bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName, bool /*checkDontDelete*/) { // Only perform the custom delete if the object doesn't have a native property by this name. // Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check @@ -64,14 +64,14 @@ bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName) return true; } -void JSStorage::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSStorage::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { ExceptionCode ec; unsigned length = m_impl->length(); for (unsigned i = 0; i < length; ++i) propertyNames.add(Identifier(exec, m_impl->key(i, ec))); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } bool JSStorage::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&) diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.cpp index 9e64bce..28cbe60 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScheduledAction.cpp @@ -101,9 +101,9 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV for (size_t i = 0; i < size; ++i) args.append(m_args[i]); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); call(exec, m_function, callType, callData, thisValue, args); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); if (exec->hadException()) reportCurrentException(exec); diff --git a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp b/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp index a1c4376..2abe5b0 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/ScriptController.cpp @@ -110,9 +110,9 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) RefPtr<Frame> protect = m_frame; - m_windowShell->window()->globalData()->timeoutChecker.start(); + m_windowShell->window()->globalData()->timeoutChecker->start(); Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), jsSourceCode, m_windowShell); - m_windowShell->window()->globalData()->timeoutChecker.stop(); + m_windowShell->window()->globalData()->timeoutChecker->stop(); // Evaluating the JavaScript could cause the frame to be deallocated // so we start the keep alive timer here. diff --git a/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp b/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp index fc3de3c..1b8eed6 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp +++ b/src/3rdparty/webkit/WebCore/bindings/js/WorkerScriptController.cpp @@ -109,9 +109,9 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, JSLock lock(SilenceAssertionsOnly); ExecState* exec = m_workerContextWrapper->globalExec(); - m_workerContextWrapper->globalData()->timeoutChecker.start(); + m_workerContextWrapper->globalData()->timeoutChecker->start(); Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), sourceCode.jsSourceCode(), m_workerContextWrapper); - m_workerContextWrapper->globalData()->timeoutChecker.stop(); + m_workerContextWrapper->globalData()->timeoutChecker->stop(); m_workerContext->thread()->workerObjectProxy().reportPendingActivity(m_workerContext->hasPendingActivity()); @@ -136,7 +136,7 @@ void WorkerScriptController::forbidExecution() // It is not critical for Interpreter::m_timeoutTime to be synchronized, we just rely on it reaching the worker thread's processor sooner or later. MutexLocker lock(m_sharedDataMutex); m_executionForbidden = true; - m_globalData->timeoutChecker.setTimeoutInterval(1); // 1ms is the smallest timeout that can be set. + m_globalData->timeoutChecker->setTimeoutInterval(1); // 1ms is the smallest timeout that can be set. } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm index 26cf3f5..5885543 100644 --- a/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/src/3rdparty/webkit/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -513,10 +513,10 @@ sub GenerateHeader push(@headerContent, " virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"}; # Custom deleteProperty function - push(@headerContent, " virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"}; + push(@headerContent, " virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&, bool checkDontDelete = true);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"}; # Custom getPropertyNames function - push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}); + push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = Structure::Prototype);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}); # Custom getPropertyAttributes function push(@headerContent, " virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned& attributes) const;\n") if $dataNode->extendedAttributes->{"CustomGetPropertyAttributes"}; @@ -1334,13 +1334,13 @@ sub GenerateImplementation } if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) { - push(@implContent, "void ${className}::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n"); + push(@implContent, "void ${className}::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes)\n"); push(@implContent, "{\n"); if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) { push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n"); push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n"); } - push(@implContent, " Base::getPropertyNames(exec, propertyNames);\n"); + push(@implContent, " Base::getPropertyNames(exec, propertyNames, listedAttributes);\n"); push(@implContent, "}\n\n"); } diff --git a/src/3rdparty/webkit/WebCore/bridge/NP_jsobject.cpp b/src/3rdparty/webkit/WebCore/bridge/NP_jsobject.cpp index 006f17f..0a51f45 100644 --- a/src/3rdparty/webkit/WebCore/bridge/NP_jsobject.cpp +++ b/src/3rdparty/webkit/WebCore/bridge/NP_jsobject.cpp @@ -122,9 +122,9 @@ bool _NPN_InvokeDefault(NPP, NPObject* o, const NPVariant* args, uint32_t argCou MarkedArgumentBuffer argList; getListFromVariantArgs(exec, args, argCount, rootObject, argList); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); JSValue resultV = call(exec, function, callType, callData, function, argList); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); // Convert and return the result of the function call. convertValueToNPVariant(exec, resultV, result); @@ -172,9 +172,9 @@ bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant* MarkedArgumentBuffer argList; getListFromVariantArgs(exec, args, argCount, rootObject, argList); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); JSValue resultV = call(exec, function, callType, callData, obj->imp, argList); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); // Convert and return the result of the function call. convertValueToNPVariant(exec, resultV, result); @@ -202,9 +202,9 @@ bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant) JSLock lock(SilenceAssertionsOnly); String scriptString = convertNPStringToUTF16(s); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); Completion completion = JSC::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(scriptString)); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); ComplType type = completion.complType(); JSValue result; @@ -442,9 +442,9 @@ bool _NPN_Construct(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, MarkedArgumentBuffer argList; getListFromVariantArgs(exec, args, argCount, rootObject, argList); ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject(); - globalObject->globalData()->timeoutChecker.start(); + globalObject->globalData()->timeoutChecker->start(); JSValue resultV = construct(exec, constructor, constructType, constructData, argList); - globalObject->globalData()->timeoutChecker.stop(); + globalObject->globalData()->timeoutChecker->stop(); // Convert and return the result. convertValueToNPVariant(exec, resultV, result); diff --git a/src/3rdparty/webkit/WebCore/bridge/c/c_instance.cpp b/src/3rdparty/webkit/WebCore/bridge/c/c_instance.cpp index fcdd166..d5c1a8b 100644 --- a/src/3rdparty/webkit/WebCore/bridge/c/c_instance.cpp +++ b/src/3rdparty/webkit/WebCore/bridge/c/c_instance.cpp @@ -238,7 +238,7 @@ JSValue CInstance::valueOf(ExecState* exec) const return stringValue(exec); } -void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray) +void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray, unsigned listedAttributes) { if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) || !_object->_class->enumerate) return; diff --git a/src/3rdparty/webkit/WebCore/bridge/c/c_instance.h b/src/3rdparty/webkit/WebCore/bridge/c/c_instance.h index f9e9de3..e7fd4bb 100644 --- a/src/3rdparty/webkit/WebCore/bridge/c/c_instance.h +++ b/src/3rdparty/webkit/WebCore/bridge/c/c_instance.h @@ -65,7 +65,7 @@ public: virtual bool supportsConstruct() const; virtual JSValue invokeConstruct(ExecState*, const ArgList&); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); JSValue stringValue(ExecState*) const; JSValue numberValue(ExecState*) const; diff --git a/src/3rdparty/webkit/WebCore/bridge/jni/jni_jsobject.mm b/src/3rdparty/webkit/WebCore/bridge/jni/jni_jsobject.mm index c9af8b0..8bb8b78 100644 --- a/src/3rdparty/webkit/WebCore/bridge/jni/jni_jsobject.mm +++ b/src/3rdparty/webkit/WebCore/bridge/jni/jni_jsobject.mm @@ -302,9 +302,9 @@ jobject JavaJSObject::call(jstring methodName, jobjectArray args) const // Call the function object. MarkedArgumentBuffer argList; getListFromJArray(exec, args, argList); - rootObject->globalObject()->globalData()->timeoutChecker.start(); + rootObject->globalObject()->globalData()->timeoutChecker->start(); JSValue result = JSC::call(exec, function, callType, callData, _imp, argList); - rootObject->globalObject()->globalData()->timeoutChecker.stop(); + rootObject->globalObject()->globalData()->timeoutChecker->stop(); return convertValueToJObject(result); } @@ -321,9 +321,9 @@ jobject JavaJSObject::eval(jstring script) const if (!rootObject) return 0; - rootObject->globalObject()->globalData()->timeoutChecker.start(); + rootObject->globalObject()->globalData()->timeoutChecker->start(); Completion completion = JSC::evaluate(rootObject->globalObject()->globalExec(), rootObject->globalObject()->globalScopeChain(), makeSource(JavaString(script))); - rootObject->globalObject()->globalData()->timeoutChecker.stop(); + rootObject->globalObject()->globalData()->timeoutChecker->stop(); ComplType type = completion.complType(); if (type == Normal) { diff --git a/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp b/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp index 506697a..020b1c7 100644 --- a/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp +++ b/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp @@ -222,7 +222,7 @@ void QtInstance::end() // Do nothing. } -void QtInstance::getPropertyNames(ExecState* exec, PropertyNameArray& array) +void QtInstance::getPropertyNames(ExecState* exec, PropertyNameArray& array, unsigned listedAttributes) { // This is the enumerable properties, so put: // properties diff --git a/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.h b/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.h index 23766b1..069c04f 100644 --- a/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.h +++ b/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.h @@ -52,7 +52,7 @@ public: virtual JSValue invokeMethod(ExecState*, const MethodList&, const ArgList&); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); JSValue stringValue(ExecState* exec) const; JSValue numberValue(ExecState* exec) const; diff --git a/src/3rdparty/webkit/WebCore/bridge/runtime.h b/src/3rdparty/webkit/WebCore/bridge/runtime.h index 2f74a4e..a67b148 100644 --- a/src/3rdparty/webkit/WebCore/bridge/runtime.h +++ b/src/3rdparty/webkit/WebCore/bridge/runtime.h @@ -100,7 +100,7 @@ public: virtual bool supportsConstruct() const { return false; } virtual JSValue invokeConstruct(ExecState*, const ArgList&) { return JSValue(); } - virtual void getPropertyNames(ExecState*, PropertyNameArray&) { } + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype) { } virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const = 0; diff --git a/src/3rdparty/webkit/WebCore/bridge/runtime_array.cpp b/src/3rdparty/webkit/WebCore/bridge/runtime_array.cpp index 2849822..84520d2 100644 --- a/src/3rdparty/webkit/WebCore/bridge/runtime_array.cpp +++ b/src/3rdparty/webkit/WebCore/bridge/runtime_array.cpp @@ -112,12 +112,12 @@ void RuntimeArray::put(ExecState* exec, unsigned index, JSValue value) getConcreteArray()->setValueAt(exec, index, value); } -bool RuntimeArray::deleteProperty(ExecState*, const Identifier&) +bool RuntimeArray::deleteProperty(ExecState*, const Identifier&, bool) { return false; } -bool RuntimeArray::deleteProperty(ExecState*, unsigned) +bool RuntimeArray::deleteProperty(ExecState*, unsigned, bool) { return false; } diff --git a/src/3rdparty/webkit/WebCore/bridge/runtime_array.h b/src/3rdparty/webkit/WebCore/bridge/runtime_array.h index 5a86e9d..dbb1559 100644 --- a/src/3rdparty/webkit/WebCore/bridge/runtime_array.h +++ b/src/3rdparty/webkit/WebCore/bridge/runtime_array.h @@ -40,8 +40,8 @@ public: virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue); - virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName); - virtual bool deleteProperty(ExecState *exec, unsigned propertyName); + virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState *exec, unsigned propertyName, bool checkDontDelete = true); virtual const ClassInfo *classInfo() const { return &s_info; } diff --git a/src/3rdparty/webkit/WebCore/bridge/runtime_object.cpp b/src/3rdparty/webkit/WebCore/bridge/runtime_object.cpp index 385f914..90129fa 100644 --- a/src/3rdparty/webkit/WebCore/bridge/runtime_object.cpp +++ b/src/3rdparty/webkit/WebCore/bridge/runtime_object.cpp @@ -187,7 +187,7 @@ void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSVa instance->end(); } -bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&) +bool RuntimeObjectImp::deleteProperty(ExecState*, const Identifier&, bool) { // Can never remove a property of a RuntimeObject. return false; @@ -241,7 +241,7 @@ ConstructType RuntimeObjectImp::getConstructData(ConstructData& constructData) return ConstructTypeHost; } -void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { if (!instance) { throwInvalidAccessError(exec); @@ -249,7 +249,7 @@ void RuntimeObjectImp::getPropertyNames(ExecState* exec, PropertyNameArray& prop } instance->begin(); - instance->getPropertyNames(exec, propertyNames); + instance->getPropertyNames(exec, propertyNames, listedAttributes); instance->end(); } diff --git a/src/3rdparty/webkit/WebCore/bridge/runtime_object.h b/src/3rdparty/webkit/WebCore/bridge/runtime_object.h index f01fe1e..1d5aa09 100644 --- a/src/3rdparty/webkit/WebCore/bridge/runtime_object.h +++ b/src/3rdparty/webkit/WebCore/bridge/runtime_object.h @@ -39,12 +39,12 @@ public: virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState* , const Identifier& propertyName); + virtual bool deleteProperty(ExecState* , const Identifier& propertyName, bool checkDontDelete = true); virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const; virtual CallType getCallData(CallData&); virtual ConstructType getConstructData(ConstructData&); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); virtual void invalidate(); Bindings::Instance* getInternalInstance() const { return instance.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/Grammar.cpp b/src/3rdparty/webkit/WebCore/generated/Grammar.cpp index 6e976b9..76f90d7 100644 --- a/src/3rdparty/webkit/WebCore/generated/Grammar.cpp +++ b/src/3rdparty/webkit/WebCore/generated/Grammar.cpp @@ -139,7 +139,7 @@ static inline bool allowAutomaticSemicolon(JSC::Lexer&, int); #define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*LEXER, yychar)) YYABORT; } while (0) #define SET_EXCEPTION_LOCATION(node, start, divot, end) node->setExceptionSourceCode((divot), (divot) - (start), (end) - (divot)) -#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line) +#define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line, (s).first_column + 1) using namespace JSC; using namespace std; diff --git a/src/3rdparty/webkit/WebCore/generated/JSCSSRuleList.cpp b/src/3rdparty/webkit/WebCore/generated/JSCSSRuleList.cpp index 5717a53..e720825 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSCSSRuleList.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSCSSRuleList.cpp @@ -172,11 +172,11 @@ JSValue jsCSSRuleListConstructor(ExecState* exec, const Identifier&, const Prope JSCSSRuleList* domObject = static_cast<JSCSSRuleList*>(asObject(slot.slotBase())); return JSCSSRuleList::getConstructor(exec, domObject->globalObject()); } -void JSCSSRuleList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSCSSRuleList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<CSSRuleList*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSCSSRuleList::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSCSSRuleList.h b/src/3rdparty/webkit/WebCore/generated/JSCSSRuleList.h index fb400b2..b48bf2b 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSCSSRuleList.h +++ b/src/3rdparty/webkit/WebCore/generated/JSCSSRuleList.h @@ -46,7 +46,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); CSSRuleList* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSCSSStyleDeclaration.cpp b/src/3rdparty/webkit/WebCore/generated/JSCSSStyleDeclaration.cpp index 87fc6e3..f0e32e3 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSCSSStyleDeclaration.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSCSSStyleDeclaration.cpp @@ -221,11 +221,11 @@ void setJSCSSStyleDeclarationCssText(ExecState* exec, JSObject* thisObject, JSVa setDOMException(exec, ec); } -void JSCSSStyleDeclaration::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSCSSStyleDeclaration::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<CSSStyleDeclaration*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSCSSStyleDeclaration::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSCSSStyleDeclaration.h b/src/3rdparty/webkit/WebCore/generated/JSCSSStyleDeclaration.h index 075d438..a4a35e6 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSCSSStyleDeclaration.h +++ b/src/3rdparty/webkit/WebCore/generated/JSCSSStyleDeclaration.h @@ -48,7 +48,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); CSSStyleDeclaration* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSCSSValueList.cpp b/src/3rdparty/webkit/WebCore/generated/JSCSSValueList.cpp index c09806f..ed40bf3 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSCSSValueList.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSCSSValueList.cpp @@ -166,11 +166,11 @@ JSValue jsCSSValueListConstructor(ExecState* exec, const Identifier&, const Prop JSCSSValueList* domObject = static_cast<JSCSSValueList*>(asObject(slot.slotBase())); return JSCSSValueList::getConstructor(exec, domObject->globalObject()); } -void JSCSSValueList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSCSSValueList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<CSSValueList*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSCSSValueList::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSCSSValueList.h b/src/3rdparty/webkit/WebCore/generated/JSCSSValueList.h index 59eb203..d166141 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSCSSValueList.h +++ b/src/3rdparty/webkit/WebCore/generated/JSCSSValueList.h @@ -42,7 +42,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); }; diff --git a/src/3rdparty/webkit/WebCore/generated/JSCSSVariablesDeclaration.cpp b/src/3rdparty/webkit/WebCore/generated/JSCSSVariablesDeclaration.cpp index 3074928..921e894 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSCSSVariablesDeclaration.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSCSSVariablesDeclaration.cpp @@ -206,11 +206,11 @@ void setJSCSSVariablesDeclarationCssText(ExecState* exec, JSObject* thisObject, imp->setCssText(value.toString(exec)); } -void JSCSSVariablesDeclaration::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSCSSVariablesDeclaration::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<CSSVariablesDeclaration*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSCSSVariablesDeclaration::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSCSSVariablesDeclaration.h b/src/3rdparty/webkit/WebCore/generated/JSCSSVariablesDeclaration.h index f2c62b0..45a3e9d 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSCSSVariablesDeclaration.h +++ b/src/3rdparty/webkit/WebCore/generated/JSCSSVariablesDeclaration.h @@ -47,7 +47,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); CSSVariablesDeclaration* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSClientRectList.cpp b/src/3rdparty/webkit/WebCore/generated/JSClientRectList.cpp index f8c99a2..d8426ef 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSClientRectList.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSClientRectList.cpp @@ -173,11 +173,11 @@ JSValue jsClientRectListConstructor(ExecState* exec, const Identifier&, const Pr JSClientRectList* domObject = static_cast<JSClientRectList*>(asObject(slot.slotBase())); return JSClientRectList::getConstructor(exec, domObject->globalObject()); } -void JSClientRectList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSClientRectList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<ClientRectList*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSClientRectList::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSClientRectList.h b/src/3rdparty/webkit/WebCore/generated/JSClientRectList.h index 851a7f9..34868a3 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSClientRectList.h +++ b/src/3rdparty/webkit/WebCore/generated/JSClientRectList.h @@ -46,7 +46,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); ClientRectList* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSDOMWindow.h b/src/3rdparty/webkit/WebCore/generated/JSDOMWindow.h index 8e7defe..a87339e 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSDOMWindow.h +++ b/src/3rdparty/webkit/WebCore/generated/JSDOMWindow.h @@ -47,8 +47,8 @@ public: virtual void mark(); - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&, bool checkDontDelete = true); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned& attributes) const; 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/3rdparty/webkit/WebCore/generated/JSDataGridColumnList.cpp b/src/3rdparty/webkit/WebCore/generated/JSDataGridColumnList.cpp index f2525a5..220d81d 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSDataGridColumnList.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSDataGridColumnList.cpp @@ -203,11 +203,11 @@ JSValue jsDataGridColumnListConstructor(ExecState* exec, const Identifier&, cons JSDataGridColumnList* domObject = static_cast<JSDataGridColumnList*>(asObject(slot.slotBase())); return JSDataGridColumnList::getConstructor(exec, domObject->globalObject()); } -void JSDataGridColumnList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDataGridColumnList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<DataGridColumnList*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSDataGridColumnList::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSDataGridColumnList.h b/src/3rdparty/webkit/WebCore/generated/JSDataGridColumnList.h index b904146..986081a 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSDataGridColumnList.h +++ b/src/3rdparty/webkit/WebCore/generated/JSDataGridColumnList.h @@ -48,7 +48,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); DataGridColumnList* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSFileList.cpp b/src/3rdparty/webkit/WebCore/generated/JSFileList.cpp index e359c69..088744e 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSFileList.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSFileList.cpp @@ -173,11 +173,11 @@ JSValue jsFileListConstructor(ExecState* exec, const Identifier&, const Property JSFileList* domObject = static_cast<JSFileList*>(asObject(slot.slotBase())); return JSFileList::getConstructor(exec, domObject->globalObject()); } -void JSFileList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSFileList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<FileList*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSFileList::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSFileList.h b/src/3rdparty/webkit/WebCore/generated/JSFileList.h index 43cac56..421fad0 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSFileList.h +++ b/src/3rdparty/webkit/WebCore/generated/JSFileList.h @@ -46,7 +46,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); FileList* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSHTMLCollection.cpp b/src/3rdparty/webkit/WebCore/generated/JSHTMLCollection.cpp index de01068..b0ac470 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSHTMLCollection.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSHTMLCollection.cpp @@ -186,11 +186,11 @@ JSValue jsHTMLCollectionConstructor(ExecState* exec, const Identifier&, const Pr JSHTMLCollection* domObject = static_cast<JSHTMLCollection*>(asObject(slot.slotBase())); return JSHTMLCollection::getConstructor(exec, domObject->globalObject()); } -void JSHTMLCollection::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSHTMLCollection::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<HTMLCollection*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSHTMLCollection::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSHTMLCollection.h b/src/3rdparty/webkit/WebCore/generated/JSHTMLCollection.h index c6b6406..c5f7ff2 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSHTMLCollection.h +++ b/src/3rdparty/webkit/WebCore/generated/JSHTMLCollection.h @@ -49,7 +49,7 @@ public: virtual JSC::CallType getCallData(JSC::CallData&); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); // Custom functions diff --git a/src/3rdparty/webkit/WebCore/generated/JSHTMLFormElement.cpp b/src/3rdparty/webkit/WebCore/generated/JSHTMLFormElement.cpp index 1f941c0..e01b1c3 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSHTMLFormElement.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSHTMLFormElement.cpp @@ -284,11 +284,11 @@ void setJSHTMLFormElementTarget(ExecState* exec, JSObject* thisObject, JSValue v imp->setTarget(valueToStringWithNullCheck(exec, value)); } -void JSHTMLFormElement::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSHTMLFormElement::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<HTMLFormElement*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSHTMLFormElement::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSHTMLFormElement.h b/src/3rdparty/webkit/WebCore/generated/JSHTMLFormElement.h index 6ad5c00..c7be16d 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSHTMLFormElement.h +++ b/src/3rdparty/webkit/WebCore/generated/JSHTMLFormElement.h @@ -42,7 +42,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); // Custom functions diff --git a/src/3rdparty/webkit/WebCore/generated/JSHTMLSelectElement.cpp b/src/3rdparty/webkit/WebCore/generated/JSHTMLSelectElement.cpp index 794d24c..223a576 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSHTMLSelectElement.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSHTMLSelectElement.cpp @@ -354,11 +354,11 @@ void setJSHTMLSelectElementSize(ExecState* exec, JSObject* thisObject, JSValue v imp->setSize(value.toInt32(exec)); } -void JSHTMLSelectElement::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSHTMLSelectElement::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<HTMLSelectElement*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSHTMLSelectElement::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSHTMLSelectElement.h b/src/3rdparty/webkit/WebCore/generated/JSHTMLSelectElement.h index 6544254..11cf587 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSHTMLSelectElement.h +++ b/src/3rdparty/webkit/WebCore/generated/JSHTMLSelectElement.h @@ -44,7 +44,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); // Custom functions diff --git a/src/3rdparty/webkit/WebCore/generated/JSHistory.h b/src/3rdparty/webkit/WebCore/generated/JSHistory.h index 8163882..6e17de0 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSHistory.h +++ b/src/3rdparty/webkit/WebCore/generated/JSHistory.h @@ -48,8 +48,8 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&, bool checkDontDelete = true); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); History* impl() const { return m_impl.get(); } private: diff --git a/src/3rdparty/webkit/WebCore/generated/JSLocation.h b/src/3rdparty/webkit/WebCore/generated/JSLocation.h index 155cfbc..09ae2a0 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSLocation.h +++ b/src/3rdparty/webkit/WebCore/generated/JSLocation.h @@ -48,8 +48,8 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&, bool checkDontDelete = true); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction); // Custom attributes diff --git a/src/3rdparty/webkit/WebCore/generated/JSMediaList.cpp b/src/3rdparty/webkit/WebCore/generated/JSMediaList.cpp index 007e976..73a2d13 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSMediaList.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSMediaList.cpp @@ -195,11 +195,11 @@ void setJSMediaListMediaText(ExecState* exec, JSObject* thisObject, JSValue valu setDOMException(exec, ec); } -void JSMediaList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSMediaList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<MediaList*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSMediaList::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSMediaList.h b/src/3rdparty/webkit/WebCore/generated/JSMediaList.h index da82e56..506eb7c 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSMediaList.h +++ b/src/3rdparty/webkit/WebCore/generated/JSMediaList.h @@ -47,7 +47,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); MediaList* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSMimeTypeArray.cpp b/src/3rdparty/webkit/WebCore/generated/JSMimeTypeArray.cpp index 8f769fb..e1fab3f 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSMimeTypeArray.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSMimeTypeArray.cpp @@ -178,11 +178,11 @@ JSValue jsMimeTypeArrayConstructor(ExecState* exec, const Identifier&, const Pro JSMimeTypeArray* domObject = static_cast<JSMimeTypeArray*>(asObject(slot.slotBase())); return JSMimeTypeArray::getConstructor(exec, domObject->globalObject()); } -void JSMimeTypeArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSMimeTypeArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<MimeTypeArray*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSMimeTypeArray::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSMimeTypeArray.h b/src/3rdparty/webkit/WebCore/generated/JSMimeTypeArray.h index f0625e4..184a79b 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSMimeTypeArray.h +++ b/src/3rdparty/webkit/WebCore/generated/JSMimeTypeArray.h @@ -46,7 +46,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); MimeTypeArray* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.cpp b/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.cpp index 355464c..84dd68e 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.cpp @@ -187,11 +187,11 @@ JSValue jsNamedNodeMapConstructor(ExecState* exec, const Identifier&, const Prop JSNamedNodeMap* domObject = static_cast<JSNamedNodeMap*>(asObject(slot.slotBase())); return JSNamedNodeMap::getConstructor(exec, domObject->globalObject()); } -void JSNamedNodeMap::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSNamedNodeMap::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<NamedNodeMap*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSNamedNodeMap::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.h b/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.h index ca64bfb..7038f4d 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.h +++ b/src/3rdparty/webkit/WebCore/generated/JSNamedNodeMap.h @@ -46,7 +46,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); NamedNodeMap* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSNodeList.cpp b/src/3rdparty/webkit/WebCore/generated/JSNodeList.cpp index 437dd84..c8fa413 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSNodeList.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSNodeList.cpp @@ -178,11 +178,11 @@ JSValue jsNodeListConstructor(ExecState* exec, const Identifier&, const Property JSNodeList* domObject = static_cast<JSNodeList*>(asObject(slot.slotBase())); return JSNodeList::getConstructor(exec, domObject->globalObject()); } -void JSNodeList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSNodeList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<NodeList*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSNodeList::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSNodeList.h b/src/3rdparty/webkit/WebCore/generated/JSNodeList.h index 21faa3a..5314d58 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSNodeList.h +++ b/src/3rdparty/webkit/WebCore/generated/JSNodeList.h @@ -49,7 +49,7 @@ public: virtual JSC::CallType getCallData(JSC::CallData&); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); NodeList* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSPlugin.cpp b/src/3rdparty/webkit/WebCore/generated/JSPlugin.cpp index 39616d6..7628617 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSPlugin.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSPlugin.cpp @@ -207,11 +207,11 @@ JSValue jsPluginConstructor(ExecState* exec, const Identifier&, const PropertySl JSPlugin* domObject = static_cast<JSPlugin*>(asObject(slot.slotBase())); return JSPlugin::getConstructor(exec, domObject->globalObject()); } -void JSPlugin::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSPlugin::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<Plugin*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSPlugin::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSPlugin.h b/src/3rdparty/webkit/WebCore/generated/JSPlugin.h index eee4c7d..18f9b78 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSPlugin.h +++ b/src/3rdparty/webkit/WebCore/generated/JSPlugin.h @@ -46,7 +46,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); Plugin* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSPluginArray.cpp b/src/3rdparty/webkit/WebCore/generated/JSPluginArray.cpp index 955d50c..45a49e2 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSPluginArray.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSPluginArray.cpp @@ -179,11 +179,11 @@ JSValue jsPluginArrayConstructor(ExecState* exec, const Identifier&, const Prope JSPluginArray* domObject = static_cast<JSPluginArray*>(asObject(slot.slotBase())); return JSPluginArray::getConstructor(exec, domObject->globalObject()); } -void JSPluginArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSPluginArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<PluginArray*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSPluginArray::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSPluginArray.h b/src/3rdparty/webkit/WebCore/generated/JSPluginArray.h index 44443f3..c2827aa 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSPluginArray.h +++ b/src/3rdparty/webkit/WebCore/generated/JSPluginArray.h @@ -46,7 +46,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); PluginArray* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSStorage.h b/src/3rdparty/webkit/WebCore/generated/JSStorage.h index fbc4ff3..42e32d6 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSStorage.h +++ b/src/3rdparty/webkit/WebCore/generated/JSStorage.h @@ -49,8 +49,8 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&, bool checkDontDelete = true); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); Storage* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSStyleSheetList.cpp b/src/3rdparty/webkit/WebCore/generated/JSStyleSheetList.cpp index a431d09..909d8e5 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSStyleSheetList.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSStyleSheetList.cpp @@ -177,11 +177,11 @@ JSValue jsStyleSheetListConstructor(ExecState* exec, const Identifier&, const Pr JSStyleSheetList* domObject = static_cast<JSStyleSheetList*>(asObject(slot.slotBase())); return JSStyleSheetList::getConstructor(exec, domObject->globalObject()); } -void JSStyleSheetList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSStyleSheetList::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<StyleSheetList*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSStyleSheetList::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSStyleSheetList.h b/src/3rdparty/webkit/WebCore/generated/JSStyleSheetList.h index 75c8c6c..589ea80 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSStyleSheetList.h +++ b/src/3rdparty/webkit/WebCore/generated/JSStyleSheetList.h @@ -46,7 +46,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); StyleSheetList* impl() const { return m_impl.get(); } diff --git a/src/3rdparty/webkit/WebCore/generated/JSWebKitCSSKeyframesRule.cpp b/src/3rdparty/webkit/WebCore/generated/JSWebKitCSSKeyframesRule.cpp index baf4e51..f4cbcfc 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSWebKitCSSKeyframesRule.cpp +++ b/src/3rdparty/webkit/WebCore/generated/JSWebKitCSSKeyframesRule.cpp @@ -190,11 +190,11 @@ void setJSWebKitCSSKeyframesRuleName(ExecState* exec, JSObject* thisObject, JSVa imp->setName(valueToStringWithNullCheck(exec, value)); } -void JSWebKitCSSKeyframesRule::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSWebKitCSSKeyframesRule::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) { for (unsigned i = 0; i < static_cast<WebKitCSSKeyframesRule*>(impl())->length(); ++i) propertyNames.add(Identifier::from(exec, i)); - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, listedAttributes); } JSValue JSWebKitCSSKeyframesRule::getConstructor(ExecState* exec, JSGlobalObject* globalObject) diff --git a/src/3rdparty/webkit/WebCore/generated/JSWebKitCSSKeyframesRule.h b/src/3rdparty/webkit/WebCore/generated/JSWebKitCSSKeyframesRule.h index cae9a5f..4cdbd0d 100644 --- a/src/3rdparty/webkit/WebCore/generated/JSWebKitCSSKeyframesRule.h +++ b/src/3rdparty/webkit/WebCore/generated/JSWebKitCSSKeyframesRule.h @@ -43,7 +43,7 @@ public: return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); } - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*); static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); }; diff --git a/src/3rdparty/webkit/WebCore/inspector/JavaScriptDebugServer.cpp b/src/3rdparty/webkit/WebCore/inspector/JavaScriptDebugServer.cpp index 10eff26..0aafd65 100644 --- a/src/3rdparty/webkit/WebCore/inspector/JavaScriptDebugServer.cpp +++ b/src/3rdparty/webkit/WebCore/inspector/JavaScriptDebugServer.cpp @@ -459,7 +459,7 @@ void JavaScriptDebugServer::callEvent(const DebuggerCallFrame& debuggerCallFrame pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject())); } -void JavaScriptDebugServer::atStatement(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +void JavaScriptDebugServer::atStatement(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, int column) { if (m_paused) return; @@ -533,7 +533,7 @@ void JavaScriptDebugServer::didExecuteProgram(const DebuggerCallFrame& debuggerC m_currentCallFrame = m_currentCallFrame->caller(); } -void JavaScriptDebugServer::didReachBreakpoint(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber) +void JavaScriptDebugServer::didReachBreakpoint(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber, int /*column*/) { if (m_paused) return; diff --git a/src/3rdparty/webkit/WebCore/inspector/JavaScriptDebugServer.h b/src/3rdparty/webkit/WebCore/inspector/JavaScriptDebugServer.h index baa6699..505a616 100644 --- a/src/3rdparty/webkit/WebCore/inspector/JavaScriptDebugServer.h +++ b/src/3rdparty/webkit/WebCore/inspector/JavaScriptDebugServer.h @@ -105,12 +105,12 @@ namespace WebCore { virtual void sourceParsed(JSC::ExecState*, const JSC::SourceCode&, int errorLine, const JSC::UString& errorMsg); virtual void callEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber); - virtual void atStatement(const JSC::DebuggerCallFrame&, intptr_t sourceID, int firstLine); + virtual void atStatement(const JSC::DebuggerCallFrame&, intptr_t sourceID, int firstLine, int column); virtual void returnEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber); virtual void exception(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber); virtual void willExecuteProgram(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno); virtual void didExecuteProgram(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno); - virtual void didReachBreakpoint(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno); + virtual void didReachBreakpoint(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno, int column); void didAddListener(Page*); void didRemoveListener(Page*); diff --git a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc index 144feb5..e3c904b 100644 --- a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc +++ b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc @@ -1,7 +1,7 @@ /*! \module QtWebKit \title QtWebKit Module - \contentspage Qt's Modules + \contentspage All Qt Modules \previouspage QtSvg \nextpage QtXml \ingroup modules diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index b150e22..52c507d 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -696,6 +696,7 @@ static void setup() (void)new QJisCodec; (void)new QSjisCodec; (void)new QEucKrCodec; + (void)new QCP949Codec; (void)new QBig5Codec; (void)new QBig5hkscsCodec; # endif // QT_NO_ICONV && !QT_BOOTSTRAPPED diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc index e0ef662..949f7b8 100644 --- a/src/corelib/global/qendian.qdoc +++ b/src/corelib/global/qendian.qdoc @@ -42,7 +42,7 @@ /*! \headerfile <QtEndian> \title Endian Conversion Functions - \ingroup classlists + \ingroup funclists \brief The <QtEndian> header provides functions to convert between little and big endian representations of numbers. */ diff --git a/src/corelib/global/qfeatures.txt b/src/corelib/global/qfeatures.txt index 9408a5b..3a6c050 100644 --- a/src/corelib/global/qfeatures.txt +++ b/src/corelib/global/qfeatures.txt @@ -1143,13 +1143,6 @@ Requires: UNDOSTACK LISTVIEW Name: QUndoView SeeAlso: ??? -Feature: SCRIPT -Description: Provides support for the QtScript module -Section: Utilities -Requires: TEXTDATE DATESTRING PROPERTIES -Name: QtScript -SeeAlso: ??? - Feature: ACCESSIBILITY Description: Provides accessibility support. Section: Utilities diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 81a5ae5..5fe2b2f 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -401,13 +401,13 @@ QT_BEGIN_NAMESPACE /*! \headerfile <QtGlobal> \title Global Qt Declarations - \ingroup classlists + \ingroup funclists - \brief The <QtGlobal> header provides basic declarations and - is included by all other Qt headers. + \brief The <QtGlobal> header file includes the fundamental global + declarations. It is included by most other Qt header files. - The declarations include \l {types}, \l functions and - \l macros. + The global declarations include \l{types}, \l{functions} and + \l{macros}. The type definitions are partly convenience definitions for basic types (some of which guarantee certain bit-sizes on all platforms diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index f42a2ff..20e7845 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -487,7 +487,7 @@ QT_END_NAMESPACE extern const char qt_core_interpreter[] __attribute__((section(".interp"))) = ELF_INTERPRETER; -extern "C" +extern "C" void qt_core_boilerplate(); void qt_core_boilerplate() { printf("This is the QtCore library version " QT_VERSION_STR "\n" diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index e43a73a..d2ad108 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1435,6 +1435,17 @@ public: RightToLeft }; + enum AnchorPoint { + AnchorLeft = 0, + AnchorHorizontalCenter, + AnchorRight, + AnchorTop, + AnchorVerticalCenter, + AnchorBottom + }; + + + enum DropAction { CopyAction = 0x1, MoveAction = 0x2, diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index d1c16e5..669fc53 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2422,6 +2422,24 @@ */ /*! + \enum Qt::AnchorPoint + + Specifies a side of a layout item that can be anchored. This is used by + QGraphicsAnchorLayout. + + \value AnchorLeft The left side of a layout item. + \value AnchorHorizontalCenter A "virtual" side that is centered between the left and the + right side of a layout item. + \value AnchorRight The right side of a layout item. + \value AnchorTop The top side of a layout item. + \value AnchorVerticalCenter A "virtual" side that is centered between the top and the + bottom side of a layout item. + \value AnchorBottom The bottom side of a layout item. + + \sa QGraphicsAnchorLayout +*/ + +/*! \enum Qt::InputMethodHint \value ImhNone No hints. diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index ca178ce..fd1e367 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -2445,7 +2445,7 @@ QDebug operator<<(QDebug debug, QDir::Filters filters) return debug; } -QDebug operator<<(QDebug debug, QDir::SortFlags sorting) +static QDebug operator<<(QDebug debug, QDir::SortFlags sorting) { if (sorting == QDir::NoSort) { debug << "QDir::SortFlags(NoSort)"; diff --git a/src/corelib/kernel/qabstracteventdispatcher_p.h b/src/corelib/kernel/qabstracteventdispatcher_p.h index 86c9d79..dc69265 100644 --- a/src/corelib/kernel/qabstracteventdispatcher_p.h +++ b/src/corelib/kernel/qabstracteventdispatcher_p.h @@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE +Q_CORE_EXPORT uint qGlobalPostedEventsCount(); + class Q_CORE_EXPORT QAbstractEventDispatcherPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QAbstractEventDispatcher) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 022ae13..e874c90 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3219,12 +3219,12 @@ static void blocking_activate(QObject *sender, int signal, QObjectPrivate::Conne /*!\internal \obsolete. - Used to be called from QMetaObject::activate(QObject *, QMetaObject *, int, int, void **) + Used to be called from QMetaObject::activate(QObject *, QMetaObject *, int, int, void **) before Qt 4.6 */ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv) { - int offset = sender->metaObject()->methodOffset(); - activate(sender, from_signal_index - offset, to_signal_index - offset, argv); + Q_UNUSED(to_signal_index); + activate(sender, from_signal_index, argv); } /*!\internal @@ -3371,7 +3371,7 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) const QMetaObject *mo = sender->metaObject(); while (mo && mo->methodOffset() > signal_index) mo = mo->superClass(); - activate(sender, signal_index - mo->methodOffset(), argv); + activate(sender, mo, signal_index - mo->methodOffset(), argv); } /*!\internal diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 54d6073..9adfa57 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -174,10 +174,13 @@ static void construct(QVariant::Private *x, const void *copy) case QVariant::UserType: break; default: - x->is_shared = true; - x->data.shared = new QVariant::PrivateShared(QMetaType::construct(x->type, copy)); - if (!x->data.shared->ptr) + void *ptr = QMetaType::construct(x->type, copy); + if (!ptr) { x->type = QVariant::Invalid; + } else { + x->is_shared = true; + x->data.shared = new QVariant::PrivateShared(ptr); + } break; } x->is_null = !copy; @@ -456,15 +459,17 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b) if (!QMetaType::isRegistered(a->type)) qFatal("QVariant::compare: type %d unknown to QVariant.", a->type); + const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr); + const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr); + /* The reason we cannot place this test in a case branch above for the types * QMetaType::VoidStar, QMetaType::QObjectStar and so forth, is that it wouldn't include * user defined pointer types. */ const char *const typeName = QMetaType::typeName(a->type); if (typeName[qstrlen(typeName) - 1] == '*') - return *static_cast<void **>(a->data.shared->ptr) == - *static_cast<void **>(b->data.shared->ptr); + return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr); - return a->data.shared->ptr == b->data.shared->ptr; + return a_ptr == b_ptr; } /*! @@ -1371,7 +1376,7 @@ void QVariant::create(int type, const void *copy) QVariant::~QVariant() { - if (d.type > Char && d.type != QMetaType::Float && d.type != QMetaType::QObjectStar && (!d.is_shared || !d.data.shared->ref.deref())) + if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char && d.type < UserType)) handler->clear(&d); } @@ -1387,7 +1392,7 @@ QVariant::QVariant(const QVariant &p) { if (d.is_shared) { d.data.shared->ref.ref(); - } else if (p.d.type > Char && p.d.type != QMetaType::Float && p.d.type != QMetaType::QObjectStar) { + } else if (p.d.type > Char && p.d.type < QVariant::UserType) { handler->construct(&d, p.constData()); d.is_null = p.d.is_null; } @@ -1627,6 +1632,22 @@ QVariant::QVariant(Type type) { create(type, 0); } QVariant::QVariant(int typeOrUserType, const void *copy) { create(typeOrUserType, copy); d.is_null = false; } + +/*! \internal + flags is true if it is a pointer type + */ +QVariant::QVariant(int typeOrUserType, const void *copy, uint flags) +{ + if (flags) { //type is a pointer type + d.type = typeOrUserType; + d.data.ptr = *reinterpret_cast<void *const*>(copy); + d.is_null = false; + } else { + create(typeOrUserType, copy); + d.is_null = false; + } +} + QVariant::QVariant(int val) { d.is_null = false; d.type = Int; d.data.i = val; } QVariant::QVariant(uint val) @@ -1743,7 +1764,7 @@ QVariant& QVariant::operator=(const QVariant &variant) if (variant.d.is_shared) { variant.d.data.shared->ref.ref(); d = variant.d; - } else if (variant.d.type > Char && variant.d.type != QMetaType::Float && variant.d.type != QMetaType::QObjectStar) { + } else if (variant.d.type > Char && variant.d.type < UserType) { d.type = variant.d.type; handler->construct(&d, variant.constData()); d.is_null = variant.d.is_null; @@ -1797,7 +1818,7 @@ const char *QVariant::typeName() const */ void QVariant::clear() { - if (!d.is_shared || !d.data.shared->ref.deref()) + if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type < UserType && d.type > Char)) handler->clear(&d); d.type = Invalid; d.is_null = true; @@ -2467,7 +2488,7 @@ double QVariant::toDouble(bool *ok) const */ float QVariant::toFloat(bool *ok) const { - return qNumVariantToHelper<float>(d, handler, ok, d.data.d); + return qNumVariantToHelper<float>(d, handler, ok, d.data.f); } /*! @@ -2484,7 +2505,7 @@ float QVariant::toFloat(bool *ok) const */ qreal QVariant::toReal(bool *ok) const { - return qNumVariantToHelper<qreal>(d, handler, ok, d.data.d); + return qNumVariantToHelper<qreal>(d, handler, ok, d.data.real); } /*! diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 79bd5b8..97af54b 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -174,6 +174,7 @@ class Q_CORE_EXPORT QVariant ~QVariant(); QVariant(Type type); QVariant(int typeOrUserType, const void *copy); + QVariant(int typeOrUserType, const void *copy, uint flags); QVariant(const QVariant &other); #ifndef QT_NO_DATASTREAM @@ -358,6 +359,7 @@ class Q_CORE_EXPORT QVariant bool b; double d; float f; + qreal real; qlonglong ll; qulonglong ull; QObject *o; @@ -444,7 +446,7 @@ inline bool qvariant_cast_helper(const QVariant &v, QVariant::Type tp, void *ptr template <typename T> inline QVariant qVariantFromValue(const T &t) { - return QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t); + return QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t, QTypeInfo<T>::isPointer); } template <> @@ -463,7 +465,7 @@ inline void qVariantSetValue(QVariant &v, const T &t) old->~T(); new (old) T(t); //call the copy constructor } else { - v = QVariant(type, &t); + v = QVariant(type, &t, QTypeInfo<T>::isPointer); } } diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 993c43b..c36899d 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -57,6 +57,7 @@ // to a pointer of the input type #include <QtCore/qglobal.h> +#include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE @@ -145,6 +146,8 @@ inline void v_clear(QVariant::Private *d, T* = 0) } +Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler(); + QT_END_NAMESPACE #endif // QVARIANT_P_H diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index e2d1f69..89dabde 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -92,7 +92,7 @@ QT_BEGIN_NAMESPACE */ /*! - \property QEventTransition::eventObject + \property QEventTransition::eventSource \brief the event source that this event transition is associated with */ @@ -205,7 +205,7 @@ void QEventTransition::setEventType(QEvent::Type type) /*! Returns the event source associated with this event transition. */ -QObject *QEventTransition::eventObject() const +QObject *QEventTransition::eventSource() const { Q_D(const QEventTransition); return d->object; @@ -215,7 +215,7 @@ QObject *QEventTransition::eventObject() const Sets the event source associated with this event transition to be the given \a object. */ -void QEventTransition::setEventObject(QObject *object) +void QEventTransition::setEventSource(QObject *object) { Q_D(QEventTransition); if (d->object == object) diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index 6cf6a96..941bfa5 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -57,15 +57,15 @@ class QEventTransitionPrivate; class Q_CORE_EXPORT QEventTransition : public QAbstractTransition { Q_OBJECT - Q_PROPERTY(QObject* eventObject READ eventObject WRITE setEventObject) + Q_PROPERTY(QObject* eventSource READ eventSource WRITE setEventSource) Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType) public: QEventTransition(QState *sourceState = 0); QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = 0); ~QEventTransition(); - QObject *eventObject() const; - void setEventObject(QObject *object); + QObject *eventSource() const; + void setEventSource(QObject *object); QEvent::Type eventType() const; void setEventType(QEvent::Type type); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 2853b1a..defa7af 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -217,6 +217,8 @@ public: static const Handler *handler; }; +Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler(); + QT_END_NAMESPACE #endif diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc index f7b7798..771c544 100644 --- a/src/corelib/tools/qalgorithms.qdoc +++ b/src/corelib/tools/qalgorithms.qdoc @@ -42,9 +42,9 @@ /*! \headerfile <QtAlgorithms> \title Generic Algorithms - \ingroup classlists + \ingroup funclists - \brief The <QtAlgorithms> header provides generic template-based algorithms. + \brief The <QtAlgorithms> header includes the generic, template-based algorithms. Qt provides a number of global template functions in \c <QtAlgorithms> that work on containers and perform well-know diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 635c799..e952ea2 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -310,6 +310,7 @@ public: // stl compatibility typedef const char & const_reference; typedef char & reference; + typedef char value_type; void push_back(char c); void push_back(const char *c); void push_back(const QByteArray &a); diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index bebf141..f54a938 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -832,7 +832,7 @@ struct QRegExpEngineKey } }; -bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key2) +static bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key2) { return key1.pattern == key2.pattern && key1.patternSyntax == key2.patternSyntax && key1.cs == key2.cs; @@ -1261,28 +1261,35 @@ struct QRegExpLookahead }; #endif -QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key) - : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2), - xmlSchemaExtensions(false) -{ - setup(); - - QString rx; +/*! \internal + convert the pattern string to the RegExp syntax. - switch (key.patternSyntax) { - case QRegExp::Wildcard: + This is also used by QScriptEngine::newRegExp to convert to a pattern that JavaScriptCore can understan + */ +Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &pattern, QRegExp::PatternSyntax patternSyntax) +{ + switch (patternSyntax) { #ifndef QT_NO_REGEXP_WILDCARD - rx = wc2rx(key.pattern); -#endif + case QRegExp::Wildcard: + return wc2rx(pattern); break; +#endif case QRegExp::FixedString: - rx = QRegExp::escape(key.pattern); + return QRegExp::escape(pattern); break; case QRegExp::W3CXmlSchema11: - xmlSchemaExtensions = true; default: - rx = key.pattern; + return pattern; } +} + +QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key) + : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2), + xmlSchemaExtensions(key.patternSyntax == QRegExp::W3CXmlSchema11) +{ + setup(); + + QString rx = qt_regexp_toCanonical(key.pattern, key.patternSyntax); valid = (parse(rx.unicode(), rx.length()) == rx.length()); if (!valid) { diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp index a676a01..851eaf0 100644 --- a/src/dbus/qdbusmessage.cpp +++ b/src/dbus/qdbusmessage.cpp @@ -707,7 +707,7 @@ QDBusMessage::MessageType QDBusMessage::type() const \sa QDBusConnection::send() */ #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t) +static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t) { switch (t) { diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp index 9badc82..de9363c 100644 --- a/src/gui/animation/qguivariantanimation.cpp +++ b/src/gui/animation/qguivariantanimation.cpp @@ -45,6 +45,10 @@ #include <private/qvariantanimation_p.h> #include <QtGui/qcolor.h> +#include <QtGui/qvector2d.h> +#include <QtGui/qvector3d.h> +#include <QtGui/qvector4d.h> +#include <QtGui/qquaternion.h> QT_BEGIN_NAMESPACE @@ -56,17 +60,35 @@ template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor _q_interpolate(f.alpha(), t.alpha(), progress)); } +template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,const QQuaternion &t, qreal progress) +{ + return QQuaternion::slerp(f, t, progress); +} + static int qRegisterGuiGetInterpolator() { qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>); + qRegisterAnimationInterpolator<QVector2D>(_q_interpolateVariant<QVector2D>); + qRegisterAnimationInterpolator<QVector3D>(_q_interpolateVariant<QVector3D>); + qRegisterAnimationInterpolator<QVector4D>(_q_interpolateVariant<QVector4D>); + qRegisterAnimationInterpolator<QQuaternion>(_q_interpolateVariant<QQuaternion>); return 1; } Q_CONSTRUCTOR_FUNCTION(qRegisterGuiGetInterpolator) static int qUnregisterGuiGetInterpolator() { + // casts required by Sun CC 5.5 qRegisterAnimationInterpolator<QColor>( - (QVariant (*)(const QColor &, const QColor &, qreal))0); // cast required by Sun CC 5.5 + (QVariant (*)(const QColor &, const QColor &, qreal))0); + qRegisterAnimationInterpolator<QVector2D>( + (QVariant (*)(const QVector2D &, const QVector2D &, qreal))0); + qRegisterAnimationInterpolator<QVector3D>( + (QVariant (*)(const QVector3D &, const QVector3D &, qreal))0); + qRegisterAnimationInterpolator<QVector4D>( + (QVariant (*)(const QVector4D &, const QVector4D &, qreal))0); + qRegisterAnimationInterpolator<QQuaternion>( + (QVariant (*)(const QQuaternion &, const QQuaternion &, qreal))0); return 1; } diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h index cb980d2..bab4a29 100644 --- a/src/gui/dialogs/qfileinfogatherer_p.h +++ b/src/gui/dialogs/qfileinfogatherer_p.h @@ -184,7 +184,7 @@ private: QMutex mutex; QWaitCondition condition; - bool abort; + volatile bool abort; QStack<QString> path; QStack<QStringList> files; diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 9d0ead1..f0df0c9 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -402,7 +402,7 @@ void QEglContext::dumpAllConfigs() QString QEglContext::extensions() { - const char* exts = eglQueryString(dpy, EGL_EXTENSIONS); + const char* exts = eglQueryString(QEglContext::defaultDisplay(0), EGL_EXTENSIONS); return QString(QLatin1String(exts)); } diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index b29937b..9412887 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -122,8 +122,8 @@ public: void dumpAllConfigs(); - QString extensions(); - bool hasExtension(const char* extensionName); + static QString extensions(); + static bool hasExtension(const char* extensionName); private: QEgl::API apiType; diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp index 22b55fe..7b582c4 100644 --- a/src/gui/egl/qeglproperties.cpp +++ b/src/gui/egl/qeglproperties.cpp @@ -257,6 +257,20 @@ static void addTag(QString& str, const QString& tag) str += tag; } +void QEglProperties::dumpAllConfigs() +{ + EGLint count = 0; + eglGetConfigs(QEglContext::defaultDisplay(0), 0, 0, &count); + if (count < 1) + return; + + EGLConfig *configs = new EGLConfig [count]; + eglGetConfigs(QEglContext::defaultDisplay(0), configs, count, &count); + for (EGLint index = 0; index < count; ++index) + qWarning() << QEglProperties(configs[index]).toString(); + delete [] configs; +} + // Convert a property list to a string suitable for debug output. QString QEglProperties::toString() const { diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h index 4ef3814..383a873 100644 --- a/src/gui/egl/qeglproperties_p.h +++ b/src/gui/egl/qeglproperties_p.h @@ -130,6 +130,8 @@ public: QString toString() const; + static void dumpAllConfigs(); + private: QVarLengthArray<int> props; }; diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp index 25550b0..7f3af17 100644 --- a/src/gui/embedded/qscreen_qws.cpp +++ b/src/gui/embedded/qscreen_qws.cpp @@ -181,7 +181,27 @@ void QScreenCursor::set(const QImage &image, int hotx, int hoty) const QRect r = boundingRect(); hotspot = QPoint(hotx, hoty); - cursor = image; + // These are in almost all cases the fastest formats to blend + QImage::Format f; + switch (qt_screen->depth()) { + case 12: + f = QImage::Format_ARGB4444_Premultiplied; + break; + case 15: + f = QImage::Format_ARGB8555_Premultiplied; + break; + case 16: + f = QImage::Format_ARGB8565_Premultiplied; + break; + case 18: + f = QImage::Format_ARGB6666_Premultiplied; + break; + default: + f = QImage::Format_ARGB32_Premultiplied; + } + + cursor = image.convertToFormat(f); + size = image.size(); if (enable && !hwaccel) diff --git a/src/gui/embedded/qscreenlinuxfb_qws.cpp b/src/gui/embedded/qscreenlinuxfb_qws.cpp index 34fc54c..69e5808 100644 --- a/src/gui/embedded/qscreenlinuxfb_qws.cpp +++ b/src/gui/embedded/qscreenlinuxfb_qws.cpp @@ -271,15 +271,13 @@ bool QLinuxFbScreen::connect(const QString &displaySpec) QScreen::setFrameBufferLittleEndian(true); #endif - // Check for explicitly specified device - const int len = 8; // "/dev/fbx" - int m = displaySpec.indexOf(QLatin1String("/dev/fb")); - - QString dev; - if (m > 0) - dev = displaySpec.mid(m, len); - else - dev = QLatin1String("/dev/fb0"); + QString dev = QLatin1String("/dev/fb0"); + foreach(QString d, args) { + if (d.startsWith(QLatin1Char('/'))) { + dev = d; + break; + } + } if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0) d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR); diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 15b86b5..547d7ce 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -22,7 +22,11 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicswidget.h \ graphicsview/qgraphicswidget_p.h \ - graphicsview/qgridlayoutengine_p.h + graphicsview/qgridlayoutengine_p.h \ + graphicsview/qgraph_p.h \ + graphicsview/qsimplex_p.h \ + graphicsview/qgraphicsanchorlayout_p.h \ + graphicsview/qgraphicsanchorlayout.h SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicsitem.cpp \ @@ -42,4 +46,7 @@ SOURCES += graphicsview/qgraphicsgridlayout.cpp \ graphicsview/qgraphicsview.cpp \ graphicsview/qgraphicswidget.cpp \ graphicsview/qgraphicswidget_p.cpp \ - graphicsview/qgridlayoutengine.cpp + graphicsview/qgridlayoutengine.cpp \ + graphicsview/qsimplex_p.cpp \ + graphicsview/qgraphicsanchorlayout_p.cpp \ + graphicsview/qgraphicsanchorlayout.cpp diff --git a/src/gui/graphicsview/qgraph_p.h b/src/gui/graphicsview/qgraph_p.h new file mode 100644 index 0000000..7130003 --- /dev/null +++ b/src/gui/graphicsview/qgraph_p.h @@ -0,0 +1,240 @@ +#include <QtCore/QHash> +#include <QtCore/QQueue> +#include <QtCore/QString> +#include <QtCore/QDebug> + +#include <float.h> + +QT_BEGIN_NAMESPACE + +template <typename Vertex, typename EdgeData> +class Graph +{ +public: + Graph() {} + + class const_iterator { + public: + const_iterator(const Graph *graph, bool begin) : g(graph){ + if (begin) { + row = g->m_graph.constBegin(); + //test if the graph is empty + if (row != g->m_graph.constEnd()) + { + column = (*row)->constBegin(); + } + } else { + row = g->m_graph.constEnd(); + } + } + + inline Vertex *operator*() { + return column.key(); + } + + inline Vertex *from() const { + return row.key(); + } + + inline Vertex *to() const { + return column.key(); + } + + inline bool operator==(const const_iterator &o) const { return !(*this != o); } + inline bool operator!=(const const_iterator &o) const { + if (row == g->m_graph.end()) { + return row != o.row; + } else { + return row != o.row || column != o.column; + } + } + inline const_iterator& operator=(const const_iterator &o) const { row = o.row; column = o.column; return *this;} + + // prefix + const_iterator &operator++() { + if (row != g->m_graph.constEnd()) { + ++column; + if (column == (*row)->constEnd()) { + ++row; + if (row != g->m_graph.constEnd()) { + column = (*row)->constBegin(); + } + } + } + return *this; + } + + private: + const Graph *g; + Q_TYPENAME QHash<Vertex *, QHash<Vertex *, EdgeData *> * >::const_iterator row; + Q_TYPENAME QHash<Vertex *, EdgeData *>::const_iterator column; + }; + + const_iterator constBegin() const { + return const_iterator(this,true); + } + + const_iterator constEnd() const { + return const_iterator(this,false); + } + + /*! + * \internal + * + * If there is an edge between \a first and \a second, it will return a structure + * containing the data associated with the edge, otherwise it will return 0. + * + */ + EdgeData *edgeData(Vertex* first, Vertex* second) { + QHash<Vertex *, EdgeData *> *row = m_graph.value(first); + return row ? row->value(second) : 0; + } + + void createEdge(Vertex *first, Vertex *second, EdgeData *data) + { + // Creates a bidirectional edge +#if defined(QT_DEBUG) && 0 + qDebug("Graph::createEdge(): %s", + qPrintable(QString::fromAscii("%1-%2") + .arg(first->toString()).arg(second->toString()))); +#endif + if (edgeData(first, second)) { +#ifdef QT_DEBUG + qWarning(qPrintable(QString::fromAscii("%1-%2 already has an edge") + .arg(first->toString()).arg(second->toString()))); +#endif + } + createDirectedEdge(first, second, data); + createDirectedEdge(second, first, data); + } + + void removeEdge(Vertex *first, Vertex *second) + { + // Removes a bidirectional edge +#if defined(QT_DEBUG) && 0 + qDebug("Graph::removeEdge(): %s", + qPrintable(QString::fromAscii("%1-%2") + .arg(first->toString()).arg(second->toString()))); +#endif + EdgeData *data = edgeData(first, second); + removeDirectedEdge(first, second); + removeDirectedEdge(second, first); + if (data) delete data; + } + + EdgeData *takeEdge(Vertex* first, Vertex* second) + { +#if defined(QT_DEBUG) && 0 + qDebug("Graph::takeEdge(): %s", + qPrintable(QString::fromAscii("%1-%2") + .arg(first->toString()).arg(second->toString()))); +#endif + // Removes a bidirectional edge + EdgeData *data = edgeData(first, second); + if (data) { + removeDirectedEdge(first, second); + removeDirectedEdge(second, first); + } + return data; + } + + QList<Vertex *> adjacentVertices(Vertex *vertex) const + { + QHash<Vertex *, EdgeData *> *row = m_graph.value(vertex); + QList<Vertex *> l; + if (row) + l = row->keys(); + return l; + } + + void setRootVertex(Vertex *vertex) + { + userVertex = vertex; + } + + QSet<Vertex*> vertices() const { + QSet<Vertex *> setOfVertices; + for (const_iterator it = constBegin(); it != constEnd(); ++it) { + setOfVertices.insert(*it); + } + return setOfVertices; + } + + QList<QPair<Vertex*, Vertex*> > connections() const { + QList<QPair<Vertex*, Vertex*> > conns; + for (const_iterator it = constBegin(); it != constEnd(); ++it) { + Vertex *from = it.from(); + Vertex *to = it.to(); + // do not return (from,to) *and* (to,from) + if (from < to) { + conns.append(qMakePair(from, to)); + } + } + return conns; + } + +#if defined(QT_DEBUG) + QString serializeToDot() { // traversal + QString strVertices; + QString edges; + + QSet<Vertex *> setOfVertices = vertices(); + for (Q_TYPENAME QSet<Vertex*>::const_iterator it = setOfVertices.begin(); it != setOfVertices.end(); ++it) { + Vertex *v = *it; + QList<Vertex*> adjacents = adjacentVertices(v); + for (int i = 0; i < adjacents.count(); ++i) { + Vertex *v1 = adjacents.at(i); + EdgeData *data = edgeData(v, v1); + bool forward = data->from == v; + if (forward) { + edges += QString::fromAscii("%1->%2 [label=\"[%3,%4,%5]\" dir=both color=\"#000000:#a0a0a0\"] \n") + .arg(v->toString()) + .arg(v1->toString()) + .arg(data->minSize) + .arg(data->prefSize) + .arg(data->maxSize) + ; + } + } + strVertices += QString::fromAscii("%1 [label=\"%2\"]\n").arg(v->toString()).arg(v->toString()); + } + return QString::fromAscii("%1\n%2\n").arg(strVertices).arg(edges); + } +#endif + + Vertex *rootVertex() const + { + return userVertex; + } + +protected: + void createDirectedEdge(Vertex *from, Vertex *to, EdgeData *data) + { + QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.value(from); + if (!adjacentToFirst) { + adjacentToFirst = new QHash<Vertex *, EdgeData *>(); + m_graph.insert(from, adjacentToFirst); + } + adjacentToFirst->insert(to, data); + } + + void removeDirectedEdge(Vertex *from, Vertex *to) + { + QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.value(from); + Q_ASSERT(adjacentToFirst); + + adjacentToFirst->remove(to); + if (adjacentToFirst->isEmpty()) { + //nobody point to 'from' so we can remove it from the graph + m_graph.remove(from); + delete adjacentToFirst; + } + } + +private: + Vertex *userVertex; + + QHash<Vertex *, QHash<Vertex *, EdgeData *> *> m_graph; +}; + +QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp new file mode 100644 index 0000000..3c2ea37 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -0,0 +1,454 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QGraphicsAnchorLayout + \brief The QGraphicsAnchorLayout class provides a layout where one can anchor widgets + together in Graphics View. + \since 4.6 + \ingroup appearance + \ingroup geomanagement + \ingroup graphicsview-api + + The anchor layout is a layout where one can specify how widgets should be placed relative to + each other. The specification is called an anchor, and it is set up by calling anchor(). + Anchors are always set up between edges of an item, where the "center" is also considered to + be an edge. Considering this example: + \code + QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; + QGraphicsWidget *a = new QGraphicsWidget; + QGraphicsWidget *b = new QGraphicsWidget; + l->anchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); + \endcode + + Here is the right edge of item A anchored to the left edge of item B, with the result that + item B will be placed to the right of item A, with a spacing between A and B. If the + spacing is negative, the items will overlap to some extent. Items that are anchored are + automatically added to the layout, and if items are removed, all their anchors will be + automatically removed + + \section1 Size Hints and Size Policies in QGraphicsLinearLayout + QGraphicsLinearLayout respects each item's size hints and size policies. However it does + not respect stretch factors currently. This might change in the future, so please refrain + from using stretch factors in anchor layout to avoid any future regressions. + + \section1 Spacing within QGraphicsAnchorLayout + + Between the items, the layout can distribute some space. If the spacing has not been + explicitly specified, the actual amount of space will usually be 0, but if the first edge + is the "opposite" of the second edge (i.e. Right is anchored to Left or vice-versa), the + size of the anchor will be queried from the style through the pixelMetric + PM_LayoutHorizontalSpacing (or PM_LayoutVerticalSpacing for vertical anchors). +*/ + +#include "qgraphicsanchorlayout_p.h" + +QT_BEGIN_NAMESPACE + +QGraphicsAnchorLayout::QGraphicsAnchorLayout(QGraphicsLayoutItem *parent) + : QGraphicsLayout(*new QGraphicsAnchorLayoutPrivate(), parent) +{ + Q_D(QGraphicsAnchorLayout); + d->createLayoutEdges(); +} + +QGraphicsAnchorLayout::~QGraphicsAnchorLayout() +{ + Q_D(QGraphicsAnchorLayout); + + for (int i = count() - 1; i >= 0; --i) { + QGraphicsLayoutItem *item = d->items.at(i); + removeAt(i); + if (item) { + if (item->ownedByLayout()) + delete item; + } + } + + d->removeCenterConstraints(this, QGraphicsAnchorLayoutPrivate::Horizontal); + d->removeCenterConstraints(this, QGraphicsAnchorLayoutPrivate::Vertical); + d->deleteLayoutEdges(); + + Q_ASSERT(d->itemCenterConstraints[0].isEmpty()); + Q_ASSERT(d->itemCenterConstraints[1].isEmpty()); + Q_ASSERT(d->items.isEmpty()); + Q_ASSERT(d->m_vertexList.isEmpty()); +} + +/*! + * Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge + * of item \a secondItem. The magnitude of the anchor is picked up from the style. Anchors + * between a layout edge and an item edge will have a size of 0. + * If there is already an anchor between the edges, the the new anchor will replace the old one. + * + * \a firstItem and \a secondItem are automatically added to the layout if they are not part + * of the layout. This means that count() can increase with up to 2. + * + * The spacing an anchor will get depends on the type of anchor. For instance, anchors from the + * Right edge of one item to the Left edge of another (or vice versa) will use the default + * horizontal spacing. The same behaviour applies to Bottom to Top anchors, (but they will use + * the default vertical spacing). For all other anchor combinations, the spacing will be 0. + * All anchoring functions will follow this rule. + * + * The spacing can also be set manually by using setAnchorSpacing() method. + * + * \sa removeAnchor(), addCornerAnchors(), addLeftAndRightAnchors(), addTopAndBottomAnchors(), + * addAllAnchors() + */ +void QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) +{ + Q_D(QGraphicsAnchorLayout); + d->anchor(firstItem, firstEdge, secondItem, secondEdge); + invalidate(); +} + +/*! + * Creates two anchors between \a firstItem and \a secondItem, where one is for the horizontal + * edge and another one for the vertical edge that the corners \a firstCorner and \a + * secondCorner specifies. + * The magnitude of the anchors is picked up from the style. + * + * This is a convenience function, since anchoring corners can be expressed as anchoring two edges. + * For instance, + * \code + * layout->addAnchor(layout, Qt::AnchorTop, b, Qt::AnchorTop); + * layout->addAnchor(layout, Qt::AnchorLeft, b, Qt::AnchorLeft); + * \endcode + * + * has the same effect as + * + * \code + * layout->addCornerAnchors(layout, Qt::TopLeft, b, Qt::TopLeft); + * \endcode + * + * If there is already an anchor between the edge pairs, it will be replaced by the anchors that + * this function specifies. + * + * \a firstItem and \a secondItem are automatically added to the layout if they are not part + * of the layout. This means that count() can increase with up to 2. + */ +void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, + Qt::Corner firstCorner, + QGraphicsLayoutItem *secondItem, + Qt::Corner secondCorner) +{ + Q_D(QGraphicsAnchorLayout); + + // Horizontal anchor + Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); + Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); + d->anchor(firstItem, firstEdge, secondItem, secondEdge); + + // Vertical anchor + firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); + secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); + d->anchor(firstItem, firstEdge, secondItem, secondEdge); + + invalidate(); +} + +/*! + \fn QGraphicsAnchorLayout::addLeftAndRightAnchors(QGraphicsLayoutItem *firstEdge, QGraphicsLayoutItem *secondEdge) + + This convenience function is equivalent to calling + \code + l->addAnchor(firstEdge, Qt::AnchorLeft, secondEdge, Qt::AnchorLeft); + l->addAnchor(firstEdge, Qt::AnchorRight, secondEdge, Qt::AnchorRight); + \endcode +*/ + +/*! + \fn QGraphicsAnchorLayout::addTopAndBottomAnchors(QGraphicsLayoutItem *firstEdge, QGraphicsLayoutItem *secondEdge) + + This convenience function is equivalent to calling + \code + l->addAnchor(firstEdge, Qt::AnchorTop, secondEdge, Qt::AnchorTop); + l->addAnchor(firstEdge, Qt::AnchorBottom, secondEdge, Qt::AnchorBottom); + \endcode +*/ + +/*! + \fn QGraphicsAnchorLayout::addAllAnchors(QGraphicsLayoutItem *firstEdge, QGraphicsLayoutItem *secondEdge) + + This convenience function is equivalent to calling + \code + l->addLeftAndRightAnchors(firstEdge, secondEdge); + l->addTopAndBottomAnchors(firstEdge, secondEdge); + \endcode +*/ + +/*! + Set the spacing between the anchor point defined by \a firstItem and \a firstEdge and + \a secondItem and \a secondEdge to be \a spacing. +*/ +void QGraphicsAnchorLayout::setAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, + qreal spacing) +{ + Q_D(QGraphicsAnchorLayout); + + if (!d->setAnchorSize(firstItem, firstEdge, secondItem, secondEdge, &spacing)) { + qWarning("setAnchorSpacing: The anchor does not exist."); + } + invalidate(); +} + +/*! + Returns the spacing between the anchor point defined by \a firstItem and \a firstEdge and + \a secondItem and \a secondEdge. The anchor must exist. +*/ +qreal QGraphicsAnchorLayout::anchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) const +{ + Q_D(const QGraphicsAnchorLayout); + qreal size = 0; + if (!d->anchorSize(firstItem, firstEdge, secondItem, secondEdge, 0, &size)) { + qWarning("anchorSpacing: The anchor does not exist."); + } + return size; +} + +/*! + Resets the spacing between the anchor point defined by \a firstItem and \a firstEdge and + \a secondItem and \a secondEdge to be the default spacing. Depending on the anchor type, the + default spacing is either 0 or a value returned from the style. + + \sa setAnchorSpacing(), anchorSpacing(), addAnchor() +*/ +void QGraphicsAnchorLayout::unsetAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) +{ + Q_D(QGraphicsAnchorLayout); + + if (!d->setAnchorSize(firstItem, firstEdge, secondItem, secondEdge, 0)) { + qWarning("unsetAnchorSpacing: The anchor does not exist."); + } + invalidate(); +} + +/*! + Removes the anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge + of item \a secondItem. If such an anchor does not exist, the layout will be left unchanged. +*/ +void QGraphicsAnchorLayout::removeAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) +{ + Q_D(QGraphicsAnchorLayout); + if ((firstItem == 0) || (secondItem == 0)) { + qWarning("QGraphicsAnchorLayout::removeAnchor: " + "Cannot remove anchor between NULL items"); + return; + } + + if (firstItem == secondItem) { + qWarning("QGraphicsAnchorLayout::removeAnchor: " + "Cannot remove anchor from the item to itself"); + return; + } + + if (d->edgeOrientation(secondEdge) != d->edgeOrientation(firstEdge)) { + qWarning("QGraphicsAnchorLayout::removeAnchor: " + "Cannot remove anchor from edges of different orientations"); + return; + } + + d->removeAnchor(firstItem, firstEdge, secondItem, secondEdge); + invalidate(); +} + +/*! + Sets the default horizontal spacing for the anchor layout to \a spacing. + + \sa horizontalSpacing(), setVerticalSpacing(), setSpacing() +*/ +void QGraphicsAnchorLayout::setHorizontalSpacing(qreal spacing) +{ + Q_D(QGraphicsAnchorLayout); + d->spacings[0] = spacing; + invalidate(); +} + +/*! + Sets the default vertical spacing for the anchor layout to \a spacing. + + \sa verticalSpacing(), setHorizontalSpacing(), setSpacing() +*/ +void QGraphicsAnchorLayout::setVerticalSpacing(qreal spacing) +{ + Q_D(QGraphicsAnchorLayout); + d->spacings[1] = spacing; + invalidate(); +} + +/*! + Sets the default horizontal and the default vertical spacing for the anchor layout to \a spacing. + + If an item is anchored with no spacing associated with the anchor, it will use the default + spacing. + \sa setHorizontalSpacing(), setVerticalSpacing() +*/ +void QGraphicsAnchorLayout::setSpacing(qreal spacing) +{ + Q_D(QGraphicsAnchorLayout); + d->spacings[0] = d->spacings[1] = spacing; + invalidate(); +} + +/*! + Returns the default horizontal spacing for the anchor layout. + + \sa verticalSpacing(), setHorizontalSpacing() +*/ +qreal QGraphicsAnchorLayout::horizontalSpacing() const +{ + Q_D(const QGraphicsAnchorLayout); + return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Horizontal); +} + +/*! + Returns the default vertical spacing for the anchor layout. + + \sa horizontalSpacing(), setVerticalSpacing() +*/ +qreal QGraphicsAnchorLayout::verticalSpacing() const +{ + Q_D(const QGraphicsAnchorLayout); + return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Vertical); +} + +/*! + \reimp +*/ +void QGraphicsAnchorLayout::setGeometry(const QRectF &geom) +{ + Q_D(QGraphicsAnchorLayout); + + QGraphicsLayout::setGeometry(geom); + d->calculateVertexPositions(QGraphicsAnchorLayoutPrivate::Horizontal); + d->calculateVertexPositions(QGraphicsAnchorLayoutPrivate::Vertical); + d->setItemsGeometries(); +} + +/*! + Removing an item will also remove any of the anchors associated with it. +*/ +void QGraphicsAnchorLayout::removeAt(int index) +{ + Q_D(QGraphicsAnchorLayout); + QGraphicsLayoutItem *item = d->items.value(index); + + if (!item) + return; + + // Removing an item affects both horizontal and vertical graphs + d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Horizontal); + d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Vertical); + + d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Horizontal); + d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Vertical); + d->removeAnchors(item); + d->items.remove(index); + + item->setParentLayoutItem(0); + invalidate(); +} + +/*! + \reimp +*/ +int QGraphicsAnchorLayout::count() const +{ + Q_D(const QGraphicsAnchorLayout); + return d->items.size(); +} + +/*! + \reimp +*/ +QGraphicsLayoutItem *QGraphicsAnchorLayout::itemAt(int index) const +{ + Q_D(const QGraphicsAnchorLayout); + return d->items.value(index); +} + +/*! + \reimp +*/ +void QGraphicsAnchorLayout::invalidate() +{ + Q_D(QGraphicsAnchorLayout); + QGraphicsLayout::invalidate(); + d->calculateGraphCacheDirty = 1; +} + +/*! + \reimp +*/ +QSizeF QGraphicsAnchorLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +{ + Q_UNUSED(which); + Q_UNUSED(constraint); + Q_D(const QGraphicsAnchorLayout); + + // Some setup calculations are delayed until the information is + // actually needed, avoiding unnecessary recalculations when + // adding multiple anchors. + + // sizeHint() / effectiveSizeHint() already have a cache + // mechanism, using invalidate() to force recalculation. However + // sizeHint() is called three times after invalidation (for max, + // min and pref), but we just need do our setup once. + + const_cast<QGraphicsAnchorLayoutPrivate *>(d)->calculateGraphs(); + + // ### apply constraint! + QSizeF engineSizeHint( + d->sizeHints[QGraphicsAnchorLayoutPrivate::Horizontal][which], + d->sizeHints[QGraphicsAnchorLayoutPrivate::Vertical][which]); + + qreal left, top, right, bottom; + getContentsMargins(&left, &top, &right, &bottom); + + return engineSizeHint + QSizeF(left + right, top + bottom); +} + +QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h new file mode 100644 index 0000000..3de9ae5 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsanchorlayout.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSANCHORLAYOUT_H +#define QGRAPHICSANCHORLAYOUT_H + +#include <QtGui/qgraphicsitem.h> +#include <QtGui/qgraphicslayout.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +class QGraphicsAnchorLayoutPrivate; + +class Q_GUI_EXPORT QGraphicsAnchorLayout : public QGraphicsLayout +{ +public: + QGraphicsAnchorLayout(QGraphicsLayoutItem *parent = 0); + virtual ~QGraphicsAnchorLayout(); + + void addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); + + void addCornerAnchors(QGraphicsLayoutItem *firstItem, Qt::Corner firstCorner, + QGraphicsLayoutItem *secondItem, Qt::Corner secondCorner); + + inline void addLeftAndRightAnchors(QGraphicsLayoutItem *firstItem, + QGraphicsLayoutItem *secondItem); + + inline void addTopAndBottomAnchors(QGraphicsLayoutItem *firstItem, + QGraphicsLayoutItem *secondItem); + + inline void addAllAnchors(QGraphicsLayoutItem *firstItem, + QGraphicsLayoutItem *secondItem); + + void setAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, + qreal spacing); + + qreal anchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) const; + + void unsetAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); + + void removeAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); + + void setHorizontalSpacing(qreal spacing); + void setVerticalSpacing(qreal spacing); + void setSpacing(qreal spacing); + qreal horizontalSpacing() const; + qreal verticalSpacing() const; + + void removeAt(int index); + void setGeometry(const QRectF &rect); + int count() const; + QGraphicsLayoutItem *itemAt(int index) const; + + void invalidate(); +protected: + QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + +private: + Q_DISABLE_COPY(QGraphicsAnchorLayout) + Q_DECLARE_PRIVATE(QGraphicsAnchorLayout) +}; + + +void QGraphicsAnchorLayout::addLeftAndRightAnchors(QGraphicsLayoutItem *firstItem, + QGraphicsLayoutItem *secondItem) +{ + addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft); + addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); +} + +void QGraphicsAnchorLayout::addTopAndBottomAnchors(QGraphicsLayoutItem *firstItem, + QGraphicsLayoutItem *secondItem) +{ + addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop); + addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom); +} + +void QGraphicsAnchorLayout::addAllAnchors(QGraphicsLayoutItem *firstItem, + QGraphicsLayoutItem *secondItem) +{ + addLeftAndRightAnchors(firstItem, secondItem); + addTopAndBottomAnchors(firstItem, secondItem); +} + +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp new file mode 100644 index 0000000..9a34ad5 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -0,0 +1,2104 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/qwidget.h> +#include <QtCore/qlinkedlist.h> +#include <QtCore/qstack.h> + +#ifdef QT_DEBUG +#include <QtCore/qfile.h> +#endif + +#include "qgraphicsanchorlayout_p.h" + +QT_BEGIN_NAMESPACE + +void AnchorData::refreshSizeHints(qreal effectiveSpacing) +{ + if (!isLayoutAnchor && from->m_item == to->m_item) { + bool hasCenter = false; + QGraphicsLayoutItem *item = from->m_item; + + if (QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge) + == QGraphicsAnchorLayoutPrivate::Horizontal) { + minSize = item->minimumWidth(); + prefSize = item->preferredWidth(); + maxSize = item->maximumWidth(); + hasCenter = (from->m_edge == Qt::AnchorHorizontalCenter + || to->m_edge == Qt::AnchorHorizontalCenter); + } else { + minSize = item->minimumHeight(); + prefSize = item->preferredHeight(); + maxSize = item->maximumHeight(); + hasCenter = (from->m_edge == Qt::AnchorVerticalCenter + || to->m_edge == Qt::AnchorVerticalCenter); + } + + if (hasCenter) { + minSize /= 2; + prefSize /= 2; + maxSize /= 2; + } + + // Set the anchor effective sizes to preferred. + // + // Note: The idea here is that all items should remain at their + // preferred size unless where that's impossible. In cases where + // the item is subject to restrictions (anchored to the layout + // edges, for instance), the simplex solver will be run to + // recalculate and override the values we set here. + sizeAtMinimum = prefSize; + sizeAtPreferred = prefSize; + sizeAtMaximum = prefSize; + + } else if (!hasSize) { + // Anchor has no size defined, use given default information + minSize = effectiveSpacing; + prefSize = effectiveSpacing; + maxSize = effectiveSpacing; + + sizeAtMinimum = prefSize; + sizeAtPreferred = prefSize; + sizeAtMaximum = prefSize; + } +} + +void ParallelAnchorData::updateChildrenSizes() +{ + firstEdge->sizeAtMinimum = secondEdge->sizeAtMinimum = sizeAtMinimum; + firstEdge->sizeAtPreferred = secondEdge->sizeAtPreferred = sizeAtPreferred; + firstEdge->sizeAtMaximum = secondEdge->sizeAtMaximum = sizeAtMaximum; + + firstEdge->updateChildrenSizes(); + secondEdge->updateChildrenSizes(); +} + +void ParallelAnchorData::refreshSizeHints(qreal effectiveSpacing) +{ + // First refresh children information + firstEdge->refreshSizeHints(effectiveSpacing); + secondEdge->refreshSizeHints(effectiveSpacing); + + // ### should we warn if the parallel connection is invalid? + // e.g. 1-2-3 with 10-20-30, the minimum of the latter is + // bigger than the maximum of the former. + + minSize = qMax(firstEdge->minSize, secondEdge->minSize); + maxSize = qMin(firstEdge->maxSize, secondEdge->maxSize); + + prefSize = qMax(firstEdge->prefSize, secondEdge->prefSize); + prefSize = qMin(prefSize, maxSize); + + // See comment in AnchorData::refreshSizeHints() about sizeAt* values + sizeAtMinimum = prefSize; + sizeAtPreferred = prefSize; + sizeAtMaximum = prefSize; +} + +/*! + \internal + returns the factor in the interval [-1, 1]. + -1 is at Minimum + 0 is at Preferred + 1 is at Maximum +*/ +static qreal getFactor(qreal value, qreal min, qreal pref, qreal max) +{ + // ### Maybe remove some of the assertions? (since outside is asserting us) + Q_ASSERT(value > min || qFuzzyCompare(value, min)); + Q_ASSERT(value < max || qFuzzyCompare(value, max)); + + if (qFuzzyCompare(value, min)) { + return -1.0; + } else if (qFuzzyCompare(value, pref)) { + return 0.0; + } else if (qFuzzyCompare(value, max)) { + return 1.0; + } else if (value < pref) { + // Since value < pref and value != pref and min <= value, + // we can assert that min < pref. + Q_ASSERT(min < pref); + return (value - min) / (pref - min) - 1; + } else { + // Since value > pref and value != pref and max >= value, + // we can assert that max > pref. + Q_ASSERT(max > pref); + return (value - pref) / (max - pref); + } +} + +void SequentialAnchorData::updateChildrenSizes() +{ + // ### REMOVE ME + // ### check whether we are guarantee to get those or we need to warn stuff at this + // point. + Q_ASSERT(sizeAtMinimum > minSize || qFuzzyCompare(sizeAtMinimum, minSize)); + Q_ASSERT(sizeAtMinimum < maxSize || qFuzzyCompare(sizeAtMinimum, maxSize)); + Q_ASSERT(sizeAtPreferred > minSize || qFuzzyCompare(sizeAtPreferred, minSize)); + Q_ASSERT(sizeAtPreferred < maxSize || qFuzzyCompare(sizeAtPreferred, maxSize)); + Q_ASSERT(sizeAtMaximum > minSize || qFuzzyCompare(sizeAtMaximum, minSize)); + Q_ASSERT(sizeAtMaximum < maxSize || qFuzzyCompare(sizeAtMaximum, maxSize)); + + // Band here refers if the value is in the Minimum To Preferred + // band (the lower band) or the Preferred To Maximum (the upper band). + + qreal minFactor = getFactor(sizeAtMinimum, minSize, prefSize, maxSize); + qreal prefFactor = getFactor(sizeAtPreferred, minSize, prefSize, maxSize); + qreal maxFactor = getFactor(sizeAtMaximum, minSize, prefSize, maxSize); + + for (int i = 0; i < m_edges.count(); ++i) { + AnchorData *e = m_edges.at(i); + + qreal bandSize = minFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize; + e->sizeAtMinimum = e->prefSize + bandSize * minFactor; + + bandSize = prefFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize; + e->sizeAtPreferred = e->prefSize + bandSize * prefFactor; + + bandSize = maxFactor > 0 ? e->maxSize - e->prefSize : e->prefSize - e->minSize; + e->sizeAtMaximum = e->prefSize + bandSize * maxFactor; + + e->updateChildrenSizes(); + } +} + +void SequentialAnchorData::refreshSizeHints(qreal effectiveSpacing) +{ + minSize = 0; + prefSize = 0; + maxSize = 0; + + for (int i = 0; i < m_edges.count(); ++i) { + AnchorData *edge = m_edges.at(i); + + // First refresh children information + edge->refreshSizeHints(effectiveSpacing); + + minSize += edge->minSize; + prefSize += edge->prefSize; + maxSize += edge->maxSize; + } + + // See comment in AnchorData::refreshSizeHints() about sizeAt* values + sizeAtMinimum = prefSize; + sizeAtPreferred = prefSize; + sizeAtMaximum = prefSize; +} + +#ifdef QT_DEBUG +void AnchorData::dump(int indent) { + if (type == Parallel) { + qDebug("%*s type: parallel:", indent, ""); + ParallelAnchorData *p = static_cast<ParallelAnchorData *>(this); + p->firstEdge->dump(indent+2); + p->secondEdge->dump(indent+2); + } else if (type == Sequential) { + SequentialAnchorData *s = static_cast<SequentialAnchorData *>(this); + int kids = s->m_edges.count(); + qDebug("%*s type: sequential(%d):", indent, "", kids); + for (int i = 0; i < kids; ++i) { + s->m_edges.at(i)->dump(indent+2); + } + } else { + qDebug("%*s type: Normal:", indent, ""); + } +} + +#endif + +QSimplexConstraint *GraphPath::constraint(const GraphPath &path) const +{ + // Calculate + QSet<AnchorData *> cPositives; + QSet<AnchorData *> cNegatives; + QSet<AnchorData *> intersection; + + cPositives = positives + path.negatives; + cNegatives = negatives + path.positives; + + intersection = cPositives & cNegatives; + + cPositives -= intersection; + cNegatives -= intersection; + + // Fill + QSimplexConstraint *c = new QSimplexConstraint; + QSet<AnchorData *>::iterator i; + for (i = cPositives.begin(); i != cPositives.end(); ++i) + c->variables.insert(*i, 1.0); + + for (i = cNegatives.begin(); i != cNegatives.end(); ++i) + c->variables.insert(*i, -1.0); + + return c; +} + +#ifdef QT_DEBUG +QString GraphPath::toString() const +{ + QString string(QLatin1String("Path: ")); + foreach(AnchorData *edge, positives) + string += QString::fromAscii(" (+++) %1").arg(edge->toString()); + + foreach(AnchorData *edge, negatives) + string += QString::fromAscii(" (---) %1").arg(edge->toString()); + + return string; +} +#endif + +QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate() + : calculateGraphCacheDirty(1) +{ + for (int i = 0; i < NOrientations; ++i) { + spacings[i] = -1; + graphSimplified[i] = false; + } +} + +Qt::AnchorPoint QGraphicsAnchorLayoutPrivate::oppositeEdge(Qt::AnchorPoint edge) +{ + switch (edge) { + case Qt::AnchorLeft: + edge = Qt::AnchorRight; + break; + case Qt::AnchorRight: + edge = Qt::AnchorLeft; + break; + case Qt::AnchorTop: + edge = Qt::AnchorBottom; + break; + case Qt::AnchorBottom: + edge = Qt::AnchorTop; + break; + default: + break; + } + return edge; +} + + +/*! + * \internal + * + * helper function in order to avoid overflowing anchor sizes + * the returned size will never be larger than FLT_MAX + * + */ +inline static qreal checkAdd(qreal a, qreal b) +{ + if (FLT_MAX - b < a) + return FLT_MAX; + return a + b; +} + +/*! + * \internal + * + * Takes the sequence of vertices described by (\a before, \a vertices, \a after) and replaces + * all anchors connected to the vertices in \a vertices with one simplified anchor between + * \a before and \a after. The simplified anchor will be a placeholder for all the previous + * anchors between \a before and \a after, and can be restored back to the anchors it is a + * placeholder for. + */ +static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph, + AnchorVertex *before, + const QVector<AnchorVertex*> &vertices, + AnchorVertex *after) +{ + int i; +#if defined(QT_DEBUG) && 0 + QString strVertices; + for (i = 0; i < vertices.count(); ++i) + strVertices += QString::fromAscii("%1 - ").arg(vertices.at(i)->toString()); + QString strPath = QString::fromAscii("%1 - %2%3").arg(before->toString(), strVertices, after->toString()); + qDebug("simplifying [%s] to [%s - %s]", qPrintable(strPath), qPrintable(before->toString()), qPrintable(after->toString())); +#endif + + qreal min = 0; + qreal pref = 0; + qreal max = 0; + + SequentialAnchorData *sequence = new SequentialAnchorData; + AnchorVertex *prev = before; + AnchorData *data; + for (i = 0; i <= vertices.count(); ++i) { + AnchorVertex *next = (i < vertices.count()) ? vertices.at(i) : after; + data = graph->takeEdge(prev, next); + min += data->minSize; + pref += data->prefSize; + max = checkAdd(max, data->maxSize); + sequence->m_edges.append(data); + prev = next; + } + + // insert new + sequence->minSize = min; + sequence->prefSize = pref; + sequence->maxSize = max; + + // Unless these values are overhidden by the simplex solver later-on, + // anchors will keep their own preferred size. + sequence->sizeAtMinimum = pref; + sequence->sizeAtPreferred = pref; + sequence->sizeAtMaximum = pref; + + sequence->setVertices(vertices); + + sequence->from = before; + sequence->to = after; + + // data here is the last edge in the sequence + // ### this seems to be here for supporting reverse order sequences, + // but doesnt seem to be used right now + if (data->from != vertices.last()) + qSwap(sequence->from, sequence->to); + + // Note that since layout 'edges' can't be simplified away from + // the graph, it's safe to assume that if there's a layout + // 'edge', it'll be in the boundaries of the sequence. + sequence->isLayoutAnchor = (sequence->m_edges.first()->isLayoutAnchor + || sequence->m_edges.last()->isLayoutAnchor); + + AnchorData *newAnchor = sequence; + if (AnchorData *oldAnchor = graph->takeEdge(before, after)) { + newAnchor = new ParallelAnchorData(oldAnchor, sequence); + + newAnchor->isLayoutAnchor = (oldAnchor->isLayoutAnchor + || sequence->isLayoutAnchor); + + min = qMax(oldAnchor->minSize, sequence->minSize); + max = qMin(oldAnchor->maxSize, sequence->maxSize); + + pref = qMax(oldAnchor->prefSize, sequence->prefSize); + pref = qMin(pref, max); + + newAnchor->minSize = min; + newAnchor->prefSize = pref; + newAnchor->maxSize = max; + + // Same as above, by default, keep preferred size. + newAnchor->sizeAtMinimum = pref; + newAnchor->sizeAtPreferred = pref; + newAnchor->sizeAtMaximum = pref; + } + graph->createEdge(before, after, newAnchor); + + // True if we created a parallel anchor + return newAnchor != sequence; +} + +/*! + \internal + + The purpose of this function is to simplify the graph. + Simplification serves two purposes: + 1. Reduce the number of edges in the graph, (thus the number of variables to the equation + solver is reduced, and the solver performs better). + 2. Be able to do distribution of sequences of edges more intelligently (esp. with sequential + anchors) + + It is essential that it must be possible to restore simplified anchors back to their "original" + form. This is done by restoreSimplifiedAnchor(). + + There are two types of simplification that can be done: + 1. Sequential simplification + Sequential simplification means that all sequences of anchors will be merged into one single + anchor. Only anhcors that points in the same direction will be merged. + 2. Parallel simplification + If a simplified sequential anchor is about to be inserted between two vertices in the graph + and there already exist an anchor between those two vertices, a parallel anchor will be + created that serves as a placeholder for the sequential anchor and the anchor that was + already between the two vertices. + + The process of simplification can be described as: + + 1. Simplify all sequences of anchors into one anchor. + If no further simplification was done, go to (3) + - If there already exist an anchor where the sequential anchor is supposed to be inserted, + take that anchor out of the graph + - Then create a parallel anchor that holds the sequential anchor and the anchor just taken + out of the graph. + 2. Go to (1) + 3. Done + + + * Gathering sequential anchors * + The algorithm walks the graph in depth-first order, and only collects vertices that has two + edges connected to it. If the vertex does not have two edges or if it is a layout edge, + it will take all the previously collected vertices and try to create a simplified sequential + anchor representing all the previously collected vertices. + Once the simplified anchor is inserted, the collected list is cleared in order to find the next + sequence to simplify. + Note that there are some catches to this that are not covered by the above explanation. +*/ +void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) +{ + static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); + if (noSimplification) + return; + + if (graphSimplified[orientation]) + return; + graphSimplified[orientation] = true; + +#if 0 + qDebug("Simplifying Graph for %s", + orientation == Horizontal ? "Horizontal" : "Vertical"); +#endif + + AnchorVertex *rootVertex = graph[orientation].rootVertex(); + + if (!rootVertex) + return; + + bool dirty; + do { + dirty = simplifyGraphIteration(orientation); + } while (dirty); +} + +bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation) +{ + Q_Q(QGraphicsAnchorLayout); + Graph<AnchorVertex, AnchorData> &g = graph[orientation]; + AnchorVertex *v = g.rootVertex(); + + QSet<AnchorVertex *> visited; + QStack<AnchorVertex *> stack; + stack.push(v); + QVector<AnchorVertex*> candidates; + + const Qt::AnchorPoint centerEdge = pickEdge(Qt::AnchorHorizontalCenter, orientation); + const Qt::AnchorPoint layoutEdge = oppositeEdge(v->m_edge); + + bool dirty = false; + + // walk depth-first. + while (!stack.isEmpty()) { + v = stack.pop(); + QList<AnchorVertex *> vertices = g.adjacentVertices(v); + const int count = vertices.count(); + bool endOfSequence = (v->m_item == q && v->m_edge == layoutEdge) || count != 2; + if (count == 2 && v->m_item != q) { + candidates.append(v); + if (visited.contains(vertices.first()) && visited.contains(vertices.last())) { + // in case of a cycle + endOfSequence = true; + } + } + if (endOfSequence && candidates.count() >= 2) { + int i; + AnchorVertex *afterSequence= 0; + QList<AnchorVertex *> adjacentOfSecondLastVertex = g.adjacentVertices(candidates.last()); + Q_ASSERT(adjacentOfSecondLastVertex.count() == 2); + if (adjacentOfSecondLastVertex.first() == candidates.at(candidates.count() - 2)) + afterSequence = adjacentOfSecondLastVertex.last(); + else + afterSequence = adjacentOfSecondLastVertex.first(); + + AnchorVertex *beforeSequence = 0; + QList<AnchorVertex *> adjacentOfSecondVertex = g.adjacentVertices(candidates.first()); + Q_ASSERT(adjacentOfSecondVertex.count() == 2); + if (adjacentOfSecondVertex.first() == candidates.at(1)) + beforeSequence = adjacentOfSecondVertex.last(); + else + beforeSequence = adjacentOfSecondVertex.first(); + // The complete path of the sequence to simplify is: beforeSequence, <candidates>, afterSequence + // where beforeSequence and afterSequence are the endpoints where the anchor is inserted + // between. +#if defined(QT_DEBUG) && 0 + // ### DEBUG + QString strCandidates; + for (i = 0; i < candidates.count(); ++i) + strCandidates += QString::fromAscii("%1 - ").arg(candidates.at(i)->toString()); + QString strPath = QString::fromAscii("%1 - %2%3").arg(beforeSequence->toString(), strCandidates, afterSequence->toString()); + qDebug("candidate list for sequential simplification:\n[%s]", qPrintable(strPath)); +#endif + + bool forward; + AnchorVertex *prev = beforeSequence; + int intervalFrom = 0; + + // Check for directionality (from). We don't want to destroy that information, + // thus we only combine anchors with the same direction. + + // "i" is the index *including* the beforeSequence and afterSequence vertices. + for (i = 1; i <= candidates.count() + 1; ++i) { + bool atVertexAfter = i > candidates.count(); + AnchorVertex *v1 = atVertexAfter ? afterSequence : candidates.at(i - 1); + AnchorData *data = g.edgeData(prev, v1); + Q_ASSERT(data); + if (i == 1) { + forward = (prev == data->from ? true : false); + } else if (forward != (prev == data->from) || atVertexAfter) { + int intervalTo = i; + if (forward != (prev == data->from)) + --intervalTo; + + // intervalFrom and intervalTo should now be indices to the vertex before and + // after the sequential anchor. + if (intervalTo - intervalFrom >= 2) { + // simplify in the range [intervalFrom, intervalTo] + + // Trim off internal center anchors (Left-Center/Center-Right) from the + // start and the end of the sequence. We never want to simplify internal + // center anchors where there is an external anchor connected to the center. + AnchorVertex *intervalVertexFrom = intervalFrom == 0 ? beforeSequence : candidates.at(intervalFrom - 1); + if (intervalVertexFrom->m_edge == centerEdge + && intervalVertexFrom->m_item == candidates.at(intervalFrom)->m_item) { + ++intervalFrom; + intervalVertexFrom = candidates.at(intervalFrom - 1); + } + AnchorVertex *intervalVertexTo = intervalTo <= candidates.count() ? candidates.at(intervalTo - 1) : afterSequence; + if (intervalVertexTo->m_edge == centerEdge + && intervalVertexTo->m_item == candidates.at(intervalTo - 2)->m_item) { + --intervalTo; + intervalVertexTo = candidates.at(intervalTo - 1); + } + + QVector<AnchorVertex*> subCandidates; + if (forward) { + subCandidates = candidates.mid(intervalFrom, intervalTo - intervalFrom - 1); + } else { + // reverse the order of the candidates. + qSwap(intervalVertexFrom, intervalVertexTo); + do { + ++intervalFrom; + subCandidates.prepend(candidates.at(intervalFrom - 1)); + } while (intervalFrom < intervalTo - 1); + } + if (simplifySequentialChunk(&g, intervalVertexFrom, subCandidates, intervalVertexTo)) { + dirty = true; + break; + } + // finished simplification of chunk with same direction + } + if (forward == (prev == data->from)) + --intervalTo; + intervalFrom = intervalTo; + + forward = !forward; + } + prev = v1; + } + + if (dirty) + break; + } + + if (endOfSequence) + candidates.clear(); + + for (int i = 0; i < count; ++i) { + AnchorVertex *next = vertices.at(i); + if (next->m_item == q && next->m_edge == centerEdge) + continue; + if (visited.contains(next)) + continue; + stack.push(next); + } + + visited.insert(v); + } + + return dirty; +} + +static void restoreSimplifiedAnchor(Graph<AnchorVertex, AnchorData> &g, + AnchorData *edge, + AnchorVertex *before, + AnchorVertex *after) +{ + Q_ASSERT(edge->type != AnchorData::Normal); +#if 0 + static const char *anchortypes[] = {"Normal", + "Sequential", + "Parallel"}; + qDebug("Restoring %s edge.", anchortypes[int(edge->type)]); +#endif + if (edge->type == AnchorData::Sequential) { + SequentialAnchorData* seqEdge = static_cast<SequentialAnchorData*>(edge); + // restore the sequential anchor + AnchorVertex *prev = before; + AnchorVertex *last = after; + if (edge->from != prev) + qSwap(last, prev); + + for (int i = 0; i < seqEdge->m_edges.count(); ++i) { + AnchorVertex *v1 = (i < seqEdge->m_children.count()) ? seqEdge->m_children.at(i) : last; + AnchorData *data = seqEdge->m_edges.at(i); + if (data->type != AnchorData::Normal) { + restoreSimplifiedAnchor(g, data, prev, v1); + } else { + g.createEdge(prev, v1, data); + } + prev = v1; + } + } else if (edge->type == AnchorData::Parallel) { + ParallelAnchorData* parallelEdge = static_cast<ParallelAnchorData*>(edge); + AnchorData *parallelEdges[2] = {parallelEdge->firstEdge, + parallelEdge->secondEdge}; + for (int i = 0; i < 2; ++i) { + AnchorData *data = parallelEdges[i]; + if (data->type == AnchorData::Normal) { + g.createEdge(before, after, data); + } else { + restoreSimplifiedAnchor(g, data, before, after); + } + } + } +} + +void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientation) +{ + if (!graphSimplified[orientation]) + return; + graphSimplified[orientation] = false; + +#if 0 + qDebug("Restoring Simplified Graph for %s", + orientation == Horizontal ? "Horizontal" : "Vertical"); +#endif + + Graph<AnchorVertex, AnchorData> &g = graph[orientation]; + + QList<QPair<AnchorVertex*, AnchorVertex*> > connections = g.connections(); + for (int i = 0; i < connections.count(); ++i) { + AnchorVertex *v1 = connections.at(i).first; + AnchorVertex *v2 = connections.at(i).second; + AnchorData *edge = g.edgeData(v1, v2); + if (edge->type != AnchorData::Normal) { + AnchorData *oldEdge = g.takeEdge(v1, v2); + restoreSimplifiedAnchor(g, edge, v1, v2); + delete oldEdge; + } + } +} + +QGraphicsAnchorLayoutPrivate::Orientation +QGraphicsAnchorLayoutPrivate::edgeOrientation(Qt::AnchorPoint edge) +{ + return edge > Qt::AnchorRight ? Vertical : Horizontal; +} + +/*! + \internal + + Create internal anchors to connect the layout edges (Left to Right and + Top to Bottom). + + These anchors doesn't have size restrictions, that will be enforced by + other anchors and items in the layout. +*/ +void QGraphicsAnchorLayoutPrivate::createLayoutEdges() +{ + Q_Q(QGraphicsAnchorLayout); + QGraphicsLayoutItem *layout = q; + + // Horizontal + AnchorData *data = new AnchorData(0, 0, QWIDGETSIZE_MAX); + addAnchor(layout, Qt::AnchorLeft, layout, + Qt::AnchorRight, data); + data->skipInPreferred = 1; + + // Set the Layout Left edge as the root of the horizontal graph. + AnchorVertex *v = internalVertex(layout, Qt::AnchorLeft); + graph[Horizontal].setRootVertex(v); + + // Vertical + data = new AnchorData(0, 0, QWIDGETSIZE_MAX); + addAnchor(layout, Qt::AnchorTop, layout, + Qt::AnchorBottom, data); + data->skipInPreferred = 1; + + // Set the Layout Top edge as the root of the vertical graph. + v = internalVertex(layout, Qt::AnchorTop); + graph[Vertical].setRootVertex(v); +} + +void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges() +{ + Q_Q(QGraphicsAnchorLayout); + + Q_ASSERT(internalVertex(q, Qt::AnchorHorizontalCenter) == NULL); + Q_ASSERT(internalVertex(q, Qt::AnchorVerticalCenter) == NULL); + + removeAnchor(q, Qt::AnchorLeft, q, Qt::AnchorRight); + removeAnchor(q, Qt::AnchorTop, q, Qt::AnchorBottom); +} + +void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) +{ + Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]); + + items.append(item); + + // Horizontal + int minimumSize = item->minimumWidth(); + int preferredSize = item->preferredWidth(); + int maximumSize = item->maximumWidth(); + + AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); + addAnchor(item, Qt::AnchorLeft, item, + Qt::AnchorRight, data); + + // Vertical + minimumSize = item->minimumHeight(); + preferredSize = item->preferredHeight(); + maximumSize = item->maximumHeight(); + + data = new AnchorData(minimumSize, preferredSize, maximumSize); + addAnchor(item, Qt::AnchorTop, item, + Qt::AnchorBottom, data); +} + +/*! + \internal + + By default, each item in the layout is represented internally as + a single anchor in each direction. For instance, from Left to Right. + + However, to support anchorage of items to the center of items, we + must split this internal anchor into two half-anchors. From Left + to Center and then from Center to Right, with the restriction that + these anchors must have the same time at all times. +*/ +void QGraphicsAnchorLayoutPrivate::createCenterAnchors( + QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge) +{ + Orientation orientation; + switch (centerEdge) { + case Qt::AnchorHorizontalCenter: + orientation = Horizontal; + break; + case Qt::AnchorVerticalCenter: + orientation = Vertical; + break; + default: + // Don't create center edges unless needed + return; + } + + Q_ASSERT(!graphSimplified[orientation]); + + // Check if vertex already exists + if (internalVertex(item, centerEdge)) + return; + + // Orientation code + Qt::AnchorPoint firstEdge; + Qt::AnchorPoint lastEdge; + + if (orientation == Horizontal) { + firstEdge = Qt::AnchorLeft; + lastEdge = Qt::AnchorRight; + } else { + firstEdge = Qt::AnchorTop; + lastEdge = Qt::AnchorBottom; + } + + AnchorVertex *first = internalVertex(item, firstEdge); + AnchorVertex *last = internalVertex(item, lastEdge); + Q_ASSERT(first && last); + + // Create new anchors + AnchorData *oldData = graph[orientation].edgeData(first, last); + + int minimumSize = oldData->minSize / 2; + int preferredSize = oldData->prefSize / 2; + int maximumSize = oldData->maxSize / 2; + + QSimplexConstraint *c = new QSimplexConstraint; + AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); + c->variables.insert(data, 1.0); + addAnchor(item, firstEdge, item, centerEdge, data); + + data = new AnchorData(minimumSize, preferredSize, maximumSize); + c->variables.insert(data, -1.0); + addAnchor(item, centerEdge, item, lastEdge, data); + + itemCenterConstraints[orientation].append(c); + + // Remove old one + removeAnchor(item, firstEdge, item, lastEdge); +} + +void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( + QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge, + bool substitute) +{ + Orientation orientation; + switch (centerEdge) { + case Qt::AnchorHorizontalCenter: + orientation = Horizontal; + break; + case Qt::AnchorVerticalCenter: + orientation = Vertical; + break; + default: + // Don't remove edges that not the center ones + return; + } + + Q_ASSERT(!graphSimplified[orientation]); + + // Orientation code + Qt::AnchorPoint firstEdge; + Qt::AnchorPoint lastEdge; + + if (orientation == Horizontal) { + firstEdge = Qt::AnchorLeft; + lastEdge = Qt::AnchorRight; + } else { + firstEdge = Qt::AnchorTop; + lastEdge = Qt::AnchorBottom; + } + + AnchorVertex *center = internalVertex(item, centerEdge); + if (!center) + return; + AnchorVertex *first = internalVertex(item, firstEdge); + + Q_ASSERT(first); + Q_ASSERT(center); + + Graph<AnchorVertex, AnchorData> &g = graph[orientation]; + + + AnchorData *oldData = g.edgeData(first, center); + // Remove center constraint + for (int i = itemCenterConstraints[orientation].count() - 1; i >= 0; --i) { + if (itemCenterConstraints[orientation][i]->variables.contains(oldData)) { + delete itemCenterConstraints[orientation].takeAt(i); + break; + } + } + + if (substitute) { + // Create the new anchor that should substitute the left-center-right anchors. + AnchorData *oldData = g.edgeData(first, center); + + int minimumSize = oldData->minSize * 2; + int preferredSize = oldData->prefSize * 2; + int maximumSize = oldData->maxSize * 2; + + AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); + addAnchor(item, firstEdge, item, lastEdge, data); + + // Remove old anchors + removeAnchor(item, firstEdge, item, centerEdge); + removeAnchor(item, centerEdge, item, lastEdge); + + } else { + // this is only called from removeAnchors() + // first, remove all non-internal anchors + QList<AnchorVertex*> adjacents = g.adjacentVertices(center); + for (int i = 0; i < adjacents.count(); ++i) { + AnchorVertex *v = adjacents.at(i); + if (v->m_item != item) { + removeAnchor(item, centerEdge, v->m_item, v->m_edge); + } + } + // when all non-internal anchors is removed it will automatically merge the + // center anchor into a left-right (or top-bottom) anchor. We must also delete that. + // by this time, the center vertex is deleted and merged into a non-centered internal anchor + removeAnchor(item, firstEdge, item, lastEdge); + } +} + + +void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem *item, + Orientation orientation) +{ + Q_ASSERT(!graphSimplified[orientation]); + + // Remove the item center constraints associated to this item + // ### This is a temporary solution. We should probably use a better + // data structure to hold items and/or their associated constraints + // so that we can remove those easily + + AnchorVertex *first = internalVertex(item, orientation == Horizontal ? + Qt::AnchorLeft : + Qt::AnchorTop); + AnchorVertex *center = internalVertex(item, orientation == Horizontal ? + Qt::AnchorHorizontalCenter : + Qt::AnchorVerticalCenter); + + // Skip if no center constraints exist + if (!center) + return; + + Q_ASSERT(first); + AnchorData *internalAnchor = graph[orientation].edgeData(first, center); + + // Look for our anchor in all item center constraints, then remove it + for (int i = 0; i < itemCenterConstraints[orientation].size(); ++i) { + if (itemCenterConstraints[orientation][i]->variables.contains(internalAnchor)) { + delete itemCenterConstraints[orientation].takeAt(i); + break; + } + } +} + +/*! + * \internal + * + * Helper function that is called from the anchor functions in the public API. + * If \a spacing is 0, it will pick up the spacing defined by the style. + */ +void QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + qreal *spacing) +{ + Q_Q(QGraphicsAnchorLayout); + if ((firstItem == 0) || (secondItem == 0)) { + qWarning("QGraphicsAnchorLayout::addAnchor(): " + "Cannot anchor NULL items"); + return; + } + + if (firstItem == secondItem) { + qWarning("QGraphicsAnchorLayout::addAnchor(): " + "Cannot anchor the item to itself"); + return; + } + + if (edgeOrientation(secondEdge) != edgeOrientation(firstEdge)) { + qWarning("QGraphicsAnchorLayout::addAnchor(): " + "Cannot anchor edges of different orientations"); + return; + } + + // Guarantee that the graph is no simplified when adding this anchor, + // anchor manipulation always happen in the full graph + restoreSimplifiedGraph(edgeOrientation(firstEdge)); + + // In QGraphicsAnchorLayout, items are represented in its internal + // graph as four anchors that connect: + // - Left -> HCenter + // - HCenter-> Right + // - Top -> VCenter + // - VCenter -> Bottom + + // Ensure that the internal anchors have been created for both items. + if (firstItem != q && !items.contains(firstItem)) { + restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal); + createItemEdges(firstItem); + addChildLayoutItem(firstItem); + } + if (secondItem != q && !items.contains(secondItem)) { + restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal); + createItemEdges(secondItem); + addChildLayoutItem(secondItem); + } + + // Create center edges if needed + createCenterAnchors(firstItem, firstEdge); + createCenterAnchors(secondItem, secondEdge); + + // Use heuristics to find out what the user meant with this anchor. + correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge); + + AnchorData *data; + if (!spacing) { + // If firstItem or secondItem is the layout itself, the spacing will default to 0. + // Otherwise, the following matrix is used (questionmark means that the spacing + // is queried from the style): + // from + // to Left HCenter Right + // Left 0 0 ? + // HCenter 0 0 0 + // Right ? 0 0 + if (firstItem != q + && secondItem != q + && pickEdge(firstEdge, Horizontal) != Qt::AnchorHorizontalCenter + && oppositeEdge(firstEdge) == secondEdge) { + data = new AnchorData; // ask the style later + } else { + data = new AnchorData(0); // spacing should be 0 + } + addAnchor(firstItem, firstEdge, secondItem, secondEdge, data); + } else if (*spacing >= 0) { + data = new AnchorData(*spacing); + addAnchor(firstItem, firstEdge, secondItem, secondEdge, data); + } else { + data = new AnchorData(-*spacing); + addAnchor(secondItem, secondEdge, firstItem, firstEdge, data); + } +} + +void QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + AnchorData *data) +{ + Q_Q(QGraphicsAnchorLayout); + + // Guarantee that the graph is no simplified when adding this anchor, + // anchor manipulation always happen in the full graph + restoreSimplifiedGraph(edgeOrientation(firstEdge)); + + // Is the Vertex (firstItem, firstEdge) already represented in our + // internal structure? + AnchorVertex *v1 = addInternalVertex(firstItem, firstEdge); + AnchorVertex *v2 = addInternalVertex(secondItem, secondEdge); + + // Remove previous anchor + // ### Could we update the existing edgeData rather than creating a new one? + if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2)) + removeAnchor(firstItem, firstEdge, secondItem, secondEdge); + + // Create a bi-directional edge in the sense it can be transversed both + // from v1 or v2. "data" however is shared between the two references + // so we still know that the anchor direction is from 1 to 2. + data->from = v1; + data->to = v2; +#ifdef QT_DEBUG + data->name = QString::fromAscii("%1 --to--> %2").arg(v1->toString()).arg(v2->toString()); +#endif + // Keep track of anchors that are connected to the layout 'edges' + data->isLayoutAnchor = (v1->m_item == q || v2->m_item == q); + + graph[edgeOrientation(firstEdge)].createEdge(v1, v2, data); +} + +void QGraphicsAnchorLayoutPrivate::removeAnchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge) +{ + // Guarantee that the graph is no simplified when adding this anchor, + // anchor manipulation always happen in the full graph + restoreSimplifiedGraph(edgeOrientation(firstEdge)); + + // Look for both vertices + AnchorVertex *v1 = internalVertex(firstItem, firstEdge); + AnchorVertex *v2 = internalVertex(secondItem, secondEdge); + + Q_ASSERT(v1 && v2); + + // Remove edge from graph + graph[edgeOrientation(firstEdge)].removeEdge(v1, v2); + + // Decrease vertices reference count (may trigger a deletion) + removeInternalVertex(firstItem, firstEdge); + removeInternalVertex(secondItem, secondEdge); +} + +bool QGraphicsAnchorLayoutPrivate::setAnchorSize(const QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + const qreal *anchorSize) +{ + // ### we can avoid restoration if we really want to, but we would have to + // search recursively through all composite anchors + restoreSimplifiedGraph(edgeOrientation(firstEdge)); + AnchorVertex *v1 = internalVertex(firstItem, firstEdge); + AnchorVertex *v2 = internalVertex(secondItem, secondEdge); + + AnchorData *data = graph[edgeOrientation(firstEdge)].edgeData(v1, v2); + if (data) { + if (anchorSize) { + data->setFixedSize(*anchorSize); + } else { + data->unsetSize(); + } + } + + return data; +} + +bool QGraphicsAnchorLayoutPrivate::anchorSize(const QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + qreal *minSize, + qreal *prefSize, + qreal *maxSize) const +{ + Q_ASSERT(minSize || prefSize || maxSize); + QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate *>(this); + that->restoreSimplifiedGraph(edgeOrientation(firstEdge)); + AnchorVertex *v1 = internalVertex(firstItem, firstEdge); + AnchorVertex *v2 = internalVertex(secondItem, secondEdge); + + AnchorData *data = that->graph[edgeOrientation(firstEdge)].edgeData(v1, v2); + if (data) { + if (minSize) + *minSize = data->minSize; + if (prefSize) + *prefSize = data->prefSize; + if (maxSize) + *maxSize = data->maxSize; + } + return data; +} + +AnchorVertex *QGraphicsAnchorLayoutPrivate::addInternalVertex(QGraphicsLayoutItem *item, + Qt::AnchorPoint edge) +{ + QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge); + QPair<AnchorVertex *, int> v = m_vertexList.value(pair); + + if (!v.first) { + Q_ASSERT(v.second == 0); + v.first = new AnchorVertex(item, edge); + } + v.second++; + m_vertexList.insert(pair, v); + return v.first; +} + +/** + * \internal + * + * returns the AnchorVertex that was dereferenced, also when it was removed. + * returns 0 if it did not exist. + */ +void QGraphicsAnchorLayoutPrivate::removeInternalVertex(QGraphicsLayoutItem *item, + Qt::AnchorPoint edge) +{ + QPair<QGraphicsLayoutItem *, Qt::AnchorPoint> pair(item, edge); + QPair<AnchorVertex *, int> v = m_vertexList.value(pair); + + if (!v.first) { + qWarning("This item with this edge is not in the graph"); + return; + } + + v.second--; + if (v.second == 0) { + // Remove reference and delete vertex + m_vertexList.remove(pair); + delete v.first; + } else { + // Update reference count + m_vertexList.insert(pair, v); + + if ((v.second == 2) && + ((edge == Qt::AnchorHorizontalCenter) || + (edge == Qt::AnchorVerticalCenter))) { + removeCenterAnchors(item, edge, true); + } + } +} + +void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge) +{ + if (AnchorVertex *v = internalVertex(item, edge)) { + Graph<AnchorVertex, AnchorData> &g = graph[edgeOrientation(edge)]; + const QList<AnchorVertex *> allVertices = graph[edgeOrientation(edge)].adjacentVertices(v); + AnchorVertex *v2; + foreach (v2, allVertices) { + g.removeEdge(v, v2); + removeInternalVertex(item, edge); + removeInternalVertex(v2->m_item, v2->m_edge); + } + } +} + +void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item) +{ + Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]); + + // remove the center anchor first!! + removeCenterAnchors(item, Qt::AnchorHorizontalCenter, false); + removeVertex(item, Qt::AnchorLeft); + removeVertex(item, Qt::AnchorRight); + + removeCenterAnchors(item, Qt::AnchorVerticalCenter, false); + removeVertex(item, Qt::AnchorTop); + removeVertex(item, Qt::AnchorBottom); +} + +/*! + \internal + + Use heuristics to determine the correct orientation of a given anchor. + + After API discussions, we decided we would like expressions like + anchor(A, Left, B, Right) to mean the same as anchor(B, Right, A, Left). + The problem with this is that anchors could become ambiguous, for + instance, what does the anchor A, B of size X mean? + + "pos(B) = pos(A) + X" or "pos(A) = pos(B) + X" ? + + To keep the API user friendly and at the same time, keep our algorithm + deterministic, we use an heuristic to determine a direction for each + added anchor and then keep it. The heuristic is based on the fact + that people usually avoid overlapping items, therefore: + + "A, RIGHT to B, LEFT" means that B is to the LEFT of A. + "B, LEFT to A, RIGHT" is corrected to the above anchor. + + Special correction is also applied when one of the items is the + layout. We handle Layout Left as if it was another items's Right + and Layout Right as another item's Left. +*/ +void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&firstItem, + Qt::AnchorPoint &firstEdge, + QGraphicsLayoutItem *&secondItem, + Qt::AnchorPoint &secondEdge) +{ + Q_Q(QGraphicsAnchorLayout); + + Qt::AnchorPoint effectiveFirst = firstEdge; + Qt::AnchorPoint effectiveSecond = secondEdge; + + if (firstItem == q) + effectiveFirst = QGraphicsAnchorLayoutPrivate::oppositeEdge(firstEdge); + if (secondItem == q) + effectiveSecond = QGraphicsAnchorLayoutPrivate::oppositeEdge(secondEdge); + + if (effectiveFirst < effectiveSecond) { + + // ### DEBUG + /* printf("Swapping Anchor from %s %d --to--> %s %d\n", + firstItem->isLayout() ? "<layout>" : + qPrintable(static_cast<QGraphicsWidget *>(firstItem)->data(0).toString()), + firstEdge, + secondItem->isLayout() ? "<layout>" : + qPrintable(static_cast<QGraphicsWidget *>(secondItem)->data(0).toString()), + secondEdge); + */ + qSwap(firstItem, secondItem); + qSwap(firstEdge, secondEdge); + } +} + +qreal QGraphicsAnchorLayoutPrivate::effectiveSpacing(Orientation orientation) const +{ + Q_Q(const QGraphicsAnchorLayout); + qreal s = spacings[orientation]; + if (s < 0) { + // ### make sure behaviour is the same as in QGraphicsGridLayout + QGraphicsLayoutItem *parent = q->parentLayoutItem(); + while (parent && parent->isLayout()) { + parent = parent->parentLayoutItem(); + } + if (parent) { + QGraphicsItem *parentItem = parent->graphicsItem(); + if (parentItem && parentItem->isWidget()) { + QGraphicsWidget *w = static_cast<QGraphicsWidget*>(parentItem); + s = w->style()->pixelMetric(orientation == Horizontal + ? QStyle::PM_LayoutHorizontalSpacing + : QStyle::PM_LayoutVerticalSpacing); + } + } + } + return s; +} + +/*! + \internal + + Called on activation. Uses Linear Programming to define minimum, preferred + and maximum sizes for the layout. Also calculates the sizes that each item + should assume when the layout is in one of such situations. +*/ +void QGraphicsAnchorLayoutPrivate::calculateGraphs() +{ + if (!calculateGraphCacheDirty) + return; + + calculateGraphs(Horizontal); + calculateGraphs(Vertical); + + calculateGraphCacheDirty = 0; +} + +// ### remove me: +QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints) +{ + QSet<AnchorData *> variableSet; + for (int i = 0; i < constraints.count(); ++i) { + const QSimplexConstraint *c = constraints[i]; + foreach (QSimplexVariable *var, c->variables.keys()) { + variableSet += static_cast<AnchorData *>(var); + } + } + return variableSet.toList(); +} + +/*! + \internal + + Calculate graphs is the method that puts together all the helper routines + so that the AnchorLayout can calculate the sizes of each item. + + In a nutshell it should do: + + 1) Update anchor nominal sizes, that is, the size that each anchor would + have if no other restrictions applied. This is done by quering the + layout style and the sizeHints of the items belonging to the layout. + + 2) Simplify the graph by grouping together parallel and sequential anchors + into "group anchors". These have equivalent minimum, preferred and maximum + sizeHints as the anchors they replace. + + 3) Check if we got to a trivial case. In some cases, the whole graph can be + simplified into a single anchor. If so, use this information. If not, + then call the Simplex solver to calculate the anchors sizes. + + 4) Once the root anchors had its sizes calculated, propagate that to the + anchors they represent. +*/ +void QGraphicsAnchorLayoutPrivate::calculateGraphs( + QGraphicsAnchorLayoutPrivate::Orientation orientation) +{ + Q_Q(QGraphicsAnchorLayout); + + // Simplify the graph + simplifyGraph(orientation); + + // Reset the nominal sizes of each anchor based on the current item sizes + setAnchorSizeHintsFromItems(orientation); + + // Traverse all graph edges and store the possible paths to each vertex + findPaths(orientation); + + // From the paths calculated above, extract the constraints that the current + // anchor setup impose, to our Linear Programming problem. + constraintsFromPaths(orientation); + + // Split the constraints and anchors into groups that should be fed to the + // simplex solver independently. Currently we find two groups: + // + // 1) The "trunk", that is, the set of anchors (items) that are connected + // to the two opposite sides of our layout, and thus need to stretch in + // order to fit in the current layout size. + // + // 2) The floating or semi-floating anchors (items) that are those which + // are connected to only one (or none) of the layout sides, thus are not + // influenced by the layout size. + QList<QList<QSimplexConstraint *> > parts; + parts = getGraphParts(orientation); + + // Now run the simplex solver to calculate Minimum, Preferred and Maximum sizes + // of the "trunk" set of constraints and variables. + // ### does trunk always exist? empty = trunk is the layout left->center->right + QList<QSimplexConstraint *> trunkConstraints = parts[0]; + QList<QSimplexConstraint *> sizeHintConstraints; + sizeHintConstraints = constraintsFromSizeHints(getVariables(trunkConstraints)); + trunkConstraints += sizeHintConstraints; + + // For minimum and maximum, use the path between the two layout sides as the + // objective function. + + // Retrieve that path + AnchorVertex *v = internalVertex(q, pickEdge(Qt::AnchorRight, orientation)); + GraphPath trunkPath = graphPaths[orientation].value(v); + + if (!trunkConstraints.isEmpty()) { +#if 0 + qDebug("Simplex used for trunk of %s", + orientation == Horizontal ? "Horizontal" : "Vertical"); +#endif + + // Solve min and max size hints for trunk + QPair<qreal, qreal> minMax = solveMinMax(trunkConstraints, trunkPath); + sizeHints[orientation][Qt::MinimumSize] = minMax.first; + sizeHints[orientation][Qt::MaximumSize] = minMax.second; + + // Solve for preferred. The objective function is calculated from the constraints + // and variables internally. + solvePreferred(trunkConstraints); + + // Propagate the new sizes down the simplified graph, ie. tell the + // group anchors to set their children anchors sizes. + + // ### we calculated variables already a few times, can't we reuse that? + QList<AnchorData *> trunkVariables = getVariables(trunkConstraints); + + for (int i = 0; i < trunkVariables.count(); ++i) + trunkVariables.at(i)->updateChildrenSizes(); + + // Calculate and set the preferred size for the layout from the edge sizes that + // were calculated above. + qreal pref(0.0); + foreach (const AnchorData *ad, trunkPath.positives) { + pref += ad->sizeAtPreferred; + } + foreach (const AnchorData *ad, trunkPath.negatives) { + pref -= ad->sizeAtPreferred; + } + sizeHints[orientation][Qt::PreferredSize] = pref; + } else { +#if 0 + qDebug("Simplex NOT used for trunk of %s", + orientation == Horizontal ? "Horizontal" : "Vertical"); +#endif + + // No Simplex is necessary because the path was simplified all the way to a single + // anchor. + Q_ASSERT(trunkPath.positives.count() == 1); + Q_ASSERT(trunkPath.negatives.count() == 0); + + AnchorData *ad = trunkPath.positives.toList()[0]; + ad->sizeAtMinimum = ad->minSize; + ad->sizeAtPreferred = ad->prefSize; + ad->sizeAtMaximum = ad->maxSize; + + // Propagate + ad->updateChildrenSizes(); + + sizeHints[orientation][Qt::MinimumSize] = ad->sizeAtMinimum; + sizeHints[orientation][Qt::PreferredSize] = ad->sizeAtPreferred; + sizeHints[orientation][Qt::MaximumSize] = ad->sizeAtMaximum; + } + + // Delete the constraints, we won't use them anymore. + qDeleteAll(sizeHintConstraints); + sizeHintConstraints.clear(); + + // For the other parts that not the trunk, solve only for the preferred size + // that is the size they will remain at, since they are not stretched by the + // layout. + + // Solve the other only for preferred, skip trunk + for (int i = 1; i < parts.count(); ++i) { + QList<QSimplexConstraint *> partConstraints = parts[i]; + QList<AnchorData *> partVariables = getVariables(partConstraints); + Q_ASSERT(!partVariables.isEmpty()); + + sizeHintConstraints = constraintsFromSizeHints(partVariables); + partConstraints += sizeHintConstraints; + solvePreferred(partConstraints); + + // Propagate size at preferred to other sizes. Semi-floats + // always will be in their sizeAtPreferred. + for (int j = 0; j < partVariables.count(); ++j) { + AnchorData *ad = partVariables[j]; + Q_ASSERT(ad); + ad->sizeAtMinimum = ad->sizeAtPreferred; + ad->sizeAtMaximum = ad->sizeAtPreferred; + ad->updateChildrenSizes(); + } + + // Delete the constraints, we won't use them anymore. + qDeleteAll(sizeHintConstraints); + sizeHintConstraints.clear(); + } + + // Clean up our data structures. They are not needed anymore since + // distribution uses just interpolation. + qDeleteAll(constraints[orientation]); + constraints[orientation].clear(); + graphPaths[orientation].clear(); // ### +} + +/*! + \internal + + For graph edges ("anchors") that represent items, this method updates their + intrinsic size restrictions, based on the item size hints. +*/ +void QGraphicsAnchorLayoutPrivate::setAnchorSizeHintsFromItems(Orientation orientation) +{ + Graph<AnchorVertex, AnchorData> &g = graph[orientation]; + QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections(); + + qreal spacing = effectiveSpacing(orientation); + + for (int i = 0; i < vertices.count(); ++i) { + AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second);; + Q_ASSERT(data->from && data->to); + data->refreshSizeHints(spacing); + } +} + +/*! + \internal + + This method walks the graph using a breadth-first search to find paths + between the root vertex and each vertex on the graph. The edges + directions in each path are considered and they are stored as a + positive edge (left-to-right) or negative edge (right-to-left). + + The list of paths is used later to generate a list of constraints. + */ +void QGraphicsAnchorLayoutPrivate::findPaths(Orientation orientation) +{ + QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue; + + QSet<AnchorData *> visited; + + AnchorVertex *root = graph[orientation].rootVertex(); + + graphPaths[orientation].insert(root, GraphPath()); + + foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) { + queue.enqueue(qMakePair(root, v)); + } + + while(!queue.isEmpty()) { + QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue(); + AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second); + + if (visited.contains(edge)) + continue; + + visited.insert(edge); + GraphPath current = graphPaths[orientation].value(pair.first); + + if (edge->from == pair.first) + current.positives.insert(edge); + else + current.negatives.insert(edge); + + graphPaths[orientation].insert(pair.second, current); + + foreach (AnchorVertex *v, + graph[orientation].adjacentVertices(pair.second)) { + queue.enqueue(qMakePair(pair.second, v)); + } + } +} + +/*! + \internal + + Each vertex on the graph that has more than one path to it + represents a contra int to the sizes of the items in these paths. + + This method walks the list of paths to each vertex, generate + the constraints and store them in a list so they can be used later + by the Simplex solver. +*/ +void QGraphicsAnchorLayoutPrivate::constraintsFromPaths(Orientation orientation) +{ + foreach (AnchorVertex *vertex, graphPaths[orientation].uniqueKeys()) + { + int valueCount = graphPaths[orientation].count(vertex); + if (valueCount == 1) + continue; + + QList<GraphPath> pathsToVertex = graphPaths[orientation].values(vertex); + for (int i = 1; i < valueCount; ++i) { + constraints[orientation] += \ + pathsToVertex[0].constraint(pathsToVertex[i]); + } + } +} + +/*! + \internal + + Create LP constraints for each anchor based on its minimum and maximum + sizes, as specified in its size hints +*/ +QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHints( + const QList<AnchorData *> &anchors) +{ + QList<QSimplexConstraint *> anchorConstraints; + for (int i = 0; i < anchors.size(); ++i) { + QSimplexConstraint *c = new QSimplexConstraint; + c->variables.insert(anchors[i], 1.0); + c->constant = anchors[i]->minSize; + c->ratio = QSimplexConstraint::MoreOrEqual; + anchorConstraints += c; + + c = new QSimplexConstraint; + c->variables.insert(anchors[i], 1.0); + c->constant = anchors[i]->maxSize; + c->ratio = QSimplexConstraint::LessOrEqual; + anchorConstraints += c; + } + + return anchorConstraints; +} + +/*! + \internal +*/ +QList< QList<QSimplexConstraint *> > +QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation) +{ + Q_Q(QGraphicsAnchorLayout); + + // Find layout vertices and edges for the current orientation. + AnchorVertex *layoutFirstVertex = \ + internalVertex(q, pickEdge(Qt::AnchorLeft, orientation)); + + AnchorVertex *layoutCentralVertex = \ + internalVertex(q, pickEdge(Qt::AnchorHorizontalCenter, orientation)); + + AnchorVertex *layoutLastVertex = \ + internalVertex(q, pickEdge(Qt::AnchorRight, orientation)); + + Q_ASSERT(layoutFirstVertex && layoutLastVertex); + + AnchorData *edgeL1 = NULL; + AnchorData *edgeL2 = NULL; + + // The layout may have a single anchor between Left and Right or two half anchors + // passing through the center + if (layoutCentralVertex) { + edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutCentralVertex); + edgeL2 = graph[orientation].edgeData(layoutCentralVertex, layoutLastVertex); + } else { + edgeL1 = graph[orientation].edgeData(layoutFirstVertex, layoutLastVertex); + } + + QLinkedList<QSimplexConstraint *> remainingConstraints; + for (int i = 0; i < constraints[orientation].count(); ++i) { + remainingConstraints += constraints[orientation][i]; + } + for (int i = 0; i < itemCenterConstraints[orientation].count(); ++i) { + remainingConstraints += itemCenterConstraints[orientation][i]; + } + + QList<QSimplexConstraint *> trunkConstraints; + QSet<QSimplexVariable *> trunkVariables; + + trunkVariables += edgeL1; + if (edgeL2) + trunkVariables += edgeL2; + + bool dirty; + do { + dirty = false; + + QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin(); + while (it != remainingConstraints.end()) { + QSimplexConstraint *c = *it; + bool match = false; + + // Check if this constraint have some overlap with current + // trunk variables... + foreach (QSimplexVariable *ad, trunkVariables) { + if (c->variables.contains(ad)) { + match = true; + break; + } + } + + // If so, we add it to trunk, and erase it from the + // remaining constraints. + if (match) { + trunkConstraints += c; + trunkVariables += QSet<QSimplexVariable *>::fromList(c->variables.keys()); + it = remainingConstraints.erase(it); + dirty = true; + } else { + // Note that we don't erase the constraint if it's not + // a match, since in a next iteration of a do-while we + // can pass on it again and it will be a match. + // + // For example: if trunk share a variable with + // remainingConstraints[1] and it shares with + // remainingConstraints[0], we need a second iteration + // of the do-while loop to match both. + ++it; + } + } + } while (dirty); + + QList< QList<QSimplexConstraint *> > result; + result += trunkConstraints; + + if (!remainingConstraints.isEmpty()) { + QList<QSimplexConstraint *> nonTrunkConstraints; + QLinkedList<QSimplexConstraint *>::iterator it = remainingConstraints.begin(); + while (it != remainingConstraints.end()) { + nonTrunkConstraints += *it; + ++it; + } + result += nonTrunkConstraints; + } + + return result; +} + +/*! + \internal + + Use the current vertices distance to calculate and set the geometry of + each item. +*/ +void QGraphicsAnchorLayoutPrivate::setItemsGeometries() +{ + AnchorVertex *firstH, *secondH, *firstV, *secondV; + + foreach (QGraphicsLayoutItem *item, items) { + firstH = internalVertex(item, Qt::AnchorLeft); + secondH = internalVertex(item, Qt::AnchorRight); + firstV = internalVertex(item, Qt::AnchorTop); + secondV = internalVertex(item, Qt::AnchorBottom); + + QPointF topLeft(firstH->distance, firstV->distance); + QPointF bottomRight(secondH->distance, secondV->distance); + + item->setGeometry(QRectF(topLeft, bottomRight)); + } +} + +/*! + \internal + + Calculate the position of each vertex based on the paths to each of + them as well as the current edges sizes. +*/ +void QGraphicsAnchorLayoutPrivate::calculateVertexPositions( + QGraphicsAnchorLayoutPrivate::Orientation orientation) +{ + Q_Q(QGraphicsAnchorLayout); + QQueue<QPair<AnchorVertex *, AnchorVertex *> > queue; + QSet<AnchorVertex *> visited; + + // Get root vertex + AnchorVertex *root = graph[orientation].rootVertex(); + + qreal widgetMargin; + qreal layoutMargin; + + // Initialize the first vertex + if (orientation == Horizontal) { + widgetMargin = q->geometry().x(); + q->getContentsMargins(&layoutMargin, 0, 0, 0); + } else { + // Root position is equal to the top margin + widgetMargin = q->geometry().y(); + q->getContentsMargins(0, &layoutMargin, 0, 0); + } + root->distance = widgetMargin + layoutMargin; + visited.insert(root); + + // Add initial edges to the queue + foreach (AnchorVertex *v, graph[orientation].adjacentVertices(root)) { + queue.enqueue(qMakePair(root, v)); + } + + // Do initial calculation required by "interpolateEdge()" + setupEdgesInterpolation(orientation); + + // Traverse the graph and calculate vertex positions, we need to + // visit all pairs since each of them could have a sequential + // anchor inside, which hides more vertices. + while (!queue.isEmpty()) { + QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue(); + AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second); + + // Both vertices were interpolated, and the anchor itself can't have other + // anchors inside (it's not a complex anchor). + if (edge->type == AnchorData::Normal && visited.contains(pair.second)) + continue; + + visited.insert(pair.second); + interpolateEdge(pair.first, edge, orientation); + + QList<AnchorVertex *> adjacents = graph[orientation].adjacentVertices(pair.second); + for (int i = 0; i < adjacents.count(); ++i) { + if (!visited.contains(adjacents.at(i))) + queue.enqueue(qMakePair(pair.second, adjacents.at(i))); + } + } +} + +/*! + \internal + + Calculate interpolation parameters based on current Layout Size. + Must once before calling "interpolateEdgeSize()" for each edge. +*/ +void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation( + Orientation orientation) +{ + Q_Q(QGraphicsAnchorLayout); + qreal lower, upper, current; + + if (orientation == Horizontal) { + current = q->contentsRect().width(); + } else { + current = q->contentsRect().height(); + } + + if (current < sizeHints[orientation][Qt::PreferredSize]) { + interpolationInterval[orientation] = MinToPreferred; + lower = sizeHints[orientation][Qt::MinimumSize]; + upper = sizeHints[orientation][Qt::PreferredSize]; + } else { + interpolationInterval[orientation] = PreferredToMax; + lower = sizeHints[orientation][Qt::PreferredSize]; + upper = sizeHints[orientation][Qt::MaximumSize]; + } + + if (upper == lower) { + interpolationProgress[orientation] = 0; + } else { + interpolationProgress[orientation] = (current - lower) / (upper - lower); + } +} + +/*! + \internal + + Calculate the current Edge size based on the current Layout size and the + size the edge is supposed to have when: + + - the layout is at its minimum size. + - the layout is at its preferred size. + - the layout is at its maximum size. + + These three key values are calculated in advance using linear + programming (more expensive) or the simplification algorithm, then + subsequential resizes of the parent layout require a simple + interpolation. + + If the edge is sequential or parallel, it's possible to have more + vertices to be initalized, so it calls specialized functions that + will recurse back to interpolateEdge(). + */ +void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, + AnchorData *edge, + Orientation orientation) +{ + qreal lower, upper; + + if (interpolationInterval[orientation] == MinToPreferred) { + lower = edge->sizeAtMinimum; + upper = edge->sizeAtPreferred; + } else { + lower = edge->sizeAtPreferred; + upper = edge->sizeAtMaximum; + } + + qreal edgeDistance = (interpolationProgress[orientation] * (upper - lower)) + lower; + + Q_ASSERT(edge->from == base || edge->to == base); + + if (edge->from == base) + edge->to->distance = base->distance + edgeDistance; + else + edge->from->distance = base->distance - edgeDistance; + + // Process child anchors + if (edge->type == AnchorData::Sequential) + interpolateSequentialEdges(edge->from, + static_cast<SequentialAnchorData *>(edge), + orientation); + else if (edge->type == AnchorData::Parallel) + interpolateParallelEdges(edge->from, + static_cast<ParallelAnchorData *>(edge), + orientation); +} + +void QGraphicsAnchorLayoutPrivate::interpolateParallelEdges( + AnchorVertex *base, ParallelAnchorData *data, Orientation orientation) +{ + // In parallels the boundary vertices are already calculate, we + // just need to look for sequential groups inside, because only + // them may have new vertices associated. + + // First edge + if (data->firstEdge->type == AnchorData::Sequential) + interpolateSequentialEdges(base, + static_cast<SequentialAnchorData *>(data->firstEdge), + orientation); + else if (data->firstEdge->type == AnchorData::Parallel) + interpolateParallelEdges(base, + static_cast<ParallelAnchorData *>(data->firstEdge), + orientation); + + // Second edge + if (data->secondEdge->type == AnchorData::Sequential) + interpolateSequentialEdges(base, + static_cast<SequentialAnchorData *>(data->secondEdge), + orientation); + else if (data->secondEdge->type == AnchorData::Parallel) + interpolateParallelEdges(base, + static_cast<ParallelAnchorData *>(data->secondEdge), + orientation); +} + +void QGraphicsAnchorLayoutPrivate::interpolateSequentialEdges( + AnchorVertex *base, SequentialAnchorData *data, Orientation orientation) +{ + AnchorVertex *prev = base; + + // ### I'm not sure whether this assumption is safe. If not, + // consider that m_edges.last() could be used instead (so + // at(0) would be the one to be treated specially). + Q_ASSERT(base == data->m_edges.at(0)->to || base == data->m_edges.at(0)->from); + + // Skip the last + for (int i = 0; i < data->m_edges.count() - 1; ++i) { + AnchorData *child = data->m_edges.at(i); + interpolateEdge(prev, child, orientation); + prev = child->to; + } + + // Treat the last specially, since we already calculated it's end + // vertex, so it's only interesting if it's a complex one + if (data->m_edges.last()->type != AnchorData::Normal) + interpolateEdge(prev, data->m_edges.last(), orientation); +} + +QPair<qreal, qreal> +QGraphicsAnchorLayoutPrivate::solveMinMax(QList<QSimplexConstraint *> constraints, + GraphPath path) +{ + QSimplex simplex; + simplex.setConstraints(constraints); + + // Obtain the objective constraint + QSimplexConstraint objective; + QSet<AnchorData *>::const_iterator iter; + for (iter = path.positives.constBegin(); iter != path.positives.constEnd(); ++iter) + objective.variables.insert(*iter, 1.0); + + for (iter = path.negatives.constBegin(); iter != path.negatives.constEnd(); ++iter) + objective.variables.insert(*iter, -1.0); + + simplex.setObjective(&objective); + + // Calculate minimum values + qreal min = simplex.solveMin(); + + // Save sizeAtMinimum results + QList<QSimplexVariable *> variables = simplex.constraintsVariables(); + for (int i = 0; i < variables.size(); ++i) { + AnchorData *ad = static_cast<AnchorData *>(variables[i]); + ad->sizeAtMinimum = ad->result; + } + + // Calculate maximum values + qreal max = simplex.solveMax(); + + // Save sizeAtMaximum results + for (int i = 0; i < variables.size(); ++i) { + AnchorData *ad = static_cast<AnchorData *>(variables[i]); + ad->sizeAtMaximum = ad->result; + } + + return qMakePair<qreal, qreal>(min, max); +} + +void QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> constraints) +{ + QList<AnchorData *> variables = getVariables(constraints); + QList<QSimplexConstraint *> preferredConstraints; + QList<QSimplexVariable *> preferredVariables; + QSimplexConstraint objective; + + // Fill the objective coefficients for this variable. In the + // end the objective function will be + // + // z = n * (A_shrink + B_shrink + ...) + (A_grower + B_grower + ...) + // + // where n is the number of variables that have + // slacks. Note that here we use the number of variables + // as coefficient, this is to mark the "shrinker slack + // variable" less likely to get value than the "grower + // slack variable". + + // This will fill the values for the structural constraints + // and we now fill the values for the slack constraints (one per variable), + // which have this form (the constant A_pref was set when creating the slacks): + // + // A + A_shrinker - A_grower = A_pref + // + for (int i = 0; i < variables.size(); ++i) { + AnchorData *ad = static_cast<AnchorData *>(variables[i]); + if (ad->skipInPreferred) + continue; + + QSimplexVariable *grower = new QSimplexVariable; + QSimplexVariable *shrinker = new QSimplexVariable; + QSimplexConstraint *c = new QSimplexConstraint; + c->variables.insert(ad, 1.0); + c->variables.insert(shrinker, 1.0); + c->variables.insert(grower, -1.0); + c->constant = ad->prefSize; + + preferredConstraints += c; + preferredVariables += grower; + preferredVariables += shrinker; + + objective.variables.insert(grower, 1.0); + objective.variables.insert(shrinker, variables.size()); + } + + + QSimplex *simplex = new QSimplex; + simplex->setConstraints(constraints + preferredConstraints); + simplex->setObjective(&objective); + + // Calculate minimum values + simplex->solveMin(); + + // Save sizeAtPreferred results + for (int i = 0; i < variables.size(); ++i) { + AnchorData *ad = static_cast<AnchorData *>(variables[i]); + ad->sizeAtPreferred = ad->result; + } + + // Make sure we delete the simplex solver -before- we delete the + // constraints used by it. + delete simplex; + + // Delete constraints and variables we created. + qDeleteAll(preferredConstraints); + qDeleteAll(preferredVariables); +} + +#ifdef QT_DEBUG +void QGraphicsAnchorLayoutPrivate::dumpGraph() +{ + QFile file(QString::fromAscii("anchorlayout.dot")); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) + qWarning("Could not write to %s", file.fileName().toLocal8Bit().constData()); + + QString str = QString::fromAscii("digraph anchorlayout {\nnode [shape=\"rect\"]\n%1}"); + QString dotContents = graph[0].serializeToDot(); + dotContents += graph[1].serializeToDot(); + file.write(str.arg(dotContents).toLocal8Bit()); + + file.close(); +} +#endif + +QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h new file mode 100644 index 0000000..15a1b44 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -0,0 +1,477 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGraphicsWidget> + +#include "qgraphicslayout_p.h" +#include "qgraphicsanchorlayout.h" +#include "qgraph_p.h" +#include "qsimplex_p.h" + +QT_BEGIN_NAMESPACE + +/* + The public QGraphicsAnchorLayout interface represents an anchorage point + as a pair of a <QGraphicsLayoutItem *> and a <Qt::AnchorPoint>. + + Internally though, it has a graph of anchorage points (vertices) and + anchors (edges), represented by the AnchorVertex and AnchorData structs + respectively. +*/ + +/*! + \internal + + Represents a vertex (anchorage point) in the internal graph +*/ +struct AnchorVertex { + AnchorVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge) + : m_item(item), m_edge(edge) {} + + AnchorVertex() + : m_item(0), m_edge(Qt::AnchorPoint(0)) {} + +#ifdef QT_DEBUG + inline QString toString() const; +#endif + QGraphicsLayoutItem *m_item; + Qt::AnchorPoint m_edge; + + // Current distance from this vertex to the layout edge (Left or Top) + // Value is calculated from the current anchors sizes. + qreal distance; +}; + +#ifdef QT_DEBUG +inline QString AnchorVertex::toString() const +{ + if (!this || !m_item) { + return QLatin1String("NULL"); + } + QString edge; + switch (m_edge) { + case Qt::AnchorLeft: + edge = QLatin1String("Left"); + break; + case Qt::AnchorHorizontalCenter: + edge = QLatin1String("HorizontalCenter"); + break; + case Qt::AnchorRight: + edge = QLatin1String("Right"); + break; + case Qt::AnchorTop: + edge = QLatin1String("Top"); + break; + case Qt::AnchorVerticalCenter: + edge = QLatin1String("VerticalCenter"); + break; + case Qt::AnchorBottom: + edge = QLatin1String("Bottom"); + break; + default: + edge = QLatin1String("None"); + break; + } + QString itemName; + if (m_item->isLayout()) { + itemName = QLatin1String("layout"); + } else { + if (QGraphicsItem *item = m_item->graphicsItem()) { + itemName = item->data(0).toString(); + } + } + edge.insert(0, QLatin1String("%1_")); + return edge.arg(itemName); +} +#endif + +/*! + \internal + + Represents an edge (anchor) in the internal graph. +*/ +struct AnchorData : public QSimplexVariable { + enum Type { + Normal = 0, + Sequential, + Parallel + }; + AnchorData(qreal minimumSize, qreal preferredSize, qreal maximumSize) + : QSimplexVariable(), from(0), to(0), + minSize(minimumSize), prefSize(preferredSize), + maxSize(maximumSize), sizeAtMinimum(preferredSize), + sizeAtPreferred(preferredSize), sizeAtMaximum(preferredSize), + skipInPreferred(0), type(Normal), hasSize(true), + isLayoutAnchor(false) {} + + AnchorData(qreal size) + : QSimplexVariable(), from(0), to(0), + minSize(size), prefSize(size), maxSize(size), + sizeAtMinimum(size), sizeAtPreferred(size), sizeAtMaximum(size), + skipInPreferred(0), type(Normal), hasSize(true), + isLayoutAnchor(false) {} + + AnchorData() + : QSimplexVariable(), from(0), to(0), + minSize(0), prefSize(0), maxSize(0), + sizeAtMinimum(0), sizeAtPreferred(0), sizeAtMaximum(0), + skipInPreferred(0), type(Normal), hasSize(false), + isLayoutAnchor(false) {} + + virtual void updateChildrenSizes() { }; + virtual void refreshSizeHints(qreal effectiveSpacing); + + virtual ~AnchorData() {} + +#ifdef QT_DEBUG + void dump(int indent = 2); + inline QString toString() const; + QString name; +#endif + + inline void setFixedSize(qreal size) + { + minSize = size; + prefSize = size; + maxSize = size; + sizeAtMinimum = size; + sizeAtPreferred = size; + sizeAtMaximum = size; + hasSize = true; + } + + inline void unsetSize() + { + hasSize = false; + } + + // Anchor is semantically directed + AnchorVertex *from; + AnchorVertex *to; + + // Size restrictions of this edge. For anchors internal to items, these + // values are derived from the respective item size hints. For anchors + // that were added by users, these values are equal to the specified anchor + // size. + qreal minSize; + qreal prefSize; + qreal maxSize; + + // These attributes define which sizes should that anchor be in when the + // layout is at its minimum, preferred or maximum sizes. Values are + // calculated by the Simplex solver based on the current layout setup. + qreal sizeAtMinimum; + qreal sizeAtPreferred; + qreal sizeAtMaximum; + + uint skipInPreferred : 1; + uint type : 2; // either Normal, Sequential or Parallel + uint hasSize : 1; // if false, get size from style. + uint isLayoutAnchor : 1; // if this anchor is connected to a layout 'edge' +protected: + AnchorData(Type type, qreal size = 0) + : QSimplexVariable(), from(0), to(0), + minSize(size), prefSize(size), + maxSize(size), sizeAtMinimum(size), + sizeAtPreferred(size), sizeAtMaximum(size), + skipInPreferred(0), type(type), hasSize(true), + isLayoutAnchor(false) {} +}; + +#ifdef QT_DEBUG +inline QString AnchorData::toString() const +{ + return QString::fromAscii("Anchor(%1)").arg(name); +} +#endif + +struct SequentialAnchorData : public AnchorData +{ + SequentialAnchorData() : AnchorData(AnchorData::Sequential) + { +#ifdef QT_DEBUG + name = QLatin1String("SequentialAnchorData"); +#endif + } + + virtual void updateChildrenSizes(); + virtual void refreshSizeHints(qreal effectiveSpacing); + + void setVertices(const QVector<AnchorVertex*> &vertices) + { + m_children = vertices; +#ifdef QT_DEBUG + name = QString::fromAscii("%1 -- %2").arg(vertices.first()->toString(), vertices.last()->toString()); +#endif + } + + QVector<AnchorVertex*> m_children; // list of vertices in the sequence + QVector<AnchorData*> m_edges; // keep the list of edges too. +}; + +struct ParallelAnchorData : public AnchorData +{ + ParallelAnchorData(AnchorData *first, AnchorData *second) + : AnchorData(AnchorData::Parallel), + firstEdge(first), secondEdge(second) + { + // ### Those asserts force that both child anchors have the same direction, + // but can't we simplify a pair of anchors in opposite directions? + Q_ASSERT(first->from == second->from); + Q_ASSERT(first->to == second->to); + from = first->from; + to = first->to; +#ifdef QT_DEBUG + name = QString::fromAscii("%1 | %2").arg(first->toString(), second->toString()); +#endif + } + + virtual void updateChildrenSizes(); + virtual void refreshSizeHints(qreal effectiveSpacing); + + AnchorData* firstEdge; + AnchorData* secondEdge; +}; + +/*! + \internal + + Representation of a valid path for a given vertex in the graph. + In this struct, "positives" is the set of anchors that have been + traversed in the forward direction, while "negatives" is the set + with the ones walked backwards. + + This paths are compared against each other to produce LP Constraints, + the exact order in which the anchors were traversed is not relevant. +*/ +class GraphPath +{ +public: + GraphPath() {}; + + QSimplexConstraint *constraint(const GraphPath &path) const; +#ifdef QT_DEBUG + QString toString() const; +#endif + QSet<AnchorData *> positives; + QSet<AnchorData *> negatives; +}; + + +/*! + \internal + + QGraphicsAnchorLayout private methods and attributes. +*/ +class QGraphicsAnchorLayoutPrivate : public QGraphicsLayoutPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsAnchorLayout) + +public: + // When the layout geometry is different from its Minimum, Preferred + // or Maximum values, interpolation is used to calculate the geometries + // of the items. + // + // Interval represents which interpolation interval are we operating in. + enum Interval { + MinToPreferred = 0, + PreferredToMax + }; + + // Several structures internal to the layout are duplicated to handle + // both Horizontal and Vertical restrictions. + // + // Orientation is used to reference the right structure in each context + enum Orientation { + Horizontal = 0, + Vertical, + NOrientations + }; + + QGraphicsAnchorLayoutPrivate(); + + static Qt::AnchorPoint oppositeEdge( + Qt::AnchorPoint edge); + + static Orientation edgeOrientation(Qt::AnchorPoint edge); + + static Qt::AnchorPoint pickEdge(Qt::AnchorPoint edge, Orientation orientation) + { + if (orientation == Vertical && int(edge) <= 2) + return (Qt::AnchorPoint)(edge + 3); + else if (orientation == Horizontal && int(edge) >= 3) { + return (Qt::AnchorPoint)(edge - 3); + } + return edge; + } + + // Init methods + void createLayoutEdges(); + void deleteLayoutEdges(); + void createItemEdges(QGraphicsLayoutItem *item); + void createCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge); + void removeCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge, bool substitute = true); + void removeCenterConstraints(QGraphicsLayoutItem *item, Orientation orientation); + + // helper function used by the 4 API functions + void anchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + qreal *spacing = 0); + + // Anchor Manipulation methods + void addAnchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + AnchorData *data); + + void removeAnchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge); + + bool setAnchorSize(const QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + const qreal *anchorSize); + + bool anchorSize(const QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + const QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + qreal *minSize = 0, + qreal *prefSize = 0, + qreal *maxSize = 0) const; + + void removeAnchors(QGraphicsLayoutItem *item); + + void removeVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); + + void correctEdgeDirection(QGraphicsLayoutItem *&firstItem, + Qt::AnchorPoint &firstEdge, + QGraphicsLayoutItem *&secondItem, + Qt::AnchorPoint &secondEdge); + // for getting the actual spacing (will query the style if the + // spacing is not explicitly set). + qreal effectiveSpacing(Orientation orientation) const; + + // Activation methods + void simplifyGraph(Orientation orientation); + bool simplifyGraphIteration(Orientation orientation); + void restoreSimplifiedGraph(Orientation orientation); + + void calculateGraphs(); + void calculateGraphs(Orientation orientation); + void setAnchorSizeHintsFromItems(Orientation orientation); + void findPaths(Orientation orientation); + void constraintsFromPaths(Orientation orientation); + QList<QSimplexConstraint *> constraintsFromSizeHints(const QList<AnchorData *> &anchors); + QList<QList<QSimplexConstraint *> > getGraphParts(Orientation orientation); + + inline AnchorVertex *internalVertex(const QPair<QGraphicsLayoutItem*, Qt::AnchorPoint> &itemEdge) const + { + return m_vertexList.value(itemEdge).first; + } + + inline AnchorVertex *internalVertex(const QGraphicsLayoutItem *item, Qt::AnchorPoint edge) const + { + return internalVertex(qMakePair(const_cast<QGraphicsLayoutItem *>(item), edge)); + } + + AnchorVertex *addInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); + void removeInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge); + + // Geometry interpolation methods + void setItemsGeometries(); + + void calculateVertexPositions(Orientation orientation); + void setupEdgesInterpolation(Orientation orientation); + void interpolateEdge(AnchorVertex *base, AnchorData *edge, Orientation orientation); + void interpolateSequentialEdges(AnchorVertex *base, SequentialAnchorData *edge, + Orientation orientation); + void interpolateParallelEdges(AnchorVertex *base, ParallelAnchorData *edge, + Orientation orientation); + + // Linear Programming solver methods + QPair<qreal, qreal> solveMinMax(QList<QSimplexConstraint *> constraints, + GraphPath path); + void solvePreferred(QList<QSimplexConstraint *> constraints); + +#ifdef QT_DEBUG + void dumpGraph(); +#endif + + + qreal spacings[NOrientations]; + // Size hints from simplex engine + qreal sizeHints[2][3]; + + // Items + QVector<QGraphicsLayoutItem *> items; + + // Mapping between high level anchorage points (Item, Edge) to low level + // ones (Graph Vertices) + + QHash<QPair<QGraphicsLayoutItem*, Qt::AnchorPoint>, QPair<AnchorVertex *, int> > m_vertexList; + + // Internal graph of anchorage points and anchors, for both orientations + Graph<AnchorVertex, AnchorData> graph[2]; + + // Graph paths and constraints, for both orientations + QMultiHash<AnchorVertex *, GraphPath> graphPaths[2]; + QList<QSimplexConstraint *> constraints[2]; + QList<QSimplexConstraint *> itemCenterConstraints[2]; + + // The interpolation interval and progress based on the current size + // as well as the key values (minimum, preferred and maximum) + Interval interpolationInterval[2]; + qreal interpolationProgress[2]; + + // ### + bool graphSimplified[2]; + + uint calculateGraphCacheDirty : 1; +}; + +QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 2b3d453..db24c77 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1011,7 +1011,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } // Resolve depth. - resolveDepth(parent ? parent->d_ptr->depth : -1); + invalidateDepthRecursively(); dirtySceneTransform = 1; // Restore the sub focus chain. @@ -4511,14 +4511,42 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore /*! \internal +*/ +int QGraphicsItemPrivate::depth() const +{ + if (itemDepth == -1) + const_cast<QGraphicsItemPrivate *>(this)->resolveDepth(); + + return itemDepth; +} - Resolves the stacking depth of this object and all its children. +/*! + \internal */ -void QGraphicsItemPrivate::resolveDepth(int parentDepth) +void QGraphicsItemPrivate::invalidateDepthRecursively() { - depth = parentDepth + 1; + if (itemDepth == -1) + return; + + itemDepth = -1; for (int i = 0; i < children.size(); ++i) - children.at(i)->d_ptr->resolveDepth(depth); + children.at(i)->d_ptr->invalidateDepthRecursively(); +} + +/*! + \internal + + Resolves the stacking depth of this object and all its ancestors. +*/ +void QGraphicsItemPrivate::resolveDepth() +{ + if (!parent) + itemDepth = 0; + else { + if (parent->d_ptr->itemDepth == -1) + parent->d_ptr->resolveDepth(); + itemDepth = parent->d_ptr->itemDepth + 1; + } } /*! @@ -5695,8 +5723,8 @@ QGraphicsItem *QGraphicsItem::commonAncestorItem(const QGraphicsItem *other) con return const_cast<QGraphicsItem *>(this); const QGraphicsItem *thisw = this; const QGraphicsItem *otherw = other; - int thisDepth = d_ptr->depth; - int otherDepth = other->d_ptr->depth; + int thisDepth = d_ptr->depth(); + int otherDepth = other->d_ptr->depth(); while (thisDepth > otherDepth) { thisw = thisw->d_ptr->parent; --thisDepth; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index cd5c595..5838fc0 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -127,7 +127,7 @@ public: graphicsEffect(0), index(-1), siblingIndex(-1), - depth(0), + itemDepth(-1), focusProxy(0), subFocusItem(0), imHints(Qt::ImhNone), @@ -215,7 +215,9 @@ public: void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; - void resolveDepth(int parentDepth); + int depth() const; + void invalidateDepthRecursively(); + void resolveDepth(); void addChild(QGraphicsItem *child); void removeChild(QGraphicsItem *child); void setParentItemHelper(QGraphicsItem *parent); @@ -428,7 +430,7 @@ public: QTransform sceneTransform; int index; int siblingIndex; - int depth; + int itemDepth; // Lazily calculated when calling depth(). QGraphicsItem *focusProxy; QList<QGraphicsItem **> focusProxyRefs; QGraphicsItem *subFocusItem; @@ -511,16 +513,17 @@ struct QGraphicsItemPrivate::TransformData return transform * *postmultiplyTransform; } - QTransform x(transform); + QMatrix4x4 x(transform); for (int i = 0; i < graphicsTransforms.size(); ++i) graphicsTransforms.at(i)->applyTo(&x); x.translate(xOrigin, yOrigin); - x.rotate(rotation, Qt::ZAxis); - x.scale(scale, scale); + x.rotate(rotation, 0, 0, 1); + x.scale(scale); x.translate(-xOrigin, -yOrigin); + QTransform t = x.toTransform(); // project the 3D matrix back to 2D. if (postmultiplyTransform) - x *= *postmultiplyTransform; - return x; + t *= *postmultiplyTransform; + return t; } }; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 1f5d106..fcd127a 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -419,8 +419,8 @@ bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGra // Find common ancestor, and each item's ancestor closest to the common // ancestor. - int item1Depth = d1->depth; - int item2Depth = d2->depth; + int item1Depth = d1->depth(); + int item2Depth = d2->depth(); const QGraphicsItem *p = item1; const QGraphicsItem *t1 = item1; while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp index 86f5b08..585e0f9 100644 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -63,10 +63,17 @@ independent transformation. The resulting operation is then combined into a single transform which is applied to QGraphicsItem. + Transformations are computed in true 3D space using QMatrix4x4. + When the transformation is applied to a QGraphicsItem, it will be + projected back to a 2D QTransform. When multiple QGraphicsTransform + objects are applied to a QGraphicsItem, all of the transformations + are computed in true 3D space, with the projection back to 2D + only occurring after the last QGraphicsTransform is applied. + If you want to create your own configurable transformation, you can create a subclass of QGraphicsTransform (or any or the existing subclasses), and reimplement the pure virtual applyTo() function, which takes a pointer to a - QTransform. Each operation you would like to apply should be exposed as + QMatrix4x4. Each operation you would like to apply should be exposed as properties (e.g., customTransform->setVerticalShear(2.5)). Inside you reimplementation of applyTo(), you can modify the provided transform respectively. @@ -136,28 +143,13 @@ QGraphicsTransform::QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *pa } /*! - Applies this transformation to an identity transform, and returns the - resulting transform. - - This is equivalent to passing an identity transform to applyTo(). - - \sa applyTo() -*/ -QTransform QGraphicsTransform::transform() const -{ - QTransform t; - applyTo(&t); - return t; -} - -/*! - \fn void QGraphicsTransform::applyTo(QTransform *transform) const + \fn void QGraphicsTransform::applyTo(QMatrix4x4 *matrix) const This pure virtual method has to be reimplemented in derived classes. - It applies this transformation to \a transform. + It applies this transformation to \a matrix. - \sa QGraphicsItem::transform() + \sa QGraphicsItem::transform(), QMatrix4x4::toTransform() */ /*! @@ -189,11 +181,12 @@ void QGraphicsTransform::update() relative to the parent as the rest of the item grows). By default the origin is QPointF(0, 0). - The two parameters xScale and yScale describe the scale factors to apply in - horizontal and vertical direction. They can take on any value, including 0 - (to collapse the item to a point) or negativate value. A negative xScale - value will mirror the item horizontally. A negative yScale value will flip - the item vertically. + The parameters xScale, yScale, and zScale describe the scale factors to + apply in horizontal, vertical, and depth directions. They can take on any + value, including 0 (to collapse the item to a point) or negative value. + A negative xScale value will mirror the item horizontally. A negative yScale + value will flip the item vertically. A negative zScale will flip the + item end for end. \sa QGraphicsTransform, QGraphicsItem::setScale(), QTransform::scale() */ @@ -202,10 +195,11 @@ class QGraphicsScalePrivate : public QGraphicsTransformPrivate { public: QGraphicsScalePrivate() - : xScale(1), yScale(1) {} - QPointF origin; + : xScale(1), yScale(1), zScale(1) {} + QVector3D origin; qreal xScale; qreal yScale; + qreal zScale; }; /*! @@ -225,21 +219,23 @@ QGraphicsScale::~QGraphicsScale() /*! \property QGraphicsScale::origin - \brief The QGraphicsScene class provides the origin of the scale. + \brief the origin of the scale in 3D space. All scaling will be done relative to this point (i.e., this point will stay fixed, relative to the parent, when the item is scaled). - \sa xScale, yScale + \sa xScale, yScale, zScale */ -QPointF QGraphicsScale::origin() const +QVector3D QGraphicsScale::origin() const { Q_D(const QGraphicsScale); return d->origin; } -void QGraphicsScale::setOrigin(const QPointF &point) +void QGraphicsScale::setOrigin(const QVector3D &point) { Q_D(QGraphicsScale); + if (d->origin == point) + return; d->origin = point; update(); emit originChanged(); @@ -254,7 +250,7 @@ void QGraphicsScale::setOrigin(const QPointF &point) provide a negative value, the item will be mirrored horizontally around its origin. - \sa yScale, origin + \sa yScale, zScale, origin */ qreal QGraphicsScale::xScale() const { @@ -280,7 +276,7 @@ void QGraphicsScale::setXScale(qreal scale) provide a negative value, the item will be flipped vertically around its origin. - \sa xScale, origin + \sa xScale, zScale, origin */ qreal QGraphicsScale::yScale() const { @@ -298,14 +294,40 @@ void QGraphicsScale::setYScale(qreal scale) } /*! + \property QGraphicsScale::zScale + \brief the depth scale factor. + + The scale factor can be any real number; the default value is 1.0. If you + set the factor to 0.0, the item will be collapsed to a single point. If you + provide a negative value, the item will be flipped end for end around its + origin. + + \sa xScale, yScale, origin +*/ +qreal QGraphicsScale::zScale() const +{ + Q_D(const QGraphicsScale); + return d->zScale; +} +void QGraphicsScale::setZScale(qreal scale) +{ + Q_D(QGraphicsScale); + if (d->zScale == scale) + return; + d->zScale = scale; + update(); + emit scaleChanged(); +} + +/*! \reimp */ -void QGraphicsScale::applyTo(QTransform *transform) const +void QGraphicsScale::applyTo(QMatrix4x4 *matrix) const { Q_D(const QGraphicsScale); - transform->translate(d->origin.x(), d->origin.y()); - transform->scale(d->xScale, d->yScale); - transform->translate(-d->origin.x(), -d->origin.y()); + matrix->translate(d->origin); + matrix->scale(d->xScale, d->yScale, d->zScale); + matrix->translate(-d->origin); } /*! @@ -319,10 +341,11 @@ void QGraphicsScale::applyTo(QTransform *transform) const /*! \fn QGraphicsScale::scaleChanged() - This signal is emitted whenever the xScale or yScale of the object - changes. + This signal is emitted whenever the xScale, yScale, or zScale + of the object changes. \sa QGraphicsScale::xScale, QGraphicsScale::yScale + \sa QGraphicsScale::zScale */ /*! @@ -359,20 +382,14 @@ void QGraphicsScale::applyTo(QTransform *transform) const \sa QGraphicsTransform, QGraphicsItem::setRotation(), QTransform::rotate() */ -#define VECTOR_FOR_AXIS_X QVector3D(1, 0, 0) -#define VECTOR_FOR_AXIS_Y QVector3D(0, 1, 0) -#define VECTOR_FOR_AXIS_Z QVector3D(0, 0, 1) - - class QGraphicsRotationPrivate : public QGraphicsTransformPrivate { public: QGraphicsRotationPrivate() - : angle(0), axis(VECTOR_FOR_AXIS_Z), simpleAxis(Qt::ZAxis) {} - QPointF origin; + : angle(0), axis(0, 0, 1) {} + QVector3D origin; qreal angle; QVector3D axis; - int simpleAxis; }; /*! @@ -392,21 +409,23 @@ QGraphicsRotation::~QGraphicsRotation() /*! \property QGraphicsRotation::origin - \brief the origin of the rotation. + \brief the origin of the rotation in 3D space. All rotations will be done relative to this point (i.e., this point will stay fixed, relative to the parent, when the item is rotated). \sa angle */ -QPointF QGraphicsRotation::origin() const +QVector3D QGraphicsRotation::origin() const { Q_D(const QGraphicsRotation); return d->origin; } -void QGraphicsRotation::setOrigin(const QPointF &point) +void QGraphicsRotation::setOrigin(const QVector3D &point) { Q_D(QGraphicsRotation); + if (d->origin == point) + return; d->origin = point; update(); emit originChanged(); @@ -448,11 +467,11 @@ void QGraphicsRotation::setAngle(qreal angle) */ /*! - \fn void QGraphicsRotation::angleChanged() + \fn void QGraphicsRotation::angleChanged() - This signal is emitted whenever the angle has changed. + This signal is emitted whenever the angle has changed. - \sa QGraphicsRotation::angle + \sa QGraphicsRotation::angle */ /*! @@ -475,18 +494,9 @@ QVector3D QGraphicsRotation::axis() const void QGraphicsRotation::setAxis(const QVector3D &axis) { Q_D(QGraphicsRotation); - if (d->axis == axis) + if (d->axis == axis) return; - d->axis = axis; - if (axis == VECTOR_FOR_AXIS_X) { - d->simpleAxis = Qt::XAxis; - } else if (axis == VECTOR_FOR_AXIS_Y) { - d->simpleAxis = Qt::YAxis; - } else if (axis == VECTOR_FOR_AXIS_Z) { - d->simpleAxis = Qt::ZAxis; - } else { - d->simpleAxis = -1; // no predefined axis - } + d->axis = axis; update(); emit axisChanged(); } @@ -495,90 +505,58 @@ void QGraphicsRotation::setAxis(const QVector3D &axis) \fn void QGraphicsRotation::setAxis(Qt::Axis axis) Convenience function to set the axis to \a axis. -*/ + Note: the Qt::YAxis rotation for QTransform is inverted from the + correct mathematical rotation in 3D space. The QGraphicsRotation + class implements a correct mathematical rotation. The following + two sequences of code will perform the same transformation: + + \code + QTransform t; + t.rotate(45, Qt::YAxis); + + QGraphicsRotation r; + r.setAxis(Qt::YAxis); + r.setAngle(-45); + \endcode +*/ void QGraphicsRotation::setAxis(Qt::Axis axis) { switch (axis) { case Qt::XAxis: - setAxis(VECTOR_FOR_AXIS_X); + setAxis(QVector3D(1, 0, 0)); break; case Qt::YAxis: - setAxis(VECTOR_FOR_AXIS_Y); + setAxis(QVector3D(0, 1, 0)); break; case Qt::ZAxis: - setAxis(VECTOR_FOR_AXIS_Z); + setAxis(QVector3D(0, 0, 1)); break; } } - -const qreal deg2rad = qreal(0.017453292519943295769); // pi/180 -static const qreal inv_dist_to_plane = 1. / 1024.; - /*! \reimp */ -void QGraphicsRotation::applyTo(QTransform *t) const +void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const { Q_D(const QGraphicsRotation); - qreal a = d->angle; - - if (a == 0.) - return; - - if (d->simpleAxis != -1) { - //that's an optimization for simple axis - t->translate(d->origin.x(), d->origin.y()); - t->rotate(a, Qt::Axis(d->simpleAxis)); - t->translate(-d->origin.x(), -d->origin.y()); - return; - } - - qreal x = d->axis.x(); - qreal y = d->axis.y(); - qreal z = d->axis.z(); - - if (x == 0. && y == 0 && z == 0) + if (d->angle == 0. || d->axis.isNull()) return; - qreal c, s; - if (a == 90. || a == -270.) { - s = 1.; - c = 0.; - } else if (a == 270. || a == -90.) { - s = -1.; - c = 0.; - } else if (a == 180.) { - s = 0.; - c = -1.; - } else { - qreal b = deg2rad*a; - s = qSin(b); - c = qCos(b); - } - - qreal len = x * x + y * y + z * z; - if (len != 1.) { - len = 1. / qSqrt(len); - x *= len; - y *= len; - z *= len; - } - - t->translate(d->origin.x(), d->origin.y()); - *t = QTransform(x*x*(1-c)+c, x*y*(1-c)+z*s, x*z*(1-c)-y*s*inv_dist_to_plane, - y*x*(1-c)-z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane, - 0, 0, 1) * *t; - t->translate(-d->origin.x(), -d->origin.y()); + matrix->translate(d->origin); + matrix->rotate(d->angle, d->axis.x(), d->axis.y(), d->axis.z()); + matrix->translate(-d->origin); } /*! \fn void QGraphicsRotation::axisChanged() This signal is emitted whenever the axis of the object changes. + + \sa QGraphicsRotation::axis */ #include "moc_qgraphicstransform.cpp" diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h index 8ccc258..d6d5b79 100644 --- a/src/gui/graphicsview/qgraphicstransform.h +++ b/src/gui/graphicsview/qgraphicstransform.h @@ -43,8 +43,9 @@ #define QGRAPHICSTRANSFORM_H #include <QtCore/QObject> -#include <QtGui/QTransform> #include <QtGui/QVector3D> +#include <QtGui/QTransform> +#include <QtGui/QMatrix4x4> QT_BEGIN_HEADER @@ -62,8 +63,7 @@ public: QGraphicsTransform(QObject *parent = 0); ~QGraphicsTransform(); - QTransform transform() const; - virtual void applyTo(QTransform *transform) const = 0; + virtual void applyTo(QMatrix4x4 *matrix) const = 0; protected Q_SLOTS: void update(); @@ -83,15 +83,16 @@ class Q_GUI_EXPORT QGraphicsScale : public QGraphicsTransform { Q_OBJECT - Q_PROPERTY(QPointF origin READ origin WRITE setOrigin NOTIFY originChanged) + Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged) Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY scaleChanged) Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY scaleChanged) + Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY scaleChanged) public: QGraphicsScale(QObject *parent = 0); ~QGraphicsScale(); - QPointF origin() const; - void setOrigin(const QPointF &point); + QVector3D origin() const; + void setOrigin(const QVector3D &point); qreal xScale() const; void setXScale(qreal); @@ -99,7 +100,10 @@ public: qreal yScale() const; void setYScale(qreal); - void applyTo(QTransform *transform) const; + qreal zScale() const; + void setZScale(qreal); + + void applyTo(QMatrix4x4 *matrix) const; Q_SIGNALS: void originChanged(); @@ -115,15 +119,15 @@ class Q_GUI_EXPORT QGraphicsRotation : public QGraphicsTransform { Q_OBJECT - Q_PROPERTY(QPointF origin READ origin WRITE setOrigin NOTIFY originChanged) + Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged) Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged) Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged) public: QGraphicsRotation(QObject *parent = 0); ~QGraphicsRotation(); - QPointF origin() const; - void setOrigin(const QPointF &point); + QVector3D origin() const; + void setOrigin(const QVector3D &point); qreal angle() const; void setAngle(qreal); @@ -132,7 +136,7 @@ public: void setAxis(const QVector3D &axis); void setAxis(Qt::Axis axis); - void applyTo(QTransform *transform) const; + void applyTo(QMatrix4x4 *matrix) const; Q_SIGNALS: void originChanged(); diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp new file mode 100644 index 0000000..7fa5ab0 --- /dev/null +++ b/src/gui/graphicsview/qsimplex_p.cpp @@ -0,0 +1,371 @@ +#include "qsimplex_p.h" + +#include <QtCore/qset.h> +#include <QtCore/qdebug.h> + +#include <stdlib.h> + +QT_BEGIN_NAMESPACE + +QSimplex::QSimplex() : objective(0), rows(0), columns(0), firstArtificial(0), matrix(0) +{ +} + +QSimplex::~QSimplex() +{ + clearDataStructures(); +} + +void QSimplex::clearDataStructures() +{ + if (matrix == 0) + return; + + // Matrix + rows = 0; + columns = 0; + firstArtificial = 0; + free(matrix); + matrix = 0; + + // Constraints + for (int i = 0; i < constraints.size(); ++i) { + delete constraints[i]->helper.first; + constraints[i]->helper.first = 0; + constraints[i]->helper.second = 0.0; + delete constraints[i]->artificial; + constraints[i]->artificial = 0; + } + constraints.clear(); + + // Other + variables.clear(); + objective = 0; +} + +void QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) +{ + clearDataStructures(); + + if (newConstraints.isEmpty()) + return; + constraints = newConstraints; + + // Set Variables direct mapping + QSet<QSimplexVariable *> variablesSet; + for (int i = 0; i < constraints.size(); ++i) + variablesSet += \ + QSet<QSimplexVariable *>::fromList(constraints[i]->variables.keys()); + variables = variablesSet.toList(); + + // Set Variables reverse mapping + for (int i = 0; i < variables.size(); ++i) { + // The variable "0" goes at the column "1", etc... + variables[i]->index = i + 1; + } + + // Normalize Constraints + int variableIndex = variables.size(); + QList <QSimplexVariable *> artificialList; + + for (int i = 0; i < constraints.size(); ++i) { + QSimplexVariable *slack; + QSimplexVariable *surplus; + QSimplexVariable *artificial; + + Q_ASSERT(constraints[i]->helper.first == 0); + Q_ASSERT(constraints[i]->artificial == 0); + + switch(constraints[i]->ratio) { + case QSimplexConstraint::LessOrEqual: + slack = new QSimplexVariable; + slack->index = ++variableIndex; + constraints[i]->helper.first = slack; + constraints[i]->helper.second = 1.0; + break; + case QSimplexConstraint::MoreOrEqual: + surplus = new QSimplexVariable; + surplus->index = ++variableIndex; + constraints[i]->helper.first = surplus; + constraints[i]->helper.second = -1.0; + // fall through + case QSimplexConstraint::Equal: + artificial = new QSimplexVariable; + constraints[i]->artificial = artificial; + artificialList += constraints[i]->artificial; + break; + } + } + + firstArtificial = variableIndex + 1; + for (int i = 0; i < artificialList.size(); ++i) + artificialList[i]->index = ++variableIndex; + artificialList.clear(); + + // Matrix + + // One for each variable plus the Basic and BFS columns (first and last) + columns = variableIndex + 2; + // One for each constraint plus the objective function + rows = constraints.size() + 1; + + matrix = (qreal *)malloc(sizeof(qreal) * columns * rows); + if (!matrix) { + qWarning() << "QSimplex: Unable to allocate memory!"; + return; + } + for (int i = columns * rows - 1; i >= 0; --i) + matrix[i] = 0.0; + + // Fill Matrix + for (int i = 1; i <= constraints.size(); ++i) { + QSimplexConstraint *c = constraints[i - 1]; + + if (c->artificial) { + // Will use artificial basic variable + setValueAt(i, 0, c->artificial->index); + setValueAt(i, c->artificial->index, 1.0); + + if (c->helper.second != 0.0) { + // Surplus variable + setValueAt(i, c->helper.first->index, c->helper.second); + } + } else { + // Slack is used as the basic variable + Q_ASSERT(c->helper.second == 1.0); + setValueAt(i, 0, c->helper.first->index); + setValueAt(i, c->helper.first->index, 1.0); + } + + QHash<QSimplexVariable *, qreal>::const_iterator iter; + for (iter = c->variables.constBegin(); + iter != c->variables.constEnd(); + ++iter) { + setValueAt(i, iter.key()->index, iter.value()); + } + + setValueAt(i, columns - 1, c->constant); + } + + // Set temporary objective: -1 * sum_of_artificial_vars + for (int j = firstArtificial; j < columns - 1; ++j) + setValueAt(0, j, 1.0); + + // Maximize our objective (artificial vars go to zero) + solveMaxHelper(); + + if (valueAt(0, columns - 1) != 0.0) { + qWarning() << "QSimplex: No feasible solution!"; + clearDataStructures(); + return; + } + + // Remove artificial variables + clearColumns(firstArtificial, columns - 2); +} + +void QSimplex::solveMaxHelper() +{ + reducedRowEchelon(); + while (iterate()) ; +} + +void QSimplex::setObjective(QSimplexConstraint *newObjective) +{ + objective = newObjective; +} + +void QSimplex::clearRow(int rowIndex) +{ + qreal *item = matrix + rowIndex * columns; + for (int i = 0; i < columns; ++i) + item[i] = 0.0; +} + +void QSimplex::clearColumns(int first, int last) +{ + for (int i = 0; i < rows; ++i) { + qreal *row = matrix + i * columns; + for (int j = first; j <= last; ++j) + row[j] = 0.0; + } +} + +void QSimplex::dumpMatrix() +{ + printf("---- Simplex Matrix ----\n"); + + printf(" "); + for (int j = 0; j < columns; ++j) + printf(" <% 2d >", j); + printf("\n"); + + for (int i = 0; i < rows; ++i) { + printf("Row %2d:", i); + + qreal *row = matrix + i * columns; + for (int j = 0; j < columns; ++j) { + printf(" % 2.2f", row[j]); + } + printf("\n"); + } + printf("------------------------\n\n"); +} + +void QSimplex::combineRows(int toIndex, int fromIndex, qreal factor) +{ + if (!factor) + return; + + qreal *from = matrix + fromIndex * columns; + qreal *to = matrix + toIndex * columns; + + for (int j = 1; j < columns; ++j) { + qreal value = from[j]; + + // skip to[j] = to[j] + factor*0.0 + if (value == 0.0) + continue; + + to[j] += factor * value; + + // ### Avoid Numerical errors + if (qAbs(to[j]) < 0.0000000001) + to[j] = 0.0; + } +} + +int QSimplex::findPivotColumn() +{ + qreal min = 0; + int minIndex = -1; + + for (int j = 0; j < columns-1; ++j) { + if (valueAt(0, j) < min) { + min = valueAt(0, j); + minIndex = j; + } + } + + return minIndex; +} + +int QSimplex::pivotRowForColumn(int column) +{ + qreal min = 999999999999.0; // ### + int minIndex = -1; + + for (int i = 1; i < rows; ++i) { + qreal divisor = valueAt(i, column); + if (divisor <= 0) + continue; + + qreal quotient = valueAt(i, columns - 1) / divisor; + if (quotient < min) { + min = quotient; + minIndex = i; + } + } + + return minIndex; +} + +void QSimplex::reducedRowEchelon() +{ + for (int i = 1; i < rows; ++i) { + int factorInObjectiveRow = valueAt(i, 0); + combineRows(0, i, -1 * valueAt(0, factorInObjectiveRow)); + } +} + +bool QSimplex::iterate() +{ + // Find Pivot column + int pivotColumn = findPivotColumn(); + if (pivotColumn == -1) + return false; + + // Find Pivot row for column + int pivotRow = pivotRowForColumn(pivotColumn); + if (pivotRow == -1) { + qWarning() << "QSimplex: Unbounded problem!"; + return false; + } + + // Normalize Pivot Row + qreal pivot = valueAt(pivotRow, pivotColumn); + if (pivot != 1.0) + combineRows(pivotRow, pivotRow, (1.0 - pivot) / pivot); + + // Update other rows + for (int row=0; row < rows; ++row) { + if (row == pivotRow) + continue; + + combineRows(row, pivotRow, -1 * valueAt(row, pivotColumn)); + } + + // Update first column + setValueAt(pivotRow, 0, pivotColumn); + + // dumpMatrix(); + // printf("------------ end of iteration --------------\n"); + return true; +} + +/*! + \internal + + Both solveMin and solveMax are interfaces to this method. + + The enum solverFactor admits 2 values: Minimum (-1) and Maximum (+1). + */ +qreal QSimplex::solver(solverFactor factor) +{ + // Remove old objective + clearRow(0); + + // Set new objective + QHash<QSimplexVariable *, qreal>::const_iterator iter; + for (iter = objective->variables.constBegin(); + iter != objective->variables.constEnd(); + ++iter) { + setValueAt(0, iter.key()->index, -1 * factor * iter.value()); + } + + solveMaxHelper(); + collectResults(); + + return factor * valueAt(0, columns - 1); +} + +qreal QSimplex::solveMin() +{ + return solver(Minimum); +} + +qreal QSimplex::solveMax() +{ + return solver(Maximum); +} + +void QSimplex::collectResults() +{ + // All variables are zero unless overridden below. + + // ### Is this really needed? Is there any chance that an + // important variable remains as non-basic at the end of simplex? + for (int i = 0; i < variables.size(); ++i) + variables[i]->result = 0; + + // Basic variables + // Update the variable indicated in the first column with the value + // in the last column. + for (int i = 1; i < rows; ++i) { + int index = valueAt(i, 0) - 1; + if (index < variables.size()) + variables[index]->result = valueAt(i, columns - 1); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qsimplex_p.h b/src/gui/graphicsview/qsimplex_p.h new file mode 100644 index 0000000..e3629df --- /dev/null +++ b/src/gui/graphicsview/qsimplex_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef QSIMPLEX_P_H +#define QSIMPLEX_P_H + +#include <QtCore/qhash.h> +#include <QtCore/qpair.h> + +QT_BEGIN_NAMESPACE + +struct QSimplexVariable +{ + QSimplexVariable() : result(0), index(0) {}; + + qreal result; + uint index; +}; + + +/*! + \internal + + Representation of a LP constraint like: + + (c1 * X1) + (c2 * X2) + ... = K + or <= K + or >= K + + Where (ci, Xi) are the pairs in "variables" and K the real "constant". +*/ +struct QSimplexConstraint +{ + QSimplexConstraint() : constant(0), ratio(Equal), artificial(0) {}; + + enum Ratio { + LessOrEqual = 0, + Equal, + MoreOrEqual + }; + + QHash<QSimplexVariable *, qreal> variables; + qreal constant; + Ratio ratio; + + QPair<QSimplexVariable *, qreal> helper; + QSimplexVariable * artificial; +}; + + +class QSimplex +{ +public: + QSimplex(); + virtual ~QSimplex(); + + qreal solveMin(); + qreal solveMax(); + QList<QSimplexVariable *> constraintsVariables(); + + void setConstraints(const QList<QSimplexConstraint *> constraints); + void setObjective(QSimplexConstraint *objective); + + void dumpMatrix(); + +private: + // Matrix handling + qreal valueAt(int row, int column); + void setValueAt(int row, int column, qreal value); + void clearRow(int rowIndex); + void clearColumns(int first, int last); + void combineRows(int toIndex, int fromIndex, qreal factor); + + // Simplex + int findPivotColumn(); + int pivotRowForColumn(int column); + void reducedRowEchelon(); + bool iterate(); + + // Helpers + void clearDataStructures(); + void solveMaxHelper(); + enum solverFactor { Minimum = -1, Maximum = 1 }; + qreal solver(solverFactor factor); + void collectResults(); + + QList<QSimplexConstraint *> constraints; + QList<QSimplexVariable *> variables; + QSimplexConstraint *objective; + + int rows; + int columns; + int firstArtificial; + + qreal *matrix; +}; + +inline QList<QSimplexVariable *> QSimplex::constraintsVariables() +{ + return variables; +} + +inline qreal QSimplex::valueAt(int rowIndex, int columnIndex) +{ + return matrix[rowIndex * columns + columnIndex]; +} + +inline void QSimplex::setValueAt(int rowIndex, int columnIndex, qreal value) +{ + matrix[rowIndex * columns + columnIndex] = value; +} + +QT_END_NAMESPACE + +#endif // QSIMPLEX_P_H diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index ccf8457..19701b4 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -81,14 +81,14 @@ static void swapPixel01(QImage *image) // 1-bpp: swap 0 and 1 pixels const int BMP_FILEHDR_SIZE = 14; // size of BMP_FILEHDR data -QDataStream &operator>>(QDataStream &s, BMP_FILEHDR &bf) +static QDataStream &operator>>(QDataStream &s, BMP_FILEHDR &bf) { // read file header s.readRawData(bf.bfType, 2); s >> bf.bfSize >> bf.bfReserved1 >> bf.bfReserved2 >> bf.bfOffBits; return s; } -QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf) +static QDataStream &operator<<(QDataStream &s, const BMP_FILEHDR &bf) { // write file header s.writeRawData(bf.bfType, 2); s << bf.bfSize << bf.bfReserved1 << bf.bfReserved2 << bf.bfOffBits; @@ -106,7 +106,7 @@ const int BMP_RLE4 = 2; // run-length encoded, 4 const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields -QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi) +static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi) { s >> bi.biSize; if (bi.biSize == BMP_WIN || bi.biSize == BMP_OS2) { @@ -128,7 +128,7 @@ QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi) return s; } -QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi) +static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi) { s << bi.biSize; s << bi.biWidth << bi.biHeight; diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h index b2944ef..5d5c211 100644 --- a/src/gui/image/qiconloader_p.h +++ b/src/gui/image/qiconloader_p.h @@ -85,6 +85,7 @@ struct QIconDirInfo class QIconLoaderEngineEntry { public: + virtual ~QIconLoaderEngineEntry() {} virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) = 0; diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 9eb71b7..d79a378 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -3378,11 +3378,7 @@ QPoint QAbstractItemView::dirtyRegionOffset() const */ void QAbstractItemView::startAutoScroll() { - Q_D(QAbstractItemView); - // ### it would be nice to make this into a style hint one day - int scrollInterval = (verticalScrollMode() == QAbstractItemView::ScrollPerItem) ? 150 : 50; - d->autoScrollTimer.start(scrollInterval, this); - d->autoScrollCount = 0; + d_func()->startAutoScroll(); } /*! @@ -3390,9 +3386,7 @@ void QAbstractItemView::startAutoScroll() */ void QAbstractItemView::stopAutoScroll() { - Q_D(QAbstractItemView); - d->autoScrollTimer.stop(); - d->autoScrollCount = 0; + d_func()->stopAutoScroll(); } /*! diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 2ba027d..e7991d2 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -126,6 +126,15 @@ public: void doDelayedItemsLayout(int delay = 0); void interruptDelayedItemsLayout() const; + void startAutoScroll() + { // ### it would be nice to make this into a style hint one day + int scrollInterval = (verticalScrollMode == QAbstractItemView::ScrollPerItem) ? 150 : 50; + autoScrollTimer.start(scrollInterval, q_func()); + autoScrollCount = 0; + } + void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;} + + bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); bool droppingOnItself(QDropEvent *event, const QModelIndex &index); diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index cc9d643..3e9db3b 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -458,15 +458,13 @@ QSize QListView::gridSize() const void QListView::setViewMode(ViewMode mode) { Q_D(QListView); - if (d->viewMode == mode) + if (d->commonListView && d->viewMode == mode) return; d->viewMode = mode; + delete d->commonListView; if (mode == ListMode) { - delete d->dynamicListView; - d->dynamicListView = 0; - if (!d->staticListView) - d->staticListView = new QStaticListViewBase(this, d); + d->commonListView = new QListModeViewBase(this, d); if (!(d->modeProperties & QListViewPrivate::Wrap)) d->setWrapping(false); if (!(d->modeProperties & QListViewPrivate::Spacing)) @@ -482,10 +480,7 @@ void QListView::setViewMode(ViewMode mode) if (!(d->modeProperties & QListViewPrivate::SelectionRectVisible)) d->showElasticBand = false; } else { - delete d->staticListView; - d->staticListView = 0; - if (!d->dynamicListView) - d->dynamicListView = new QDynamicListViewBase(this, d); + d->commonListView = new QIconModeViewBase(this, d); if (!(d->modeProperties & QListViewPrivate::Wrap)) d->setWrapping(true); if (!(d->modeProperties & QListViewPrivate::Spacing)) @@ -549,24 +544,12 @@ void QListView::setRowHidden(int row, bool hide) { Q_D(QListView); const bool hidden = d->isHidden(row); - if (d->viewMode == ListMode) { - if (hide && !hidden) - d->hiddenRows.append(d->model->index(row, 0)); - else if (!hide && hidden) - d->hiddenRows.remove(d->hiddenRows.indexOf(d->model->index(row, 0))); - d->doDelayedItemsLayout(); - } else { - if (hide && !hidden) { - d->dynamicListView->removeItem(row); - d->hiddenRows.append(d->model->index(row, 0)); - } else if (!hide && hidden) { - d->hiddenRows.remove(d->hiddenRows.indexOf(d->model->index(row, 0))); - d->dynamicListView->insertItem(row); - } - if (d->resizeMode == Adjust) - d->doDelayedItemsLayout(); - d->viewport->update(); - } + if (hide && !hidden) + d->commonListView->appendHiddenRow(row); + else if (!hide && hidden) + d->commonListView->removeHiddenRow(row); + d->doDelayedItemsLayout(); + d->viewport->update(); } /*! @@ -575,7 +558,7 @@ void QListView::setRowHidden(int row, bool hide) QRect QListView::visualRect(const QModelIndex &index) const { Q_D(const QListView); - return d->mapToViewport(rectForIndex(index), d->viewMode == QListView::ListMode); + return d->mapToViewport(rectForIndex(index)); } /*! @@ -612,69 +595,17 @@ int QListViewPrivate::horizontalScrollToValue(const QModelIndex &index, const QR const bool rightOf = q->isRightToLeft() ? rect.right() > area.right() : (rect.right() > area.right()) && (rect.left() > area.left()); - int horizontalValue = hbar->value(); - - // ScrollPerItem - if (q->horizontalScrollMode() == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) { - const QListViewItem item = indexToListViewItem(index); - const QRect rect = q->visualRect(index); - horizontalValue = staticListView->horizontalPerItemValue(itemIndex(item), - horizontalValue, area.width(), - leftOf, rightOf, isWrapping(), hint, rect.width()); - } else { // ScrollPerPixel - if (q->isRightToLeft()) { - if (hint == QListView::PositionAtCenter) { - horizontalValue += ((area.width() - rect.width()) / 2) - rect.left(); - } else { - if (leftOf) - horizontalValue -= rect.left(); - else if (rightOf) - horizontalValue += qMin(rect.left(), area.width() - rect.right()); - } - } else { - if (hint == QListView::PositionAtCenter) { - horizontalValue += rect.left() - ((area.width()- rect.width()) / 2); - } else { - if (leftOf) - horizontalValue += rect.left(); - else if (rightOf) - horizontalValue += qMin(rect.left(), rect.right() - area.width()); - } - } - } - return horizontalValue; + return commonListView->horizontalScrollToValue(q->visualIndex(index), hint, leftOf, rightOf, area, rect); } int QListViewPrivate::verticalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const { Q_Q(const QListView); - const QRect area = viewport->rect(); const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top()); const bool below = (hint == QListView::EnsureVisible && rect.bottom() > area.bottom()); - - int verticalValue = vbar->value(); - - // ScrollPerItem - if (verticalScrollMode == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) { - const QListViewItem item = indexToListViewItem(index); - const QRect rect = q->visualRect(index); - verticalValue = staticListView->verticalPerItemValue(itemIndex(item), - verticalValue, area.height(), - above, below, isWrapping(), hint, rect.height()); - - } else { // ScrollPerPixel - QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing()); - if (hint == QListView::PositionAtTop || above) - verticalValue += adjusted.top(); - else if (hint == QListView::PositionAtBottom || below) - verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1); - else if (hint == QListView::PositionAtCenter) - verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2); - } - - return verticalValue; + return commonListView->verticalScrollToValue(q->visualIndex(index), hint, above, below, area, rect); } void QListViewPrivate::selectAll(QItemSelectionModel::SelectionFlags command) @@ -766,23 +697,12 @@ void QListView::setRootIndex(const QModelIndex &index) Scroll the view contents by \a dx and \a dy. */ + void QListView::scrollContentsBy(int dx, int dy) { Q_D(QListView); - d->delayedAutoScroll.stop(); // auto scroll was canceled by the user scrolling - - if (d->viewMode == ListMode) - d->staticListView->scrollContentsBy(dx, dy); - else if (state() == DragSelectingState) - d->scrollElasticBandBy(isRightToLeft() ? -dx : dx, dy); - - d->scrollContentsBy(isRightToLeft() ? -dx : dx, dy); - - // update the dragged items - if (d->viewMode == IconMode) // ### move to dynamic class - if (!d->dynamicListView->draggedItems.isEmpty()) - d->viewport->update(d->dynamicListView->draggedItemsRect().translated(dx, dy)); + d->commonListView->scrollContentsBy(dx, dy, d->state == QListView::DragSelectingState); } /*! @@ -811,9 +731,7 @@ QSize QListView::contentsSize() const */ void QListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - Q_D(QListView); - if (d->viewMode == IconMode) - d->dynamicListView->dataChanged(topLeft, bottomRight); + d_func()->commonListView->dataChanged(topLeft, bottomRight); QAbstractItemView::dataChanged(topLeft, bottomRight); } @@ -864,7 +782,7 @@ void QListView::mouseMoveEvent(QMouseEvent *e) && d->selectionMode != NoSelection) { QRect rect(d->pressedPosition, e->pos() + QPoint(horizontalOffset(), verticalOffset())); rect = rect.normalized(); - d->viewport->update(d->mapToViewport(rect.united(d->elasticBand), d->viewMode == QListView::ListMode)); + d->viewport->update(d->mapToViewport(rect.united(d->elasticBand))); d->elasticBand = rect; } } @@ -878,7 +796,7 @@ void QListView::mouseReleaseEvent(QMouseEvent *e) QAbstractItemView::mouseReleaseEvent(e); // #### move this implementation into a dynamic class if (d->showElasticBand && d->elasticBand.isValid()) { - d->viewport->update(d->mapToViewport(d->elasticBand, d->viewMode == QListView::ListMode)); + d->viewport->update(d->mapToViewport(d->elasticBand)); d->elasticBand = QRect(); } } @@ -935,69 +853,27 @@ void QListView::resizeEvent(QResizeEvent *e) */ void QListView::dragMoveEvent(QDragMoveEvent *e) { - // ### move implementation to dynamic - Q_D(QListView); - if (e->source() == this && d->viewMode == IconMode) { - // the ignore by default - e->ignore(); - if (d->canDecode(e)) { - // get old dragged items rect - QRect itemsRect = d->dynamicListView->itemsRect(d->dynamicListView->draggedItems); - d->viewport->update(itemsRect.translated(d->dynamicListView->draggedItemsDelta())); - // update position - d->dynamicListView->draggedItemsPos = e->pos(); - // get new items rect - d->viewport->update(itemsRect.translated(d->dynamicListView->draggedItemsDelta())); - // set the item under the cursor to current - QModelIndex index; - if (d->movement == Snap) { - QRect rect(d->dynamicListView->snapToGrid(e->pos() + d->offset()), d->gridSize()); - const QVector<QModelIndex> intersectVector = d->intersectingSet(rect); - index = intersectVector.count() > 0 - ? intersectVector.last() : QModelIndex(); - } else { - index = indexAt(e->pos()); - } - // check if we allow drops here - if (e->source() == this && d->dynamicListView->draggedItems.contains(index)) - e->accept(); // allow changing item position - else if (d->model->flags(index) & Qt::ItemIsDropEnabled) - e->accept(); // allow dropping on dropenabled items - else if (!index.isValid()) - e->accept(); // allow dropping in empty areas - } - // do autoscrolling - if (d->shouldAutoScroll(e->pos())) - startAutoScroll(); - } else { // not internal + if (!d_func()->commonListView->filterDragMoveEvent(e)) QAbstractItemView::dragMoveEvent(e); - } } + /*! \reimp */ void QListView::dragLeaveEvent(QDragLeaveEvent *e) { - // ### move implementation to dynamic - Q_D(QListView); - if (d->viewMode == IconMode) { - d->viewport->update(d->dynamicListView->draggedItemsRect()); // erase the area - d->dynamicListView->draggedItemsPos = QPoint(-1, -1); // don't draw the dragged items - } - QAbstractItemView::dragLeaveEvent(e); + if (!d_func()->commonListView->filterDragLeaveEvent(e)) + QAbstractItemView::dragLeaveEvent(e); } /*! \reimp */ -void QListView::dropEvent(QDropEvent *event) +void QListView::dropEvent(QDropEvent *e) { - Q_D(QListView); - if (event->source() == this && d->viewMode == IconMode) - internalDrop(event); // ### move to dynamic - else - QAbstractItemView::dropEvent(event); + if (!d_func()->commonListView->filterDropEvent(e)) + QAbstractItemView::dropEvent(e); } /*! @@ -1005,10 +881,7 @@ void QListView::dropEvent(QDropEvent *event) */ void QListView::startDrag(Qt::DropActions supportedActions) { - Q_D(QListView); - if (d->viewMode == IconMode) // ### move to dynamic - internalDrag(supportedActions); - else + if (!d_func()->commonListView->filterStartDrag(supportedActions)) QAbstractItemView::startDrag(supportedActions); } @@ -1020,41 +893,8 @@ void QListView::startDrag(Qt::DropActions supportedActions) */ void QListView::internalDrop(QDropEvent *event) { - Q_D(QListView); - if (d->viewMode == QListView::ListMode) - return; - - // ### move to dynamic class - QPoint offset(horizontalOffset(), verticalOffset()); - QPoint end = event->pos() + offset; - QPoint start = d->pressedPosition; - QPoint delta = (d->movement == Snap ? - d->dynamicListView->snapToGrid(end) - - d->dynamicListView->snapToGrid(start) : end - start); - QSize contents = d->contentsSize(); - QList<QModelIndex> indexes = d->selectionModel->selectedIndexes(); - for (int i = 0; i < indexes.count(); ++i) { - QModelIndex index = indexes.at(i); - QRect rect = rectForIndex(index); - d->viewport->update(d->mapToViewport(rect, d->viewMode == QListView::ListMode)); - QPoint dest = rect.topLeft() + delta; - if (isRightToLeft()) - dest.setX(d->flipX(dest.x()) - rect.width()); - d->dynamicListView->moveItem(index.row(), dest); - update(index); - } - stopAutoScroll(); - d->dynamicListView->draggedItems.clear(); - emit indexesMoved(indexes); - event->accept(); // we have handled the event - // if the size has not grown, we need to check if it has shrinked - if (d->dynamicListView - && (d->contentsSize().width() <= contents.width() - || d->contentsSize().height() <= contents.height())) { - d->dynamicListView->updateContentsSize(); - } - if (d->contentsSize() != contents) - updateGeometries(); + // ### Qt5: remove that function + Q_UNUSED(event); } /*! @@ -1065,31 +905,8 @@ void QListView::internalDrop(QDropEvent *event) */ void QListView::internalDrag(Qt::DropActions supportedActions) { - Q_D(QListView); - if (d->viewMode == QListView::ListMode) - return; - - // #### move to dynamic class - - // This function does the same thing as in QAbstractItemView::startDrag(), - // plus adding viewitems to the draggedItems list. - // We need these items to draw the drag items - QModelIndexList indexes = d->selectionModel->selectedIndexes(); - if (indexes.count() > 0 ) { - if (d->viewport->acceptDrops()) { - QModelIndexList::ConstIterator it = indexes.constBegin(); - for (; it != indexes.constEnd(); ++it) - if (d->model->flags(*it) & Qt::ItemIsDragEnabled - && (*it).column() == d->column) - d->dynamicListView->draggedItems.push_back(*it); - } - QDrag *drag = new QDrag(this); - drag->setMimeData(d->model->mimeData(indexes)); - Qt::DropAction action = drag->exec(supportedActions, Qt::CopyAction); - d->dynamicListView->draggedItems.clear(); - if (action == Qt::MoveAction) - d->clearOrRemove(); - } + // ### Qt5: remove that function + Q_UNUSED(supportedActions); } #endif // QT_NO_DRAGANDDROP @@ -1117,6 +934,7 @@ QStyleOptionViewItem QListView::viewOptions() const return option; } + /*! \reimp */ @@ -1213,18 +1031,7 @@ void QListView::paintEvent(QPaintEvent *e) } #ifndef QT_NO_DRAGANDDROP - // #### move this implementation into a dynamic class - if (d->viewMode == IconMode) - if (!d->dynamicListView->draggedItems.isEmpty() - && d->viewport->rect().contains(d->dynamicListView->draggedItemsPos)) { - QPoint delta = d->dynamicListView->draggedItemsDelta(); - painter.translate(delta.x(), delta.y()); - d->dynamicListView->drawItems(&painter, d->dynamicListView->draggedItems); - } - // FIXME: Until the we can provide a proper drop indicator - // in IconMode, it makes no sense to show it - if (d->viewMode == ListMode) - d->paintDropIndicator(&painter); + d->commonListView->paintDragDrop(&painter); #endif #ifndef QT_NO_RUBBERBAND @@ -1263,31 +1070,7 @@ QModelIndex QListView::indexAt(const QPoint &p) const */ int QListView::horizontalOffset() const { - Q_D(const QListView); - // ### split into static and dynamic - if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem && d->viewMode == ListMode) { - if (d->isWrapping()) { - if (d->flow == TopToBottom && !d->staticListView->segmentPositions.isEmpty()) { - const int max = d->staticListView->segmentPositions.count() - 1; - int currentValue = qBound(0, horizontalScrollBar()->value(), max); - int position = d->staticListView->segmentPositions.at(currentValue); - int maximumValue = qBound(0, horizontalScrollBar()->maximum(), max); - int maximum = d->staticListView->segmentPositions.at(maximumValue); - return (isRightToLeft() ? maximum - position : position); - } - //return 0; - } else { - if (d->flow == LeftToRight && !d->staticListView->flowPositions.isEmpty()) { - int position = d->staticListView->flowPositions.at(horizontalScrollBar()->value()); - int maximum = d->staticListView->flowPositions.at(horizontalScrollBar()->maximum()); - return (isRightToLeft() ? maximum - position : position); - } - //return 0; - } - } - return (isRightToLeft() - ? horizontalScrollBar()->maximum() - horizontalScrollBar()->value() - : horizontalScrollBar()->value()); + return d_func()->commonListView->horizontalOffset(); } /*! @@ -1295,30 +1078,7 @@ int QListView::horizontalOffset() const */ int QListView::verticalOffset() const { - // ## split into static and dynamic - Q_D(const QListView); - if (verticalScrollMode() == QAbstractItemView::ScrollPerItem && d->viewMode == ListMode) { - if (d->isWrapping()) { - if (d->flow == LeftToRight && !d->staticListView->segmentPositions.isEmpty()) { - int value = verticalScrollBar()->value(); - if (value >= d->staticListView->segmentPositions.count()) { - //qWarning("QListView: Vertical scroll bar is out of bounds"); - return 0; - } - return d->staticListView->segmentPositions.at(value); - } - } else { - if (d->flow == TopToBottom && !d->staticListView->flowPositions.isEmpty()) { - int value = verticalScrollBar()->value(); - if (value > d->staticListView->flowPositions.count()) { - //qWarning("QListView: Vertical scroll bar is out of bounds"); - return 0; - } - return d->staticListView->flowPositions.at(value) - d->spacing(); - } - } - } - return verticalScrollBar()->value(); + return d_func()->commonListView->verticalOffset(); } /*! @@ -1444,15 +1204,7 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie */ QRect QListView::rectForIndex(const QModelIndex &index) const { - Q_D(const QListView); - if (!d->isIndexValid(index) - || index.parent() != d->root - || index.column() != d->column - || isIndexHidden(index)) - return QRect(); - d->executePostedLayout(); - QListViewItem item = d->indexToListViewItem(index); - return d->viewItemRect(item); + return d_func()->rectForIndex(index); } /*! @@ -1460,8 +1212,8 @@ QRect QListView::rectForIndex(const QModelIndex &index) const Sets the contents position of the item at \a index in the model to the given \a position. - If the list view's movement mode is Static, this function will have no - effect. + If the list view's movement mode is Static or its view mode is ListView, + this function will have no effect. */ void QListView::setPositionForIndex(const QPoint &position, const QModelIndex &index) { @@ -1473,15 +1225,7 @@ void QListView::setPositionForIndex(const QPoint &position, const QModelIndex &i return; d->executePostedLayout(); - if (index.row() >= d->dynamicListView->items.count()) - return; - const QSize oldContents = d->contentsSize(); - update(index); // update old position - d->dynamicListView->moveItem(index.row(), position); - update(index); // update new position - - if (d->contentsSize() != oldContents) - updateGeometries(); // update the scroll bars + d->commonListView->setPositionForIndex(position, index); } /*! @@ -1717,99 +1461,8 @@ void QListView::updateGeometries() QModelIndex index = d->model->index(0, d->column, d->root); QStyleOptionViewItemV4 option = d->viewOptionsV4(); QSize step = d->itemSize(option, index); - - QSize csize = d->contentsSize(); - QSize vsize = d->viewport->size(); - QSize max = maximumViewportSize(); - if (max.width() >= d->contentsSize().width() && max.height() >= d->contentsSize().height()) - vsize = max; - - // ### reorder the logic - - // ### split into static and dynamic - - const bool vertical = verticalScrollMode() == QAbstractItemView::ScrollPerItem; - const bool horizontal = horizontalScrollMode() == QAbstractItemView::ScrollPerItem; - - if (d->flow == TopToBottom) { - if (horizontal && d->isWrapping() && d->viewMode == ListMode) { - const QVector<int> segmentPositions = d->staticListView->segmentPositions; - const int steps = segmentPositions.count() - 1; - if (steps > 0) { - int pageSteps = d->staticListView->perItemScrollingPageSteps(vsize.width(), - csize.width(), - isWrapping()); - horizontalScrollBar()->setSingleStep(1); - horizontalScrollBar()->setPageStep(pageSteps); - horizontalScrollBar()->setRange(0, steps - pageSteps); - } else { - horizontalScrollBar()->setRange(0, 0); - } - } else { - horizontalScrollBar()->setSingleStep(step.width() + d->spacing()); - horizontalScrollBar()->setPageStep(vsize.width()); - horizontalScrollBar()->setRange(0, d->contentsSize().width() - vsize.width()); - } - if (vertical && !d->isWrapping() && d->viewMode == ListMode) { - const QVector<int> flowPositions = d->staticListView->flowPositions; - const int steps = flowPositions.count() - 1; - if (steps > 0) { - int pageSteps = d->staticListView->perItemScrollingPageSteps(vsize.height(), - csize.height(), - isWrapping()); - verticalScrollBar()->setSingleStep(1); - verticalScrollBar()->setPageStep(pageSteps); - verticalScrollBar()->setRange(0, steps - pageSteps); - } else { - verticalScrollBar()->setRange(0, 0); - } - // } else if (vertical && d->isWrapping() && d->movement == Static) { - // ### wrapped scrolling in flow direction - } else { - verticalScrollBar()->setSingleStep(step.height() + d->spacing()); - verticalScrollBar()->setPageStep(vsize.height()); - verticalScrollBar()->setRange(0, d->contentsSize().height() - vsize.height()); - } - } else { // LeftToRight - if (horizontal && !d->isWrapping() && d->viewMode == ListMode) { - const QVector<int> flowPositions = d->staticListView->flowPositions; - int steps = flowPositions.count() - 1; - if (steps > 0) { - int pageSteps = d->staticListView->perItemScrollingPageSteps(vsize.width(), - csize.width(), - isWrapping()); - horizontalScrollBar()->setSingleStep(1); - horizontalScrollBar()->setPageStep(pageSteps); - horizontalScrollBar()->setRange(0, steps - pageSteps); - } else { - horizontalScrollBar()->setRange(0, 0); - } - // } else if (horizontal && d->isWrapping() && d->movement == Static) { - // ### wrapped scrolling in flow direction - } else { - horizontalScrollBar()->setSingleStep(step.width() + d->spacing()); - horizontalScrollBar()->setPageStep(vsize.width()); - horizontalScrollBar()->setRange(0, d->contentsSize().width() - vsize.width()); - } - if (vertical && d->isWrapping() && d->viewMode == ListMode) { - const QVector<int> segmentPositions = d->staticListView->segmentPositions; - int steps = segmentPositions.count() - 1; - if (steps > 0) { - int pageSteps = d->staticListView->perItemScrollingPageSteps(vsize.height(), - csize.height(), - isWrapping()); - verticalScrollBar()->setSingleStep(1); - verticalScrollBar()->setPageStep(pageSteps); - verticalScrollBar()->setRange(0, steps - pageSteps); - } else { - verticalScrollBar()->setRange(0, 0); - } - } else { - verticalScrollBar()->setSingleStep(step.height() + d->spacing()); - verticalScrollBar()->setPageStep(vsize.height()); - verticalScrollBar()->setRange(0, d->contentsSize().height() - vsize.height()); - } - } + d->commonListView->updateHorizontalScrollBar(step); + d->commonListView->updateVerticalScrollBar(step); } QAbstractItemView::updateGeometries(); @@ -1958,14 +1611,14 @@ bool QListView::event(QEvent *e) QListViewPrivate::QListViewPrivate() : QAbstractItemViewPrivate(), - dynamicListView(0), + commonListView(0), wrap(false), space(0), flow(QListView::TopToBottom), movement(QListView::Static), resizeMode(QListView::Fixed), layoutMode(QListView::SinglePass), - viewMode(QListView::IconMode), //this will ensure the first initialization to ListView + viewMode(QListView::ListMode), modeProperties(0), column(0), uniformItemSizes(false), @@ -1976,21 +1629,14 @@ QListViewPrivate::QListViewPrivate() QListViewPrivate::~QListViewPrivate() { - if (viewMode == QListView::ListMode) - delete staticListView; - else - delete dynamicListView; + delete commonListView; } void QListViewPrivate::clear() { - // ### split into dynamic and static // initialization of data structs cachedItemSize = QSize(); - if (viewMode == QListView::ListMode) - staticListView->clear(); - else - dynamicListView->clear(); + commonListView->clear(); } void QListViewPrivate::prepareItemsLayout() @@ -1999,7 +1645,7 @@ void QListViewPrivate::prepareItemsLayout() clear(); //take the size as if there were scrollbar in order to prevent scrollbar to blink - layoutBounds = QRect(QPoint(0,0), q->maximumViewportSize()); + layoutBounds = QRect(QPoint(), q->maximumViewportSize()); int frameAroundContents = 0; if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) @@ -2017,15 +1663,8 @@ void QListViewPrivate::prepareItemsLayout() layoutBounds.adjust(0, 0, -verticalMargin, -horizontalMargin); - int rowCount = model->rowCount(root); - int colCount = model->columnCount(root); - if (colCount <= 0) - rowCount = 0; // no contents - if (viewMode == QListView::ListMode) { - staticListView->flowPositions.resize(rowCount); - } else { - dynamicListView->tree.create(qMax(rowCount - hiddenRows.count(), 0)); - } + int rowCount = model->columnCount(root) <= 0 ? 0 : model->rowCount(root); + commonListView->setRowCount(rowCount); } /*! @@ -2033,7 +1672,6 @@ void QListViewPrivate::prepareItemsLayout() */ bool QListViewPrivate::doItemsLayout(int delta) { - // ### split into static and dynamic int max = model->rowCount(root) - 1; int first = batchStartRow(); int last = qMin(first + delta - 1, max); @@ -2057,9 +1695,7 @@ bool QListViewPrivate::doItemsLayout(int delta) info.flow = flow; info.max = max; - if (viewMode == QListView::ListMode) - return staticListView->doBatchedItemLayout(info, max); - return dynamicListView->doBatchedItemLayout(info, max); + return commonListView->doBatchedItemLayout(info, max); } QListViewItem QListViewPrivate::indexToListViewItem(const QModelIndex &index) const @@ -2067,29 +1703,16 @@ QListViewItem QListViewPrivate::indexToListViewItem(const QModelIndex &index) co if (!index.isValid() || isHidden(index.row())) return QListViewItem(); - if (viewMode == QListView::ListMode) - return staticListView->indexToListViewItem(index); - return dynamicListView->indexToListViewItem(index); + return commonListView->indexToListViewItem(index); } - -int QListViewPrivate::itemIndex(const QListViewItem &item) const -{ - if (viewMode == QListView::ListMode) - return staticListView->itemIndex(item); - return dynamicListView->itemIndex(item); -} - -QRect QListViewPrivate::mapToViewport(const QRect &rect, bool greedy) const +QRect QListViewPrivate::mapToViewport(const QRect &rect, bool extend) const { Q_Q(const QListView); if (!rect.isValid()) return rect; - QRect result = rect; - if (greedy) - result = staticListView->mapToViewport(rect); - + QRect result = extend ? commonListView->mapToViewport(rect) : rect; int dx = -q->horizontalOffset(); int dy = -q->verticalOffset(); result.adjust(dx, dy, dx, dy); @@ -2177,46 +1800,217 @@ QItemSelection QListViewPrivate::selection(const QRect &rect) const } /* - * Static ListView Implementation + * Common ListView Implementation */ -int QStaticListViewBase::verticalPerItemValue(int itemIndex, int verticalValue, int areaHeight, - bool above, bool below, bool wrap, - QListView::ScrollHint hint, int itemHeight) const +void QCommonListViewBase::appendHiddenRow(int row) +{ + dd->hiddenRows.append(dd->model->index(row, 0)); +} + +void QCommonListViewBase::removeHiddenRow(int row) { - int value = qBound(0, verticalValue, flowPositions.count() - 1); - if (above) - return perItemScrollToValue(itemIndex, value, areaHeight, QListView::PositionAtTop, - Qt::Vertical,wrap, itemHeight); - else if (below) - return perItemScrollToValue(itemIndex, value, areaHeight, QListView::PositionAtBottom, - Qt::Vertical, wrap, itemHeight); - else if (hint != QListView::EnsureVisible) - return perItemScrollToValue(itemIndex, value, areaHeight, hint, Qt::Vertical, wrap, itemHeight); - return value; + dd->hiddenRows.remove(dd->hiddenRows.indexOf(dd->model->index(row, 0))); } -int QStaticListViewBase::horizontalPerItemValue(int itemIndex, int horizontalValue, int areaWidth, - bool leftOf, bool rightOf, bool wrap, - QListView::ScrollHint hint, int itemWidth) const +void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) { - int value = qBound(0, horizontalValue, flowPositions.count() - 1); + horizontalScrollBar()->setSingleStep(step.width() + spacing()); + horizontalScrollBar()->setPageStep(viewport()->width()); + horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width()); +} + +void QCommonListViewBase::updateVerticalScrollBar(const QSize &step) +{ + verticalScrollBar()->setSingleStep(step.height() + spacing()); + verticalScrollBar()->setPageStep(viewport()->height()); + verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height()); +} + +void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/) +{ + dd->scrollContentsBy(isRightToLeft() ? -dx : dx, dy); +} + +int QCommonListViewBase::verticalScrollToValue(int /*index*/, QListView::ScrollHint hint, + bool above, bool below, const QRect &area, const QRect &rect) const +{ + int verticalValue = verticalScrollBar()->value(); + QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing()); + if (hint == QListView::PositionAtTop || above) + verticalValue += adjusted.top(); + else if (hint == QListView::PositionAtBottom || below) + verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1); + else if (hint == QListView::PositionAtCenter) + verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2); + return verticalValue; +} + +int QCommonListViewBase::horizontalOffset() const +{ + return (isRightToLeft() ? horizontalScrollBar()->maximum() - horizontalScrollBar()->value() : horizontalScrollBar()->value()); +} + +int QCommonListViewBase::horizontalScrollToValue(const int /*index*/, QListView::ScrollHint hint, + bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const +{ + int horizontalValue = horizontalScrollBar()->value(); + if (isRightToLeft()) { + if (hint == QListView::PositionAtCenter) { + horizontalValue += ((area.width() - rect.width()) / 2) - rect.left(); + } else { + if (leftOf) + horizontalValue -= rect.left(); + else if (rightOf) + horizontalValue += qMin(rect.left(), area.width() - rect.right()); + } + } else { + if (hint == QListView::PositionAtCenter) { + horizontalValue += rect.left() - ((area.width()- rect.width()) / 2); + } else { + if (leftOf) + horizontalValue += rect.left(); + else if (rightOf) + horizontalValue += qMin(rect.left(), rect.right() - area.width()); + } + } + return horizontalValue; +} + +/* + * ListMode ListView Implementation +*/ + +#ifndef QT_NO_DRAGANDDROP +void QListModeViewBase::paintDragDrop(QPainter *painter) +{ + // FIXME: Until the we can provide a proper drop indicator + // in IconMode, it makes no sense to show it + dd->paintDropIndicator(painter); +} +#endif //QT_NO_DRAGANDDROP + +void QListModeViewBase::updateVerticalScrollBar(const QSize &step) +{ + if (verticalScrollMode() == QAbstractItemView::ScrollPerItem + && ((flow() == QListView::TopToBottom && !isWrapping()) + || (flow() == QListView::LeftToRight && isWrapping()))) { + const int steps = (flow() == QListView::TopToBottom ? flowPositions : segmentPositions).count() - 1; + if (steps > 0) { + const int pageSteps = perItemScrollingPageSteps(viewport()->height(), contentsSize.height(), isWrapping()); + verticalScrollBar()->setSingleStep(1); + verticalScrollBar()->setPageStep(pageSteps); + verticalScrollBar()->setRange(0, steps - pageSteps); + } else { + verticalScrollBar()->setRange(0, 0); + } + // } else if (vertical && d->isWrapping() && d->movement == Static) { + // ### wrapped scrolling in flow direction + } else { + QCommonListViewBase::updateVerticalScrollBar(step); + } +} + +void QListModeViewBase::updateHorizontalScrollBar(const QSize &step) +{ + if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem + && ((flow() == QListView::TopToBottom && isWrapping()) + || (flow() == QListView::LeftToRight && !isWrapping()))) { + int steps = (flow() == QListView::TopToBottom ? segmentPositions : flowPositions).count() - 1; + if (steps > 0) { + const int pageSteps = perItemScrollingPageSteps(viewport()->width(), contentsSize.width(), isWrapping()); + horizontalScrollBar()->setSingleStep(1); + horizontalScrollBar()->setPageStep(pageSteps); + horizontalScrollBar()->setRange(0, steps - pageSteps); + } else { + horizontalScrollBar()->setRange(0, 0); + } + } else { + QCommonListViewBase::updateHorizontalScrollBar(step); + } +} + +int QListModeViewBase::verticalScrollToValue(int index, QListView::ScrollHint hint, + bool above, bool below, const QRect &area, const QRect &rect) const +{ + if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { + int value = qBound(0, verticalScrollBar()->value(), flowPositions.count() - 1); + if (above) + hint = QListView::PositionAtTop; + else if (below) + hint = QListView::PositionAtBottom; + if (hint == QListView::EnsureVisible) + return value; + + return perItemScrollToValue(index, value, area.height(), hint, Qt::Vertical, isWrapping(), rect.height()); + } + + return QCommonListViewBase::verticalScrollToValue(index, hint, above, below, area, rect); +} + +int QListModeViewBase::horizontalOffset() const +{ + if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) { + if (isWrapping()) { + if (flow() == QListView::TopToBottom && !segmentPositions.isEmpty()) { + const int max = segmentPositions.count() - 1; + int currentValue = qBound(0, horizontalScrollBar()->value(), max); + int position = segmentPositions.at(currentValue); + int maximumValue = qBound(0, horizontalScrollBar()->maximum(), max); + int maximum = segmentPositions.at(maximumValue); + return (isRightToLeft() ? maximum - position : position); + } + } else if (flow() == QListView::LeftToRight && !flowPositions.isEmpty()) { + int position = flowPositions.at(horizontalScrollBar()->value()); + int maximum = flowPositions.at(horizontalScrollBar()->maximum()); + return (isRightToLeft() ? maximum - position : position); + } + } + return QCommonListViewBase::horizontalOffset(); +} + +int QListModeViewBase::verticalOffset() const +{ + if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { + if (isWrapping()) { + if (flow() == QListView::LeftToRight && !segmentPositions.isEmpty()) { + int value = verticalScrollBar()->value(); + if (value >= segmentPositions.count()) + return 0; + return segmentPositions.at(value); + } + } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) { + int value = verticalScrollBar()->value(); + if (value > flowPositions.count()) + return 0; + return flowPositions.at(value) - spacing(); + } + } + return QCommonListViewBase::verticalOffset(); +} + +int QListModeViewBase::horizontalScrollToValue(int index, QListView::ScrollHint hint, + bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const +{ + if (horizontalScrollMode() != QAbstractItemView::ScrollPerItem) + return QCommonListViewBase::horizontalScrollToValue(index, hint, leftOf, rightOf, area, rect); + + int value = qBound(0, horizontalScrollBar()->value(), flowPositions.count() - 1); if (leftOf) - return perItemScrollToValue(itemIndex, value, areaWidth, QListView::PositionAtTop, - Qt::Horizontal, wrap, itemWidth); + hint = QListView::PositionAtTop; else if (rightOf) - return perItemScrollToValue(itemIndex, value, areaWidth, QListView::PositionAtBottom, - Qt::Horizontal, wrap, itemWidth); - else if (hint != QListView::EnsureVisible) - return perItemScrollToValue(itemIndex, value, areaWidth, hint, Qt::Horizontal, wrap, itemWidth); - return value; + hint = QListView::PositionAtBottom; + if (hint == QListView::EnsureVisible) + return value; + + return perItemScrollToValue(index, value, area.width(), hint, Qt::Horizontal, isWrapping(), rect.width()); } -void QStaticListViewBase::scrollContentsBy(int &dx, int &dy) +void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) { // ### reorder this logic - const int verticalValue = verticalScrollBarValue(); - const int horizontalValue = horizontalScrollBarValue(); + const int verticalValue = verticalScrollBar()->value(); + const int horizontalValue = horizontalScrollBar()->value(); const bool vertical = (verticalScrollMode() == QAbstractItemView::ScrollPerItem); const bool horizontal = (horizontalScrollMode() == QAbstractItemView::ScrollPerItem); @@ -2255,9 +2049,10 @@ void QStaticListViewBase::scrollContentsBy(int &dx, int &dy) dx = previousCoordinate - currentCoordinate; } } + QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand); } -bool QStaticListViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max) +bool QListModeViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max) { doStaticLayout(info); if (batchStartRow > max) { // stop items layout @@ -2269,7 +2064,7 @@ bool QStaticListViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, i return false; // not done } -QListViewItem QStaticListViewBase::indexToListViewItem(const QModelIndex &index) const +QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) const { if (flowPositions.isEmpty() || segmentPositions.isEmpty() @@ -2305,7 +2100,7 @@ QListViewItem QStaticListViewBase::indexToListViewItem(const QModelIndex &index) return QListViewItem(QRect(pos, size), index.row()); } -QPoint QStaticListViewBase::initStaticLayout(const QListViewLayoutInfo &info) +QPoint QListModeViewBase::initStaticLayout(const QListViewLayoutInfo &info) { int x, y; if (info.first == 0) { @@ -2340,7 +2135,7 @@ QPoint QStaticListViewBase::initStaticLayout(const QListViewLayoutInfo &info) /*! \internal */ -void QStaticListViewBase::doStaticLayout(const QListViewLayoutInfo &info) +void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) { const bool useItemSize = !info.grid.isValid(); const QPoint topLeft = initStaticLayout(info); @@ -2443,7 +2238,7 @@ void QStaticListViewBase::doStaticLayout(const QListViewLayoutInfo &info) Finds the set of items intersecting with \a area. In this function, itemsize is counted from topleft to the start of the next item. */ -QVector<QModelIndex> QStaticListViewBase::intersectingStaticSet(const QRect &area) const +QVector<QModelIndex> QListModeViewBase::intersectingSet(const QRect &area) const { QVector<QModelIndex> ret; int segStartPosition; @@ -2480,19 +2275,14 @@ QVector<QModelIndex> QStaticListViewBase::intersectingStaticSet(const QRect &are ret += index; #if 0 // for debugging else - qWarning("intersectingStaticSet: row %d was invalid", row); + qWarning("intersectingSet: row %d was invalid", row); #endif } } return ret; } -int QStaticListViewBase::itemIndex(const QListViewItem &item) const -{ - return item.indexHint; -} - -QRect QStaticListViewBase::mapToViewport(const QRect &rect) const +QRect QListModeViewBase::mapToViewport(const QRect &rect) const { if (isWrapping()) return rect; @@ -2510,7 +2300,7 @@ QRect QStaticListViewBase::mapToViewport(const QRect &rect) const return result; } -int QStaticListViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const +int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const { const QVector<int> positions = (wrap ? segmentPositions : flowPositions); if (positions.isEmpty() || bounds <= length) @@ -2538,7 +2328,7 @@ int QStaticListViewBase::perItemScrollingPageSteps(int length, int bounds, bool return qMax(pageSteps, 1); } -int QStaticListViewBase::perItemScrollToValue(int index, int scrollValue, int viewportSize, +int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int viewportSize, QAbstractItemView::ScrollHint hint, Qt::Orientation orientation, bool wrap, int itemExtent) const { @@ -2598,7 +2388,7 @@ int QStaticListViewBase::perItemScrollToValue(int index, int scrollValue, int vi return scrollValue; } -void QStaticListViewBase::clear() +void QListModeViewBase::clear() { flowPositions.clear(); segmentPositions.clear(); @@ -2610,10 +2400,175 @@ void QStaticListViewBase::clear() } /* - * Dynamic ListView Implementation + * IconMode ListView Implementation */ -void QDynamicListViewBase::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +void QIconModeViewBase::setPositionForIndex(const QPoint &position, const QModelIndex &index) +{ + if (index.row() >= items.count()) + return; + const QSize oldContents = contentsSize; + qq->update(index); // update old position + moveItem(index.row(), position); + qq->update(index); // update new position + + if (contentsSize != oldContents) + dd->viewUpdateGeometries(); // update the scroll bars +} + +void QIconModeViewBase::appendHiddenRow(int row) +{ + if (row >= 0 && row < items.count()) //remove item + tree.removeLeaf(items.at(row).rect(), row); + QCommonListViewBase::appendHiddenRow(row); +} + +void QIconModeViewBase::removeHiddenRow(int row) +{ + QCommonListViewBase::appendHiddenRow(row); + if (row >= 0 && row < items.count()) //insert item + tree.insertLeaf(items.at(row).rect(), row); +} + +#ifndef QT_NO_DRAGANDDROP +void QIconModeViewBase::paintDragDrop(QPainter *painter) +{ + if (!draggedItems.isEmpty() && viewport()->rect().contains(draggedItemsPos)) { + //we need to draw the items that arre dragged + painter->translate(draggedItemsDelta()); + QStyleOptionViewItemV4 option = viewOptions(); + option.state &= ~QStyle::State_MouseOver; + QVector<QModelIndex>::const_iterator it = draggedItems.begin(); + QListViewItem item = indexToListViewItem(*it); + for (; it != draggedItems.end(); ++it) { + item = indexToListViewItem(*it); + option.rect = viewItemRect(item); + delegate(*it)->paint(painter, option, *it); + } + } +} + +bool QIconModeViewBase::filterStartDrag(Qt::DropActions supportedActions) +{ + // This function does the same thing as in QAbstractItemView::startDrag(), + // plus adding viewitems to the draggedItems list. + // We need these items to draw the drag items + QModelIndexList indexes = dd->selectionModel->selectedIndexes(); + if (indexes.count() > 0 ) { + if (viewport()->acceptDrops()) { + QModelIndexList::ConstIterator it = indexes.constBegin(); + for (; it != indexes.constEnd(); ++it) + if (dd->model->flags(*it) & Qt::ItemIsDragEnabled + && (*it).column() == dd->column) + draggedItems.push_back(*it); + } + QDrag *drag = new QDrag(qq); + drag->setMimeData(dd->model->mimeData(indexes)); + Qt::DropAction action = drag->exec(supportedActions, Qt::CopyAction); + draggedItems.clear(); + if (action == Qt::MoveAction) + dd->clearOrRemove(); + } + return true; +} + +bool QIconModeViewBase::filterDropEvent(QDropEvent *e) +{ + if (e->source() != qq) + return false; + + const QSize contents = contentsSize; + QPoint offset(horizontalOffset(), verticalOffset()); + QPoint end = e->pos() + offset; + QPoint start = dd->pressedPosition; + QPoint delta = (dd->movement == QListView::Snap ? snapToGrid(end) - snapToGrid(start) : end - start); + QList<QModelIndex> indexes = dd->selectionModel->selectedIndexes(); + for (int i = 0; i < indexes.count(); ++i) { + QModelIndex index = indexes.at(i); + QRect rect = dd->rectForIndex(index); + viewport()->update(mapToViewport(rect)); + QPoint dest = rect.topLeft() + delta; + if (qq->isRightToLeft()) + dest.setX(dd->flipX(dest.x()) - rect.width()); + moveItem(index.row(), dest); + qq->update(index); + } + dd->stopAutoScroll(); + draggedItems.clear(); + dd->emitIndexesMoved(indexes); + e->accept(); // we have handled the event + // if the size has not grown, we need to check if it has shrinked + if (contentsSize != contents) { + if ((contentsSize.width() <= contents.width() + || contentsSize.height() <= contents.height())) { + updateContentsSize(); + } + dd->viewUpdateGeometries(); + } + return true; +} + +bool QIconModeViewBase::filterDragLeaveEvent(QDragLeaveEvent *e) +{ + viewport()->update(draggedItemsRect()); // erase the area + draggedItemsPos = QPoint(-1, -1); // don't draw the dragged items + return QCommonListViewBase::filterDragLeaveEvent(e); +} + +bool QIconModeViewBase::filterDragMoveEvent(QDragMoveEvent *e) +{ + if (e->source() != qq || !dd->canDecode(e)) + return false; + + // ignore by default + e->ignore(); + // get old dragged items rect + QRect itemsRect = this->itemsRect(draggedItems); + viewport()->update(itemsRect.translated(draggedItemsDelta())); + // update position + draggedItemsPos = e->pos(); + // get new items rect + viewport()->update(itemsRect.translated(draggedItemsDelta())); + // set the item under the cursor to current + QModelIndex index; + if (movement() == QListView::Snap) { + QRect rect(snapToGrid(e->pos() + offset()), gridSize()); + const QVector<QModelIndex> intersectVector = intersectingSet(rect); + index = intersectVector.count() > 0 ? intersectVector.last() : QModelIndex(); + } else { + index = qq->indexAt(e->pos()); + } + // check if we allow drops here + if (draggedItems.contains(index)) + e->accept(); // allow changing item position + else if (dd->model->flags(index) & Qt::ItemIsDropEnabled) + e->accept(); // allow dropping on dropenabled items + else if (!index.isValid()) + e->accept(); // allow dropping in empty areas + + // the event was treated. do autoscrolling + if (dd->shouldAutoScroll(e->pos())) + dd->startAutoScroll(); + return true; +} +#endif // QT_NO_DRAGANDDROP + +void QIconModeViewBase::setRowCount(int rowCount) +{ + tree.create(qMax(rowCount - hiddenCount(), 0)); +} + +void QIconModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) +{ + if (scrollElasticBand) + dd->scrollElasticBandBy(isRightToLeft() ? -dx : dx, dy); + + QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand); + if (!draggedItems.isEmpty()) + viewport()->update(draggedItemsRect().translated(dx, dy)); +} + +void QIconModeViewBase::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { if (column() >= topLeft.column() && column() <= bottomRight.column()) { QStyleOptionViewItemV4 option = viewOptions(); @@ -2623,23 +2578,29 @@ void QDynamicListViewBase::dataChanged(const QModelIndex &topLeft, const QModelI } } -bool QDynamicListViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max) +bool QIconModeViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max) { if (info.last >= items.count()) { - createItems(info.last + 1); + //first we create the items + QStyleOptionViewItemV4 option = viewOptions(); + for (int row = items.count(); row <= info.last; ++row) { + QSize size = itemSize(option, modelIndex(row)); + QListViewItem item(QRect(0, 0, size.width(), size.height()), row); // default pos + items.append(item); + } doDynamicLayout(info); } return (batchStartRow > max); // done } -QListViewItem QDynamicListViewBase::indexToListViewItem(const QModelIndex &index) const +QListViewItem QIconModeViewBase::indexToListViewItem(const QModelIndex &index) const { if (index.isValid() && index.row() < items.count()) return items.at(index.row()); return QListViewItem(); } -void QDynamicListViewBase::initBspTree(const QSize &contents) +void QIconModeViewBase::initBspTree(const QSize &contents) { // remove all items from the tree int leafCount = tree.leafCount(); @@ -2656,7 +2617,7 @@ void QDynamicListViewBase::initBspTree(const QSize &contents) tree.init(QRect(0, 0, contents.width(), contents.height()), type); } -QPoint QDynamicListViewBase::initDynamicLayout(const QListViewLayoutInfo &info) +QPoint QIconModeViewBase::initDynamicLayout(const QListViewLayoutInfo &info) { int x, y; if (info.first == 0) { @@ -2678,7 +2639,7 @@ QPoint QDynamicListViewBase::initDynamicLayout(const QListViewLayoutInfo &info) /*! \internal */ -void QDynamicListViewBase::doDynamicLayout(const QListViewLayoutInfo &info) +void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info) { const bool useItemSize = !info.grid.isValid(); const QPoint topLeft = initDynamicLayout(info); @@ -2712,7 +2673,7 @@ void QDynamicListViewBase::doDynamicLayout(const QListViewLayoutInfo &info) if (moved.count() != items.count()) moved.resize(items.count()); - QRect rect(QPoint(0, 0), topLeft); + QRect rect(QPoint(), topLeft); QListViewItem *item = 0; for (int row = info.first; row <= info.last; ++row) { item = &items[row]; @@ -2805,43 +2766,18 @@ void QDynamicListViewBase::doDynamicLayout(const QListViewLayoutInfo &info) viewport()->update(); } -QVector<QModelIndex> QDynamicListViewBase::intersectingDynamicSet(const QRect &area) const +QVector<QModelIndex> QIconModeViewBase::intersectingSet(const QRect &area) const { - QDynamicListViewBase *that = const_cast<QDynamicListViewBase*>(this); + QIconModeViewBase *that = const_cast<QIconModeViewBase*>(this); QBspTree::Data data(static_cast<void*>(that)); QVector<QModelIndex> res; that->interSectingVector = &res; - that->tree.climbTree(area, &QDynamicListViewBase::addLeaf, data); + that->tree.climbTree(area, &QIconModeViewBase::addLeaf, data); that->interSectingVector = 0; return res; } -void QDynamicListViewBase::createItems(int to) -{ - int count = items.count(); - QSize size; - QStyleOptionViewItemV4 option = viewOptions(); - for (int row = count; row < to; ++row) { - size = itemSize(option, modelIndex(row)); - QListViewItem item(QRect(0, 0, size.width(), size.height()), row); // default pos - items.append(item); - } -} - -void QDynamicListViewBase::drawItems(QPainter *painter, const QVector<QModelIndex> &indexes) const -{ - QStyleOptionViewItemV4 option = viewOptions(); - option.state &= ~QStyle::State_MouseOver; - QVector<QModelIndex>::const_iterator it = indexes.begin(); - QListViewItem item = indexToListViewItem(*it); - for (; it != indexes.end(); ++it) { - item = indexToListViewItem(*it); - option.rect = viewItemRect(item); - delegate(*it)->paint(painter, option, *it); - } -} - -QRect QDynamicListViewBase::itemsRect(const QVector<QModelIndex> &indexes) const +QRect QIconModeViewBase::itemsRect(const QVector<QModelIndex> &indexes) const { QVector<QModelIndex>::const_iterator it = indexes.begin(); QListViewItem item = indexToListViewItem(*it); @@ -2853,7 +2789,7 @@ QRect QDynamicListViewBase::itemsRect(const QVector<QModelIndex> &indexes) const return rect; } -int QDynamicListViewBase::itemIndex(const QListViewItem &item) const +int QIconModeViewBase::itemIndex(const QListViewItem &item) const { if (!item.isValid()) return -1; @@ -2889,11 +2825,11 @@ int QDynamicListViewBase::itemIndex(const QListViewItem &item) const return -1; } -void QDynamicListViewBase::addLeaf(QVector<int> &leaf, const QRect &area, +void QIconModeViewBase::addLeaf(QVector<int> &leaf, const QRect &area, uint visited, QBspTree::Data data) { QListViewItem *vi; - QDynamicListViewBase *_this = static_cast<QDynamicListViewBase *>(data.ptr); + QIconModeViewBase *_this = static_cast<QIconModeViewBase *>(data.ptr); for (int i = 0; i < leaf.count(); ++i) { int idx = leaf.at(i); if (idx < 0 || idx >= _this->items.count()) @@ -2909,19 +2845,7 @@ void QDynamicListViewBase::addLeaf(QVector<int> &leaf, const QRect &area, } } -void QDynamicListViewBase::insertItem(int index) -{ - if (index >= 0 && index < items.count()) - tree.insertLeaf(items.at(index).rect(), index); -} - -void QDynamicListViewBase::removeItem(int index) -{ - if (index >= 0 && index < items.count()) - tree.removeLeaf(items.at(index).rect(), index); -} - -void QDynamicListViewBase::moveItem(int index, const QPoint &dest) +void QIconModeViewBase::moveItem(int index, const QPoint &dest) { // does not impact on the bintree itself or the contents rect QListViewItem *item = &items[index]; @@ -2941,14 +2865,14 @@ void QDynamicListViewBase::moveItem(int index, const QPoint &dest) moved.setBit(index, true); } -QPoint QDynamicListViewBase::snapToGrid(const QPoint &pos) const +QPoint QIconModeViewBase::snapToGrid(const QPoint &pos) const { int x = pos.x() - (pos.x() % gridSize().width()); int y = pos.y() - (pos.y() % gridSize().height()); return QPoint(x, y); } -QPoint QDynamicListViewBase::draggedItemsDelta() const +QPoint QIconModeViewBase::draggedItemsDelta() const { if (movement() == QListView::Snap) { QPoint snapdelta = QPoint((offset().x() % gridSize().width()), @@ -2958,7 +2882,7 @@ QPoint QDynamicListViewBase::draggedItemsDelta() const return draggedItemsPos - pressedPosition(); } -QRect QDynamicListViewBase::draggedItemsRect() const +QRect QIconModeViewBase::draggedItemsRect() const { QRect rect = itemsRect(draggedItems); rect.translate(draggedItemsDelta()); @@ -2977,7 +2901,7 @@ void QListViewPrivate::scrollElasticBandBy(int dx, int dy) elasticBand.moveTop(elasticBand.top() - dy); } -void QDynamicListViewBase::clear() +void QIconModeViewBase::clear() { tree.destroy(); items.clear(); @@ -2986,7 +2910,7 @@ void QDynamicListViewBase::clear() batchSavedDeltaSeg = 0; } -void QDynamicListViewBase::updateContentsSize() +void QIconModeViewBase::updateContentsSize() { QRect bounding; for (int i = 0; i < items.count(); ++i) @@ -3039,7 +2963,7 @@ int QListView::visualIndex(const QModelIndex &index) const Q_D(const QListView); d->executePostedLayout(); QListViewItem itm = d->indexToListViewItem(index); - return d->itemIndex(itm); + return d->commonListView->itemIndex(itm); } QT_END_NAMESPACE diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index 6c8d324..db9eb59 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -67,8 +67,8 @@ QT_BEGIN_NAMESPACE class QListViewItem { friend class QListViewPrivate; - friend class QStaticListViewBase; - friend class QDynamicListViewBase; + friend class QListModeViewBase; + friend class QIconModeViewBase; public: inline QListViewItem() : x(-1), y(-1), w(0), h(0), indexHint(-1), visited(0xffff) {} @@ -120,8 +120,42 @@ class QListViewPrivate; class QCommonListViewBase { public: - inline QCommonListViewBase(QListView *q, QListViewPrivate *d) : dd(d), qq(q) {} - + inline QCommonListViewBase(QListView *q, QListViewPrivate *d) : dd(d), qq(q), batchStartRow(0), batchSavedDeltaSeg(0) {} + virtual ~QCommonListViewBase() {} + + //common interface + virtual int itemIndex(const QListViewItem &item) const = 0; + virtual QListViewItem indexToListViewItem(const QModelIndex &index) const = 0; + virtual bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max) = 0; + virtual void clear() = 0; + virtual void setRowCount(int) = 0; + virtual QVector<QModelIndex> intersectingSet(const QRect &area) const = 0; + + virtual int horizontalScrollToValue(int index, QListView::ScrollHint hint, + bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const; + virtual int verticalScrollToValue(int index, QListView::ScrollHint hint, + bool above, bool below, const QRect &area, const QRect &rect) const; + virtual void scrollContentsBy(int dx, int dy, bool scrollElasticBand); + virtual QRect mapToViewport(const QRect &rect) const {return rect;} + virtual int horizontalOffset() const; + virtual int verticalOffset() const { return verticalScrollBar()->value(); } + virtual void updateHorizontalScrollBar(const QSize &step); + virtual void updateVerticalScrollBar(const QSize &step); + virtual void dataChanged(const QModelIndex &, const QModelIndex &) { } + virtual void appendHiddenRow(int row); + virtual void removeHiddenRow(int row); + virtual void setPositionForIndex(const QPoint &, const QModelIndex &) { } + +#ifndef QT_NO_DRAGANDDROP + virtual void paintDragDrop(QPainter *painter) = 0; + virtual bool filterDragMoveEvent(QDragMoveEvent *) { return false; } + virtual bool filterDragLeaveEvent(QDragLeaveEvent *) { return false; } + virtual bool filterDropEvent(QDropEvent *) { return false; } + virtual bool filterStartDrag(Qt::DropActions) { return false; } +#endif + + + //other inline members inline int spacing() const; inline bool isWrapping() const; inline QSize gridSize() const; @@ -133,8 +167,8 @@ public: inline bool uniformItemSizes() const; inline int column() const; - inline int verticalScrollBarValue() const; - inline int horizontalScrollBarValue() const; + inline QScrollBar *verticalScrollBar() const; + inline QScrollBar *horizontalScrollBar() const; inline QListView::ScrollMode verticalScrollMode() const; inline QListView::ScrollMode horizontalScrollMode() const; @@ -157,110 +191,107 @@ public: QListViewPrivate *dd; QListView *qq; + QSize contentsSize; + int batchStartRow; + int batchSavedDeltaSeg; }; -// ### rename to QListModeViewBase -class QStaticListViewBase : public QCommonListViewBase +class QListModeViewBase : public QCommonListViewBase { - friend class QListViewPrivate; public: - QStaticListViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d), - batchStartRow(0), batchSavedDeltaSeg(0), batchSavedPosition(0) {} + QListModeViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d) {} QVector<int> flowPositions; QVector<int> segmentPositions; QVector<int> segmentStartRows; QVector<int> segmentExtents; - QSize contentsSize; - // used when laying out in batches - int batchStartRow; - int batchSavedDeltaSeg; int batchSavedPosition; + //reimplementations + int itemIndex(const QListViewItem &item) const { return item.indexHint; } + QListViewItem indexToListViewItem(const QModelIndex &index) const; bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max); + void clear(); + void setRowCount(int rowCount) { flowPositions.resize(rowCount); } + QVector<QModelIndex> intersectingSet(const QRect &area) const; + + int horizontalScrollToValue(int index, QListView::ScrollHint hint, + bool leftOf, bool rightOf,const QRect &area, const QRect &rect) const; + int verticalScrollToValue(int index, QListView::ScrollHint hint, + bool above, bool below, const QRect &area, const QRect &rect) const; + void scrollContentsBy(int dx, int dy, bool scrollElasticBand); + QRect mapToViewport(const QRect &rect) const; + int horizontalOffset() const; + int verticalOffset() const; + void updateHorizontalScrollBar(const QSize &step); + void updateVerticalScrollBar(const QSize &step); + +#ifndef QT_NO_DRAGANDDROP + void paintDragDrop(QPainter *painter); +#endif +private: QPoint initStaticLayout(const QListViewLayoutInfo &info); void doStaticLayout(const QListViewLayoutInfo &info); - QVector<QModelIndex> intersectingStaticSet(const QRect &area) const; - - int itemIndex(const QListViewItem &item) const; - - int perItemScrollingPageSteps(int length, int bounds, bool wrap) const; - int perItemScrollToValue(int index, int value, int height, QAbstractItemView::ScrollHint hint, Qt::Orientation orientation, bool wrap, int extent) const; - - QRect mapToViewport(const QRect &rect) const; - - QListViewItem indexToListViewItem(const QModelIndex &index) const; - - void scrollContentsBy(int &dx, int &dy); - - int verticalPerItemValue(int itemIndex, int verticalValue, int areaHeight, - bool above, bool below, bool wrap, QListView::ScrollHint hint, int itemHeight) const; - int horizontalPerItemValue(int itemIndex, int horizontalValue, int areaWidth, - bool leftOf, bool rightOf, bool wrap, QListView::ScrollHint hint, int itemWidth) const; - - void clear(); + int perItemScrollingPageSteps(int length, int bounds, bool wrap) const; }; -// ### rename to QIconModeViewBase -class QDynamicListViewBase : public QCommonListViewBase +class QIconModeViewBase : public QCommonListViewBase { - friend class QListViewPrivate; public: - QDynamicListViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d), - batchStartRow(0), batchSavedDeltaSeg(0), interSectingVector(0) {} + QIconModeViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d), interSectingVector(0) {} QBspTree tree; QVector<QListViewItem> items; QBitArray moved; - QSize contentsSize; - QVector<QModelIndex> draggedItems; // indices to the tree.itemVector mutable QPoint draggedItemsPos; // used when laying out in batches - int batchStartRow; - int batchSavedDeltaSeg; - QVector<QModelIndex> *interSectingVector; //used from within intersectingDynamicSet + QVector<QModelIndex> *interSectingVector; //used from within intersectingSet - void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + //reimplementations + int itemIndex(const QListViewItem &item) const; + QListViewItem indexToListViewItem(const QModelIndex &index) const; bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max); + void clear(); + void setRowCount(int rowCount); + QVector<QModelIndex> intersectingSet(const QRect &area) const; + + void scrollContentsBy(int dx, int dy, bool scrollElasticBand); + void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void appendHiddenRow(int row); + void removeHiddenRow(int row); + void setPositionForIndex(const QPoint &position, const QModelIndex &index); + +#ifndef QT_NO_DRAGANDDROP + void paintDragDrop(QPainter *painter); + bool filterDragMoveEvent(QDragMoveEvent *); + bool filterDragLeaveEvent(QDragLeaveEvent *); + bool filterDropEvent(QDropEvent *e); + bool filterStartDrag(Qt::DropActions); +#endif +private: void initBspTree(const QSize &contents); QPoint initDynamicLayout(const QListViewLayoutInfo &info); void doDynamicLayout(const QListViewLayoutInfo &info); - QVector<QModelIndex> intersectingDynamicSet(const QRect &area) const; - static void addLeaf(QVector<int> &leaf, const QRect &area, uint visited, QBspTree::Data data); - - void insertItem(int index); - void removeItem(int index); - void moveItem(int index, const QPoint &dest); - - int itemIndex(const QListViewItem &item) const; - - void createItems(int to); - void drawItems(QPainter *painter, const QVector<QModelIndex> &indexes) const; QRect itemsRect(const QVector<QModelIndex> &indexes) const; - - QPoint draggedItemsDelta() const; QRect draggedItemsRect() const; - QPoint snapToGrid(const QPoint &pos) const; - - void scrollElasticBandBy(int dx, int dy); - - QListViewItem indexToListViewItem(const QModelIndex &index) const; - - void clear(); void updateContentsSize(); + QPoint draggedItemsDelta() const; + void drawItems(QPainter *painter, const QVector<QModelIndex> &indexes) const; + void moveItem(int index, const QPoint &dest); + }; class QListViewPrivate: public QAbstractItemViewPrivate @@ -278,23 +309,13 @@ public: inline QVector<QModelIndex> intersectingSet(const QRect &area, bool doLayout = true) const { if (doLayout) executePostedLayout(); QRect a = (q_func()->isRightToLeft() ? flipX(area.normalized()) : area.normalized()); - return (viewMode == QListView::ListMode) ? staticListView->intersectingStaticSet(a) - : dynamicListView->intersectingDynamicSet(a); + return commonListView->intersectingSet(a); } - // ### FIXME: - inline void resetBatchStartRow() - { if (viewMode == QListView::ListMode) staticListView->batchStartRow = 0; - else dynamicListView->batchStartRow = 0; } - inline int batchStartRow() const - { return (viewMode == QListView::ListMode - ? staticListView->batchStartRow : dynamicListView->batchStartRow); } - inline QSize contentsSize() const - { return (viewMode == QListView::ListMode - ? staticListView->contentsSize : dynamicListView->contentsSize); } - inline void setContentsSize(int w, int h) - { if (viewMode == QListView::ListMode) staticListView->contentsSize = QSize(w, h); - else dynamicListView->contentsSize = QSize(w, h); } + inline void resetBatchStartRow() { commonListView->batchStartRow = 0; } + inline int batchStartRow() const { return commonListView->batchStartRow; } + inline QSize contentsSize() const { return commonListView->contentsSize; } + inline void setContentsSize(int w, int h) { commonListView->contentsSize = QSize(w, h); } inline int flipX(int x) const { return qMax(viewport->width(), contentsSize().width()) - x; } @@ -305,12 +326,22 @@ public: inline QRect viewItemRect(const QListViewItem &item) const { if (q_func()->isRightToLeft()) return flipX(item.rect()); return item.rect(); } - int itemIndex(const QListViewItem &item) const; QListViewItem indexToListViewItem(const QModelIndex &index) const; inline QModelIndex listViewItemToIndex(const QListViewItem &item) const - { return model->index(itemIndex(item), column, root); } + { return model->index(commonListView->itemIndex(item), column, root); } + + QRect rectForIndex(const QModelIndex &index) const + { + if (!isIndexValid(index) || index.parent() != root || index.column() != column || isHidden(index.row())) + return QRect(); + executePostedLayout(); + return viewItemRect(indexToListViewItem(index)); + } + + void viewUpdateGeometries() { q_func()->updateGeometries(); } - QRect mapToViewport(const QRect &rect, bool greedy = false) const; + + QRect mapToViewport(const QRect &rect, bool extend = true) const; QModelIndex closestIndex(const QRect &target, const QVector<QModelIndex> &candidates) const; QSize itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const; @@ -351,10 +382,10 @@ public: QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const; - union { - QDynamicListViewBase *dynamicListView; - QStaticListViewBase *staticListView; - }; + void emitIndexesMoved(const QModelIndexList &indexes) { emit q_func()->indexesMoved(indexes); } + + + QCommonListViewBase *commonListView; // ### FIXME: see if we can move the members into the dynamic/static classes @@ -412,8 +443,8 @@ inline QPoint QCommonListViewBase::pressedPosition() const { return dd->pressedP inline bool QCommonListViewBase::uniformItemSizes() const { return dd->uniformItemSizes; } inline int QCommonListViewBase::column() const { return dd->column; } -inline int QCommonListViewBase::verticalScrollBarValue() const { return qq->verticalScrollBar()->value(); } -inline int QCommonListViewBase::horizontalScrollBarValue() const { return qq->horizontalScrollBar()->value(); } +inline QScrollBar *QCommonListViewBase::verticalScrollBar() const { return qq->verticalScrollBar(); } +inline QScrollBar *QCommonListViewBase::horizontalScrollBar() const { return qq->horizontalScrollBar(); } inline QListView::ScrollMode QCommonListViewBase::verticalScrollMode() const { return qq->verticalScrollMode(); } inline QListView::ScrollMode QCommonListViewBase::horizontalScrollMode() const { return qq->horizontalScrollMode(); } diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 574d845..ccf6ac9 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -101,6 +101,10 @@ extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp #include "qdatetime.h" +#ifdef QT_MAC_USE_COCOA +#include <private/qt_cocoa_helpers_mac_p.h> +#endif + //#define ALIEN_DEBUG static void initResources() @@ -3477,6 +3481,15 @@ void QApplication::changeOverrideCursor(const QCursor &cursor) if (qApp->d_func()->cursor_list.isEmpty()) return; qApp->d_func()->cursor_list.removeFirst(); +#ifdef QT_MAC_USE_COCOA + // We use native NSCursor stacks in Cocoa. The currentCursor is the + // top of this stack. So to avoid flickering of cursor, we have to + // change the cusor instead of pop-ing the existing OverrideCursor + // and pushing the new one. + qApp->d_func()->cursor_list.prepend(cursor); + qt_cocoaChangeOverrideCursor(cursor); + return; +#endif setOverrideCursor(cursor); } #endif diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index 572df70..172d07b 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -197,11 +197,19 @@ static void cleanupCocoaApplicationDelegate() } } - // Prevent Cocoa from terminating the application, since this simply - // exits the program whithout allowing QApplication::exec() to return. - // The call to QApplication::quit() above will instead quit the - // application from the Qt side. - return NSTerminateCancel; + if (qtPrivate->threadData->eventLoops.size() == 0) { + // INVARIANT: No event loop is executing. This probably + // means that Qt is used as a plugin, or as a part of a native + // Cocoa application. In any case it should be fine to + // terminate now: + return NSTerminateNow; + } else { + // Prevent Cocoa from terminating the application, since this simply + // exits the program whithout allowing QApplication::exec() to return. + // The call to QApplication::quit() above will instead quit the + // application from the Qt side. + return NSTerminateCancel; + } } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 7ac0d89..5a0209d 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -667,7 +667,15 @@ extern "C" { - (void)mouseMoved:(NSEvent *)theEvent { - qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); + // We always enable mouse tracking for all QCocoaView-s. In cases where we have + // child views, we will receive mouseMoved for both parent & the child (if + // mouse is over the child). We need to ignore the parent mouseMoved in such + // cases. + NSPoint windowPoint = [theEvent locationInWindow]; + NSView *candidateView = [[[self window] contentView] hitTest:windowPoint]; + if (candidateView && candidateView == self) { + qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); + } } - (void)mouseDown:(NSEvent *)theEvent diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp index a4042c1..8f92fea 100644 --- a/src/gui/kernel/qdnd_x11.cpp +++ b/src/gui/kernel/qdnd_x11.cpp @@ -1073,12 +1073,14 @@ void qt_xdnd_send_leave() if (!qt_xdnd_current_target) return; + QDragManager *manager = QDragManager::self(); + XClientMessageEvent leave; leave.type = ClientMessage; leave.window = qt_xdnd_current_target; leave.format = 32; leave.message_type = ATOM(XdndLeave); - leave.data.l[0] = qt_xdnd_dragsource_xid; + leave.data.l[0] = manager->dragPrivate()->source->effectiveWinId(); leave.data.l[1] = 0; // flags leave.data.l[2] = 0; // x, y leave.data.l[3] = 0; // w, h @@ -1094,8 +1096,8 @@ void qt_xdnd_send_leave() else XSendEvent(X11->display, qt_xdnd_current_proxy_target, False, NoEventMask, (XEvent*)&leave); + // reset the drag manager state - QDragManager *manager = QDragManager::self(); manager->willDrop = false; if (global_accepted_action != Qt::IgnoreAction) manager->emitActionChanged(Qt::IgnoreAction); diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index c965bac..0027deb 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -99,11 +99,11 @@ struct QShortcutEntry QObject *owner; }; -#ifndef QT_NO_DEBUG_STREAM +#if 0 //ndef QT_NO_DEBUG_STREAM /*! \internal QDebug operator<< for easy debug output of the shortcut entries. */ -QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) { +static QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) { if (!se) return dbg << "QShortcutEntry(0x0)"; dbg.nospace() diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 7596802..a9b8970 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1238,4 +1238,12 @@ void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse) } } +#ifdef QT_MAC_USE_COCOA +void qt_cocoaChangeOverrideCursor(const QCursor &cursor) +{ + QMacCocoaAutoReleasePool pool; + [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set]; +} +#endif + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 24d7096..932abef 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -133,6 +133,7 @@ bool qt_mac_checkForNativeSizeGrip(const QWidget *widget); void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent); #ifdef QT_MAC_USE_COCOA bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); +void qt_cocoaChangeOverrideCursor(const QCursor &cursor); #endif void qt_mac_menu_collapseSeparators(void * /*NSMenu */ menu, bool collapse); bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index 98d48de..dda5e2b 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -576,6 +576,15 @@ void QWidgetPrivate::show_sys() if (q->isWindow()) { + + if (!q->testAttribute(Qt::WA_ShowWithoutActivating) + && q->windowType() != Qt::Popup + && q->windowType() != Qt::Tool + && q->windowType() != Qt::ToolTip) { + QWidget::qwsDisplay()->requestFocus(data.winid,true); + } + + if (QWindowSurface *surface = q->windowSurface()) { const QRect frameRect = q->frameGeometry(); if (surface->geometry() != frameRect) @@ -592,12 +601,6 @@ void QWidgetPrivate::show_sys() #endif data.fstrut_dirty = true; invalidateBuffer(r); - if (!q->testAttribute(Qt::WA_ShowWithoutActivating) - && q->windowType() != Qt::Popup - && q->windowType() != Qt::Tool - && q->windowType() != Qt::ToolTip) { - QWidget::qwsDisplay()->requestFocus(data.winid,true); - } bool staysontop = (q->windowFlags() & Qt::WindowStaysOnTopHint) || q->windowType() == Qt::Popup; diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 5f7bb5a..fbb4b97 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -2060,8 +2060,6 @@ void QWidgetPrivate::winSetupGestures() Q_Q(QWidget); if (!q) return; - q->setAttribute(Qt::WA_DontCreateNativeAncestors); - q->setAttribute(Qt::WA_NativeWindow); if (!q->isVisible()) return; QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 8fc439b..36ffcbe 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -41,6 +41,7 @@ #include "qmatrix4x4.h" #include <QtCore/qmath.h> +#include <QtCore/qvariant.h> #include <QtGui/qmatrix.h> #include <QtGui/qtransform.h> @@ -1438,18 +1439,59 @@ QMatrix QMatrix4x4::toAffine() const qreal(m[3][0]), qreal(m[3][1])); } +static const qreal inv_dist_to_plane = 1. / 1024.; + /*! Returns the conventional Qt 2D transformation matrix that - corresponds to this matrix. It is assumed that this matrix - only contains 2D transformation elements. + corresponds to this matrix. + + If \a distanceToPlane is non-zero, it indicates a projection + factor to use to adjust for the z co-ordinate. The default + value of 1024 corresponds to the projection factor used + by QTransform::rotate() for the x and y axes. + + If \a distToPlane is zero, then the returned QTransform + is formed by simply dropping the third row and third column + of the QMatrix4x4. This is suitable for implementing + orthographic projections where the z co-ordinate should + be dropped rather than projected. \sa toAffine() */ -QTransform QMatrix4x4::toTransform() const +QTransform QMatrix4x4::toTransform(qreal distanceToPlane) const { - return QTransform(qreal(m[0][0]), qreal(m[0][1]), qreal(m[0][3]), - qreal(m[1][0]), qreal(m[1][1]), qreal(m[1][3]), - qreal(m[3][0]), qreal(m[3][1]), qreal(m[3][3])); + if (distanceToPlane == 1024.0f) { + // Optimize the common case with constants. + return QTransform(qreal(m[0][0]), qreal(m[0][1]), + qreal(m[0][3]) - qreal(m[0][2]) * + inv_dist_to_plane, + qreal(m[1][0]), qreal(m[1][1]), + qreal(m[1][3]) - qreal(m[1][2]) * + inv_dist_to_plane, + qreal(m[3][0]), qreal(m[3][1]), + qreal(m[3][3]) - qreal(m[3][2]) * + inv_dist_to_plane); + } else if (distanceToPlane != 0.0f) { + // The following projection matrix is pre-multiplied with "matrix": + // | 1 0 0 0 | + // | 0 1 0 0 | + // | 0 0 1 0 | + // | 0 0 d 1 | + // where d = -1 / distanceToPlane. After projection, row 3 and + // column 3 are dropped to form the final QTransform. + qreal d = 1.0f / distanceToPlane; + return QTransform(qreal(m[0][0]), qreal(m[0][1]), + qreal(m[0][3]) - qreal(m[0][2]) * d, + qreal(m[1][0]), qreal(m[1][1]), + qreal(m[1][3]) - qreal(m[1][2]) * d, + qreal(m[3][0]), qreal(m[3][1]), + qreal(m[3][3]) - qreal(m[3][2]) * d); + } else { + // Orthographic projection: drop row 3 and column 3. + return QTransform(qreal(m[0][0]), qreal(m[0][1]), qreal(m[0][3]), + qreal(m[1][0]), qreal(m[1][1]), qreal(m[1][3]), + qreal(m[3][0]), qreal(m[3][1]), qreal(m[3][3])); + } } /*! @@ -1776,6 +1818,14 @@ void QMatrix4x4::inferSpecialType() flagBits = Scale; } +/*! + Returns the matrix as a QVariant. +*/ +QMatrix4x4::operator QVariant() const +{ + return QVariant(QVariant::Matrix4x4, this); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QMatrix4x4 &m) diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index b02608d..10e628b 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -58,6 +58,7 @@ QT_MODULE(Gui) class QMatrix; class QTransform; +class QVariant; class Q_GUI_EXPORT QMatrix4x4 { @@ -158,7 +159,7 @@ public: void toValueArray(qreal *values) const; QMatrix toAffine() const; - QTransform toTransform() const; + QTransform toTransform(qreal distanceToPlane = 1024.0f) const; QPoint map(const QPoint& point) const; QPointF map(const QPointF& point) const; @@ -182,6 +183,8 @@ public: void inferSpecialType(); + operator QVariant() const; + #ifndef QT_NO_DEBUG_STREAM friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m); #endif diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index b2c598f..f279388 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -41,6 +41,7 @@ #include "qquaternion.h" #include <QtCore/qmath.h> +#include <QtCore/qvariant.h> #include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE @@ -560,6 +561,14 @@ QQuaternion QQuaternion::nlerp return (q1 * (1.0f - t) + q2b * t).normalized(); } +/*! + Returns the quaternion as a QVariant. +*/ +QQuaternion::operator QVariant() const +{ + return QVariant(QVariant::Quaternion, this); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QQuaternion &q) diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index a2fb29f..af60b61 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -54,6 +54,7 @@ QT_MODULE(Gui) #ifndef QT_NO_QUATERNION class QMatrix4x4; +class QVariant; class Q_GUI_EXPORT QQuaternion { @@ -118,6 +119,8 @@ public: QVector4D toVector4D() const; #endif + operator QVariant() const; + #ifndef QT_NO_VECTOR3D static QQuaternion fromAxisAndAngle(const QVector3D& axis, qreal angle); #endif diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp index 1662020..35c86a1 100644 --- a/src/gui/math3d/qvector2d.cpp +++ b/src/gui/math3d/qvector2d.cpp @@ -43,6 +43,7 @@ #include "qvector3d.h" #include "qvector4d.h" #include <QtCore/qdebug.h> +#include <QtCore/qvariant.h> #include <QtCore/qmath.h> QT_BEGIN_NAMESPACE @@ -402,6 +403,14 @@ QVector4D QVector2D::toVector4D() const \sa toPoint(), toVector3D() */ +/*! + Returns the 2D vector as a QVariant. +*/ +QVector2D::operator QVariant() const +{ + return QVariant(QVariant::Vector2D, this); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QVector2D &vector) diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h index 93052f6..d9727e2 100644 --- a/src/gui/math3d/qvector2d.h +++ b/src/gui/math3d/qvector2d.h @@ -53,6 +53,7 @@ QT_MODULE(Gui) class QVector3D; class QVector4D; +class QVariant; #ifndef QT_NO_VECTOR2D @@ -114,6 +115,8 @@ public: QPoint toPoint() const; QPointF toPointF() const; + operator QVariant() const; + private: float xp, yp; diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp index 0e3f4e1..5c96979 100644 --- a/src/gui/math3d/qvector3d.cpp +++ b/src/gui/math3d/qvector3d.cpp @@ -43,6 +43,7 @@ #include "qvector2d.h" #include "qvector4d.h" #include <QtCore/qmath.h> +#include <QtCore/qvariant.h> #include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE @@ -530,6 +531,14 @@ QVector4D QVector3D::toVector4D() const */ /*! + Returns the 3D vector as a QVariant. +*/ +QVector3D::operator QVariant() const +{ + return QVariant(QVariant::Vector3D, this); +} + +/*! Returns the length of the vector from the origin. \sa lengthSquared(), normalized() diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h index 36292d2..d1370fb 100644 --- a/src/gui/math3d/qvector3d.h +++ b/src/gui/math3d/qvector3d.h @@ -127,6 +127,8 @@ public: QPoint toPoint() const; QPointF toPointF() const; + operator QVariant() const; + private: float xp, yp, zp; diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp index a2efff7..11eb4c4 100644 --- a/src/gui/math3d/qvector4d.cpp +++ b/src/gui/math3d/qvector4d.cpp @@ -43,6 +43,7 @@ #include "qvector3d.h" #include "qvector2d.h" #include <QtCore/qdebug.h> +#include <QtCore/qvariant.h> #include <QtCore/qmath.h> QT_BEGIN_NAMESPACE @@ -500,6 +501,14 @@ QVector3D QVector4D::toVector3DAffine() const \sa toPoint(), toVector2D() */ +/*! + Returns the 4D vector as a QVariant. +*/ +QVector4D::operator QVariant() const +{ + return QVariant(QVariant::Vector4D, this); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QVector4D &vector) diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h index 42db45b..69ccd30 100644 --- a/src/gui/math3d/qvector4d.h +++ b/src/gui/math3d/qvector4d.h @@ -124,6 +124,8 @@ public: QPoint toPoint() const; QPointF toPointF() const; + operator QVariant() const; + private: float xp, yp, zp, wp; diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index e447301..cd78de0 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -374,9 +374,9 @@ template <typename T> void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl, const uchar *src = srcPixels + y * sbpl; const uchar *srcEnd = src + srcOffset; while (src < srcEnd) { -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) +#if defined(QT_ARCH_ARM) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) // non-16-bit aligned memory access is not possible on PowerPC, - // ARM <v6 (QT_ARCH_ARMV6) & SH + // ARM <v6 (QT_ARCH_ARMV6) & SH & AVR32 quint16 spix = (quint16(src[2])<<8) + src[1]; #else quint16 spix = *(quint16 *) (src + 1); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index ab35ead..c4da0a6 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2561,6 +2561,8 @@ void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op) QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint); d->state->clipEnabled = true; d->extended->clip(vp, op); + if (op == Qt::ReplaceClip || op == Qt::NoClip) + d->state->clipInfo.clear(); d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); d->state->clipOperation = op; return; @@ -2607,6 +2609,8 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op) if (d->extended) { d->state->clipEnabled = true; d->extended->clip(rect, op); + if (op == Qt::ReplaceClip || op == Qt::NoClip) + d->state->clipInfo.clear(); d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix); d->state->clipOperation = op; return; @@ -2660,6 +2664,8 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) if (d->extended) { d->state->clipEnabled = true; d->extended->clip(r, op); + if (op == Qt::NoClip || op == Qt::ReplaceClip) + d->state->clipInfo.clear(); d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix); d->state->clipOperation = op; return; @@ -3064,6 +3070,8 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op) if (d->extended) { d->state->clipEnabled = true; d->extended->clip(path, op); + if (op == Qt::NoClip || op == Qt::ReplaceClip) + d->state->clipInfo.clear(); d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix); d->state->clipOperation = op; return; diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp index 51f40e3..6a5ea49 100644 --- a/src/gui/styles/gtksymbols.cpp +++ b/src/gui/styles/gtksymbols.cpp @@ -642,7 +642,7 @@ GtkStyle* QGtk::gtkStyle(const QString &path) return 0; } -static void update_toolbar_style(GtkWidget *gtkToolBar, GParamSpec *pspec, gpointer user_data) +static void update_toolbar_style(GtkWidget *gtkToolBar, GParamSpec *, gpointer) { GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS; g_object_get(gtkToolBar, "toolbar-style", &toolbar_style, NULL); diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 533ef46..e7aeed0 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -63,10 +63,10 @@ QT_BEGIN_NAMESPACE // The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 } #if !defined(Q_CC_DIAB) # define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \ - QTextUndoCommand c = { a1, a2, a3, a4, a5, a6, { a7 }, a8 } + QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6, { a7 }, a8 } #else # define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \ - QTextUndoCommand c = { a1, a2, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8 + QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8 #endif /* @@ -961,14 +961,18 @@ int QTextDocumentPrivate::undoRedo(bool undo) B->revision = c.revision; } - if (undo) { - if (undoState == 0 || !undoStack[undoState-1].block) - break; - } else { + if (!undo) ++undoState; - if (undoState == undoStack.size() || !undoStack[undoState-1].block) - break; - } + + bool inBlock = ( + undoState > 0 + && undoState < undoStack.size() + && undoStack[undoState].block_part + && undoStack[undoState-1].block_part + && !undoStack[undoState-1].block_end + ); + if (!inBlock) + break; } undoEnabled = true; int editPos = -1; @@ -993,7 +997,8 @@ void QTextDocumentPrivate::appendUndoItem(QAbstractUndoItem *item) QTextUndoCommand c; c.command = QTextUndoCommand::Custom; - c.block = editBlock != 0; + c.block_part = editBlock != 0; + c.block_end = 0; c.operation = QTextUndoCommand::MoveCursor; c.format = 0; c.strPos = 0; @@ -1014,9 +1019,10 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) if (!undoStack.isEmpty() && modified) { QTextUndoCommand &last = undoStack[undoState - 1]; - if ( (last.block && c.block) // part of the same block => can merge - || (!c.block && !last.block // two single undo items => can merge - && (undoState < 2 || !undoStack[undoState-2].block))) { + + if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge + || (!c.block_part && !last.block_part)) { // two single undo items => can merge + if (last.tryMerge(c)) return; } @@ -1028,7 +1034,7 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) emitUndoAvailable(true); emitRedoAvailable(false); - if (!c.block) + if (!c.block_part) emit document()->undoCommandAdded(); } @@ -1094,7 +1100,7 @@ void QTextDocumentPrivate::joinPreviousEditBlock() beginEditBlock(); if (undoEnabled && undoState) - undoStack[undoState - 1].block = true; + undoStack[undoState - 1].block_end = false; } void QTextDocumentPrivate::endEditBlock() @@ -1103,10 +1109,10 @@ void QTextDocumentPrivate::endEditBlock() return; if (undoEnabled && undoState > 0) { - const bool wasBlocking = undoStack[undoState - 1].block; - undoStack[undoState - 1].block = false; - if (wasBlocking) + if (undoStack[undoState - 1].block_part) { + undoStack[undoState - 1].block_end = true; emit document()->undoCommandAdded(); + } } finishEdit(); diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 55aa17e..363309c 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -139,7 +139,9 @@ public: MoveCursor = 1 }; quint16 command; - quint8 block; ///< All undo commands that have this set to true are combined with the preceding command on undo/redo. + uint block_part : 1; // all commands that are part of an undo block (including the first and the last one) have this set to 1 + uint block_end : 1; // the last command in an undo block has this set to 1. + uint block_padding : 6; // padding since block used to be a quint8 quint8 operation; int format; quint32 strPos; diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp index 942df89..8428125 100644 --- a/src/gui/widgets/qabstractscrollarea.cpp +++ b/src/gui/widgets/qabstractscrollarea.cpp @@ -923,6 +923,10 @@ bool QAbstractScrollArea::event(QEvent *e) case QEvent::DragMove: case QEvent::DragLeave: #endif + // ignore touch events in case they have been propagated from the viewport + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: return false; case QEvent::StyleChange: case QEvent::LayoutDirectionChange: @@ -963,6 +967,9 @@ bool QAbstractScrollArea::viewportEvent(QEvent *e) case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: case QEvent::MouseMove: case QEvent::ContextMenu: #ifndef QT_NO_WHEELEVENT diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index bf2d58a..397e0b5 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -65,19 +65,37 @@ QT_BEGIN_NAMESPACE -const int QHttpNetworkConnectionPrivate::channelCount = 6; +const int QHttpNetworkConnectionPrivate::defaultChannelCount = 6; + +// the maximum amount of requests that might be pipelined into a socket +// from what was suggested, 3 seems to be OK +const int QHttpNetworkConnectionPrivate::defaultPipelineLength = 3; + QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt) : hostName(hostName), port(port), encrypt(encrypt), + channelCount(defaultChannelCount), pendingAuthSignal(false), pendingProxyAuthSignal(false) #ifndef QT_NO_NETWORKPROXY , networkProxy(QNetworkProxy::NoProxy) #endif +{ + channels = new QHttpNetworkConnectionChannel[channelCount]; +} +QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt) +: hostName(hostName), port(port), encrypt(encrypt), + channelCount(channelCount), + pendingAuthSignal(false), pendingProxyAuthSignal(false) +#ifndef QT_NO_NETWORKPROXY + , networkProxy(QNetworkProxy::NoProxy) +#endif { channels = new QHttpNetworkConnectionChannel[channelCount]; } + + QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate() { for (int i = 0; i < channelCount; ++i) { @@ -139,17 +157,6 @@ qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailableNextBlock(const return reply.d_func()->responseData.sizeNextBlock(); } -qint64 QHttpNetworkConnectionPrivate::compressedBytesAvailable(const QHttpNetworkReply &reply) const -{ - return reply.d_func()->compressedData.size(); -} - -void QHttpNetworkConnectionPrivate::eraseData(QHttpNetworkReply *reply) -{ - reply->d_func()->compressedData.clear(); - reply->d_func()->responseData.clear(); -} - void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair) { QHttpNetworkRequest &request = messagePair.first; @@ -223,231 +230,8 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair) reply->d_func()->requestIsPrepared = true; } -bool QHttpNetworkConnectionPrivate::ensureConnection(QAbstractSocket *socket) -{ - // make sure that this socket is in a connected state, if not initiate - // connection to the host. - if (socket->state() != QAbstractSocket::ConnectedState) { - // connect to the host if not already connected. - int index = indexOf(socket); - // resend this request after we receive the disconnected signal - if (socket->state() == QAbstractSocket::ClosingState) { - channels[index].resendCurrent = true; - return false; - } - channels[index].state = QHttpNetworkConnectionChannel::ConnectingState; - channels[index].pendingEncrypt = encrypt; - - // This workaround is needed since we use QAuthenticator for NTLM authentication. The "phase == Done" - // is the usual criteria for emitting authentication signals. The "phase" is set to "Done" when the - // last header for Authorization is generated by the QAuthenticator. Basic & Digest logic does not - // check the "phase" for generating the Authorization header. NTLM authentication is a two stage - // process & needs the "phase". To make sure the QAuthenticator uses the current username/password - // the phase is reset to Start. - QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[index].authenticator); - if (priv && priv->phase == QAuthenticatorPrivate::Done) - priv->phase = QAuthenticatorPrivate::Start; - priv = QAuthenticatorPrivate::getPrivate(channels[index].proxyAuthenticator); - if (priv && priv->phase == QAuthenticatorPrivate::Done) - priv->phase = QAuthenticatorPrivate::Start; - - QString connectHost = hostName; - qint16 connectPort = port; - -#ifndef QT_NO_NETWORKPROXY - // HTTPS always use transparent proxy. - if (networkProxy.type() != QNetworkProxy::NoProxy && !encrypt) { - connectHost = networkProxy.hostName(); - connectPort = networkProxy.port(); - } -#endif - if (encrypt) { -#ifndef QT_NO_OPENSSL - QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); - sslSocket->connectToHostEncrypted(connectHost, connectPort); - if (channels[index].ignoreAllSslErrors) - sslSocket->ignoreSslErrors(); - sslSocket->ignoreSslErrors(channels[index].ignoreSslErrorsList); -#else - emitReplyError(socket, channels[index].reply, QNetworkReply::ProtocolUnknownError); -#endif - } else { - socket->connectToHost(connectHost, connectPort); - } - return false; - } - return true; -} - -bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket) -{ - Q_Q(QHttpNetworkConnection); - int i = indexOf(socket); - switch (channels[i].state) { - case QHttpNetworkConnectionChannel::IdleState: { // write the header - if (!ensureConnection(socket)) { - // wait for the connection (and encryption) to be done - // sendRequest will be called again from either - // _q_connected or _q_encrypted - return false; - } - channels[i].written = 0; // excluding the header - channels[i].bytesTotal = 0; - if (channels[i].reply) { - channels[i].reply->d_func()->clear(); - channels[i].reply->d_func()->connection = q; - channels[i].reply->d_func()->autoDecompress = channels[i].request.d->autoDecompress; - } - channels[i].state = QHttpNetworkConnectionChannel::WritingState; - channels[i].pendingEncrypt = false; - // if the url contains authentication parameters, use the new ones - // both channels will use the new authentication parameters - if (!channels[i].request.url().userInfo().isEmpty()) { - QUrl url = channels[i].request.url(); - QAuthenticator &auth = channels[i].authenticator; - if (url.userName() != auth.user() - || (!url.password().isEmpty() && url.password() != auth.password())) { - auth.setUser(url.userName()); - auth.setPassword(url.password()); - copyCredentials(i, &auth, false); - } - // clear the userinfo, since we use the same request for resending - // userinfo in url can conflict with the one in the authenticator - url.setUserInfo(QString()); - channels[i].request.setUrl(url); - } - createAuthorization(socket, channels[i].request); -#ifndef QT_NO_NETWORKPROXY - QByteArray header = QHttpNetworkRequestPrivate::header(channels[i].request, - (networkProxy.type() != QNetworkProxy::NoProxy)); -#else - QByteArray header = QHttpNetworkRequestPrivate::header(channels[i].request, - false); -#endif - socket->write(header); - QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); - if (uploadByteDevice) { - // connect the signals so this function gets called again - QObject::connect(uploadByteDevice, SIGNAL(readyRead()), &channels[i], SLOT(_q_uploadDataReadyRead())); - - channels[i].bytesTotal = channels[i].request.contentLength(); - } else { - socket->flush(); // ### Remove this when pipelining is implemented. We want less TCP packets! - channels[i].state = QHttpNetworkConnectionChannel::WaitingState; - break; - } - // write the initial chunk together with the headers - // fall through - } - case QHttpNetworkConnectionChannel::WritingState: - { - // write the data - QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); - if (!uploadByteDevice || channels[i].bytesTotal == channels[i].written) { - if (uploadByteDevice) - emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal); - channels[i].state = QHttpNetworkConnectionChannel::WaitingState; // now wait for response - sendRequest(socket); - break; - } - - // only feed the QTcpSocket buffer when there is less than 32 kB in it - const qint64 socketBufferFill = 32*1024; - const qint64 socketWriteMaxSize = 16*1024; - - -#ifndef QT_NO_OPENSSL - QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); - // if it is really an ssl socket, check more than just bytesToWrite() - while ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0)) - <= socketBufferFill && channels[i].bytesTotal != channels[i].written) -#else - while (socket->bytesToWrite() <= socketBufferFill - && channels[i].bytesTotal != channels[i].written) -#endif - { - // get pointer to upload data - qint64 currentReadSize; - qint64 desiredReadSize = qMin(socketWriteMaxSize, channels[i].bytesTotal - channels[i].written); - const char *readPointer = uploadByteDevice->readPointer(desiredReadSize, currentReadSize); - - if (currentReadSize == -1) { - // premature eof happened - emitReplyError(socket, channels[i].reply, QNetworkReply::UnknownNetworkError); - return false; - break; - } else if (readPointer == 0 || currentReadSize == 0) { - // nothing to read currently, break the loop - break; - } else { - qint64 currentWriteSize = socket->write(readPointer, currentReadSize); - if (currentWriteSize == -1 || currentWriteSize != currentReadSize) { - // socket broke down - emitReplyError(socket, channels[i].reply, QNetworkReply::UnknownNetworkError); - return false; - } else { - channels[i].written += currentWriteSize; - uploadByteDevice->advanceReadPointer(currentWriteSize); - - emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal); - - if (channels[i].written == channels[i].bytesTotal) { - // make sure this function is called once again - channels[i].state = QHttpNetworkConnectionChannel::WaitingState; - sendRequest(socket); - break; - } - } - } - } - break; - } - - case QHttpNetworkConnectionChannel::WaitingState: - { - QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); - if (uploadByteDevice) { - QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), &channels[i], SLOT(_q_uploadDataReadyRead())); - } - // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called - // this is needed if the sends an reply before we have finished sending the request. In that - // case receiveReply had been called before but ignored the server reply - receiveReply(socket, channels[i].reply); - break; - } - case QHttpNetworkConnectionChannel::ReadingState: - case QHttpNetworkConnectionChannel::Wait4AuthState: - // ignore _q_bytesWritten in these states - // fall through - default: - break; - } - return true; -} - -bool QHttpNetworkConnectionPrivate::shouldEmitSignals(QHttpNetworkReply *reply) -{ - // for 401 & 407 don't emit the data signals. Content along with these - // responses are send only if the authentication fails. - return (reply && reply->d_func()->statusCode != 401 && reply->d_func()->statusCode != 407); -} - -bool QHttpNetworkConnectionPrivate::expectContent(QHttpNetworkReply *reply) -{ - // check whether we can expect content after the headers (rfc 2616, sec4.4) - if (!reply) - return false; - if ((reply->d_func()->statusCode >= 100 && reply->d_func()->statusCode < 200) - || reply->d_func()->statusCode == 204 || reply->d_func()->statusCode == 304) - return false; - if (reply->d_func()->request.operation() == QHttpNetworkRequest::Head) - return !shouldEmitSignals(reply); - if (reply->d_func()->contentLength() == 0) - return false; - return true; -} void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, @@ -460,271 +244,13 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket, emit reply->finishedWithError(errorCode, reply->d_func()->errorString); int i = indexOf(socket); // remove the corrupt data if any - eraseData(channels[i].reply); - closeChannel(i); + reply->d_func()->eraseData(); + channels[i].close(); // send the next request QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); } } -#ifndef QT_NO_COMPRESS -bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete) -{ - Q_ASSERT(socket); - Q_ASSERT(reply); - - qint64 total = compressedBytesAvailable(*reply); - if (total >= CHUNK || dataComplete) { - int i = indexOf(socket); - // uncompress the data - QByteArray content, inflated; - content = reply->d_func()->compressedData; - reply->d_func()->compressedData.clear(); - - int ret = Z_OK; - if (content.size()) - ret = reply->d_func()->gunzipBodyPartially(content, inflated); - int retCheck = (dataComplete) ? Z_STREAM_END : Z_OK; - if (ret >= retCheck) { - if (inflated.size()) { - reply->d_func()->totalProgress += inflated.size(); - reply->d_func()->appendUncompressedReplyData(inflated); - if (shouldEmitSignals(reply)) { - // important: At the point of this readyRead(), inflated must be cleared, - // else implicit sharing will trigger memcpy when the user is reading data! - emit reply->readyRead(); - // make sure that the reply is valid - if (channels[i].reply != reply) - return true; - emit reply->dataReadProgress(reply->d_func()->totalProgress, 0); - // make sure that the reply is valid - if (channels[i].reply != reply) - return true; - - } - } - } else { - emitReplyError(socket, reply, QNetworkReply::ProtocolFailure); - return false; - } - } - return true; -} -#endif - -void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply) -{ - Q_ASSERT(socket); - - Q_Q(QHttpNetworkConnection); - qint64 bytes = 0; - QAbstractSocket::SocketState state = socket->state(); - int i = indexOf(socket); - - // connection might be closed to signal the end of data - if (state == QAbstractSocket::UnconnectedState) { - if (!socket->bytesAvailable()) { - if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { - reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState; - channels[i].state = QHttpNetworkConnectionChannel::IdleState; - allDone(socket, reply); - } else { - // try to reconnect/resend before sending an error. - if (channels[i].reconnectAttempts-- > 0) { - resendCurrentRequest(socket); - } else if (reply) { - reply->d_func()->errorString = errorDetail(QNetworkReply::RemoteHostClosedError, socket); - emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString); - QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); - } - } - } - } - - // read loop for the response - while (socket->bytesAvailable()) { - QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState; - switch (state) { - case QHttpNetworkReplyPrivate::NothingDoneState: - case QHttpNetworkReplyPrivate::ReadingStatusState: { - qint64 statusBytes = reply->d_func()->readStatus(socket); - if (statusBytes == -1) { - // error reading the status, close the socket and emit error - socket->close(); - reply->d_func()->errorString = errorDetail(QNetworkReply::ProtocolFailure, socket); - emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString); - QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); - break; - } - bytes += statusBytes; - channels[i].lastStatus = reply->d_func()->statusCode; - break; - } - case QHttpNetworkReplyPrivate::ReadingHeaderState: - bytes += reply->d_func()->readHeader(socket); - if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { - if (reply->d_func()->isGzipped() && reply->d_func()->autoDecompress) { - // remove the Content-Length from header - reply->d_func()->removeAutoDecompressHeader(); - } else { - reply->d_func()->autoDecompress = false; - } - if (reply && reply->d_func()->statusCode == 100) { - reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState; - break; // ignore - } - if (shouldEmitSignals(reply)) - emit reply->headerChanged(); - if (!expectContent(reply)) { - reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState; - channels[i].state = QHttpNetworkConnectionChannel::IdleState; - allDone(socket, reply); - return; - } - } - break; - case QHttpNetworkReplyPrivate::ReadingDataState: { - if (!reply->d_func()->isChunked() && !reply->d_func()->autoDecompress - && reply->d_func()->bodyLength > 0) { - // bulk files like images should fulfill these properties and - // we can therefore save on memory copying - bytes = reply->d_func()->readBodyFast(socket, &reply->d_func()->responseData); - reply->d_func()->totalProgress += bytes; - if (shouldEmitSignals(reply)) { - emit reply->readyRead(); - // make sure that the reply is valid - if (channels[i].reply != reply) - return; - emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); - // make sure that the reply is valid - if (channels[i].reply != reply) - return; - } - } - else - { - // use the traditional slower reading (for compressed encoding, chunked encoding, - // no content-length etc) - QByteDataBuffer byteDatas; - bytes = reply->d_func()->readBody(socket, &byteDatas); - if (bytes) { - if (reply->d_func()->autoDecompress) - reply->d_func()->appendCompressedReplyData(byteDatas); - else - reply->d_func()->appendUncompressedReplyData(byteDatas); - - if (!reply->d_func()->autoDecompress) { - reply->d_func()->totalProgress += bytes; - if (shouldEmitSignals(reply)) { - // important: At the point of this readyRead(), the byteDatas list must be empty, - // else implicit sharing will trigger memcpy when the user is reading data! - emit reply->readyRead(); - // make sure that the reply is valid - if (channels[i].reply != reply) - return; - emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); - // make sure that the reply is valid - if (channels[i].reply != reply) - return; - } - } -#ifndef QT_NO_COMPRESS - else if (!expand(socket, reply, false)) { // expand a chunk if possible - return; // ### expand failed - } -#endif - } - } - if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) - break; - // everything done, fall through - } - case QHttpNetworkReplyPrivate::AllDoneState: - channels[i].state = QHttpNetworkConnectionChannel::IdleState; - allDone(socket, reply); - break; - default: - break; - } - } -} - -void QHttpNetworkConnectionPrivate::allDone(QAbstractSocket *socket, QHttpNetworkReply *reply) -{ -#ifndef QT_NO_COMPRESS - // expand the whole data. - if (expectContent(reply) && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd) - expand(socket, reply, true); // ### if expand returns false, its an error -#endif - // while handling 401 & 407, we might reset the status code, so save this. - bool emitFinished = shouldEmitSignals(reply); - handleStatus(socket, reply); - // ### at this point there should be no more data on the socket - // close if server requested - int i = indexOf(socket); - if (reply->d_func()->connectionCloseEnabled()) - closeChannel(i); - // queue the finished signal, this is required since we might send new requests from - // slot connected to it. The socket will not fire readyRead signal, if we are already - // in the slot connected to readyRead - if (emitFinished) - QMetaObject::invokeMethod(reply, "finished", Qt::QueuedConnection); - // reset the reconnection attempts after we receive a complete reply. - // in case of failures, each channel will attempt two reconnects before emitting error. - channels[i].reconnectAttempts = 2; -} - -void QHttpNetworkConnectionPrivate::handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply) -{ - Q_ASSERT(socket); - Q_ASSERT(reply); - - Q_Q(QHttpNetworkConnection); - - int statusCode = reply->statusCode(); - bool resend = false; - - switch (statusCode) { - case 401: - case 407: - if (handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend)) { - if (resend) { - int i = indexOf(socket); - - QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); - if (uploadByteDevice) { - if (uploadByteDevice->reset()) { - channels[i].written = 0; - } else { - emitReplyError(socket, reply, QNetworkReply::ContentReSendError); - break; - } - } - - eraseData(reply); - - // also use async _q_startNextRequest so we dont break with closed - // proxy or server connections.. - channels[i].resendCurrent = true; - QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); - } - } else { - int i = indexOf(socket); - emit channels[i].reply->headerChanged(); - emit channels[i].reply->readyRead(); - QNetworkReply::NetworkError errorCode = (statusCode == 407) - ? QNetworkReply::ProxyAuthenticationRequiredError - : QNetworkReply::AuthenticationRequiredError; - reply->d_func()->errorString = errorDetail(errorCode, socket); - emit q->error(errorCode, reply->d_func()->errorString); - emit channels[i].reply->finished(); - } - break; - default: - QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); - } -} - void QHttpNetworkConnectionPrivate::copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy) { Q_ASSERT(auth); @@ -747,6 +273,7 @@ void QHttpNetworkConnectionPrivate::copyCredentials(int fromChannel, QAuthentica } +// handles the authentication for one channel and eventually re-starts the other channels bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend) { @@ -786,8 +313,8 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket if (priv->phase == QAuthenticatorPrivate::Done) { if ((isProxy && pendingProxyAuthSignal) ||(!isProxy && pendingAuthSignal)) { // drop the request - eraseData(channels[i].reply); - closeChannel(i); + reply->d_func()->eraseData(); + channels[i].close(); channels[i].lastStatus = 0; channels[i].state = QHttpNetworkConnectionChannel::Wait4AuthState; return false; @@ -892,7 +419,24 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor return reply; } -void QHttpNetworkConnectionPrivate::unqueueAndSendRequest(QAbstractSocket *socket) +void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair) +{ + Q_Q(QHttpNetworkConnection); + + QHttpNetworkRequest request = pair.first; + switch (request.priority()) { + case QHttpNetworkRequest::HighPriority: + highPriorityQueue.prepend(pair); + break; + case QHttpNetworkRequest::NormalPriority: + case QHttpNetworkRequest::LowPriority: + lowPriorityQueue.prepend(pair); + break; + } + QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); +} + +void QHttpNetworkConnectionPrivate::dequeueAndSendRequest(QAbstractSocket *socket) { Q_ASSERT(socket); @@ -906,8 +450,9 @@ void QHttpNetworkConnectionPrivate::unqueueAndSendRequest(QAbstractSocket *socke channels[i].request = messagePair.first; channels[i].reply = messagePair.second; - sendRequest(socket); + // remove before sendRequest! else we might pipeline the same request again highPriorityQueue.removeAt(j); + channels[i].sendRequest(); return; } } @@ -919,28 +464,113 @@ void QHttpNetworkConnectionPrivate::unqueueAndSendRequest(QAbstractSocket *socke prepareRequest(messagePair); channels[i].request = messagePair.first; channels[i].reply = messagePair.second; - sendRequest(socket); + // remove before sendRequest! else we might pipeline the same request again lowPriorityQueue.removeAt(j); + channels[i].sendRequest(); return; } } } -void QHttpNetworkConnectionPrivate::closeChannel(int channel) +// this is called from _q_startNextRequest and when a request has been sent down a socket from the channel +void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket) { - channels[channel].close(); + // return fast if there is nothing to pipeline + if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) + return; + + int i = indexOf(socket); + + bool highPriorityQueueProcessingDone = false; + bool lowPriorityQueueProcessingDone = false; + + while (!highPriorityQueueProcessingDone && !lowPriorityQueueProcessingDone) { + // this loop runs once per request we intend to pipeline in. + + if (channels[i].pipeliningSupported != QHttpNetworkConnectionChannel::PipeliningProbablySupported) + return; + + // the current request that is in must already support pipelining + if (!channels[i].request.isPipeliningAllowed()) + return; + + // the current request must be a idempotent (right now we only check GET) + if (channels[i].request.operation() != QHttpNetworkRequest::Get) + return; + + // check if socket is connected + if (socket->state() != QAbstractSocket::ConnectedState) + return; + + // check for resendCurrent + if (channels[i].resendCurrent) + return; + + // we do not like authentication stuff + // ### make sure to be OK with this in later releases + if (!channels[i].authenticator.isNull() || !channels[i].authenticator.user().isEmpty()) + return; + if (!channels[i].proxyAuthenticator.isNull() || !channels[i].proxyAuthenticator.user().isEmpty()) + return; + + // check for pipeline length + if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) + return; + + // must be in ReadingState or WaitingState + if (! (channels[i].state == QHttpNetworkConnectionChannel::WaitingState + || channels[i].state == QHttpNetworkConnectionChannel::ReadingState)) + return; + + highPriorityQueueProcessingDone = fillPipeline(highPriorityQueue, channels[i]); + // not finished with highPriorityQueue? then loop again + if (!highPriorityQueueProcessingDone) + continue; + // highPriorityQueue was processed, now deal with the lowPriorityQueue + lowPriorityQueueProcessingDone = fillPipeline(lowPriorityQueue, channels[i]); + } } -void QHttpNetworkConnectionPrivate::resendCurrentRequest(QAbstractSocket *socket) +// returns true when the processing of a queue has been done +bool QHttpNetworkConnectionPrivate::fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel) { - Q_Q(QHttpNetworkConnection); - Q_ASSERT(socket); - int i = indexOf(socket); - closeChannel(i); - channels[i].resendCurrent = true; - QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); + if (queue.isEmpty()) + return true; + + for (int i = 0; i < queue.length(); i++) { + HttpMessagePair messagePair = queue.at(i); + const QHttpNetworkRequest &request = messagePair.first; + + // we currently do not support pipelining if HTTP authentication is used + if (!request.url().userInfo().isEmpty()) + continue; + + // take only GET requests + if (request.operation() != QHttpNetworkRequest::Get) + continue; + + if (!request.isPipeliningAllowed()) + continue; + + // remove it from the queue + queue.takeAt(i); + // we modify the queue we iterate over here, but since we return from the function + // afterwards this is fine. + + // actually send it + if (!messagePair.second->d_func()->requestIsPrepared) + prepareRequest(messagePair); + channel.pipelineInto(messagePair); + + // return false because we processed something and need to process again + return false; + } + + // return true, the queue has been processed and not changed + return true; } + QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket) { Q_ASSERT(socket); @@ -992,7 +622,7 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply) if (channels[i].reply == reply) { channels[i].reply = 0; if (reply->d_func()->connectionCloseEnabled()) - closeChannel(i); + channels[i].close(); QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); return; } @@ -1031,7 +661,7 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() channels[i].resendCurrent = false; channels[i].state = QHttpNetworkConnectionChannel::IdleState; if (channels[i].reply) - sendRequest(channels[i].socket); + channels[i].sendRequest(); } } QAbstractSocket *socket = 0; @@ -1043,20 +673,33 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() break; } } - if (!socket) - return; // this will be called after finishing current request. - unqueueAndSendRequest(socket); + + // this socket is free, + if (socket) + dequeueAndSendRequest(socket); + + // try to push more into all sockets + // ### FIXME we should move this to the beginning of the function + // as soon as QtWebkit is properly using the pipelining + // (e.g. not for XMLHttpRequest or the first page load) + // ### FIXME we should also divide the requests more even + // on the connected sockets + //tryToFillPipeline(socket); + // return fast if there is nothing to pipeline + if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) + return; + for (int j = 0; j < channelCount; j++) + fillPipeline(channels[j].socket); } void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests() { // send the request using the idle socket for (int i = 0 ; i < channelCount; ++i) { - QAbstractSocket *socket = channels[i].socket; if (channels[i].state == QHttpNetworkConnectionChannel::Wait4AuthState) { channels[i].state = QHttpNetworkConnectionChannel::IdleState; if (channels[i].reply) - sendRequest(socket); + channels[i].sendRequest(); } } } @@ -1069,6 +712,13 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 d->init(); } +QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, quint16 port, bool encrypt, QObject *parent) + : QObject(*(new QHttpNetworkConnectionPrivate(connectionCount, hostName, port, encrypt)), parent) +{ + Q_D(QHttpNetworkConnection); + d->init(); +} + QHttpNetworkConnection::~QHttpNetworkConnection() { } @@ -1215,6 +865,19 @@ void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int #endif //QT_NO_OPENSSL +#ifndef QT_NO_NETWORKPROXY +// only called from QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired, not +// from QHttpNetworkConnectionChannel::handleAuthenticationChallenge +// e.g. it is for SOCKS proxies which require authentication. +void QHttpNetworkConnectionPrivate::emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator* auth) +{ + Q_Q(QHttpNetworkConnection); + emit q->proxyAuthenticationRequired(proxy, auth, q); + int i = indexOf(chan->socket); + copyCredentials(i, auth, true); +} +#endif + QT_END_NAMESPACE diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 99dda2a..af764ed 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -89,6 +89,7 @@ class Q_AUTOTEST_EXPORT QHttpNetworkConnection : public QObject public: QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0); + QHttpNetworkConnection(quint16 channelCount, const QString &hostName, quint16 port = 80, bool encrypt = false, QObject *parent = 0); ~QHttpNetworkConnection(); //The hostname to which this is connected to. @@ -153,7 +154,11 @@ class QHttpNetworkConnectionPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QHttpNetworkConnection) public: + static const int defaultChannelCount; + static const int defaultPipelineLength; + QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt); + QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt); ~QHttpNetworkConnectionPrivate(); void init(); @@ -166,12 +171,13 @@ public: bool isSocketReading(QAbstractSocket *socket) const; QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request); - void unqueueAndSendRequest(QAbstractSocket *socket); + void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke + void dequeueAndSendRequest(QAbstractSocket *socket); void prepareRequest(HttpMessagePair &request); - bool sendRequest(QAbstractSocket *socket); - void receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply); - void resendCurrentRequest(QAbstractSocket *socket); - void closeChannel(int channel); + + void fillPipeline(QAbstractSocket *socket); + bool fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel); + void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy); // private slots @@ -179,9 +185,9 @@ public: void _q_restartAuthPendingRequests(); // send the currently blocked request void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request); - bool ensureConnection(QAbstractSocket *socket); + QString errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket); - void eraseData(QHttpNetworkReply *reply); + #ifndef QT_NO_COMPRESS bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete); #endif @@ -191,7 +197,7 @@ public: quint16 port; bool encrypt; - static const int channelCount; + const int channelCount; QHttpNetworkConnectionChannel *channels; // parallel connections to the server bool pendingAuthSignal; // there is an incomplete authentication signal @@ -199,14 +205,11 @@ public: qint64 uncompressedBytesAvailable(const QHttpNetworkReply &reply) const; qint64 uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const; - qint64 compressedBytesAvailable(const QHttpNetworkReply &reply) const; + void emitReplyError(QAbstractSocket *socket, QHttpNetworkReply *reply, QNetworkReply::NetworkError errorCode); bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend); - void allDone(QAbstractSocket *socket, QHttpNetworkReply *reply); - void handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply); - inline bool shouldEmitSignals(QHttpNetworkReply *reply); - inline bool expectContent(QHttpNetworkReply *reply); + #ifndef QT_NO_OPENSSL QSslConfiguration sslConfiguration(const QHttpNetworkReply &reply) const; @@ -214,6 +217,7 @@ public: #ifndef QT_NO_NETWORKPROXY QNetworkProxy networkProxy; + void emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator* auth); #endif //The request queues diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 5ffab76..9d78c55 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -41,6 +41,7 @@ #include "qhttpnetworkconnection_p.h" #include "qhttpnetworkconnectionchannel_p.h" +#include "private/qnoncontiguousbytedevice_p.h" #include <qpair.h> #include <qdebug.h> @@ -113,61 +114,646 @@ void QHttpNetworkConnectionChannel::close() } +bool QHttpNetworkConnectionChannel::sendRequest() +{ + switch (state) { + case QHttpNetworkConnectionChannel::IdleState: { // write the header + if (!ensureConnection()) { + // wait for the connection (and encryption) to be done + // sendRequest will be called again from either + // _q_connected or _q_encrypted + return false; + } + written = 0; // excluding the header + bytesTotal = 0; + if (reply) { + reply->d_func()->clear(); + reply->d_func()->connection = connection; + reply->d_func()->autoDecompress = request.d->autoDecompress; + reply->d_func()->pipeliningUsed = false; + } + state = QHttpNetworkConnectionChannel::WritingState; + pendingEncrypt = false; + // if the url contains authentication parameters, use the new ones + // both channels will use the new authentication parameters + if (!request.url().userInfo().isEmpty()) { + QUrl url = request.url(); + QAuthenticator &auth = authenticator; + if (url.userName() != auth.user() + || (!url.password().isEmpty() && url.password() != auth.password())) { + auth.setUser(url.userName()); + auth.setPassword(url.password()); + connection->d_func()->copyCredentials(connection->d_func()->indexOf(socket), &auth, false); + } + // clear the userinfo, since we use the same request for resending + // userinfo in url can conflict with the one in the authenticator + url.setUserInfo(QString()); + request.setUrl(url); + } + connection->d_func()->createAuthorization(socket, request); +#ifndef QT_NO_NETWORKPROXY + QByteArray header = QHttpNetworkRequestPrivate::header(request, + (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy)); +#else + QByteArray header = QHttpNetworkRequestPrivate::header(request, false); +#endif + socket->write(header); + QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); + if (uploadByteDevice) { + // connect the signals so this function gets called again + QObject::connect(uploadByteDevice, SIGNAL(readyRead()),this, SLOT(_q_uploadDataReadyRead())); + + bytesTotal = request.contentLength(); + } else { + state = QHttpNetworkConnectionChannel::WaitingState; + sendRequest(); + break; + } + // write the initial chunk together with the headers + // fall through + } + case QHttpNetworkConnectionChannel::WritingState: + { + // write the data + QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); + if (!uploadByteDevice || bytesTotal == written) { + if (uploadByteDevice) + emit reply->dataSendProgress(written, bytesTotal); + state = QHttpNetworkConnectionChannel::WaitingState; // now wait for response + sendRequest(); + break; + } + + // only feed the QTcpSocket buffer when there is less than 32 kB in it + const qint64 socketBufferFill = 32*1024; + const qint64 socketWriteMaxSize = 16*1024; + + +#ifndef QT_NO_OPENSSL + QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); + // if it is really an ssl socket, check more than just bytesToWrite() + while ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0)) + <= socketBufferFill && bytesTotal != written) +#else + while (socket->bytesToWrite() <= socketBufferFill + && bytesTotal != written) +#endif + { + // get pointer to upload data + qint64 currentReadSize; + qint64 desiredReadSize = qMin(socketWriteMaxSize, bytesTotal - written); + const char *readPointer = uploadByteDevice->readPointer(desiredReadSize, currentReadSize); + + if (currentReadSize == -1) { + // premature eof happened + connection->d_func()->emitReplyError(socket, reply, QNetworkReply::UnknownNetworkError); + return false; + break; + } else if (readPointer == 0 || currentReadSize == 0) { + // nothing to read currently, break the loop + break; + } else { + qint64 currentWriteSize = socket->write(readPointer, currentReadSize); + if (currentWriteSize == -1 || currentWriteSize != currentReadSize) { + // socket broke down + connection->d_func()->emitReplyError(socket, reply, QNetworkReply::UnknownNetworkError); + return false; + } else { + written += currentWriteSize; + uploadByteDevice->advanceReadPointer(currentWriteSize); + + emit reply->dataSendProgress(written, bytesTotal); + + if (written == bytesTotal) { + // make sure this function is called once again + state = QHttpNetworkConnectionChannel::WaitingState; + sendRequest(); + break; + } + } + } + } + break; + } + + case QHttpNetworkConnectionChannel::WaitingState: + { + QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); + if (uploadByteDevice) { + QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(_q_uploadDataReadyRead())); + } + + // HTTP pipelining + connection->d_func()->fillPipeline(socket); + socket->flush(); + + // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called + // this is needed if the sends an reply before we have finished sending the request. In that + // case receiveReply had been called before but ignored the server reply + receiveReply(); + break; + } + case QHttpNetworkConnectionChannel::ReadingState: + case QHttpNetworkConnectionChannel::Wait4AuthState: + // ignore _q_bytesWritten in these states + // fall through + default: + break; + } + return true; +} + + +void QHttpNetworkConnectionChannel::receiveReply() +{ + Q_ASSERT(socket); + + qint64 bytes = 0; + QAbstractSocket::SocketState socketState = socket->state(); + + // connection might be closed to signal the end of data + if (socketState == QAbstractSocket::UnconnectedState) { + if (!socket->bytesAvailable()) { + if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { + reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState; + this->state = QHttpNetworkConnectionChannel::IdleState; + allDone(); + } else { + // try to reconnect/resend before sending an error. + if (reconnectAttempts-- > 0) { + closeAndResendCurrentRequest(); + } else if (reply) { + reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket); + emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString); + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } + } + } + } + + // read loop for the response + while (socket->bytesAvailable()) { + QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState; + switch (state) { + case QHttpNetworkReplyPrivate::NothingDoneState: + case QHttpNetworkReplyPrivate::ReadingStatusState: { + eatWhitespace(); + qint64 statusBytes = reply->d_func()->readStatus(socket); + if (statusBytes == -1 && reconnectAttempts <= 0) { + // too many errors reading/receiving/parsing the status, close the socket and emit error + close(); + reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::ProtocolFailure, socket); + emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString); + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + break; + } else if (statusBytes == -1) { + reconnectAttempts--; + reply->d_func()->clear(); + closeAndResendCurrentRequest(); + break; + } + bytes += statusBytes; + lastStatus = reply->d_func()->statusCode; + break; + } + case QHttpNetworkReplyPrivate::ReadingHeaderState: + bytes += reply->d_func()->readHeader(socket); + if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { + if (reply->d_func()->isGzipped() && reply->d_func()->autoDecompress) { + // remove the Content-Length from header + reply->d_func()->removeAutoDecompressHeader(); + } else { + reply->d_func()->autoDecompress = false; + } + if (reply && reply->d_func()->statusCode == 100) { + reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState; + break; // ignore + } + if (reply->d_func()->shouldEmitSignals()) + emit reply->headerChanged(); + if (!reply->d_func()->expectContent()) { + reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState; + this->state = QHttpNetworkConnectionChannel::IdleState; + allDone(); + return; + } + } + break; + case QHttpNetworkReplyPrivate::ReadingDataState: { + if (!reply->d_func()->isChunked() && !reply->d_func()->autoDecompress + && reply->d_func()->bodyLength > 0) { + // bulk files like images should fulfill these properties and + // we can therefore save on memory copying + bytes = reply->d_func()->readBodyFast(socket, &reply->d_func()->responseData); + reply->d_func()->totalProgress += bytes; + if (reply->d_func()->shouldEmitSignals()) { + QPointer<QHttpNetworkReply> replyPointer = reply; + emit reply->readyRead(); + // make sure that the reply is valid + if (replyPointer.isNull()) + return; + emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); + // make sure that the reply is valid + if (replyPointer.isNull()) + return; + } + } + else + { + // use the traditional slower reading (for compressed encoding, chunked encoding, + // no content-length etc) + QByteDataBuffer byteDatas; + bytes = reply->d_func()->readBody(socket, &byteDatas); + if (bytes) { + if (reply->d_func()->autoDecompress) + reply->d_func()->appendCompressedReplyData(byteDatas); + else + reply->d_func()->appendUncompressedReplyData(byteDatas); + + if (!reply->d_func()->autoDecompress) { + reply->d_func()->totalProgress += bytes; + if (reply->d_func()->shouldEmitSignals()) { + QPointer<QHttpNetworkReply> replyPointer = reply; + // important: At the point of this readyRead(), the byteDatas list must be empty, + // else implicit sharing will trigger memcpy when the user is reading data! + emit reply->readyRead(); + // make sure that the reply is valid + if (replyPointer.isNull()) + return; + emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); + // make sure that the reply is valid + if (replyPointer.isNull()) + return; + } + } +#ifndef QT_NO_COMPRESS + else if (!expand(false)) { // expand a chunk if possible + return; // ### expand failed + } +#endif + } + } + if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) + break; + // everything done, fall through + } + case QHttpNetworkReplyPrivate::AllDoneState: + this->state = QHttpNetworkConnectionChannel::IdleState; + allDone(); + break; + default: + break; + } + } +} + +bool QHttpNetworkConnectionChannel::ensureConnection() +{ + // make sure that this socket is in a connected state, if not initiate + // connection to the host. + if (socket->state() != QAbstractSocket::ConnectedState) { + // connect to the host if not already connected. + // resend this request after we receive the disconnected signal + if (socket->state() == QAbstractSocket::ClosingState) { + resendCurrent = true; + return false; + } + state = QHttpNetworkConnectionChannel::ConnectingState; + pendingEncrypt = connection->d_func()->encrypt; + + // reset state + pipeliningSupported = PipeliningSupportUnknown; + + // This workaround is needed since we use QAuthenticator for NTLM authentication. The "phase == Done" + // is the usual criteria for emitting authentication signals. The "phase" is set to "Done" when the + // last header for Authorization is generated by the QAuthenticator. Basic & Digest logic does not + // check the "phase" for generating the Authorization header. NTLM authentication is a two stage + // process & needs the "phase". To make sure the QAuthenticator uses the current username/password + // the phase is reset to Start. + QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(authenticator); + if (priv && priv->phase == QAuthenticatorPrivate::Done) + priv->phase = QAuthenticatorPrivate::Start; + priv = QAuthenticatorPrivate::getPrivate(proxyAuthenticator); + if (priv && priv->phase == QAuthenticatorPrivate::Done) + priv->phase = QAuthenticatorPrivate::Start; + + QString connectHost = connection->d_func()->hostName; + qint16 connectPort = connection->d_func()->port; + +#ifndef QT_NO_NETWORKPROXY + // HTTPS always use transparent proxy. + if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !connection->d_func()->encrypt) { + connectHost = connection->d_func()->networkProxy.hostName(); + connectPort = connection->d_func()->networkProxy.port(); + } +#endif + if (connection->d_func()->encrypt) { +#ifndef QT_NO_OPENSSL + QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); + sslSocket->connectToHostEncrypted(connectHost, connectPort); + if (ignoreAllSslErrors) + sslSocket->ignoreSslErrors(); + sslSocket->ignoreSslErrors(ignoreSslErrorsList); +#else + connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError); +#endif + } else { + socket->connectToHost(connectHost, connectPort); + } + return false; + } + return true; +} + + +#ifndef QT_NO_COMPRESS +bool QHttpNetworkConnectionChannel::expand(bool dataComplete) +{ + Q_ASSERT(socket); + Q_ASSERT(reply); + + qint64 total = reply->d_func()->compressedData.size(); + if (total >= CHUNK || dataComplete) { + // uncompress the data + QByteArray content, inflated; + content = reply->d_func()->compressedData; + reply->d_func()->compressedData.clear(); + + int ret = Z_OK; + if (content.size()) + ret = reply->d_func()->gunzipBodyPartially(content, inflated); + int retCheck = (dataComplete) ? Z_STREAM_END : Z_OK; + if (ret >= retCheck) { + if (inflated.size()) { + reply->d_func()->totalProgress += inflated.size(); + reply->d_func()->appendUncompressedReplyData(inflated); + if (reply->d_func()->shouldEmitSignals()) { + QPointer<QHttpNetworkReply> replyPointer = reply; + // important: At the point of this readyRead(), inflated must be cleared, + // else implicit sharing will trigger memcpy when the user is reading data! + emit reply->readyRead(); + // make sure that the reply is valid + if (replyPointer.isNull()) + return true; + emit reply->dataReadProgress(reply->d_func()->totalProgress, 0); + // make sure that the reply is valid + if (replyPointer.isNull()) + return true; + + } + } + } else { + connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolFailure); + return false; + } + } + return true; +} +#endif + + +void QHttpNetworkConnectionChannel::allDone() +{ +#ifndef QT_NO_COMPRESS + // expand the whole data. + if (reply->d_func()->expectContent() && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd) + expand(true); // ### if expand returns false, its an error +#endif + // while handling 401 & 407, we might reset the status code, so save this. + bool emitFinished = reply->d_func()->shouldEmitSignals(); + handleStatus(); + // ### at this point there should be no more data on the socket + // close if server requested + if (reply->d_func()->connectionCloseEnabled()) + close(); + // queue the finished signal, this is required since we might send new requests from + // slot connected to it. The socket will not fire readyRead signal, if we are already + // in the slot connected to readyRead + if (emitFinished) + QMetaObject::invokeMethod(reply, "finished", Qt::QueuedConnection); + // reset the reconnection attempts after we receive a complete reply. + // in case of failures, each channel will attempt two reconnects before emitting error. + reconnectAttempts = 2; + + detectPipeliningSupport(); + + // move next from pipeline to current request + if (!alreadyPipelinedRequests.isEmpty()) { + if (resendCurrent || reply->d_func()->connectionCloseEnabled() || socket->state() != QAbstractSocket::ConnectedState) { + // move the pipelined ones back to the main queue + requeueCurrentlyPipelinedRequests(); + } else { + // there were requests pipelined in and we can continue + HttpMessagePair messagePair = alreadyPipelinedRequests.takeFirst(); + + request = messagePair.first; + reply = messagePair.second; + state = QHttpNetworkConnectionChannel::ReadingState; + resendCurrent = false; + + written = 0; // message body, excluding the header, irrelevant here + bytesTotal = 0; // message body total, excluding the header, irrelevant here + + // pipeline even more + connection->d_func()->fillPipeline(socket); + + // continue reading + receiveReply(); + } + } else if (alreadyPipelinedRequests.isEmpty() && socket->bytesAvailable() > 0) { + eatWhitespace(); + // this is weird. we had nothing pipelined but still bytes available. better close it. + if (socket->bytesAvailable() > 0) + close(); + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } else if (alreadyPipelinedRequests.isEmpty()) { + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } +} + +void QHttpNetworkConnectionChannel::detectPipeliningSupport() +{ + // detect HTTP Pipelining support + QByteArray serverHeaderField = reply->headerField("Server"); + if ( + // check for broken servers in server reply header + // this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining + (!serverHeaderField.contains("Microsoft-IIS/4.")) + && (!serverHeaderField.contains("Microsoft-IIS/5.")) + && (!serverHeaderField.contains("Netscape-Enterprise/3.")) + // check for HTTP/1.1 + && (reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1) + // check for not having connection close + && (!reply->d_func()->connectionCloseEnabled()) + // check if it is still connected + && (socket->state() == QAbstractSocket::ConnectedState) + ) { + pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningProbablySupported; + } else { + pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown; + } +} + +// called when the connection broke and we need to queue some pipelined requests again +void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests() +{ + for (int i = 0; i < alreadyPipelinedRequests.length(); i++) + connection->d_func()->requeueRequest(alreadyPipelinedRequests.at(i)); + alreadyPipelinedRequests.clear(); + + close(); + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); +} + +void QHttpNetworkConnectionChannel::eatWhitespace() +{ + char c; + while (socket->bytesAvailable()) { + if (socket->peek(&c, 1) != 1) + return; + + // read all whitespace and line endings + if (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31) { + socket->read(&c, 1); + continue; + } else { + break; + } + } +} + +void QHttpNetworkConnectionChannel::handleStatus() +{ + Q_ASSERT(socket); + Q_ASSERT(reply); + + int statusCode = reply->statusCode(); + bool resend = false; + + switch (statusCode) { + case 401: // auth required + case 407: // proxy auth required + if (connection->d_func()->handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend)) { + if (resend) { + QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); + if (uploadByteDevice) { + if (uploadByteDevice->reset()) { + written = 0; + } else { + connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ContentReSendError); + break; + } + } + + reply->d_func()->eraseData(); + + if (alreadyPipelinedRequests.isEmpty()) { + // this does a re-send without closing the connection + resendCurrent = true; + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } else { + // we had requests pipelined.. better close the connection in closeAndResendCurrentRequest + closeAndResendCurrentRequest(); + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } + } + } else { + emit reply->headerChanged(); + emit reply->readyRead(); + QNetworkReply::NetworkError errorCode = (statusCode == 407) + ? QNetworkReply::ProxyAuthenticationRequiredError + : QNetworkReply::AuthenticationRequiredError; + reply->d_func()->errorString = connection->d_func()->errorDetail(errorCode, socket); + emit connection->error(errorCode, reply->d_func()->errorString); + emit reply->finished(); + } + break; + default: + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } +} + +void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) +{ + // this is only called for simple GET + + QHttpNetworkRequest &request = pair.first; + QHttpNetworkReply *reply = pair.second; + if (reply) { + reply->d_func()->clear(); + reply->d_func()->connection = connection; + reply->d_func()->autoDecompress = request.d->autoDecompress; + reply->d_func()->pipeliningUsed = true; + } + +#ifndef QT_NO_NETWORKPROXY + QByteArray header = QHttpNetworkRequestPrivate::header(request, + (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy)); +#else + QByteArray header = QHttpNetworkRequestPrivate::header(request, false); +#endif + socket->write(header); + + alreadyPipelinedRequests.append(pair); +} + +void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest() +{ + requeueCurrentlyPipelinedRequests(); + close(); + resendCurrent = true; + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); +} + //private slots void QHttpNetworkConnectionChannel::_q_readyRead() { - if (!socket) - return; // ### error if (connection->d_func()->isSocketWaiting(socket) || connection->d_func()->isSocketReading(socket)) { state = QHttpNetworkConnectionChannel::ReadingState; if (reply) - connection->d_func()->receiveReply(socket, reply); + receiveReply(); } - // ### error } void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes) { Q_UNUSED(bytes); - if (!socket) - return; // ### error // bytes have been written to the socket. write even more of them :) if (connection->d_func()->isSocketWriting(socket)) - connection->d_func()->sendRequest(socket); + sendRequest(); // otherwise we do nothing } void QHttpNetworkConnectionChannel::_q_disconnected() { - if (!socket) - return; // ### error // read the available data before closing if (connection->d_func()->isSocketWaiting(socket) || connection->d_func()->isSocketReading(socket)) { state = QHttpNetworkConnectionChannel::ReadingState; if (reply) - connection->d_func()->receiveReply(socket, reply); + receiveReply(); } else if (state == QHttpNetworkConnectionChannel::IdleState && resendCurrent) { // re-sending request because the socket was in ClosingState QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } state = QHttpNetworkConnectionChannel::IdleState; + + requeueCurrentlyPipelinedRequests(); } void QHttpNetworkConnectionChannel::_q_connected() { - if (!socket) - return; // ### error - // improve performance since we get the request sent by the kernel ASAP socket->setSocketOption(QAbstractSocket::LowDelayOption, 1); + pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown; + // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again! //channels[i].reconnectAttempts = 2; if (!pendingEncrypt) { state = QHttpNetworkConnectionChannel::IdleState; if (reply) - connection->d_func()->sendRequest(socket); + sendRequest(); else close(); } @@ -193,7 +779,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket // while "Reading" the _q_disconnected() will handle this. if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { if (reconnectAttempts-- > 0) { - connection->d_func()->resendCurrentRequest(socket); + closeAndResendCurrentRequest(); return; } else { send2Reply = true; @@ -206,7 +792,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket case QAbstractSocket::SocketTimeoutError: // try to reconnect/resend before sending an error. if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) { - connection->d_func()->resendCurrentRequest(socket); + closeAndResendCurrentRequest(); return; } send2Reply = true; @@ -244,13 +830,13 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket #ifndef QT_NO_NETWORKPROXY void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth) { - emit connection->proxyAuthenticationRequired(proxy, auth, connection); + connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth); } #endif void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead() { - connection->d_func()->sendRequest(socket); + sendRequest(); } #ifndef QT_NO_OPENSSL @@ -259,7 +845,7 @@ void QHttpNetworkConnectionChannel::_q_encrypted() if (!socket) return; // ### error state = QHttpNetworkConnectionChannel::IdleState; - connection->d_func()->sendRequest(socket); + sendRequest(); } void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors) diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index f937669..220b72c 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -82,10 +82,14 @@ class QHttpNetworkReply; class QByteArray; class QHttpNetworkConnection; +#ifndef HttpMessagePair +typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair; +#endif + class QHttpNetworkConnectionChannel : public QObject { Q_OBJECT public: - enum ChannelState { + enum ChannelState { IdleState = 0, // ready to send request ConnectingState = 1, // connecting to host WritingState = 2, // writing the data @@ -112,12 +116,24 @@ public: bool ignoreAllSslErrors; QList<QSslError> ignoreSslErrorsList; #endif + + // HTTP pipelining -> http://en.wikipedia.org/wiki/Http_pipelining + enum PipeliningSupport { + PipeliningSupportUnknown, // default for a new connection + PipeliningProbablySupported, // after having received a server response that indicates support + PipeliningNotSupported // currently not used + }; + PipeliningSupport pipeliningSupported; + QList<HttpMessagePair> alreadyPipelinedRequests; + + QHttpNetworkConnectionChannel() : socket(0), state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false), lastStatus(0), pendingEncrypt(false), reconnectAttempts(2), authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None) #ifndef QT_NO_OPENSSL , ignoreAllSslErrors(false) #endif + , pipeliningSupported(PipeliningSupportUnknown) , connection(0) {} @@ -127,6 +143,23 @@ public: void init(); void close(); + bool sendRequest(); + void receiveReply(); + + bool ensureConnection(); + + bool expand(bool dataComplete); + void allDone(); // reply header + body have been read + void handleStatus(); // called from allDone() + + void pipelineInto(HttpMessagePair &pair); + void requeueCurrentlyPipelinedRequests(); + void detectPipeliningSupport(); + + void closeAndResendCurrentRequest(); + + void eatWhitespace(); + protected slots: void _q_bytesWritten(qint64 bytes); // proceed sending void _q_readyRead(); // pending data to read diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index c31c59c..4a315e4 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -187,6 +187,10 @@ bool QHttpNetworkReply::isFinished() const return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; } +bool QHttpNetworkReply::isPipeliningUsed() const +{ + return d_func()->pipeliningUsed; +} QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) @@ -195,6 +199,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) chunkedTransferEncoding(0), currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), autoDecompress(false), responseData(), requestIsPrepared(false) + ,pipeliningUsed(false) { } @@ -418,20 +423,26 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) } bool ok = parseStatus(fragment); state = ReadingHeaderState; - fragment.clear(); // next fragment - - if (!ok) + fragment.clear(); + if (!ok) { return -1; + } break; } else { c = 0; - bytes += socket->read(&c, 1); + int haveRead = socket->read(&c, 1); + if (haveRead == -1) + return -1; + bytes += haveRead; fragment.append(c); } // is this a valid reply? if (fragment.length() >= 5 && !fragment.startsWith("HTTP/")) + { + fragment.clear(); return -1; + } } @@ -568,7 +579,6 @@ qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QByteData if (contentRead + haveRead == bodyLength) { state = AllDoneState; - socket->readAll(); // Read the rest to clean (CRLF) ### will break pipelining } contentRead += haveRead; @@ -588,8 +598,6 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuff } else { bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable()); } - if (state == AllDoneState) - socket->readAll(); // Read the rest to clean (CRLF) ### will break pipelining contentRead += bytes; return bytes; } @@ -717,6 +725,33 @@ void QHttpNetworkReplyPrivate::appendCompressedReplyData(QByteDataBuffer &data) } +bool QHttpNetworkReplyPrivate::shouldEmitSignals() +{ + // for 401 & 407 don't emit the data signals. Content along with these + // responses are send only if the authentication fails. + return (statusCode != 401 && statusCode != 407); +} + +bool QHttpNetworkReplyPrivate::expectContent() +{ + // check whether we can expect content after the headers (rfc 2616, sec4.4) + if ((statusCode >= 100 && statusCode < 200) + || statusCode == 204 || statusCode == 304) + return false; + if (request.operation() == QHttpNetworkRequest::Head) + return !shouldEmitSignals(); + if (contentLength() == 0) + return false; + return true; +} + +void QHttpNetworkReplyPrivate::eraseData() +{ + compressedData.clear(); + responseData.clear(); +} + + // SSL support below #ifndef QT_NO_OPENSSL diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 5aee067..8d4d724 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -128,6 +128,8 @@ public: bool isFinished() const; + bool isPipeliningUsed() const; + #ifndef QT_NO_OPENSSL QSslConfiguration sslConfiguration() const; void setSslConfiguration(const QSslConfiguration &config); @@ -177,6 +179,10 @@ public: void appendUncompressedReplyData(QByteDataBuffer &data); void appendCompressedReplyData(QByteDataBuffer &data); + bool shouldEmitSignals(); + bool expectContent(); + void eraseData(); + qint64 bytesAvailable() const; bool isChunked(); bool connectionCloseEnabled(); @@ -219,6 +225,8 @@ public: QByteDataBuffer responseData; // uncompressed body QByteArray compressedData; // compressed body (temporary) bool requestIsPrepared; + + bool pipeliningUsed; }; diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 693e1f4..8b2c4e9 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op, QHttpNetworkRequest::Priority pri, const QUrl &newUrl) : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0), - autoDecompress(false) + autoDecompress(false), pipeliningAllowed(false) { } @@ -60,6 +60,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest priority = other.priority; uploadByteDevice = other.uploadByteDevice; autoDecompress = other.autoDecompress; + pipeliningAllowed = other.pipeliningAllowed; } QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate() @@ -239,6 +240,16 @@ void QHttpNetworkRequest::setPriority(Priority priority) d->priority = priority; } +bool QHttpNetworkRequest::isPipeliningAllowed() const +{ + return d->pipeliningAllowed; +} + +void QHttpNetworkRequest::setPipeliningAllowed(bool b) +{ + d->pipeliningAllowed = b; +} + void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd) { d->uploadByteDevice = bd; diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index ffacb14..2468be9 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -106,6 +106,9 @@ public: Priority priority() const; void setPriority(Priority priority); + bool isPipeliningAllowed() const; + void setPipeliningAllowed(bool b); + void setUploadByteDevice(QNonContiguousByteDevice *bd); QNonContiguousByteDevice* uploadByteDevice() const; @@ -113,6 +116,7 @@ private: QSharedDataPointer<QHttpNetworkRequestPrivate> d; friend class QHttpNetworkRequestPrivate; friend class QHttpNetworkConnectionPrivate; + friend class QHttpNetworkConnectionChannel; }; class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate @@ -132,6 +136,7 @@ public: QHttpNetworkRequest::Priority priority; mutable QNonContiguousByteDevice* uploadByteDevice; bool autoDecompress; + bool pipeliningAllowed; }; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 479990a..3532de8 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -516,6 +516,9 @@ void QNetworkAccessHttpBackend::postRequest() return; // no need to send the request! :) } + if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true) + httpRequest.setPipeliningAllowed(true); + httpReply = http->sendRequest(httpRequest); httpReply->setParent(this); #ifndef QT_NO_OPENSSL @@ -713,6 +716,8 @@ void QNetworkAccessHttpBackend::checkForRedirect(const int statusCode) void QNetworkAccessHttpBackend::replyHeaderChanged() { + setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, httpReply->isPipeliningUsed()); + // reconstruct the HTTP header QList<QPair<QByteArray, QByteArray> > headerMap = httpReply->header(); QList<QPair<QByteArray, QByteArray> >::ConstIterator it = headerMap.constBegin(), diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index ce5f6c7..839bf31 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -804,7 +804,13 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(QNetworkAccessBac QAuthenticator *authenticator) { Q_Q(QNetworkAccessManager); - + // ### FIXME Tracking of successful authentications + // This code is a bit broken right now for SOCKS authentication + // first request: proxyAuthenticationRequired gets emitted, credentials gets saved + // second request: (proxy != backend->reply->lastProxyAuthentication) does not evaluate to true, + // proxyAuthenticationRequired gets emitted again + // possible solution: some tracking inside the authenticator + // or a new function proxyAuthenticationSucceeded(true|false) if (proxy != backend->reply->lastProxyAuthentication) { QNetworkAuthenticationCredential *cred = fetchCachedCredentials(proxy); if (cred) { diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 721f8c4..c6cbddd 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -167,6 +167,16 @@ QT_BEGIN_NAMESPACE When using this flag with sequential upload data, the ContentLengthHeader header must be set. + \value HttpPipeliningAllowedAttribute + Requests only, type: QVariant::Bool (default: false) + Indicates whether the QNetworkAccessManager code is + allowed to use HTTP pipelining with this request. + + \value HttpPipeliningWasUsedAttribute + Replies only, type: QVariant::Bool + Indicates whether the HTTP pipelining was used for receiving + this reply. + \value User Special type. Additional information can be passed in QVariants with types ranging from User to UserMax. The default diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index aaeed48..2c26038 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -76,6 +76,8 @@ public: CacheSaveControlAttribute, SourceIsFromCacheAttribute, DoNotBufferUploadDataAttribute, + HttpPipeliningAllowedAttribute, + HttpPipeliningWasUsedAttribute, User = 1000, UserMax = 32767 diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index ee1369d..77b2a7e 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -162,16 +162,13 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, QWindowsSockInit bust; // makes sure WSAStartup was callled #endif - // Support for IDNA - QString lookup = QString::fromLatin1(QUrl::toAce(name)); - QHostInfoResult *result = new QHostInfoResult; result->autoDelete = false; QObject::connect(result, SIGNAL(resultsReady(QHostInfo)), receiver, member); int id = result->lookupId = theIdCounter.fetchAndAddRelaxed(1); - if (lookup.isEmpty()) { + if (name.isEmpty()) { QHostInfo info(id); info.setError(QHostInfo::HostNotFound); info.setErrorString(QObject::tr("No host name given")); @@ -182,7 +179,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, } QHostInfoAgent *agent = theAgent(); - agent->addHostName(lookup, result); + agent->addHostName(name, result); #if !defined QT_NO_THREAD if (!agent->isRunning()) @@ -226,13 +223,7 @@ QHostInfo QHostInfo::fromName(const QString &name) qDebug("QHostInfo::fromName(\"%s\")",name.toLatin1().constData()); #endif - if (!name.isEmpty()) - return QHostInfoAgent::fromName(QLatin1String(QUrl::toAce(name))); - - QHostInfo retval; - retval.d->err = HostNotFound; - retval.d->errorStr = QObject::tr("No host name given"); - return retval; + return QHostInfoAgent::fromName(name); } /*! diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 4a23399..e3d51e7 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -124,7 +124,6 @@ static void resolveLibrary() QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QHostInfo results; - results.setHostName(hostName); #if defined(QHOSTINFO_DEBUG) qDebug("QHostInfoAgent::fromName(%s) looking up...", @@ -194,6 +193,22 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) #endif } + // IDN support + QByteArray aceHostname; + if (results.hostName().isEmpty()) { + // it's a hostname resolution + aceHostname = QUrl::toAce(hostName); + results.setHostName(hostName); + if (aceHostname.isEmpty()) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(hostName.isEmpty() ? QObject::tr("No host name given") : QObject::tr("Invalid hostname")); + return results; + } + } else { + // it's an IP reverse resolution + aceHostname = results.hostName().toLatin1(); + } + #if !defined (QT_NO_GETADDRINFO) // Call getaddrinfo, and place all IPv4 addresses at the start and // the IPv6 addresses at the end of the address list in results. @@ -205,12 +220,12 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) hints.ai_flags = Q_ADDRCONFIG; #endif - int result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res); + int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); # ifdef Q_ADDRCONFIG if (result == EAI_BADFLAGS) { // if the lookup failed with AI_ADDRCONFIG set, try again without it hints.ai_flags = 0; - result = getaddrinfo(hostName.toLatin1().constData(), 0, &hints, &res); + result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); } # endif @@ -264,7 +279,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // use one QHostInfoAgent, but if more agents are introduced, locking // must be provided. QMutexLocker locker(::getHostByNameMutex()); - hostent *result = gethostbyname(hostName.toLatin1().constData()); + hostent *result = gethostbyname(aceHostname.constData()); if (result) { if (result->h_addrtype == AF_INET) { QList<QHostAddress> addresses; diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index 93dc720..c5dc2d2 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -52,6 +52,7 @@ #include <qlibrary.h> #include <qtimer.h> #include <qmutex.h> +#include <qurl.h> #include <private/qmutexpool_p.h> QT_BEGIN_NAMESPACE @@ -129,7 +130,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) } QHostInfo results; - results.setHostName(hostName); #if defined(QHOSTINFO_DEBUG) qDebug("QHostInfoAgent::fromName(%p): looking up \"%s\" (IPv6 support is %s)", @@ -178,12 +178,28 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) } } + // IDN support + QByteArray aceHostname; + if (results.hostName().isEmpty()) { + // it's a hostname resolution + aceHostname = QUrl::toAce(hostName); + results.setHostName(hostName); + if (aceHostname.isEmpty()) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(hostName.isEmpty() ? QObject::tr("No host name given") : QObject::tr("Invalid hostname")); + return results; + } + } else { + // it's an IP reverse resolution + aceHostname = results.hostName().toLatin1(); + } + if (local_getaddrinfo && local_freeaddrinfo) { // Call getaddrinfo, and place all IPv4 addresses at the start // and the IPv6 addresses at the end of the address list in // results. qt_addrinfo *res; - int err = local_getaddrinfo(hostName.toLatin1().constData(), 0, 0, &res); + int err = local_getaddrinfo(aceHostname.constData(), 0, 0, &res); if (err == 0) { QList<QHostAddress> addresses; for (qt_addrinfo *p = res; p != 0; p = p->ai_next) { @@ -218,7 +234,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) } } else { // Fall back to gethostbyname, which only supports IPv4. - hostent *ent = gethostbyname(hostName.toLatin1().constData()); + hostent *ent = gethostbyname(aceHostname.constData()); if (ent) { char **p; QList<QHostAddress> addresses; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index c1e39a7..e654f25 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -246,6 +246,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) #ifdef QT_OPENGL_ES_2 QDataBuffer<uchar> buffer(4*oldWidth*oldHeight); + buffer.resize(4*oldWidth*oldHeight); glReadPixels(0, 0, oldWidth, oldHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data()); // do an in-place conversion from GL_RGBA to GL_ALPHA diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index e031fb5..d3c0bf1 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1302,7 +1302,6 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) #if defined(QT_OPENGL_ES) eglContext = 0; #endif - pbo = 0; fbo = 0; crWin = false; initDone = false; @@ -1646,12 +1645,6 @@ QGLContext::~QGLContext() void QGLContextPrivate::cleanup() { - Q_Q(QGLContext); - if (pbo) { - QGLContext *ctx = q; - glDeleteBuffers(1, &pbo); - pbo = 0; - } } typedef QHash<QString, GLuint> QGLDDSCache; @@ -1915,14 +1908,6 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G QGLContext *ctx = q; - bool use_pbo = false; - if (QGLExtensions::glExtensions & QGLExtensions::PixelBufferObject) { - - use_pbo = qt_resolve_buffer_extensions(ctx); - if (use_pbo && pbo == 0) - glGenBuffers(1, &pbo); - } - // the GL_BGRA format is only present in GL version >= 1.2 GLenum texture_format = (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) ? GL_BGRA : GL_RGBA; @@ -1957,20 +1942,10 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G glTexParameterf(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); #endif glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - - // Mipmap generation causes huge slowdown with PBO's for some reason - use_pbo = false; } else { glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } - uchar *ptr = 0; - if (use_pbo) { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); - glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, img.width() * img.height() * 4, 0, GL_STREAM_DRAW_ARB); - ptr = reinterpret_cast<uchar *>(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB)); - } - QImage::Format target_format = img.format(); // Note: the clean param is only true when a texture is bound // from the QOpenGLPaintEngine - in that case we have to force @@ -1980,21 +1955,10 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G if (img.format() != target_format) img = img.convertToFormat(target_format); - if (ptr) { - QImage buffer(ptr, img.width(), img.height(), target_format); - convertToGLFormatHelper(buffer, img, texture_format); - glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); - glTexImage2D(target, 0, format, img.width(), img.height(), 0, texture_format, - GL_UNSIGNED_BYTE, 0); - } else { - QImage tx(scale ? QSize(tx_w, tx_h) : img.size(), target_format); - convertToGLFormatHelper(tx, img, texture_format); - glTexImage2D(target, 0, format, tx.width(), tx.height(), 0, texture_format, - GL_UNSIGNED_BYTE, tx.bits()); - } - - if (use_pbo) - glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); + QImage tx(scale ? QSize(tx_w, tx_h) : img.size(), target_format); + convertToGLFormatHelper(tx, img, texture_format); + glTexImage2D(target, 0, format, tx.width(), tx.height(), 0, texture_format, + GL_UNSIGNED_BYTE, tx.bits()); // this assumes the size of a texture is always smaller than the max cache size int cost = img.width()*img.height()*4/1024; @@ -3409,12 +3373,15 @@ bool QGLWidget::event(QEvent *e) setContext(new QGLContext(d->glcx->requestedFormat(), this)); // ### recreating the overlay isn't supported atm } + } + #if defined(QT_OPENGL_ES) - // The window may have been re-created during re-parent - if so, the EGL + if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) { + // The window may have been re-created during re-parent or state change - if so, the EGL // surface will need to be re-created. d->recreateEglSurface(false); -#endif } +#endif #elif defined(Q_WS_WIN) if (e->type() == QEvent::ParentChange) { QGLContext *newContext = new QGLContext(d->glcx->requestedFormat(), this); diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 92aea6c..ab040ed 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -252,7 +252,6 @@ public: #endif QGLFormat glFormat; QGLFormat reqFormat; - GLuint pbo; GLuint fbo; uint valid : 1; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index ba715c3..956189c 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -559,7 +559,9 @@ void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, QRasterPaintEngine::drawPixmap(r, pixmap, sr); } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) - || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) { + || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip + || (state()->renderHints & QPainter::SmoothPixmapTransform + && state()->matrix.mapRect(r).size() != sr.size())) { RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ); d->lock(); @@ -593,7 +595,8 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset); } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) - || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) { + || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip + || (state()->renderHints & QPainter::SmoothPixmapTransform && state()->matrix.isScaling())) { RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset); const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ); d->lock(); @@ -709,7 +712,8 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) case Qt::TexturePattern: { if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) - || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)) { + || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) + || (state()->renderHints & QPainter::SmoothPixmapTransform && state()->matrix.isScaling())) { break; } @@ -843,6 +847,13 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m { if (!surface) return; + + static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0; + if (forceRasterFallBack) { + compositionModeStatus = 0; + return; + } + compositionModeStatus = PorterDuff_SupportedBlits; switch (mode) { case QPainter::CompositionMode_Clear: diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index dc53847..45de07a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1029,10 +1029,10 @@ bool QDirectFBScreen::connect(const QString &displaySpec) surface = createDFBSurface(description, DontTrackSurface); #endif // Work out what format we're going to use for surfaces with an alpha channel - d_ptr->alphaPixmapFormat = QDirectFBScreen::getImageFormat(surface); + QImage::Format pixelFormat = QDirectFBScreen::getImageFormat(surface); + d_ptr->alphaPixmapFormat = pixelFormat; - setPixelFormat(d_ptr->alphaPixmapFormat); - switch (d_ptr->alphaPixmapFormat) { + switch (pixelFormat) { case QImage::Format_RGB666: d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied; break; @@ -1040,9 +1040,9 @@ bool QDirectFBScreen::connect(const QString &displaySpec) d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied; break; case QImage::Format_RGB32: - qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the RGB32 pixelformat. " - "We recommmend using ARGB instead"); - return false; + pixelFormat = d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied; + // ### Format_RGB32 doesn't work so well with Qt. Force ARGB32 for windows/pixmaps + break; case QImage::Format_Indexed8: qWarning("QDirectFBScreen::connect(). Qt/DirectFB does not work with the LUT8 pixelformat."); return false; @@ -1064,8 +1064,8 @@ bool QDirectFBScreen::connect(const QString &displaySpec) // works already break; } - - QScreen::d = ::depth(pixelFormat()); + setPixelFormat(pixelFormat); + QScreen::d = ::depth(pixelFormat); data = 0; lstep = 0; size = 0; diff --git a/src/plugins/script/script.pro b/src/plugins/script/script.pro index dbcecea..eaae56b 100644 --- a/src/plugins/script/script.pro +++ b/src/plugins/script/script.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -contains(QT_CONFIG, dbus):SUBDIRS += qtdbus +contains(QT_CONFIG, script):contains(QT_CONFIG, dbus):SUBDIRS += qtdbus diff --git a/src/script/api/api.pri b/src/script/api/api.pri new file mode 100644 index 0000000..17ec9b6 --- /dev/null +++ b/src/script/api/api.pri @@ -0,0 +1,32 @@ +SOURCES += \ + $$PWD/qscriptclass.cpp \ + $$PWD/qscriptclasspropertyiterator.cpp \ + $$PWD/qscriptcontext.cpp \ + $$PWD/qscriptcontextinfo.cpp \ + $$PWD/qscriptengine.cpp \ + $$PWD/qscriptengineagent.cpp \ + $$PWD/qscriptextensionplugin.cpp \ + $$PWD/qscriptstring.cpp \ + $$PWD/qscriptvalue.cpp \ + $$PWD/qscriptvalueiterator.cpp \ + $$PWD/qscriptable.cpp + +HEADERS += \ + $$PWD/qscriptclass.h \ + $$PWD/qscriptclasspropertyiterator.h \ + $$PWD/qscriptcontext.h \ + $$PWD/qscriptcontext_p.h \ + $$PWD/qscriptcontextinfo.h \ + $$PWD/qscriptengine.h \ + $$PWD/qscriptengine_p.h \ + $$PWD/qscriptengineagent.h \ + $$PWD/qscriptengineagent_p.h \ + $$PWD/qscriptextensioninterface.h \ + $$PWD/qscriptextensionplugin.h \ + $$PWD/qscriptstring.h \ + $$PWD/qscriptstring_p.h \ + $$PWD/qscriptvalue.h \ + $$PWD/qscriptvalue_p.h \ + $$PWD/qscriptvalueiterator.h \ + $$PWD/qscriptable.h \ + $$PWD/qscriptable_p.h diff --git a/src/script/qscriptable.cpp b/src/script/api/qscriptable.cpp index 97c0173..eb5972c 100644 --- a/src/script/qscriptable.cpp +++ b/src/script/api/qscriptable.cpp @@ -40,16 +40,8 @@ ****************************************************************************/ #include "qscriptable.h" - -#ifndef QT_NO_QOBJECT - -#ifndef QT_NO_SCRIPT - #include "qscriptable_p.h" - #include "qscriptengine.h" -#include "qscriptcontext.h" -#include "qscriptvalue.h" QT_BEGIN_NAMESPACE @@ -189,7 +181,4 @@ QScriptValue QScriptable::argument(int index) const return QScriptValue(); } -#endif // QT_NO_SCRIPT -#endif // QT_NO_QOBJECT - QT_END_NAMESPACE diff --git a/src/script/qscriptable.h b/src/script/api/qscriptable.h index eef7ae4..5434cd9 100644 --- a/src/script/qscriptable.h +++ b/src/script/api/qscriptable.h @@ -44,8 +44,6 @@ #include <QtCore/qobjectdefs.h> -#ifndef QT_NO_SCRIPT - QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -85,5 +83,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT #endif // QSCRIPTABLE_H diff --git a/src/script/qscriptable_p.h b/src/script/api/qscriptable_p.h index c8400e0..a32422d 100644 --- a/src/script/qscriptable_p.h +++ b/src/script/api/qscriptable_p.h @@ -42,8 +42,6 @@ #ifndef QSCRIPTABLE_P_H #define QSCRIPTABLE_P_H -#include <QtCore/qobjectdefs.h> - // // W A R N I N G // ------------- @@ -55,12 +53,11 @@ // We mean it. // -#ifndef QT_NO_SCRIPT +#include <QtCore/qobjectdefs.h> QT_BEGIN_NAMESPACE -class QScriptEngine; - +class QScriptable; class QScriptablePrivate { Q_DECLARE_PUBLIC(QScriptable) @@ -79,6 +76,4 @@ public: QT_END_NAMESPACE -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/qscriptclass.cpp b/src/script/api/qscriptclass.cpp index 1df57d0..cff6ce5 100644 --- a/src/script/qscriptclass.cpp +++ b/src/script/api/qscriptclass.cpp @@ -34,31 +34,13 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qscriptclass.h" - -#ifndef QT_NO_SCRIPT - -#include <QtCore/qstringlist.h> - -#include "qscriptclasspropertyiterator.h" #include "qscriptstring.h" -#include "qscriptstring_p.h" -#include "qscriptclass_p.h" -#include "qscriptclassinfo_p.h" -#include "qscriptengine_p.h" -#include "qscriptcontext_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptfunction_p.h" - -Q_DECLARE_METATYPE(QScriptContext*) -Q_DECLARE_METATYPE(QScriptValueList) QT_BEGIN_NAMESPACE @@ -69,7 +51,7 @@ QT_BEGIN_NAMESPACE \brief The QScriptClass class provides an interface for defining custom behavior of (a class of) Qt Script objects. \ingroup script - + \mainclass The QScriptClass class defines an interface for handling various aspects of interaction with the Qt Script objects associated with @@ -149,292 +131,27 @@ QT_BEGIN_NAMESPACE \sa queryProperty() */ -class QScriptCustomClassData : public QScriptClassData +class QScriptClassPrivate { + Q_DECLARE_PUBLIC(QScriptClass) public: - QScriptCustomClassData(QScriptClass *klass); - ~QScriptCustomClassData(); - - virtual void mark(const QScriptValueImpl &object, int generation); - virtual bool resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode access); - virtual bool get(const QScriptValueImpl &obj, const QScript::Member &m, - QScriptValueImpl *result); - virtual bool put(QScriptValueImpl *object, const QScript::Member &member, - const QScriptValueImpl &value); - virtual bool removeMember(const QScriptValueImpl &object, - const QScript::Member &member); - virtual bool implementsHasInstance(const QScriptValueImpl &object); - virtual bool hasInstance(const QScriptValueImpl &object, - const QScriptValueImpl &value); - virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object); - - QScriptClass *scriptClass() const; - -private: - QScriptClass *m_class; -}; + QScriptClassPrivate() {} + virtual ~QScriptClassPrivate() {} -class QScriptCustomClassDataIterator : public QScriptClassDataIterator -{ -public: - QScriptCustomClassDataIterator(const QScriptValueImpl &object, - QScriptClass *klass); - virtual ~QScriptCustomClassDataIterator(); + QScriptEngine *engine; - virtual bool hasNext() const; - virtual void next(QScript::Member *member); - - virtual bool hasPrevious() const; - virtual void previous(QScript::Member *member); - - virtual void toFront(); - virtual void toBack(); - -private: - void iteratorToMember(QScript::Member *member); - - QScriptClassPropertyIterator *m_it; + QScriptClass *q_ptr; }; -QScriptCustomClassData::QScriptCustomClassData(QScriptClass *klass) - : m_class(klass) -{ -} - -QScriptCustomClassData::~QScriptCustomClassData() -{ -} - -void QScriptCustomClassData::mark(const QScriptValueImpl &, int) -{ -} - -bool QScriptCustomClassData::resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode access) -{ - uint id = 0; - QScriptClass::QueryFlags queryIn = 0; - if (access & QScript::Read) - queryIn |= QScriptClass::HandlesReadAccess; - if (access & QScript::Write) - queryIn |= QScriptClass::HandlesWriteAccess; - QScriptEnginePrivate *eng = object.engine(); - QScriptString str = eng->internedString(nameId); - QScriptClass::QueryFlags queryOut; - queryOut = m_class->queryProperty(eng->toPublic(object), str, queryIn, &id); - if (queryOut & queryIn) { - if (base) - *base = object; - QScriptValue::PropertyFlags flags = m_class->propertyFlags(eng->toPublic(object), str, id); - member->native(nameId, id, flags); - return true; - } - return false; -} - -bool QScriptCustomClassData::get(const QScriptValueImpl &object, const QScript::Member &member, - QScriptValueImpl *result) -{ - QScriptEnginePrivate *eng = object.engine(); - QScriptString str = eng->internedString(member.nameId()); - *result = eng->toImpl(m_class->property(eng->toPublic(object), str, member.id())); - if (!result->isValid()) - *result = eng->undefinedValue(); - return true; -} - -bool QScriptCustomClassData::put(QScriptValueImpl *object, const QScript::Member &member, - const QScriptValueImpl &value) -{ - QScriptEnginePrivate *eng = object->engine(); - QScriptString str = eng->internedString(member.nameId()); - QScriptValue publicObject = eng->toPublic(*object); - m_class->setProperty(publicObject, str, member.id(), eng->toPublic(value)); - return true; -} - -bool QScriptCustomClassData::removeMember(const QScriptValueImpl &object, - const QScript::Member &member) -{ - QScriptEnginePrivate *eng = object.engine(); - QScriptString str = eng->internedString(member.nameId()); - QScriptValue publicObject = eng->toPublic(object); - m_class->setProperty(publicObject, str, member.id(), QScriptValue()); - return true; -} - -bool QScriptCustomClassData::implementsHasInstance(const QScriptValueImpl &object) -{ - if (object.classInfo() != QScriptClassPrivate::get(m_class)->classInfo()) - return false; - return m_class->supportsExtension(QScriptClass::HasInstance); -} - -bool QScriptCustomClassData::hasInstance(const QScriptValueImpl &object, - const QScriptValueImpl &value) -{ - QScriptEnginePrivate *eng = object.engine(); - QScriptValueList arguments; - arguments << eng->toPublic(object) << eng->toPublic(value); - QVariant ret = m_class->extension(QScriptClass::HasInstance, qVariantFromValue(arguments)); - return ret.toBool(); -} - -QScriptClassDataIterator *QScriptCustomClassData::newIterator(const QScriptValueImpl &object) -{ - return new QScriptCustomClassDataIterator(object, m_class); -} - -QScriptClass *QScriptCustomClassData::scriptClass() const -{ - return m_class; -} - - - -QScriptCustomClassDataIterator::QScriptCustomClassDataIterator(const QScriptValueImpl &object, - QScriptClass *klass) -{ - QScriptEnginePrivate *eng = object.engine(); - m_it = klass->newIterator(eng->toPublic(object)); -} - -QScriptCustomClassDataIterator::~QScriptCustomClassDataIterator() -{ - if (m_it) { - delete m_it; - m_it = 0; - } -} - -bool QScriptCustomClassDataIterator::hasNext() const -{ - return m_it && m_it->hasNext(); -} - -void QScriptCustomClassDataIterator::next(QScript::Member *member) -{ - if (m_it) { - m_it->next(); - iteratorToMember(member); - } -} - -bool QScriptCustomClassDataIterator::hasPrevious() const -{ - return m_it && m_it->hasPrevious(); -} - -void QScriptCustomClassDataIterator::previous(QScript::Member *member) -{ - if (m_it) { - m_it->previous(); - iteratorToMember(member); - } -} - -void QScriptCustomClassDataIterator::toFront() -{ - if (m_it) - m_it->toFront(); -} - -void QScriptCustomClassDataIterator::toBack() -{ - if (m_it) - m_it->toBack(); -} - -void QScriptCustomClassDataIterator::iteratorToMember(QScript::Member *member) -{ - QScriptString str = m_it->name(); - QScriptNameIdImpl *nameId = 0; - if (str.isValid()) - nameId = QScriptStringPrivate::get(str)->nameId; - member->native(nameId, m_it->id(), m_it->flags()); -} - - - -QScriptClassPrivate::QScriptClassPrivate(QScriptClass *q) - : engine(0), m_classInfo(0), q_ptr(q) -{ -} - -QScriptClassPrivate::~QScriptClassPrivate() -{ - if (m_classInfo) { - // classInfo is owned by engine - // set the data to the normal Object class data - delete m_classInfo->data(); - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - m_classInfo->setData(eng_p->m_class_object->data()); - } -} - -QScriptClassPrivate *QScriptClassPrivate::get(QScriptClass *klass) -{ - return klass->d_func(); -} - -QScriptClassInfo *QScriptClassPrivate::classInfo() -{ - Q_Q(QScriptClass); - if (m_classInfo) - return m_classInfo; - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - int classType = eng_p->registerCustomClassType(); - if (q->supportsExtension(QScriptClass::Callable)) - classType |= QScriptClassInfo::FunctionBased; - QString name = q->name(); - if (name.isEmpty()) - name = QLatin1String("Object"); - m_classInfo = eng_p->registerClass(name, classType); - m_classInfo->setData(new QScriptCustomClassData(q_func())); - return m_classInfo; -} - -QScriptClass *QScriptClassPrivate::classFromInfo(QScriptClassInfo *info) -{ - QScriptCustomClassData *data = static_cast<QScriptCustomClassData*>(info->data()); - Q_ASSERT(data != 0); - return data->scriptClass(); -} - -static QScriptValueImpl callScriptClassFunction(QScriptContextPrivate *ctx, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - qMetaTypeId<QScriptContext*>(); - if (QScriptClassData *data = classInfo->data()) { - QScriptCustomClassData *customData = static_cast<QScriptCustomClassData*>(data); - QScriptClass *klass = customData->scriptClass(); - QVariant arg = qVariantFromValue(QScriptContextPrivate::get(ctx)); - QVariant ret = klass->extension(QScriptClass::Callable, arg); - QScriptValueImpl val = eng->valueFromVariant(ret); - if (val.isValid()) - return val; - } - return eng->undefinedValue(); -} - -QScriptFunction *QScriptClassPrivate::newFunction() -{ - return new QScript::C2Function(callScriptClassFunction, /*length=*/0, - classInfo(), /*name=*/QString()); -} - /*! Constructs a QScriptClass object to be used in the given \a engine. The engine does not take ownership of the QScriptClass object. */ QScriptClass::QScriptClass(QScriptEngine *engine) - : d_ptr(new QScriptClassPrivate(this)) + : d_ptr(new QScriptClassPrivate) { + d_ptr->q_ptr = this; d_ptr->engine = engine; } @@ -680,5 +397,3 @@ QVariant QScriptClass::extension(Extension extension, const QVariant &argument) } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptclass.h b/src/script/api/qscriptclass.h index 0ad0535..ad41ada 100644 --- a/src/script/qscriptclass.h +++ b/src/script/api/qscriptclass.h @@ -44,8 +44,6 @@ #include <QtCore/qstring.h> -#ifndef QT_NO_SCRIPT - #include <QtCore/qvariant.h> #include <QtScript/qscriptvalue.h> @@ -116,6 +114,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/qscriptclasspropertyiterator.cpp b/src/script/api/qscriptclasspropertyiterator.cpp index c6a7fff..4efbc19 100644 --- a/src/script/qscriptclasspropertyiterator.cpp +++ b/src/script/api/qscriptclasspropertyiterator.cpp @@ -41,9 +41,6 @@ #include "qscriptclasspropertyiterator.h" -#ifndef QT_NO_SCRIPT - -#include "qscriptclasspropertyiterator_p.h" #include "qscriptstring.h" QT_BEGIN_NAMESPACE @@ -74,14 +71,17 @@ QT_BEGIN_NAMESPACE \sa QScriptClass::newIterator(), QScriptValueIterator */ -QScriptClassPropertyIteratorPrivate::QScriptClassPropertyIteratorPrivate(QScriptClassPropertyIterator *q) - : q_ptr(q) +class QScriptClassPropertyIteratorPrivate { -} + Q_DECLARE_PUBLIC(QScriptClassPropertyIterator) +public: + QScriptClassPropertyIteratorPrivate() {} + virtual ~QScriptClassPropertyIteratorPrivate() {} -QScriptClassPropertyIteratorPrivate::~QScriptClassPropertyIteratorPrivate() -{ -} + QScriptValue object; + + QScriptClassPropertyIterator *q_ptr; +}; /*! Constructs an iterator for traversing \a object. @@ -90,8 +90,9 @@ QScriptClassPropertyIteratorPrivate::~QScriptClassPropertyIteratorPrivate() sequence of properties (before the first property). */ QScriptClassPropertyIterator::QScriptClassPropertyIterator(const QScriptValue &object) - : d_ptr(new QScriptClassPropertyIteratorPrivate(this)) + : d_ptr(new QScriptClassPropertyIteratorPrivate) { + d_ptr->q_ptr = this; d_ptr->object = object; } @@ -221,5 +222,3 @@ QScriptValue::PropertyFlags QScriptClassPropertyIterator::flags() const } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptclasspropertyiterator.h b/src/script/api/qscriptclasspropertyiterator.h index 3f870b4..de416be 100644 --- a/src/script/qscriptclasspropertyiterator.h +++ b/src/script/api/qscriptclasspropertyiterator.h @@ -44,8 +44,6 @@ #include <QtCore/qstring.h> -#ifndef QT_NO_SCRIPT - #include <QtScript/qscriptvalue.h> QT_BEGIN_HEADER @@ -91,6 +89,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp new file mode 100644 index 0000000..0b1ca33 --- /dev/null +++ b/src/script/api/qscriptcontext.cpp @@ -0,0 +1,764 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptcontext.h" + +#include "qscriptcontext_p.h" +#include "qscriptcontextinfo.h" +#include "qscriptengine.h" +#include "qscriptengine_p.h" +#include "../bridge/qscriptactivationobject_p.h" + +#include "Arguments.h" +#include "CodeBlock.h" +#include "Error.h" +#include "JSFunction.h" +#include "JSObject.h" +#include "JSGlobalObject.h" + +#include <QtCore/qstringlist.h> + +QT_BEGIN_NAMESPACE + +/*! + \since 4.3 + \class QScriptContext + + \brief The QScriptContext class represents a Qt Script function invocation. + + \ingroup script + \mainclass + + A QScriptContext provides access to the `this' object and arguments + passed to a script function. You typically want to access this + information when you're writing a native (C++) function (see + QScriptEngine::newFunction()) that will be called from script + code. For example, when the script code + + \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 0 + + is evaluated, a QScriptContext will be created, and the context will + carry the arguments as QScriptValues; in this particular case, the + arguments will be one QScriptValue containing the number 20.5, a second + QScriptValue containing the string \c{"hello"}, and a third QScriptValue + containing a Qt Script object. + + Use argumentCount() to get the number of arguments passed to the + function, and argument() to get an argument at a certain index. The + argumentsObject() function returns a Qt Script array object + containing all the arguments; you can use the QScriptValueIterator + to iterate over its elements, or pass the array on as arguments to + another script function using QScriptValue::call(). + + Use thisObject() to get the `this' object associated with the function call, + and setThisObject() to set the `this' object. If you are implementing a + native "instance method", you typically fetch the thisObject() and access + one or more of its properties: + + \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 1 + + Use isCalledAsConstructor() to determine if the function was called + as a constructor (e.g. \c{"new foo()"} (as constructor) or just + \c{"foo()"}). When a function is called as a constructor, the + thisObject() contains the newly constructed object that the function + is expected to initialize. + + Use throwValue() or throwError() to throw an exception. + + Use callee() to obtain the QScriptValue that represents the function being + called. This can for example be used to call the function recursively. + + Use parentContext() to get a pointer to the context that precedes + this context in the activation stack. This is mostly useful for + debugging purposes (e.g. when constructing some form of backtrace). + + The activationObject() function returns the object that is used to + hold the local variables associated with this function call. You can + replace the activation object by calling setActivationObject(). A + typical usage of these functions is when you want script code to be + evaluated in the context of the parent context, e.g. to implement an + include() function: + + \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 2 + + Use backtrace() to get a human-readable backtrace associated with + this context. This can be useful for debugging purposes when + implementing native functions. The toString() function provides a + string representation of the context. (QScriptContextInfo provides + more detailed debugging-related information about the + QScriptContext.) + + Use engine() to obtain a pointer to the QScriptEngine that this context + resides in. + + \sa QScriptContextInfo, QScriptEngine::newFunction(), QScriptable +*/ + +/*! + \enum QScriptContext::ExecutionState + + This enum specifies the frameution state of the context. + + \value NormalState The context is in a normal state. + + \value ExceptionState The context is in an exceptional state. +*/ + +/*! + \enum QScriptContext::Error + + This enum specifies types of error. + + \value ReferenceError A reference error. + + \value SyntaxError A syntax error. + + \value TypeError A type error. + + \value RangeError A range error. + + \value URIError A URI error. + + \value UnknownError An unknown error. +*/ + +/*! + \internal +*/ +QScriptContext::QScriptContext() +{ + //QScriptContext doesn't exist, pointer to QScriptContext are just pointer to JSC::CallFrame + Q_ASSERT(false); +} + +/*! + Throws an exception with the given \a value. + Returns the value thrown (the same as the argument). + + \sa throwError(), state() +*/ +QScriptValue QScriptContext::throwValue(const QScriptValue &value) +{ + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + JSC::JSValue jscValue = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(value); + frame->setException(jscValue); + return value; +} + +/*! + Throws an \a error with the given \a text. + Returns the created error object. + + The \a text will be stored in the \c{message} property of the error + object. + + The error object will be initialized to contain information about + the location where the error occurred; specifically, it will have + properties \c{lineNumber}, \c{fileName} and \c{stack}. These + properties are described in \l {QtScript Extensions to ECMAScript}. + + \sa throwValue(), state() +*/ +QScriptValue QScriptContext::throwError(Error error, const QString &text) +{ + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + JSC::ErrorType jscError = JSC::GeneralError; + switch (error) { + case UnknownError: + break; + case ReferenceError: + jscError = JSC::ReferenceError; + break; + case SyntaxError: + jscError = JSC::SyntaxError; + break; + case TypeError: + jscError = JSC::TypeError; + break; + case RangeError: + jscError = JSC::RangeError; + break; + case URIError: + jscError = JSC::URIError; + break; + } + JSC::JSObject *result = JSC::throwError(frame, jscError, text); + return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); +} + +/*! + \overload + + Throws an error with the given \a text. + Returns the created error object. + + \sa throwValue(), state() +*/ +QScriptValue QScriptContext::throwError(const QString &text) +{ + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + JSC::JSObject *result = JSC::throwError(frame, JSC::GeneralError, text); + return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); +} + +/*! + Destroys this QScriptContext. +*/ +QScriptContext::~QScriptContext() +{ + //QScriptContext doesn't exist, pointer to QScriptContext are just pointer to JSC::CallFrame + Q_ASSERT(false); +} + +/*! + Returns the QScriptEngine that this QScriptContext belongs to. +*/ +QScriptEngine *QScriptContext::engine() const +{ + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame)); +} + +/*! + Returns the function argument at the given \a index. + + If \a index >= argumentCount(), a QScriptValue of + the primitive type Undefined is returned. + + \sa argumentCount() +*/ +QScriptValue QScriptContext::argument(int index) const +{ + if (index < 0) + return QScriptValue(); + if (index >= argumentCount()) + return QScriptValue(QScriptValue::UndefinedValue); + QScriptValue v = argumentsObject().property(index); + return v; +} + +/*! + Returns the callee. The callee is the function object that this + QScriptContext represents an invocation of. +*/ +QScriptValue QScriptContext::callee() const +{ + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(frame->callee()); +} + +/*! + Returns the arguments object of this QScriptContext. + + The arguments object has properties \c callee (equal to callee()) + and \c length (equal to argumentCount()), and properties \c 0, \c 1, + ..., argumentCount() - 1 that provide access to the argument + values. Initially, property \c P (0 <= \c P < argumentCount()) has + the same value as argument(\c P). In the case when \c P is less + than the number of formal parameters of the function, \c P shares + its value with the corresponding property of the activation object + (activationObject()). This means that changing this property changes + the corresponding property of the activation object and vice versa. + + \sa argument(), activationObject() +*/ +QScriptValue QScriptContext::argumentsObject() const +{ + JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this)); + + if (frame == frame->lexicalGlobalObject()->globalExec() || frame->callerFrame()->hasHostCallFrameFlag()) { + // <global> or <eval> context doesn't have arguments. return an empty object + return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject(); + } + + //for a js function + if (frame->codeBlock() && frame->callee()) { + JSC::JSValue result = frame->interpreter()->retrieveArguments(frame, JSC::asFunction(frame->callee())); + return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); + } + + //for a native function + if (!frame->optionalCalleeArguments()) { + Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later + JSC::Arguments* arguments = new (&frame->globalData())JSC::Arguments(frame, JSC::Arguments::NoParameters); + frame->setCalleeArguments(arguments); + } + return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(frame->optionalCalleeArguments()); +} + +/*! + Returns true if the function was called as a constructor + (e.g. \c{"new foo()"}); otherwise returns false. + + When a function is called as constructor, the thisObject() + contains the newly constructed object to be initialized. +*/ +bool QScriptContext::isCalledAsConstructor() const +{ + JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this)); + + //For native functions, look up flags. + uint flags = QScriptEnginePrivate::contextFlags(frame); + if (flags & QScriptEnginePrivate::NativeContext) + return flags & QScriptEnginePrivate::CalledAsConstructorContext; + + //Not a native function, try to look up in the bytecode if we where called from op_construct + JSC::Instruction* returnPC = frame->returnPC(); + + if (!returnPC) + return false; + + JSC::CallFrame *callerFrame = QScriptEnginePrivate::frameForContext(parentContext()); + if (!callerFrame) + return false; + + if (returnPC[-JSC::op_construct_length].u.opcode == frame->interpreter()->getOpcode(JSC::op_construct)) { + //We are maybe called from the op_construct opcode which has 6 opperands. + //But we need to check we are not called from op_call with 4 opperands + + //we make sure that the returnPC[-1] (thisRegister) is smaller than the returnPC[-3] (registerOffset) + //as if it was an op_call, the returnPC[-1] would be the registerOffset, bigger than returnPC[-3] (funcRegister) + return returnPC[-1].u.operand < returnPC[-3].u.operand; + } + return false; +} + +/*! + Returns the parent context of this QScriptContext. +*/ +QScriptContext *QScriptContext::parentContext() const +{ + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + JSC::CallFrame *callerFrame = frame->callerFrame()->removeHostCallFrameFlag(); + if (callerFrame && callerFrame->callerFrame()->hasHostCallFrameFlag() + && callerFrame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(frame)->globalExec()) { + //skip the "fake" context created in Interpreter::execute. + callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag(); + } + return reinterpret_cast<QScriptContext *>(callerFrame); +} + +/*! + Returns the number of arguments passed to the function + in this invocation. + + Note that the argument count can be different from the + formal number of arguments (the \c{length} property of + callee()). + + \sa argument() +*/ +int QScriptContext::argumentCount() const +{ + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + int argc = frame->argumentCount(); + if (argc != 0) + --argc; // -1 due to "this" + return argc; +} + +/*! + \internal +*/ +QScriptValue QScriptContext::returnValue() const +{ + qWarning("QScriptContext::returnValue() not implemented"); + return QScriptValue(); +} + +/*! + \internal +*/ +void QScriptContext::setReturnValue(const QScriptValue &result) +{ + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + JSC::CallFrame *callerFrame = frame->callerFrame(); + if (!callerFrame->codeBlock()) + return; + Q_ASSERT_X(false, Q_FUNC_INFO, "check me"); + int dst = frame->registers()[JSC::RegisterFile::ReturnValueRegister].i(); // returnValueRegister() is private + callerFrame[dst] = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(result); +} + +/*! + Returns the activation object of this QScriptContext. The activation + object provides access to the local variables associated with this + context. + + \sa argument(), argumentsObject() +*/ + +QScriptValue QScriptContext::activationObject() const +{ + JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this)); + JSC::JSObject *result = 0; + + uint flags = QScriptEnginePrivate::contextFlags(frame); + if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) { + //For native functions, lazily create it if needed + QScript::QScriptActivationObject *scope = new (frame) QScript::QScriptActivationObject(frame); + frame->setScopeChain(frame->scopeChain()->copy()->push(scope)); + result = scope; + QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext); + } else { + // look in scope chain + JSC::ScopeChainNode *node = frame->scopeChain(); + JSC::ScopeChainIterator it(node); + for (it = node->begin(); it != node->end(); ++it) { + if ((*it) && (*it)->isVariableObject()) { + result = *it; + break; + } + } + } + if (!result) { + if (!parentContext()) + return engine()->globalObject(); + + qWarning("QScriptContext::activationObject: could not get activation object for frame"); + return QScriptValue(); + /*JSC::CodeBlock *codeBlock = frame->codeBlock(); + if (!codeBlock) { + // non-Qt native function + Q_ASSERT(true); //### this should in theorry not happen + result = new (frame)QScript::QScriptActivationObject(frame); + } else { + // ### this is wrong + JSC::FunctionBodyNode *body = static_cast<JSC::FunctionBodyNode*>(codeBlock->ownerNode()); + result = new (frame)JSC::JSActivation(frame, body); + }*/ + } + + if (result && result->isObject(&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(); + } + + return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); +} + +/*! + Sets the activation object of this QScriptContext to be the given \a + activation. + + If \a activation is not an object, this function does nothing. +*/ +void QScriptContext::setActivationObject(const QScriptValue &activation) +{ + if (!activation.isObject()) + return; + else if (activation.engine() != engine()) { + qWarning("QScriptContext::setActivationObject() failed: " + "cannot set an object created in " + "a different engine"); + return; + } + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); + JSC::JSObject *object = JSC::asObject(engine->scriptValueToJSCValue(activation)); + if (object == engine->originalGlobalObjectProxy) + object = engine->originalGlobalObject(); + + uint flags = QScriptEnginePrivate::contextFlags(frame); + if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) { + //For native functions, we create a scope node + JSC::JSObject *scope = object; + if (!scope->isVariableObject()) { + // Create a QScriptActivationObject that acts as a proxy + scope = new (frame) QScript::QScriptActivationObject(frame, scope); + } + frame->setScopeChain(frame->scopeChain()->copy()->push(scope)); + QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext); + return; + } + + // else replace the first activation object in the scope chain + JSC::ScopeChainNode *node = frame->scopeChain(); + while (node != 0) { + if (node->object && node->object->isVariableObject()) { + if (!object->isVariableObject()) { + if (node->object->isObject(&QScript::QScriptActivationObject::info)) { + static_cast<QScript::QScriptActivationObject*>(node->object)->setDelegate(object); + } else { + // Create a QScriptActivationObject that acts as a proxy + node->object = new (frame) QScript::QScriptActivationObject(frame, object); + } + } else { + node->object = object; + } + break; + } + node = node->next; + } +} + +/*! + Returns the `this' object associated with this QScriptContext. +*/ +QScriptValue QScriptContext::thisObject() const +{ + JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this)); + QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); + JSC::JSValue result = engine->thisForContext(frame); + if (!result || result.isNull()) + result = frame->globalThisValue(); + return engine->scriptValueFromJSCValue(result); +} + +/*! + Sets the `this' object associated with this QScriptContext to be + \a thisObject. + + If \a thisObject is not an object, this function does nothing. +*/ +void QScriptContext::setThisObject(const QScriptValue &thisObject) +{ + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + if (!thisObject.isObject()) + return; + if (thisObject.engine() != engine()) { + qWarning("QScriptContext::setThisObject() failed: " + "cannot set an object created in " + "a different engine"); + return; + } + if (frame == frame->lexicalGlobalObject()->globalExec()) { + engine()->setGlobalObject(thisObject); + return; + } + JSC::JSValue jscThisObject = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(thisObject); + JSC::CodeBlock *cb = frame->codeBlock(); + if (cb != 0) { + frame[cb->thisRegister()] = jscThisObject; + } else { + JSC::Register* thisRegister = frame->registers() - JSC::RegisterFile::CallFrameHeaderSize - frame->argumentCount(); + thisRegister[0] = jscThisObject; + } +} + +/*! + Returns the frameution state of this QScriptContext. +*/ +QScriptContext::ExecutionState QScriptContext::state() const +{ + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + if (frame->hadException()) + return QScriptContext::ExceptionState; + return QScriptContext::NormalState; +} + +/*! + Returns a human-readable backtrace of this QScriptContext. + + Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}. + + To access individual pieces of debugging-related information (for + example, to construct your own backtrace representation), use + QScriptContextInfo. + + \sa QScriptEngine::uncaughtExceptionBacktrace(), QScriptContextInfo, toString() +*/ +QStringList QScriptContext::backtrace() const +{ + QStringList result; + const QScriptContext *ctx = this; + while (ctx) { + result.append(ctx->toString()); + ctx = ctx->parentContext(); + } + return result; +} + +/*! + \since 4.4 + + Returns a string representation of this context. + This is useful for debugging. + + \sa backtrace() +*/ +QString QScriptContext::toString() const +{ + QScriptContextInfo info(this); + QString result; + + QString functionName = info.functionName(); + if (functionName.isEmpty()) { + if (parentContext()) { + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + if (info.functionType() == QScriptContextInfo::ScriptFunction) + result.append(QLatin1String("<anonymous>")); + else if(frame->callerFrame()->hasHostCallFrameFlag()) + result.append(QLatin1String("<eval>")); + else + result.append(QLatin1String("<native>")); + } else { + result.append(QLatin1String("<global>")); + } + } else { + result.append(functionName); + } + + QStringList parameterNames = info.functionParameterNames(); + result.append(QLatin1Char('(')); + for (int i = 0; i < argumentCount(); ++i) { + if (i > 0) + result.append(QLatin1String(", ")); + if (i < parameterNames.count()) { + result.append(parameterNames.at(i)); + result.append(QLatin1String(" = ")); + } + QScriptValue arg = argument(i); + if (arg.isString()) + result.append(QLatin1Char('\'')); + result.append(arg.toString()); + if (arg.isString()) + result.append(QLatin1Char('\'')); + + } + result.append(QLatin1Char(')')); + + QString fileName = info.fileName(); + int lineNumber = info.lineNumber(); + result.append(QLatin1String(" at ")); + if (!fileName.isEmpty()) { + result.append(fileName); + result.append(QLatin1Char(':')); + } + result.append(QString::number(lineNumber)); + return result; +} + +/*! + \internal + \since 4.5 + + Returns the scope chain of this QScriptContext. +*/ +QScriptValueList QScriptContext::scopeChain() const +{ + activationObject(); //ensure the creation of the normal scope for native context + const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); + QScriptValueList result; + JSC::ScopeChainNode *node = frame->scopeChain(); + JSC::ScopeChainIterator it(node); + for (it = node->begin(); it != node->end(); ++it) { + JSC::JSObject *object = *it; + if (!object) + continue; + if (object->isObject(&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(); + } + result.append(engine->scriptValueFromJSCValue(object)); + } + return result; +} + +/*! + \internal + \since 4.5 + + Adds the given \a object to the front of this context's scope chain. + + If \a object is not an object, this function does nothing. +*/ +void QScriptContext::pushScope(const QScriptValue &object) +{ + activationObject(); //ensure the creation of the normal scope for native context + if (!object.isObject()) + return; + else if (object.engine() != engine()) { + qWarning("QScriptContext::pushScope() failed: " + "cannot push an object created in " + "a different engine"); + return; + } + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + 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 + 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(jscObject)); +} + +/*! + \internal + \since 4.5 + + Removes the front object from this context's scope chain, and + returns the removed object. + + If the scope chain is already empty, this function returns an + invalid QScriptValue. +*/ +QScriptValue QScriptContext::popScope() +{ + JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); + JSC::ScopeChainNode *scope = frame->scopeChain(); + Q_ASSERT(scope != 0); + QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); + QScriptValue result = engine->scriptValueFromJSCValue(scope->object); + if (!scope->next) { + // We cannot have a null scope chain, so just zap the object pointer. + scope->object = 0; + } else { + frame->setScopeChain(scope->pop()); + } + return result; +} + +QT_END_NAMESPACE diff --git a/src/script/qscriptcontext.h b/src/script/api/qscriptcontext.h index e0d158b..53d07cc 100644 --- a/src/script/qscriptcontext.h +++ b/src/script/api/qscriptcontext.h @@ -44,8 +44,6 @@ #include <QtCore/qobjectdefs.h> -#ifndef QT_NO_SCRIPT - #include <QtScript/qscriptvalue.h> QT_BEGIN_HEADER @@ -121,5 +119,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT #endif diff --git a/src/script/qscriptobjectdata_p.h b/src/script/api/qscriptcontext_p.h index bc38ebd..e8cc47e 100644 --- a/src/script/qscriptobjectdata_p.h +++ b/src/script/api/qscriptcontext_p.h @@ -39,14 +39,8 @@ ** ****************************************************************************/ -#ifndef QSCRIPTOBJECTDATA_P_H -#define QSCRIPTOBJECTDATA_P_H - -#include <QtCore/qglobal.h> - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE +#ifndef QSCRIPTCONTEXT_P_H +#define QSCRIPTCONTEXT_P_H // // W A R N I N G @@ -59,23 +53,24 @@ QT_BEGIN_NAMESPACE // We mean it. // -class QScriptEnginePrivate; +#include <QtCore/qobjectdefs.h> -class QScriptObjectData +QT_BEGIN_NAMESPACE + +namespace JSC { -protected: - inline QScriptObjectData() {} + class JSObject; + class ArgList; + class ExecState; +} -public: - virtual void finalize(QScriptEnginePrivate *) {} - virtual ~QScriptObjectData() {} +#include "wtf/Platform.h" +#include "JSValue.h" -private: - Q_DISABLE_COPY(QScriptObjectData) -}; +class QScriptEnginePrivate; -QT_END_NAMESPACE +class QScriptContext; -#endif // QT_NO_SCRIPT +QT_END_NAMESPACE #endif diff --git a/src/script/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index dd3dbab..0049680 100644 --- a/src/script/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -39,17 +39,17 @@ ** ****************************************************************************/ +#include "config.h" #include "qscriptcontextinfo.h" -#ifndef QT_NO_SCRIPT - -#include "qscriptcontextinfo_p.h" -#include "qscriptengine_p.h" #include "qscriptcontext_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" +#include "qscriptengine.h" +#include "qscriptengine_p.h" +#include "../bridge/qscriptqobject_p.h" #include <QtCore/qdatastream.h> +#include <QtCore/qmetaobject.h> +#include "CodeBlock.h" +#include "JSFunction.h" QT_BEGIN_NAMESPACE @@ -97,11 +97,37 @@ QT_BEGIN_NAMESPACE \value NativeFunction The function is a built-in Qt Script function, or it was defined through a call to QScriptEngine::newFunction(). */ +class QScriptContextInfoPrivate +{ + Q_DECLARE_PUBLIC(QScriptContextInfo) +public: + QScriptContextInfoPrivate(); + QScriptContextInfoPrivate(const QScriptContext *context); + ~QScriptContextInfoPrivate(); + + qint64 scriptId; + int lineNumber; + int columnNumber; + QString fileName; + + QString functionName; + QScriptContextInfo::FunctionType functionType; + + int functionStartLineNumber; + int functionEndLineNumber; + int functionMetaIndex; + + QStringList parameterNames; + + QBasicAtomicInt ref; + + QScriptContextInfo *q_ptr; +}; + /*! \internal */ QScriptContextInfoPrivate::QScriptContextInfoPrivate() - : q_ptr(0) { ref = 0; functionType = QScriptContextInfo::NativeFunction; @@ -117,7 +143,6 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate() \internal */ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *context) - : q_ptr(0) { Q_ASSERT(context); ref = 0; @@ -125,67 +150,73 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte functionMetaIndex = -1; functionStartLineNumber = -1; functionEndLineNumber = -1; + scriptId = -1; + lineNumber = -1; + columnNumber = -1; - const QScriptContextPrivate *ctx_p = QScriptContextPrivate::get(context); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - scriptId = ctx_p->scriptId(); -#endif - fileName = ctx_p->fileName(); - lineNumber = ctx_p->currentLine; - columnNumber = ctx_p->currentColumn; - - QScriptValueImpl callee = ctx_p->engine()->toImpl(context->callee()); - QScriptFunction *fun = callee.toFunction(); - if (fun) { - functionName = fun->functionName(); - functionStartLineNumber = fun->startLineNumber(); - functionEndLineNumber = fun->endLineNumber(); - - switch (fun->type()) { - case QScriptFunction::Unknown: - functionType = QScriptContextInfo::NativeFunction; - break; - - case QScriptFunction::Script: - functionType = QScriptContextInfo::ScriptFunction; - for (int i = 0; i < fun->formals.count(); ++i) - parameterNames.append(fun->formals.at(i)->s); - break; - - case QScriptFunction::C: - functionType = QScriptContextInfo::NativeFunction; - break; - - case QScriptFunction::C2: - functionType = QScriptContextInfo::NativeFunction; - break; - - case QScriptFunction::C3: - functionType = QScriptContextInfo::NativeFunction; - break; - - case QScriptFunction::Qt: { - functionType = QScriptContextInfo::QtFunction; - functionMetaIndex = ctx_p->calleeMetaIndex; - -#ifndef QT_NO_QOBJECT - const QMetaObject *meta; - meta = static_cast<QScript::QtFunction*>(fun)->metaObject(); - if (meta) { - QMetaMethod method = meta->method(functionMetaIndex); - QList<QByteArray> formals = method.parameterNames(); - for (int i = 0; i < formals.count(); ++i) - parameterNames.append(QLatin1String(formals.at(i))); + const JSC::ExecState *frame = QScriptEnginePrivate::frameForContext(context); + + // Get the line number: + + //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context + QScriptContext *rewindContext = context->engine()->currentContext(); + if (rewindContext != context) { //ignore top context (native function) + // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored + while (rewindContext && rewindContext->parentContext() != context) + rewindContext = rewindContext->parentContext(); + if (rewindContext) { + JSC::ExecState *aboveFrame = QScriptEnginePrivate::frameForContext(rewindContext); + frame = aboveFrame->callerFrame()->removeHostCallFrameFlag(); //it will be different for the global context. + + JSC::Instruction *returnPC = aboveFrame->returnPC(); + JSC::CodeBlock *codeBlock = frame->codeBlock(); + if (returnPC && codeBlock) { + lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), + returnPC - codeBlock->instructions().begin() -1); } -#endif - } break; + } + } else { + // An agent might have provided the line number. + lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber; + } + + // Get the filename and the scriptId: + JSC::CodeBlock *codeBlock = frame->codeBlock(); + if (codeBlock) { + JSC::SourceProvider *source = codeBlock->source(); + scriptId = source->asID(); + fileName = source->url(); + } - case QScriptFunction::QtProperty: - functionType = QScriptContextInfo::QtPropertyFunction; - functionMetaIndex = ctx_p->calleeMetaIndex; - break; + // Get the others informations: + JSC::JSObject *callee = frame->callee(); + if (callee && callee->isObject(&JSC::InternalFunction::info)) + functionName = JSC::asInternalFunction(callee)->name(&frame->globalData()); + if (callee && callee->isObject(&JSC::JSFunction::info)) { + functionType = QScriptContextInfo::ScriptFunction; + JSC::FunctionBodyNode *body = JSC::asFunction(callee)->body(); + functionStartLineNumber = body->firstLine(); + functionEndLineNumber = body->lastLine(); + const JSC::Identifier* params = body->parameters(); + for (size_t i = 0; i < body->parameterCount(); ++i) + parameterNames.append(params[i].ustring()); + // ### get the function name from the AST + } else if (callee && callee->isObject(&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(); + const QMetaObject *meta = static_cast<QScript::QtFunction*>(callee)->metaObject(); + if (meta != 0) { + QMetaMethod method = meta->method(functionMetaIndex); + QList<QByteArray> formals = method.parameterNames(); + for (int i = 0; i < formals.count(); ++i) + parameterNames.append(QLatin1String(formals.at(i))); } } + else if (callee && callee->isObject(&QScript::QtPropertyFunction::info)) { + functionType = QScriptContextInfo::QtPropertyFunction; + functionMetaIndex = static_cast<QScript::QtPropertyFunction*>(callee)->propertyIndex(); + } } /*! @@ -549,5 +580,3 @@ Q_SCRIPT_EXPORT QDataStream &operator>>(QDataStream &in, QScriptContextInfo &inf #endif QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptcontextinfo.h b/src/script/api/qscriptcontextinfo.h index a82dfb5..78ac2a8 100644 --- a/src/script/qscriptcontextinfo.h +++ b/src/script/api/qscriptcontextinfo.h @@ -44,8 +44,6 @@ #include <QtCore/qobjectdefs.h> -#ifndef QT_NO_SCRIPT - #include <QtCore/qlist.h> #include <QtCore/qstringlist.h> @@ -120,6 +118,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp new file mode 100644 index 0000000..6fde08f --- /dev/null +++ b/src/script/api/qscriptengine.cpp @@ -0,0 +1,3851 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptengine.h" +#include "qscriptsyntaxchecker_p.h" +#include "qnumeric.h" + +#include "qscriptengine_p.h" +#include "qscriptengineagent_p.h" +#include "qscriptcontext_p.h" +#include "qscriptstring_p.h" +#include "qscriptvalue_p.h" +#include "qscriptvalueiterator.h" +#include "qscriptclass.h" +#include "qdebug.h" + +#include <QtCore/qstringlist.h> +#include <QtCore/qmetaobject.h> + +#include "Error.h" +#include "JSArray.h" +#include "JSLock.h" +#include "Interpreter.h" +#include "DateConstructor.h" +#include "RegExpConstructor.h" + +#include "PrototypeFunction.h" +#include "InitializeThreading.h" +#include "ObjectPrototype.h" +#include "SourceCode.h" +#include "FunctionPrototype.h" +#include "TimeoutChecker.h" +#include "JSFunction.h" +#include "Parser.h" +#include "Operations.h" + +#include "utils/qscriptdate_p.h" +#include "bridge/qscriptfunction_p.h" +#include "bridge/qscriptobject_p.h" +#include "bridge/qscriptclassobject_p.h" +#include "bridge/qscriptvariant_p.h" +#include "bridge/qscriptqobject_p.h" +#include "bridge/qscriptglobalobject_p.h" +#include "bridge/qscriptactivationobject_p.h" + +#ifndef QT_NO_QOBJECT +#include <QtCore/qcoreapplication.h> +#include <QtCore/qdir.h> +#include <QtCore/qfile.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qpluginloader.h> +#include <QtCore/qset.h> +#include <QtCore/qtextstream.h> +#include "qscriptextensioninterface.h" +#endif + +Q_DECLARE_METATYPE(QScriptValue) +#ifndef QT_NO_QOBJECT +Q_DECLARE_METATYPE(QObjectList) +#endif +Q_DECLARE_METATYPE(QList<int>) + +QT_BEGIN_NAMESPACE + +/*! + \since 4.3 + \class QScriptEngine + \reentrant + + \brief The QScriptEngine class provides an environment for evaluating Qt Script code. + + \ingroup script + \mainclass + + See the \l{QtScript} documentation for information about the Qt Script language, + and how to get started with scripting your C++ application. + + \section1 Evaluating Scripts + + Use evaluate() to evaluate script code; this is the C++ equivalent + of the built-in script function \c{eval()}. + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 0 + + evaluate() returns a QScriptValue that holds the result of the + evaluation. The QScriptValue class provides functions for converting + the result to various C++ types (e.g. QScriptValue::toString() + and QScriptValue::toNumber()). + + The following code snippet shows how a script function can be + defined and then invoked from C++ using QScriptValue::call(): + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 1 + + As can be seen from the above snippets, a script is provided to the + engine in the form of a string. One common way of loading scripts is + by reading the contents of a file and passing it to evaluate(): + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 2 + + Here we pass the name of the file as the second argument to + evaluate(). This does not affect evaluation in any way; the second + argument is a general-purpose string that is used to identify the + script for debugging purposes (for example, our filename will now + show up in any uncaughtExceptionBacktrace() involving the script). + + \section1 Engine Configuration + + The globalObject() function returns the \bold {Global Object} + associated with the script engine. Properties of the Global Object + are accessible from any script code (i.e. they are global + variables). Typically, before evaluating "user" scripts, you will + want to configure a script engine by adding one or more properties + to the Global Object: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 3 + + Adding custom properties to the scripting environment is one of the + standard means of providing a scripting API that is specific to your + application. Usually these custom properties are objects created by + the newQObject() or newObject() functions, or constructor functions + created by newFunction(). + + \section1 Script Exceptions + + evaluate() can throw a script exception (e.g. due to a syntax + error); in that case, the return value is the value that was thrown + (typically an \c{Error} object). You can check whether the + evaluation caused an exception by calling hasUncaughtException(). In + that case, you can call toString() on the error object to obtain an + error message. The current uncaught exception is also available + through uncaughtException(). You can obtain a human-readable + backtrace of the exception with uncaughtExceptionBacktrace(). + Calling clearExceptions() will cause any uncaught exceptions to be + cleared. + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4 + + The checkSyntax() function can be used to determine whether code can be + usefully passed to evaluate(). + + \section1 Script Object Creation + + Use newObject() to create a standard Qt Script object; this is the + C++ equivalent of the script statement \c{new Object()}. You can use + the object-specific functionality in QScriptValue to manipulate the + script object (e.g. QScriptValue::setProperty()). Similarly, use + newArray() to create a Qt Script array object. Use newDate() to + create a \c{Date} object, and newRegExp() to create a \c{RegExp} + object. + + \section1 QObject Integration + + Use newQObject() to wrap a QObject (or subclass) + pointer. newQObject() returns a proxy script object; properties, + children, and signals and slots of the QObject are available as + properties of the proxy object. No binding code is needed because it + is done dynamically using the Qt meta object system. + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 5 + + Use qScriptConnect() to connect a C++ signal to a script function; + this is the Qt Script equivalent of QObject::connect(). When a + script function is invoked in response to a C++ signal, it can cause + a script exception; you can connect to the signalHandlerException() + signal to catch such an exception. + + Use newQMetaObject() to wrap a QMetaObject; this gives you a "script + representation" of a QObject-based class. newQMetaObject() returns a + proxy script object; enum values of the class are available as + properties of the proxy object. You can also specify a function that + will be used to construct objects of the class (e.g. when the + constructor is invoked from a script). For classes that have a + "standard" Qt constructor, Qt Script can provide a default script + constructor for you; see scriptValueFromQMetaObject(). + + See the \l{QtScript} documentation for more information on + the QObject integration. + + \section1 Support for Custom C++ Types + + Use newVariant() to wrap a QVariant. This can be used to store + values of custom (non-QObject) C++ types that have been registered + with the Qt meta-type system. To make such types scriptable, you + typically associate a prototype (delegate) object with the C++ type + by calling setDefaultPrototype(); the prototype object defines the + scripting API for the C++ type. Unlike the QObject integration, + there is no automatic binding possible here; i.e. you have to create + the scripting API yourself, for example by using the QScriptable + class. + + Use fromScriptValue() to cast from a QScriptValue to another type, + and toScriptValue() to create a QScriptValue from another value. + You can specify how the conversion of C++ types is to be performed + with qScriptRegisterMetaType() and qScriptRegisterSequenceMetaType(). + By default, Qt Script will use QVariant to store values of custom + types. + + \section1 Importing Extensions + + Use importExtension() to import plugin-based extensions into the + engine. Call availableExtensions() to obtain a list naming all the + available extensions, and importedExtensions() to obtain a list + naming only those extensions that have been imported. + + Call pushContext() to open up a new variable scope, and popContext() + to close the current scope. This is useful if you are implementing + an extension that evaluates script code containing temporary + variable definitions (e.g. \c{var foo = 123;}) that are safe to + discard when evaluation has completed. + + \section1 Native Functions + + Use newFunction() to wrap native (C++) functions, including + constructors for your own custom types, so that these can be invoked + from script code. Such functions must have the signature + QScriptEngine::FunctionSignature. You may then pass the function as + argument to newFunction(). Here is an example of a function that + returns the sum of its first two arguments: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 6 + + To expose this function to script code, you can set it as a property + of the Global Object: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 7 + + Once this is done, script code can call your function in the exact + same manner as a "normal" script function: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 8 + + \section1 Long-running Scripts + + If you need to evaluate possibly long-running scripts from the main + (GUI) thread, you should first call setProcessEventsInterval() to + make sure that the GUI stays responsive. You can abort a currently + running script by calling abortEvaluation(). You can determine + whether an engine is currently running a script by calling + isEvaluating(). + + \section1 Core Debugging/Tracing Facilities + + Since Qt 4.4, you can be notified of events pertaining to script + execution (e.g. script function calls and statement execution) + through the QScriptEngineAgent interface; see the setAgent() + function. This can be used to implement debugging and profiling of a + QScriptEngine. + + \sa QScriptValue, QScriptContext, QScriptEngineAgent + +*/ + +/*! + \enum QScriptEngine::ValueOwnership + + This enum specifies the ownership when wrapping a C++ value, e.g. by using newQObject(). + + \value QtOwnership The standard Qt ownership rules apply, i.e. the associated object will never be explicitly deleted by the script engine. This is the default. (QObject ownership is explained in \l{Object Trees and Object Ownership}.) + \value ScriptOwnership The value is owned by the script environment. The associated data will be deleted when appropriate (i.e. after the garbage collector has discovered that there are no more live references to the value). + \value AutoOwnership If the associated object has a parent, the Qt ownership rules apply (QtOwnership); otherwise, the object is owned by the script environment (ScriptOwnership). +*/ + +/*! + \enum QScriptEngine::QObjectWrapOption + + These flags specify options when wrapping a QObject pointer with newQObject(). + + \value ExcludeChildObjects The script object will not expose child objects as properties. + \value ExcludeSuperClassMethods The script object will not expose signals and slots inherited from the superclass. + \value ExcludeSuperClassProperties The script object will not expose properties inherited from the superclass. + \value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties + \value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot. + \value AutoCreateDynamicProperties Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object. + \value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object. + \value SkipMethodsInEnumeration Don't include methods (signals and slots) when enumerating the object's properties. +*/ + +class QScriptSyntaxCheckResultPrivate +{ +public: + QScriptSyntaxCheckResultPrivate() { ref = 0; } + ~QScriptSyntaxCheckResultPrivate() {} + + QScriptSyntaxCheckResult::State state; + int errorColumnNumber; + int errorLineNumber; + QString errorMessage; + QBasicAtomicInt ref; +}; + +class QScriptTypeInfo +{ +public: + QScriptTypeInfo() : signature(0, '\0'), marshal(0), demarshal(0) + { } + + QByteArray signature; + QScriptEngine::MarshalFunction marshal; + QScriptEngine::DemarshalFunction demarshal; + JSC::JSValue prototype; +}; + +namespace QScript +{ + +struct GlobalClientData : public JSC::JSGlobalData::ClientData +{ + GlobalClientData(QScriptEnginePrivate *e) + : engine(e) {} + virtual ~GlobalClientData() {} + virtual void mark() { engine->mark(); } + + QScriptEnginePrivate *engine; +}; + +class TimeoutCheckerProxy : public JSC::TimeoutChecker +{ +public: + TimeoutCheckerProxy(const JSC::TimeoutChecker& originalChecker) + : JSC::TimeoutChecker(originalChecker) + , m_shouldProcessEvents(false) + , m_shouldAbortEvaluation(false) + {} + + void setShouldProcessEvents(bool shouldProcess) { m_shouldProcessEvents = shouldProcess; } + void setShouldAbort(bool shouldAbort) { m_shouldAbortEvaluation = shouldAbort; } + bool shouldAbort() { return m_shouldAbortEvaluation; } + + virtual bool didTimeOut(JSC::ExecState* exec) + { + if (JSC::TimeoutChecker::didTimeOut(exec)) + return true; + + if (m_shouldProcessEvents) + QCoreApplication::processEvents(); + + return m_shouldAbortEvaluation; + } + +private: + bool m_shouldProcessEvents; + bool m_shouldAbortEvaluation; +}; + +static int toDigit(char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + else if ((c >= 'a') && (c <= 'z')) + return 10 + c - 'a'; + else if ((c >= 'A') && (c <= 'Z')) + return 10 + c - 'A'; + return -1; +} + +qsreal integerFromString(const char *buf, int size, int radix) +{ + if (size == 0) + return qSNaN(); + + qsreal sign = 1.0; + int i = 0; + if (buf[0] == '+') { + ++i; + } else if (buf[0] == '-') { + sign = -1.0; + ++i; + } + + if (((size-i) >= 2) && (buf[i] == '0')) { + if (((buf[i+1] == 'x') || (buf[i+1] == 'X')) + && (radix < 34)) { + if ((radix != 0) && (radix != 16)) + return 0; + radix = 16; + i += 2; + } else { + if (radix == 0) { + radix = 8; + ++i; + } + } + } else if (radix == 0) { + radix = 10; + } + + int j = i; + for ( ; i < size; ++i) { + int d = toDigit(buf[i]); + if ((d == -1) || (d >= radix)) + break; + } + qsreal result; + if (j == i) { + if (!qstrcmp(buf, "Infinity")) + result = qInf(); + else + result = qSNaN(); + } else { + result = 0; + qsreal multiplier = 1; + for (--i ; i >= j; --i, multiplier *= radix) + result += toDigit(buf[i]) * multiplier; + } + result *= sign; + return result; +} + +qsreal integerFromString(const QString &str, int radix) +{ + QByteArray ba = str.trimmed().toUtf8(); + return integerFromString(ba.constData(), ba.size(), radix); +} + +QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec) +{ + return static_cast<GlobalClientData*>(exec->globalData().clientData)->engine; +} + +bool isFunction(JSC::JSValue value) +{ + if (!value || !value.isObject()) + return false; + JSC::CallData callData; + return (JSC::asObject(value)->getCallData(callData) != JSC::CallTypeNone); +} + +static JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +static JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); + +JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState *exec, JSC::JSObject */*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args) +{ +#ifndef QT_NO_QOBJECT + if (args.size() == 0) { + return JSC::throwError(exec, JSC::GeneralError, "Function.prototype.disconnect: no arguments given"); + } + + if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) { + return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: this object is not a signal"); + } + + QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject)); + + const QMetaObject *meta = qtSignal->metaObject(); + if (!meta) { + return JSC::throwError(exec, JSC::TypeError, "Function.prototype.discconnect: cannot disconnect from deleted QObject"); + } + + QMetaMethod sig = meta->method(qtSignal->initialIndex()); + if (sig.methodType() != QMetaMethod::Signal) { + QString message = QString::fromLatin1("Function.prototype.disconnect: %0::%1 is not a signal") + .arg(QLatin1String(qtSignal->metaObject()->className())) + .arg(QLatin1String(sig.signature())); + return JSC::throwError(exec, JSC::TypeError, message); + } + + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + + JSC::JSValue receiver; + JSC::JSValue slot; + JSC::JSValue arg0 = args.at(0); + if (args.size() < 2) { + slot = arg0; + } else { + receiver = arg0; + JSC::JSValue arg1 = args.at(1); + if (isFunction(arg1)) + slot = arg1; + else { + // ### don't go via QScriptValue + QScriptValue tmp = engine->scriptValueFromJSCValue(arg0); + QString propertyName(arg1.toString(exec)); + slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype)); + } + } + + if (!isFunction(slot)) { + return JSC::throwError(exec, JSC::TypeError, "Function.prototype.disconnect: target is not a function"); + } + + bool ok = engine->scriptDisconnect(thisObject, receiver, slot); + if (!ok) { + QString message = QString::fromLatin1("Function.prototype.disconnect: failed to disconnect from %0::%1") + .arg(QLatin1String(qtSignal->metaObject()->className())) + .arg(QLatin1String(sig.signature())); + return JSC::throwError(exec, JSC::GeneralError, message); + } + return JSC::jsUndefined(); +#else + Q_UNUSED(eng); + return context->throwError(QScriptContext::TypeError, + QLatin1String("Function.prototype.disconnect")); +#endif // QT_NO_QOBJECT +} + +JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState *exec, JSC::JSObject */*callee*/, JSC::JSValue thisObject, const JSC::ArgList &args) +{ +#ifndef QT_NO_QOBJECT + if (args.size() == 0) { + return JSC::throwError(exec, JSC::GeneralError,"Function.prototype.connect: no arguments given"); + } + + if (!JSC::asObject(thisObject)->inherits(&QScript::QtFunction::info)) { + return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: this object is not a signal"); + } + + QScript::QtFunction *qtSignal = static_cast<QScript::QtFunction*>(JSC::asObject(thisObject)); + + const QMetaObject *meta = qtSignal->metaObject(); + if (!meta) { + return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: cannot connect to deleted QObject"); + } + + QMetaMethod sig = meta->method(qtSignal->initialIndex()); + if (sig.methodType() != QMetaMethod::Signal) { + QString message = QString::fromLatin1("Function.prototype.connect: %0::%1 is not a signal") + .arg(QLatin1String(qtSignal->metaObject()->className())) + .arg(QLatin1String(sig.signature())); + return JSC::throwError(exec, JSC::TypeError, message); + } + + { + QList<int> overloads = qtSignal->overloadedIndexes(); + if (!overloads.isEmpty()) { + overloads.append(qtSignal->initialIndex()); + QByteArray signature = sig.signature(); + QString message = QString::fromLatin1("Function.prototype.connect: ambiguous connect to %0::%1(); candidates are\n") + .arg(QLatin1String(qtSignal->metaObject()->className())) + .arg(QLatin1String(signature.left(signature.indexOf('(')))); + for (int i = 0; i < overloads.size(); ++i) { + QMetaMethod mtd = meta->method(overloads.at(i)); + message.append(QString::fromLatin1(" %0\n").arg(QString::fromLatin1(mtd.signature()))); + } + message.append(QString::fromLatin1("Use e.g. object['%0'].connect() to connect to a particular overload") + .arg(QLatin1String(signature))); + return JSC::throwError(exec, JSC::GeneralError, message); + } + } + + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + + JSC::JSValue receiver; + JSC::JSValue slot; + JSC::JSValue arg0 = args.at(0); + if (args.size() < 2) { + slot = arg0; + } else { + receiver = arg0; + JSC::JSValue arg1 = args.at(1); + if (isFunction(arg1)) + slot = arg1; + else { + // ### don't go via QScriptValue + QScriptValue tmp = engine->scriptValueFromJSCValue(arg0); + QString propertyName = arg1.toString(exec); + slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype)); + } + } + + if (!isFunction(slot)) { + return JSC::throwError(exec, JSC::TypeError, "Function.prototype.connect: target is not a function"); + } + + bool ok = engine->scriptConnect(thisObject, receiver, slot, Qt::AutoConnection); + if (!ok) { + QString message = QString::fromLatin1("Function.prototype.connect: failed to connect to %0::%1") + .arg(QLatin1String(qtSignal->metaObject()->className())) + .arg(QLatin1String(sig.signature())); + return JSC::throwError(exec, JSC::GeneralError, message); + } + return JSC::jsUndefined(); +#else + Q_UNUSED(eng); + Q_UNUSED(classInfo); + return context->throwError(QScriptContext::TypeError, + QLatin1String("Function.prototype.connect")); +#endif // QT_NO_QOBJECT +} + +static JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +static JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +static JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); + +JSC::JSValue JSC_HOST_CALL functionPrint(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList& args) +{ + QString result; + for (unsigned i = 0; i < args.size(); ++i) { + if (i != 0) + result.append(QLatin1Char(' ')); + QString s(args.at(i).toString(exec)); + if (exec->hadException()) + break; + result.append(s); + } + if (exec->hadException()) + return exec->exception(); + qDebug(qPrintable(result)); + return JSC::jsUndefined(); +} + +JSC::JSValue JSC_HOST_CALL functionGC(JSC::ExecState* exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + engine->collectGarbage(); + return JSC::jsUndefined(); +} + +JSC::JSValue JSC_HOST_CALL functionVersion(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&) +{ + return JSC::JSValue(exec, 1); +} + +static JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +static JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); +static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); + +JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) +{ + if (args.size() < 2) + return JSC::throwError(exec, JSC::GeneralError, "qsTranslate() requires at least two arguments"); + if (!args.at(0).isString()) + return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): first argument (context) must be a string"); + if (!args.at(1).isString()) + return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): second argument (text) must be a string"); + if ((args.size() > 2) && !args.at(2).isString()) + return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (comment) must be a string"); + if ((args.size() > 3) && !args.at(3).isString()) + return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fourth argument (encoding) must be a string"); + if ((args.size() > 4) && !args.at(4).isNumber()) + return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fifth argument (n) must be a number"); +#ifndef QT_NO_QOBJECT + QString context(args.at(0).toString(exec)); +#endif + QString text(args.at(1).toString(exec)); +#ifndef QT_NO_QOBJECT + QString comment; + if (args.size() > 2) + comment = args.at(2).toString(exec); + QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr; + if (args.size() > 3) { + QString encStr(args.at(3).toString(exec)); + if (encStr == QLatin1String("CodecForTr")) + encoding = QCoreApplication::CodecForTr; + else if (encStr == QLatin1String("UnicodeUTF8")) + encoding = QCoreApplication::UnicodeUTF8; + else + return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("qsTranslate(): invalid encoding '%s'").arg(encStr)); + } + int n = -1; + if (args.size() > 4) + n = args.at(4).toInt32(exec); +#endif + QString result; +#ifndef QT_NO_QOBJECT + result = QCoreApplication::translate(context.toLatin1().constData(), + text.toLatin1().constData(), + comment.toLatin1().constData(), + encoding, n); +#else + result = text; +#endif + return JSC::jsString(exec, result); +} + +JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) +{ + if (args.size() < 2) + return JSC::jsUndefined(); + return args.at(1); +} + +JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) +{ + if (args.size() < 1) + return JSC::throwError(exec, JSC::GeneralError, "qsTr() requires at least one argument"); + if (!args.at(0).isString()) + return JSC::throwError(exec, JSC::GeneralError, "qsTr(): first argument (text) must be a string"); + if ((args.size() > 1) && !args.at(1).isString()) + return JSC::throwError(exec, JSC::GeneralError, "qsTr(): second argument (comment) must be a string"); + if ((args.size() > 2) && !args.at(2).isNumber()) + return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (n) must be a number"); +#ifndef QT_NO_QOBJECT + QString context; +// ### implement context resolution +// if (ctx->parentContext()) +// context = QFileInfo(ctx->parentContext()->fileName()).baseName(); +#endif + QString text(args.at(0).toString(exec)); +#ifndef QT_NO_QOBJECT + QString comment; + if (args.size() > 1) + comment = args.at(1).toString(exec); + int n = -1; + if (args.size() > 2) + n = args.at(2).toInt32(exec); +#endif + QString result; +#ifndef QT_NO_QOBJECT + result = QCoreApplication::translate(context.toLatin1().constData(), + text.toLatin1().constData(), + comment.toLatin1().constData(), + QCoreApplication::CodecForTr, n); +#else + result = text; +#endif + return JSC::jsString(exec, result); +} + +JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) +{ + if (args.size() < 1) + return JSC::jsUndefined(); + return args.at(0); +} + +static JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); + +JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisObject, const JSC::ArgList &args) +{ + QString value(thisObject.toString(exec)); + JSC::JSValue arg = (args.size() != 0) ? args.at(0) : JSC::jsUndefined(); + QString result; + if (arg.isString()) + result = value.arg(arg.toString(exec)); + else if (arg.isNumber()) + result = value.arg(arg.toNumber(exec)); + return JSC::jsString(exec, result); +} + + +#if !defined(QT_NO_QOBJECT) && !defined(QT_NO_LIBRARY) +static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng) +{ + QString path = ctx->argument(0).toString(); + QStringList components = path.split(QLatin1Char('.')); + QScriptValue o = eng->globalObject(); + for (int i = 0; i < components.count(); ++i) { + QString name = components.at(i); + QScriptValue oo = o.property(name); + if (!oo.isValid()) { + oo = eng->newObject(); + o.setProperty(name, oo); + } + o = oo; + } + return o; +} +#endif + +} // namespace QScript + +QScriptEnginePrivate::QScriptEnginePrivate() + : registeredScriptValues(0), inEval(false) +{ + qMetaTypeId<QScriptValue>(); + + JSC::initializeThreading(); // ### hmmm + + globalData = JSC::JSGlobalData::create().releaseRef(); + globalData->clientData = new QScript::GlobalClientData(this); + JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject(); + + JSC::ExecState* exec = globalObject->globalExec(); + + scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype()); + + qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure()); + qobjectWrapperObjectStructure = QScriptObject::createStructure(qobjectPrototype); + + qmetaobjectPrototype = new (exec) QScript::QMetaObjectPrototype(exec, QScript::QMetaObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure()); + qmetaobjectWrapperObjectStructure = QScript::QMetaObjectWrapperObject::createStructure(qmetaobjectPrototype); + + variantPrototype = new (exec) QScript::QVariantPrototype(exec, QScript::QVariantPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure()); + variantWrapperObjectStructure = QScriptObject::createStructure(variantPrototype); + + globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "print"), QScript::functionPrint)); + globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "gc"), QScript::functionGC)); + globalObject->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 0, JSC::Identifier(exec, "version"), QScript::functionVersion)); + + // ### rather than extending Function.prototype, consider creating a QtSignal.prototype + globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "disconnect"), QScript::functionDisconnect)); + globalObject->functionPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, globalObject->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "connect"), QScript::functionConnect)); + + JSC::TimeoutChecker* originalChecker = globalData->timeoutChecker; + globalData->timeoutChecker = new QScript::TimeoutCheckerProxy(*originalChecker); + delete originalChecker; + + currentFrame = exec; + + originalGlobalObjectProxy = 0; + activeAgent = 0; + agentLineNumber = -1; + processEventsInterval = -1; +} + +QScriptEnginePrivate::~QScriptEnginePrivate() +{ + while (!ownedAgents.isEmpty()) + delete ownedAgents.takeFirst(); + detachAllRegisteredScriptValues(); + qDeleteAll(m_qobjectData); + qDeleteAll(m_typeInfos); + JSC::JSLock lock(false); + globalData->heap.destroy(); + globalData->deref(); +} + +QScriptValue QScriptEnginePrivate::scriptValueFromJSCValue(JSC::JSValue value) +{ + if (!value) + return QScriptValue(); + + QScriptValuePrivate *p_value = new QScriptValuePrivate(); + p_value->engine = this; + p_value->initFrom(value); + return QScriptValuePrivate::toPublic(p_value); +} + +JSC::JSValue QScriptEnginePrivate::scriptValueToJSCValue(const QScriptValue &value) +{ + QScriptValuePrivate *vv = QScriptValuePrivate::get(value); + if (!vv) + return JSC::JSValue(); + if (vv->type != QScriptValuePrivate::JSC) { + Q_ASSERT(!vv->engine || vv->engine == this); + vv->engine = this; + if (vv->type == QScriptValuePrivate::Number) { + vv->initFrom(JSC::jsNumber(currentFrame, vv->numberValue)); + } else { //QScriptValuePrivate::String + vv->initFrom(JSC::jsString(currentFrame, vv->stringValue)); + } + } + return vv->jscValue; +} + +QScriptValue QScriptEnginePrivate::scriptValueFromVariant(const QVariant &v) +{ + Q_Q(QScriptEngine); + QScriptValue result = q->create(v.userType(), v.data()); + Q_ASSERT(result.isValid()); + return result; +} + +QVariant QScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value, int targetType) +{ + QVariant v(targetType, (void *)0); + if (QScriptEnginePrivate::convert(value, targetType, v.data(), this)) + return v; + if (uint(targetType) == QVariant::LastType) + return value.toVariant(); + if (value.isVariant()) { + v = value.toVariant(); + if (v.canConvert(QVariant::Type(targetType))) { + v.convert(QVariant::Type(targetType)); + return v; + } + QByteArray typeName = v.typeName(); + if (typeName.endsWith('*') + && (QMetaType::type(typeName.left(typeName.size()-1)) == targetType)) { + return QVariant(targetType, *reinterpret_cast<void* *>(v.data())); + } + } + + return QVariant(); +} + +JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(const QVariant &v) +{ + // ### it's inefficient to convert to QScriptValue and then to JSValue + QScriptValue vv = scriptValueFromVariant(v); + QScriptValuePrivate *p = QScriptValuePrivate::get(vv); + switch (p->type) { + case QScriptValuePrivate::JSC: + return p->jscValue; + case QScriptValuePrivate::Number: + return JSC::jsNumber(currentFrame, p->numberValue); + case QScriptValuePrivate::String: { + JSC::UString str = p->stringValue; + return JSC::jsString(currentFrame, str); + } + } + return JSC::JSValue(); +} + +QVariant QScriptEnginePrivate::jscValueToVariant(JSC::JSValue value, int targetType) +{ + // ### it's inefficient to convert to QScriptValue and then to QVariant + return scriptValueToVariant(scriptValueFromJSCValue(value), targetType); +} + +QScriptValue QScriptEnginePrivate::arrayFromStringList(const QStringList &lst) +{ + Q_Q(QScriptEngine); + QScriptValue arr = q->newArray(lst.size()); + for (int i = 0; i < lst.size(); ++i) + arr.setProperty(i, QScriptValue(q, lst.at(i))); + return arr; +} + +QStringList QScriptEnginePrivate::stringListFromArray(const QScriptValue &arr) +{ + QStringList lst; + uint len = arr.property(QLatin1String("length")).toUInt32(); + for (uint i = 0; i < len; ++i) + lst.append(arr.property(i).toString()); + return lst; +} + +QScriptValue QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst) +{ + Q_Q(QScriptEngine); + QScriptValue arr = q->newArray(lst.size()); + for (int i = 0; i < lst.size(); ++i) + arr.setProperty(i, scriptValueFromVariant(lst.at(i))); + return arr; +} + +QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValue &arr) +{ + QVariantList lst; + uint len = arr.property(QLatin1String("length")).toUInt32(); + for (uint i = 0; i < len; ++i) + lst.append(arr.property(i).toVariant()); + return lst; +} + +QScriptValue QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap) +{ + Q_Q(QScriptEngine); + QScriptValue obj = q->newObject(); + QVariantMap::const_iterator it; + for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) + obj.setProperty(it.key(), scriptValueFromVariant(it.value())); + return obj; +} + +QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValue &obj) +{ + QVariantMap vmap; + QScriptValueIterator it(obj); + while (it.hasNext()) { + it.next(); + vmap.insert(it.name(), it.value().toVariant()); + } + return vmap; +} + +JSC::JSValue QScriptEnginePrivate::defaultPrototype(int metaTypeId) const +{ + QScriptTypeInfo *info = m_typeInfos.value(metaTypeId); + if (!info) + return JSC::JSValue(); + return info->prototype; +} + +void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, JSC::JSValue prototype) +{ + QScriptTypeInfo *info = m_typeInfos.value(metaTypeId); + if (!info) { + info = new QScriptTypeInfo(); + m_typeInfos.insert(metaTypeId, info); + } + info->prototype = prototype; +} + +QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame) +{ + return reinterpret_cast<QScriptContext *>(frame); +} + +JSC::ExecState *QScriptEnginePrivate::frameForContext(QScriptContext *context) +{ + return reinterpret_cast<JSC::ExecState*>(context); +} + +const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScriptContext *context) +{ + return reinterpret_cast<const JSC::ExecState*>(context); +} + +JSC::JSGlobalObject *QScriptEnginePrivate::originalGlobalObject() const +{ + return globalData->head; +} + +JSC::JSObject *QScriptEnginePrivate::customGlobalObject() const +{ + QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject()); + return glob->customGlobalObject; +} + +JSC::JSObject *QScriptEnginePrivate::getOriginalGlobalObjectProxy() +{ + if (!originalGlobalObjectProxy) { + JSC::ExecState* exec = currentFrame; + originalGlobalObjectProxy = new (exec)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject()); + } + return originalGlobalObjectProxy; +} + +JSC::JSObject *QScriptEnginePrivate::globalObject() const +{ + QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject()); + if (glob->customGlobalObject) + return glob->customGlobalObject; + return glob; +} + +void QScriptEnginePrivate::setGlobalObject(JSC::JSObject *object) +{ + if (object == globalObject()) + return; + QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject()); + if (object == originalGlobalObjectProxy) + glob->customGlobalObject = 0; + else { + Q_ASSERT(object != originalGlobalObject()); + glob->customGlobalObject = object; + } +} + +JSC::ExecState *QScriptEnginePrivate::globalExec() const +{ + return originalGlobalObject()->globalExec(); +} + +/*! + \internal + + If the given \a value is the original global object, returns the custom + global object or a proxy to the original global object; otherwise returns \a + value. +*/ +JSC::JSValue QScriptEnginePrivate::toUsableValue(JSC::JSValue value) +{ + if (!value || !value.isObject() || !JSC::asObject(value)->isGlobalObject()) + return value; + Q_ASSERT(JSC::asObject(value) == originalGlobalObject()); + if (customGlobalObject()) + return customGlobalObject(); + if (!originalGlobalObjectProxy) + originalGlobalObjectProxy = new (currentFrame)QScript::OriginalGlobalObjectProxy(scriptObjectStructure, originalGlobalObject()); + return originalGlobalObjectProxy; +} +/*! + \internal + Return the 'this' value for a given context + The result may be null for the global context +*/ +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(); + return thisRegister->jsValue(); + } +} + +/*! \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++ + + when setting flags, NativeContext should always be set + + contextFlags returns 0 for non native context + */ +uint QScriptEnginePrivate::contextFlags(JSC::ExecState *exec) +{ + if (exec->codeBlock()) + return 0; //js function doesn't have flags + + return exec->returnValueRegister(); +} + +void QScriptEnginePrivate::setContextFlags(JSC::ExecState *exec, uint flags) +{ + Q_ASSERT(!exec->codeBlock()); + quintptr flag_ptr = flags; + exec->registers()[JSC::RegisterFile::ReturnValueRegister] = JSC::JSValue(reinterpret_cast<JSC::JSObject*>(flag_ptr)); +} + + +void QScriptEnginePrivate::mark() +{ + if (!originalGlobalObject()->marked()) + originalGlobalObject()->mark(); + if (!globalObject()->marked()) + globalObject()->mark(); + if (originalGlobalObjectProxy && !originalGlobalObjectProxy->marked()) + originalGlobalObjectProxy->mark(); + + if (qobjectPrototype && !qobjectPrototype->marked()) + qobjectPrototype->mark(); + if (qmetaobjectPrototype && !qmetaobjectPrototype->marked()) + qmetaobjectPrototype->mark(); + if (variantPrototype && !variantPrototype->marked()) + variantPrototype->mark(); + + { + QScriptValuePrivate *it; + for (it = registeredScriptValues; it != 0; it = it->next) { + if (it->isJSC() && !it->jscValue.marked()) + it->jscValue.mark(); + } + } + +#ifndef QT_NO_QOBJECT + { + QHash<QObject*, QScript::QObjectData*>::const_iterator it; + for (it = m_qobjectData.constBegin(); it != m_qobjectData.constEnd(); ++it) { + QScript::QObjectData *qdata = it.value(); + qdata->mark(); + } + } +#endif + + { + 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(); + } + } +} + +bool QScriptEnginePrivate::isCollecting() const +{ + return globalData->heap.isBusy(); +} + +void QScriptEnginePrivate::collectGarbage() +{ + JSC::JSLock lock(false); + globalData->heap.collect(); +} + +QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const +{ + return static_cast<QScript::TimeoutCheckerProxy*>(globalData->timeoutChecker); +} + +void QScriptEnginePrivate::agentDeleted(QScriptEngineAgent *agent) +{ + ownedAgents.removeOne(agent); + if (activeAgent == agent) { + QScriptEngineAgentPrivate::get(agent)->detach(); + activeAgent = 0; + } +} + +#ifndef QT_NO_QOBJECT + +JSC::JSValue QScriptEnginePrivate::newQObject( + QObject *object, QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options) +{ + if (!object) + return JSC::jsNull(); + JSC::ExecState* exec = currentFrame; + QScript::QObjectData *data = qobjectData(object); + bool preferExisting = (options & QScriptEngine::PreferExistingWrapperObject) != 0; + QScriptEngine::QObjectWrapOptions opt = options & ~QScriptEngine::PreferExistingWrapperObject; + QScriptObject *result = 0; + if (preferExisting) + result = data->findWrapper(ownership, opt); + if (!result) { + result = new (exec) QScriptObject(qobjectWrapperObjectStructure); + if (preferExisting) + data->registerWrapper(result, ownership, opt); + } + Q_ASSERT(result != 0); + result->setDelegate(new QScript::QObjectDelegate(object, ownership, options)); + /*if (setDefaultPrototype)*/ { + const QMetaObject *meta = object->metaObject(); + while (meta) { + QByteArray typeString = meta->className(); + typeString.append('*'); + int typeId = QMetaType::type(typeString); + if (typeId != 0) { + JSC::JSValue proto = defaultPrototype(typeId); + if (proto) { + result->setPrototype(proto); + break; + } + } + meta = meta->superClass(); + } + } + return result; +} + +JSC::JSValue QScriptEnginePrivate::newQMetaObject( + const QMetaObject *metaObject, JSC::JSValue ctor) +{ + if (!metaObject) + return JSC::jsNull(); + JSC::ExecState* exec = currentFrame; + QScript::QMetaObjectWrapperObject *result = new (exec) QScript::QMetaObjectWrapperObject(exec, metaObject, ctor, qmetaobjectWrapperObjectStructure); + return result; +} + +bool QScriptEnginePrivate::convertToNativeQObject(const QScriptValue &value, + const QByteArray &targetType, + void **result) +{ + if (!targetType.endsWith('*')) + return false; + if (QObject *qobject = value.toQObject()) { + int start = targetType.startsWith("const ") ? 6 : 0; + QByteArray className = targetType.mid(start, targetType.size()-start-1); + if (void *instance = qobject->qt_metacast(className)) { + *result = instance; + return true; + } + } + return false; +} + +QScript::QObjectData *QScriptEnginePrivate::qobjectData(QObject *object) +{ + QHash<QObject*, QScript::QObjectData*>::const_iterator it; + it = m_qobjectData.constFind(object); + if (it != m_qobjectData.constEnd()) + return it.value(); + + QScript::QObjectData *data = new QScript::QObjectData(this); + m_qobjectData.insert(object, data); + QObject::connect(object, SIGNAL(destroyed(QObject*)), + q_func(), SLOT(_q_objectDestroyed(QObject *))); + return data; +} + +void QScriptEnginePrivate::_q_objectDestroyed(QObject *object) +{ + QHash<QObject*, QScript::QObjectData*>::iterator it; + it = m_qobjectData.find(object); + Q_ASSERT(it != m_qobjectData.end()); + QScript::QObjectData *data = it.value(); + m_qobjectData.erase(it); + delete data; +} + +void QScriptEnginePrivate::disposeQObject(QObject *object) +{ + // TODO +/* if (isCollecting()) { + // wait until we're done with GC before deleting it + int index = m_qobjectsToBeDeleted.indexOf(object); + if (index == -1) + m_qobjectsToBeDeleted.append(object); + } else*/ { + delete object; + } +} + +void QScriptEnginePrivate::emitSignalHandlerException() +{ + Q_Q(QScriptEngine); + emit q->signalHandlerException(q->uncaughtException()); +} + +bool QScriptEnginePrivate::scriptConnect(QObject *sender, const char *signal, + JSC::JSValue receiver, JSC::JSValue function, + Qt::ConnectionType type) +{ + Q_ASSERT(sender); + Q_ASSERT(signal); + const QMetaObject *meta = sender->metaObject(); + int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1)); + if (index == -1) + return false; + return scriptConnect(sender, index, receiver, function, /*wrapper=*/JSC::JSValue(), type); +} + +bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, const char *signal, + JSC::JSValue receiver, JSC::JSValue function) +{ + Q_ASSERT(sender); + Q_ASSERT(signal); + const QMetaObject *meta = sender->metaObject(); + int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1)); + if (index == -1) + return false; + return scriptDisconnect(sender, index, receiver, function); +} + +bool QScriptEnginePrivate::scriptConnect(QObject *sender, int signalIndex, + JSC::JSValue receiver, JSC::JSValue function, + JSC::JSValue senderWrapper, + Qt::ConnectionType type) +{ + QScript::QObjectData *data = qobjectData(sender); + return data->addSignalHandler(sender, signalIndex, receiver, function, senderWrapper, type); +} + +bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, int signalIndex, + JSC::JSValue receiver, JSC::JSValue function) +{ + QScript::QObjectData *data = qobjectData(sender); + if (!data) + return false; + return data->removeSignalHandler(sender, signalIndex, receiver, function); +} + +bool QScriptEnginePrivate::scriptConnect(JSC::JSValue signal, JSC::JSValue receiver, + JSC::JSValue function, Qt::ConnectionType type) +{ + QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal)); + int index = fun->mostGeneralMethod(); + return scriptConnect(fun->qobject(), index, receiver, function, fun->wrapperObject(), type); +} + +bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver, + JSC::JSValue function) +{ + QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(JSC::asObject(signal)); + int index = fun->mostGeneralMethod(); + return scriptDisconnect(fun->qobject(), index, receiver, function); +} + +#endif + +void QScriptEnginePrivate::registerScriptValue(QScriptValuePrivate *value) +{ + value->prev = 0; + value->next = registeredScriptValues; + if (registeredScriptValues) + registeredScriptValues->prev = value; + registeredScriptValues = value; +} + +void QScriptEnginePrivate::unregisterScriptValue(QScriptValuePrivate *value) +{ + if (value->prev) + value->prev->next = value->next; + if (value->next) + value->next->prev = value->prev; + if (value == registeredScriptValues) + registeredScriptValues = value->next; + value->prev = 0; + value->next = 0; +} + +void QScriptEnginePrivate::detachAllRegisteredScriptValues() +{ + QScriptValuePrivate *it; + QScriptValuePrivate *next; + for (it = registeredScriptValues; it != 0; it = next) { + it->detachFromEngine(); + next = it->next; + it->prev = 0; + it->next = 0; + } + registeredScriptValues = 0; +} + +#ifdef QT_NO_QOBJECT + +QScriptEngine::QScriptEngine() + : d_ptr(new QScriptEnginePrivate) +{ + d_ptr->q_ptr = this; +} + +/*! \internal +*/ +QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd) + : d_ptr(&dd) +{ + d_ptr->q_ptr = this; +} +#else + +/*! + Constructs a QScriptEngine object. + + The globalObject() is initialized to have properties as described in + \l{ECMA-262}, Section 15.1. +*/ +QScriptEngine::QScriptEngine() + : QObject(*new QScriptEnginePrivate, 0) +{ +} + +/*! + Constructs a QScriptEngine object with the given \a parent. + + The globalObject() is initialized to have properties as described in + \l{ECMA-262}, Section 15.1. +*/ + +QScriptEngine::QScriptEngine(QObject *parent) + : QObject(*new QScriptEnginePrivate, parent) +{ +} + +/*! \internal +*/ +QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent) + : QObject(dd, parent) +{ +} +#endif + +/*! + Destroys this QScriptEngine. +*/ +QScriptEngine::~QScriptEngine() +{ +#ifdef QT_NO_QOBJECT + delete d_ptr; + d_ptr = 0; +#endif +} + +/*! + Returns this engine's Global Object. + + By default, the Global Object contains the built-in objects that are + part of \l{ECMA-262}, such as Math, Date and String. Additionally, + you can set properties of the Global Object to make your own + extensions available to all script code. Non-local variables in + script code will be created as properties of the Global Object, as + well as local variables in global code. +*/ +QScriptValue QScriptEngine::globalObject() const +{ + Q_D(const QScriptEngine); + JSC::JSObject *result = d->globalObject(); + return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result); +} + +/*! + \since 4.5 + + Sets this engine's Global Object to be the given \a object. + If \a object is not a valid script object, this function does + nothing. + + When setting a custom global object, you may want to use + QScriptValueIterator to copy the properties of the standard Global + Object; alternatively, you can set the internal prototype of your + custom object to be the original Global Object. +*/ +void QScriptEngine::setGlobalObject(const QScriptValue &object) +{ + Q_D(QScriptEngine); + if (!object.isObject()) + return; + JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object)); + d->setGlobalObject(jscObject); +} + +/*! + Returns a QScriptValue of the primitive type Null. + + \sa undefinedValue() +*/ +QScriptValue QScriptEngine::nullValue() +{ + Q_D(QScriptEngine); + return d->scriptValueFromJSCValue(JSC::jsNull()); +} + +/*! + Returns a QScriptValue of the primitive type Undefined. + + \sa nullValue() +*/ +QScriptValue QScriptEngine::undefinedValue() +{ + Q_D(QScriptEngine); + return d->scriptValueFromJSCValue(JSC::jsUndefined()); +} + +/*! + Creates a constructor function from \a fun, with the given \a length. + The \c{prototype} property of the resulting function is set to be the + given \a prototype. The \c{constructor} property of \a prototype is + set to be the resulting function. + + When a function is called as a constructor (e.g. \c{new Foo()}), the + `this' object associated with the function call is the new object + that the function is expected to initialize; the prototype of this + default constructed object will be the function's public + \c{prototype} property. If you always want the function to behave as + a constructor (e.g. \c{Foo()} should also create a new object), or + if you need to create your own object rather than using the default + `this' object, you should make sure that the prototype of your + object is set correctly; either by setting it manually, or, when + wrapping a custom type, by having registered the defaultPrototype() + of that type. Example: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9 + + To wrap a custom type and provide a constructor for it, you'd typically + do something like this: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10 +*/ +QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, + const QScriptValue &prototype, + int length) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); + QScriptValue result = d->scriptValueFromJSCValue(function); + result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable); + const_cast<QScriptValue&>(prototype) + .setProperty(QLatin1String("constructor"), result, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + return result; +} + +#ifndef QT_NO_REGEXP +/*! + Creates a QtScript object of class RegExp with the given + \a regexp. + + \sa QScriptValue::toRegExp() +*/ +QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSValue buf[2]; + JSC::ArgList args(buf, sizeof(buf)); + + //convert the pattern to a ECMAScript pattern + extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); + QString pattern = qt_regexp_toCanonical(regexp.pattern(), regexp.patternSyntax()); + if (regexp.isMinimal()) { + QString ecmaPattern; + int len = pattern.length(); + ecmaPattern.reserve(len); + int i = 0; + const QChar *wc = pattern.unicode(); + bool inBracket = false; + while (i < len) { + QChar c = wc[i++]; + ecmaPattern += c; + switch (c.unicode()) { + case '?': + case '+': + case '*': + case '}': + if (!inBracket) + ecmaPattern += QLatin1Char('?'); + break; + case '\\': + if (i < len) + ecmaPattern += wc[i++]; + break; + case '[': + inBracket = true; + break; + case ']': + inBracket = false; + break; + default: + break; + } + } + pattern = ecmaPattern; + } + + JSC::UString jscPattern = pattern; + QString flags; + if (regexp.caseSensitivity() == Qt::CaseInsensitive) + flags.append(QLatin1Char('i')); + JSC::UString jscFlags = flags; + buf[0] = JSC::jsString(exec, jscPattern); + buf[1] = JSC::jsString(exec, jscFlags); + JSC::JSObject* result = JSC::constructRegExp(exec, args); + return d->scriptValueFromJSCValue(result); +} + +#endif // QT_NO_REGEXP + +/*! + Creates a QtScript object holding the given variant \a value. + + If a default prototype has been registered with the meta type id of + \a value, then the prototype of the created object will be that + prototype; otherwise, the prototype will be the Object prototype + object. + + \sa setDefaultPrototype(), QScriptValue::toVariant() +*/ +QScriptValue QScriptEngine::newVariant(const QVariant &value) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + QScriptObject *obj = new (exec) QScriptObject(d->variantWrapperObjectStructure); + obj->setDelegate(new QScript::QVariantDelegate(value)); + QScriptValue result = d->scriptValueFromJSCValue(obj); + QScriptValue proto = defaultPrototype(value.userType()); + if (proto.isValid()) + result.setPrototype(proto); + return result; +} + +/*! + \since 4.4 + \overload + + Initializes the given Qt Script \a object to hold the given variant + \a value, and returns the \a object. + + This function enables you to "promote" a plain Qt Script object + (created by the newObject() function) to a variant, or to replace + the variant contained inside an object previously created by the + newVariant() function. + + The prototype() of the \a object will remain unchanged. + + If \a object is not an object, this function behaves like the normal + newVariant(), i.e. it creates a new script object and returns it. + + This function is useful when you want to provide a script + constructor for a C++ type. If your constructor is invoked in a + \c{new} expression (QScriptContext::isCalledAsConstructor() returns + true), you can pass QScriptContext::thisObject() (the default + constructed script object) to this function to initialize the new + object. +*/ +QScriptValue QScriptEngine::newVariant(const QScriptValue &object, + const QVariant &value) +{ + if (!object.isObject()) + return newVariant(value); + JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue); + if (!jscObject->isObject(&QScriptObject::info)) { + qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported"); + return QScriptValue(); + } + QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); + if (!object.isVariant()) { + delete jscScriptObject->delegate(); + jscScriptObject->setDelegate(new QScript::QVariantDelegate(value)); + } else { + QScriptValuePrivate::get(object)->setVariantValue(value); + } + return object; +} + +#ifndef QT_NO_QOBJECT +/*! + Creates a QtScript object that wraps the given QObject \a + object, using the given \a ownership. The given \a options control + various aspects of the interaction with the resulting script object. + + Signals and slots, properties and children of \a object are + available as properties of the created QScriptValue. For more + information, see the \l{QtScript} documentation. + + If \a object is a null pointer, this function returns nullValue(). + + If a default prototype has been registered for the \a object's class + (or its superclass, recursively), the prototype of the new script + object will be set to be that default prototype. + + If the given \a object is deleted outside of QtScript's control, any + attempt to access the deleted QObject's members through the QtScript + wrapper object (either by script code or C++) will result in a + script exception. + + \sa QScriptValue::toQObject() +*/ +QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership, + const QObjectWrapOptions &options) +{ + Q_D(QScriptEngine); + JSC::JSValue jscQObject = d->newQObject(object, ownership, options); + return d->scriptValueFromJSCValue(jscQObject); +} + +/*! + \since 4.4 + \overload + + Initializes the given \a scriptObject to hold the given \a qtObject, + and returns the \a scriptObject. + + This function enables you to "promote" a plain Qt Script object + (created by the newObject() function) to a QObject proxy, or to + replace the QObject contained inside an object previously created by + the newQObject() function. + + The prototype() of the \a scriptObject will remain unchanged. + + If \a scriptObject is not an object, this function behaves like the + normal newQObject(), i.e. it creates a new script object and returns + it. + + This function is useful when you want to provide a script + constructor for a QObject-based class. If your constructor is + invoked in a \c{new} expression + (QScriptContext::isCalledAsConstructor() returns true), you can pass + QScriptContext::thisObject() (the default constructed script object) + to this function to initialize the new object. +*/ +QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject, + QObject *qtObject, + ValueOwnership ownership, + const QObjectWrapOptions &options) +{ + if (!scriptObject.isObject()) + return newQObject(qtObject, ownership, options); + JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue); + if (!jscObject->isObject(&QScriptObject::info)) { + qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported"); + return QScriptValue(); + } + QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); + if (!scriptObject.isQObject()) { + delete jscScriptObject->delegate(); + jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options)); + } else { + QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate()); + delegate->setValue(qtObject); + delegate->setOwnership(ownership); + delegate->setOptions(options); + } + return scriptObject; +} + +#endif // QT_NO_QOBJECT + +/*! + Creates a QtScript object of class Object. + + The prototype of the created object will be the Object + prototype object. + + \sa newArray(), QScriptValue::setProperty() +*/ +QScriptValue QScriptEngine::newObject() +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSObject *result = new (exec)QScriptObject(d->scriptObjectStructure); + return d->scriptValueFromJSCValue(result); +} + +/*! + \since 4.4 + \overload + + Creates a QtScript Object of the given class, \a scriptClass. + + The prototype of the created object will be the Object + prototype object. + + \a data, if specified, is set as the internal data of the + new object (using QScriptValue::setData()). + + \sa QScriptValue::scriptClass() +*/ +QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass, + const QScriptValue &data) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure); + result->setDelegate(new QScript::ClassObjectDelegate(scriptClass)); + QScriptValue scriptObject = d->scriptValueFromJSCValue(result); + scriptObject.setData(data); + QScriptValue proto = scriptClass->prototype(); + if (proto.isValid()) + scriptObject.setPrototype(proto); + return scriptObject; +} + +/*! + \internal +*/ +QScriptValue QScriptEngine::newActivationObject() +{ + qWarning("QScriptEngine::newActivationObject() not implemented"); + // ### JSActivation or JSVariableObject? + return QScriptValue(); +} + +/*! + Creates a QScriptValue that wraps a native (C++) function. \a fun + must be a C++ function with signature QScriptEngine::FunctionSignature. \a + length is the number of arguments that \a fun expects; this becomes + the \c{length} property of the created QScriptValue. + + Note that \a length only gives an indication of the number of + arguments that the function expects; an actual invocation of a + function can include any number of arguments. You can check the + \l{QScriptContext::argumentCount()}{argumentCount()} of the + QScriptContext associated with the invocation to determine the + actual number of arguments passed. + + A \c{prototype} property is automatically created for the resulting + function object, to provide for the possibility that the function + will be used as a constructor. + + By combining newFunction() and the property flags + QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you + can create script object properties that behave like normal + properties in script code, but are in fact accessed through + functions (analogous to how properties work in \l{Qt's Property + System}). Example: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11 + + When the property \c{foo} of the script object is subsequently + accessed in script code, \c{getSetFoo()} will be invoked to handle + the access. In this particular case, we chose to store the "real" + value of \c{foo} as a property of the accessor function itself; you + are of course free to do whatever you like in this function. + + In the above example, a single native function was used to handle + both reads and writes to the property; the argument count is used to + determine if we are handling a read or write. You can also use two + separate functions; just specify the relevant flag + (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when + setting the property, e.g.: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12 + + \sa QScriptValue::call() +*/ +QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); + QScriptValue result = d->scriptValueFromJSCValue(function); + QScriptValue proto = newObject(); + result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); + proto.setProperty(QLatin1String("constructor"), result, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + return result; +} + +/*! + \internal + \since 4.4 +*/ +QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg); + QScriptValue result = d->scriptValueFromJSCValue(function); + QScriptValue proto = newObject(); + result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); + proto.setProperty(QLatin1String("constructor"), result, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + return result; +} + +/*! + Creates a QtScript object of class Array with the given \a length. + + \sa newObject() +*/ +QScriptValue QScriptEngine::newArray(uint length) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSArray* result = JSC::constructEmptyArray(exec, length); + return d->scriptValueFromJSCValue(result); +} + +/*! + Creates a QtScript object of class RegExp with the given + \a pattern and \a flags. + + The legal flags are 'g' (global), 'i' (ignore case), and 'm' + (multiline). +*/ +QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSValue buf[2]; + JSC::ArgList args(buf, sizeof(buf)); + JSC::UString jscPattern = pattern; + QString strippedFlags; + if (flags.contains(QLatin1Char('i'))) + strippedFlags += QLatin1Char('i'); + if (flags.contains(QLatin1Char('m'))) + strippedFlags += QLatin1Char('m'); + if (flags.contains(QLatin1Char('g'))) + strippedFlags += QLatin1Char('g'); + JSC::UString jscFlags = strippedFlags; + buf[0] = JSC::jsString(exec, jscPattern); + buf[1] = JSC::jsString(exec, jscFlags); + JSC::JSObject* result = JSC::constructRegExp(exec, args); + return d->scriptValueFromJSCValue(result); +} + +/*! + Creates a QtScript object of class Date with the given + \a value (the number of milliseconds since 01 January 1970, + UTC). +*/ +QScriptValue QScriptEngine::newDate(qsreal value) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSValue val = JSC::jsNumber(exec, value); + JSC::ArgList args(&val, 1); + JSC::JSObject *result = JSC::constructDate(exec, args); + return d->scriptValueFromJSCValue(result); +} + +/*! + Creates a QtScript object of class Date from the given \a value. + + \sa QScriptValue::toDateTime() +*/ +QScriptValue QScriptEngine::newDate(const QDateTime &value) +{ + return newDate(QScript::FromDateTime(value)); +} + +#ifndef QT_NO_QOBJECT +/*! + Creates a QtScript object that represents a QObject class, using the + the given \a metaObject and constructor \a ctor. + + Enums of \a metaObject (declared with Q_ENUMS) are available as + properties of the created QScriptValue. When the class is called as + a function, \a ctor will be called to create a new instance of the + class. + + Example: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 27 + + \sa newQObject(), scriptValueFromQMetaObject() +*/ +QScriptValue QScriptEngine::newQMetaObject( + const QMetaObject *metaObject, const QScriptValue &ctor) +{ + Q_D(QScriptEngine); + JSC::JSValue jscCtor = d->scriptValueToJSCValue(ctor); + JSC::JSValue jscQMetaObject = d->newQMetaObject(metaObject, jscCtor); + return d->scriptValueFromJSCValue(jscQMetaObject); +} + +/*! + \fn QScriptValue QScriptEngine::scriptValueFromQMetaObject() + + Creates a QScriptValue that represents the Qt class \c{T}. + + This function is used in combination with one of the + Q_SCRIPT_DECLARE_QMETAOBJECT() macro. Example: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13 + + \warning This function is not available with MSVC 6. Use + qScriptValueFromQMetaObject() instead if you need to support that version + of the compiler. + + \sa QScriptEngine::newQMetaObject() +*/ + +/*! + \fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine) + \since 4.3 + \relates QScriptEngine + + Uses \a engine to create a QScriptValue that represents the Qt class + \c{T}. + + This function is equivalent to + QScriptEngine::scriptValueFromQMetaObject(). It is provided as a + work-around for MSVC 6, which doesn't support member template + functions. + + \sa QScriptEngine::newQMetaObject() +*/ +#endif // QT_NO_QOBJECT + +/*! + \obsolete + + Returns true if \a program can be evaluated; i.e. the code is + sufficient to determine whether it appears to be a syntactically + correct program, or contains a syntax error. + + This function returns false if \a program is incomplete; i.e. the + input is syntactically correct up to the point where the input is + terminated. + + Note that this function only does a static check of \a program; + e.g. it does not check whether references to variables are + valid, and so on. + + A typical usage of canEvaluate() is to implement an interactive + interpreter for QtScript. The user is repeatedly queried for + individual lines of code; the lines are concatened internally, and + only when canEvaluate() returns true for the resulting program is it + passed to evaluate(). + + The following are some examples to illustrate the behavior of + canEvaluate(). (Note that all example inputs are assumed to have an + explicit newline as their last character, since otherwise the + QtScript parser would automatically insert a semi-colon character at + the end of the input, and this could cause canEvaluate() to produce + different results.) + + Given the input + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 14 + canEvaluate() will return true, since the program appears to be complete. + + Given the input + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 15 + canEvaluate() will return false, since the if-statement is not complete, + but is syntactically correct so far. + + Given the input + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 16 + canEvaluate() will return true, but evaluate() will throw a + SyntaxError given the same input. + + Given the input + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 17 + canEvaluate() will return true, even though the code is clearly not + syntactically valid QtScript code. evaluate() will throw a + SyntaxError when this code is evaluated. + + Given the input + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 18 + canEvaluate() will return true, but evaluate() will throw a + ReferenceError if \c{foo} is not defined in the script + environment. + + \sa evaluate(), checkSyntax() +*/ +bool QScriptEngine::canEvaluate(const QString &program) const +{ + return QScriptEnginePrivate::canEvaluate(program); +} + + +bool QScriptEnginePrivate::canEvaluate(const QString &program) +{ + QScript::SyntaxChecker checker; + QScript::SyntaxChecker::Result result = checker.checkSyntax(program); + return (result.state != QScript::SyntaxChecker::Intermediate); +} + +/*! + \since 4.5 + + Checks the syntax of the given \a program. Returns a + QScriptSyntaxCheckResult object that contains the result of the check. +*/ +QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program) +{ + return QScriptEnginePrivate::checkSyntax(program); +} + +QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &program) +{ + QScript::SyntaxChecker checker; + QScript::SyntaxChecker::Result result = checker.checkSyntax(program); + QScriptSyntaxCheckResultPrivate *p = new QScriptSyntaxCheckResultPrivate(); + switch (result.state) { + case QScript::SyntaxChecker::Error: + p->state = QScriptSyntaxCheckResult::Error; + break; + case QScript::SyntaxChecker::Intermediate: + p->state = QScriptSyntaxCheckResult::Intermediate; + break; + case QScript::SyntaxChecker::Valid: + p->state = QScriptSyntaxCheckResult::Valid; + break; + } + p->errorLineNumber = result.errorLineNumber; + p->errorColumnNumber = result.errorColumnNumber; + p->errorMessage = result.errorMessage; + return QScriptSyntaxCheckResult(p); +} + + + +/*! + Evaluates \a program, using \a lineNumber as the base line number, + and returns the result of the evaluation. + + The script code will be evaluated in the current context. + + The evaluation of \a program can cause an exception in the + engine; in this case the return value will be the exception + that was thrown (typically an \c{Error} object). You can call + hasUncaughtException() to determine if an exception occurred in + the last call to evaluate(). + + \a lineNumber is used to specify a starting line number for \a + program; line number information reported by the engine that pertain + to this evaluation (e.g. uncaughtExceptionLineNumber()) will be + based on this argument. For example, if \a program consists of two + lines of code, and the statement on the second line causes a script + exception, uncaughtExceptionLineNumber() would return the given \a + lineNumber plus one. When no starting line number is specified, line + numbers will be 1-based. + + \a fileName is used for error reporting. For example in error objects + the file name is accessible through the "fileName" property if it's + provided with this function. + + \sa canEvaluate(), hasUncaughtException(), isEvaluating(), abortEvaluation() +*/ +QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber) +{ + Q_D(QScriptEngine); + + JSC::JSLock lock(false); // ### hmmm + QBoolBlocker inEval(d->inEval, true); + currentContext()->activationObject(); //force the creation of a context for native function; + + JSC::UString jscProgram = program; + JSC::UString jscFileName = fileName; + JSC::ExecState* exec = d->currentFrame; + JSC::SourceCode source = JSC::makeSource(jscProgram, jscFileName, lineNumber); + + 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); + + if (debugger) { + debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, exceptionValue), sourceId, false); + debugger->evaluateStop(exceptionValue, sourceId); + } + exec->globalData().scriptpool->stopEvaluating(source); + + return d->scriptValueFromJSCValue(exceptionValue); + } + + 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); + + if (d->timeoutChecker()->shouldAbort()) { + if (d->abortResult.isError()) + exec->setException(d->scriptValueToJSCValue(d->abortResult)); + + if (debugger) + debugger->evaluateStop(d->scriptValueToJSCValue(d->abortResult), sourceId); + exec->globalData().scriptpool->stopEvaluating(source); + + return d->abortResult; + } + + if (exceptionValue) { + exec->setException(exceptionValue); + + 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); +} + + +/*! + Returns the current context. + + The current context is typically accessed to retrieve the arguments + and `this' object in native functions; for convenience, it is + available as the first argument in QScriptEngine::FunctionSignature. +*/ +QScriptContext *QScriptEngine::currentContext() const +{ + Q_D(const QScriptEngine); + return const_cast<QScriptEnginePrivate*>(d)->contextForFrame(d->currentFrame); +} + +/*! + Enters a new execution context and returns the associated + QScriptContext object. + + Once you are done with the context, you should call popContext() to + restore the old context. + + By default, the `this' object of the new context is the Global Object. + The context's \l{QScriptContext::callee()}{callee}() will be invalid. + + This function is useful when you want to evaluate script code + as if it were the body of a function. You can use the context's + \l{QScriptContext::activationObject()}{activationObject}() to initialize + local variables that will be available to scripts. Example: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 19 + + In the above example, the new variable "tmp" defined in the script + will be local to the context; in other words, the script doesn't + have any effect on the global environment. + + Returns 0 in case of stack overflow + + \sa popContext() +*/ +QScriptContext *QScriptEngine::pushContext() +{ + Q_D(QScriptEngine); + + JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject, + JSC::ArgList(), /*callee = */0); + + if (agent()) + agent()->contextPush(); + + return d->contextForFrame(newFrame); +} + +/*! \internal + push a context for a native function. + JSC native function doesn't have different stackframe or context. so we need to create one. + + use popContext right after to go back to the previous context the context if no stack overflow has hapenned + + exec is the current top frame. + + return the new top frame. (might be the same as exec if a new stackframe was not needed) or 0 if stack overflow +*/ +JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSValue _thisObject, + const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor) +{ + JSC::JSValue thisObject = _thisObject; + if (calledAsConstructor) { + //JSC doesn't create default created object for native functions. so we do it + JSC::JSValue prototype = callee->get(exec, exec->propertyNames().prototype); + JSC::Structure *structure = prototype.isObject() ? JSC::asObject(prototype)->inheritorID() + : originalGlobalObject()->emptyObjectStructure(); + thisObject = new (exec) QScriptObject(structure); + } + + int flags = NativeContext; + if (calledAsConstructor) + flags |= CalledAsConstructorContext; + + JSC::CallFrame *newCallFrame = exec; + if (callee == 0 || !(exec->callee() == callee && exec->returnPC() != 0)) { + //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)) + return 0; //### Stack overflow + newCallFrame = JSC::CallFrame::create(oldEnd); + 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); + } else { + setContextFlags(newCallFrame, flags); + if (calledAsConstructor) { + //update the new created this + JSC::Register* thisRegister = newCallFrame->registers() - JSC::RegisterFile::CallFrameHeaderSize - newCallFrame->argumentCount(); + *thisRegister = thisObject; + } + } + currentFrame = newCallFrame; + return newCallFrame; +} + + +/*! + Pops the current execution context and restores the previous one. + This function must be used in conjunction with pushContext(). + + \sa pushContext() +*/ +void QScriptEngine::popContext() +{ + if (agent()) + agent()->contextPop(); + Q_D(QScriptEngine); + if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0 + || !currentContext()->parentContext()) { + qWarning("QScriptEngine::popContext() doesn't match with pushContext()"); + return; + } + + d->popContext(); +} + +/*! \internal + counter part of QScriptEnginePrivate::pushContext + */ +void QScriptEnginePrivate::popContext() +{ + bool hasScope = contextFlags(currentFrame) & HasScopeContext; + if (currentFrame->returnPC() == 0) { //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(); + } +} + +/*! + Returns true if the last script evaluation resulted in an uncaught + exception; otherwise returns false. + + The exception state is cleared when evaluate() is called. + + \sa uncaughtException(), uncaughtExceptionLineNumber(), + uncaughtExceptionBacktrace() +*/ +bool QScriptEngine::hasUncaughtException() const +{ + Q_D(const QScriptEngine); + JSC::ExecState* exec = d->globalExec(); + return exec->hadException(); +} + +/*! + Returns the current uncaught exception, or an invalid QScriptValue + if there is no uncaught exception. + + The exception value is typically an \c{Error} object; in that case, + you can call toString() on the return value to obtain an error + message. + + \sa hasUncaughtException(), uncaughtExceptionLineNumber(), + uncaughtExceptionBacktrace() +*/ +QScriptValue QScriptEngine::uncaughtException() const +{ + Q_D(const QScriptEngine); + JSC::ExecState* exec = d->globalExec(); + return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(exec->exception()); +} + +/*! + Returns the line number where the last uncaught exception occurred. + + Line numbers are 1-based, unless a different base was specified as + the second argument to evaluate(). + + \sa hasUncaughtException(), uncaughtExceptionBacktrace() +*/ +int QScriptEngine::uncaughtExceptionLineNumber() const +{ + if (!hasUncaughtException()) + return -1; + return uncaughtException().property(QLatin1String("lineNumber")).toInt32(); +} + +/*! + Returns a human-readable backtrace of the last uncaught exception. + + Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}. + + \sa uncaughtException() +*/ +QStringList QScriptEngine::uncaughtExceptionBacktrace() const +{ + if (!hasUncaughtException()) + return QStringList(); +// ### currently no way to get a full backtrace from JSC without installing a +// debugger that reimplements exception() and store the backtrace there. + QScriptValue value = uncaughtException(); + if (!value.isError()) + return QStringList(); + QStringList result; + result.append(QString::fromLatin1("<anonymous>()@%0:%1") + .arg(value.property(QLatin1String("fileName")).toString()) + .arg(value.property(QLatin1String("lineNumber")).toInt32())); + return result; +} + +/*! + \since 4.4 + + Clears any uncaught exceptions in this engine. + + \sa hasUncaughtException() +*/ +void QScriptEngine::clearExceptions() +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + exec->clearException(); +} + +/*! + Returns the default prototype associated with the given \a metaTypeId, + or an invalid QScriptValue if no default prototype has been set. + + \sa setDefaultPrototype() +*/ +QScriptValue QScriptEngine::defaultPrototype(int metaTypeId) const +{ + Q_D(const QScriptEngine); + return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(d->defaultPrototype(metaTypeId)); +} + +/*! + Sets the default prototype of the C++ type identified by the given + \a metaTypeId to \a prototype. + + The default prototype provides a script interface for values of + type \a metaTypeId when a value of that type is accessed from script + code. Whenever the script engine (implicitly or explicitly) creates + a QScriptValue from a value of type \a metaTypeId, the default + prototype will be set as the QScriptValue's prototype. + + The \a prototype object itself may be constructed using one of two + principal techniques; the simplest is to subclass QScriptable, which + enables you to define the scripting API of the type through QObject + properties and slots. Another possibility is to create a script + object by calling newObject(), and populate the object with the + desired properties (e.g. native functions wrapped with + newFunction()). + + \sa defaultPrototype(), qScriptRegisterMetaType(), QScriptable, {Default Prototypes Example} +*/ +void QScriptEngine::setDefaultPrototype(int metaTypeId, const QScriptValue &prototype) +{ + Q_D(QScriptEngine); + d->setDefaultPrototype(metaTypeId, d->scriptValueToJSCValue(prototype)); +} + +/*! + \typedef QScriptEngine::FunctionSignature + \relates QScriptEngine + + The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}. + + A function with such a signature can be passed to + QScriptEngine::newFunction() to wrap the function. +*/ + +/*! + \typedef QScriptEngine::FunctionWithArgSignature + \relates QScriptEngine + + The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}. + + A function with such a signature can be passed to + QScriptEngine::newFunction() to wrap the function. +*/ + +/*! + \typedef QScriptEngine::MarshalFunction + \internal +*/ + +/*! + \typedef QScriptEngine::DemarshalFunction + \internal +*/ + +/*! + \internal +*/ +QScriptValue QScriptEngine::create(int type, const void *ptr) +{ + Q_D(QScriptEngine); + return d->create(type, ptr); +} + +QScriptValue QScriptEnginePrivate::create(int type, const void *ptr) +{ + Q_ASSERT(ptr != 0); + QScriptValue result; + QScriptTypeInfo *info = m_typeInfos.value(type); + if (info && info->marshal) { + result = info->marshal(q_func(), ptr); + } else { + // check if it's one of the types we know + switch (QMetaType::Type(type)) { + case QMetaType::Void: + result = QScriptValue(QScriptValue::UndefinedValue); + break; + case QMetaType::Bool: + result = QScriptValue(*reinterpret_cast<const bool*>(ptr)); + break; + case QMetaType::Int: + result = QScriptValue(*reinterpret_cast<const int*>(ptr)); + break; + case QMetaType::UInt: + result = QScriptValue(*reinterpret_cast<const uint*>(ptr)); + break; + case QMetaType::LongLong: + result = QScriptValue(qsreal(*reinterpret_cast<const qlonglong*>(ptr))); + break; + case QMetaType::ULongLong: +#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 +#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") + result = QScriptValue(qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); +#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) + result = QScriptValue(qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); +#else + result = QScriptValue(qsreal(*reinterpret_cast<const qulonglong*>(ptr))); +#endif + break; + case QMetaType::Double: + result = QScriptValue(*reinterpret_cast<const double*>(ptr)); + break; + case QMetaType::QString: + result = QScriptValue(q_func(), *reinterpret_cast<const QString*>(ptr)); + break; + case QMetaType::Float: + result = QScriptValue(*reinterpret_cast<const float*>(ptr)); + break; + case QMetaType::Short: + result = QScriptValue(*reinterpret_cast<const short*>(ptr)); + break; + case QMetaType::UShort: + result = QScriptValue(*reinterpret_cast<const unsigned short*>(ptr)); + break; + case QMetaType::Char: + result = QScriptValue(*reinterpret_cast<const char*>(ptr)); + break; + case QMetaType::UChar: + result = QScriptValue(*reinterpret_cast<const unsigned char*>(ptr)); + break; + case QMetaType::QChar: + result = QScriptValue((*reinterpret_cast<const QChar*>(ptr)).unicode()); + break; + case QMetaType::QStringList: + result = arrayFromStringList(*reinterpret_cast<const QStringList *>(ptr)); + break; + case QMetaType::QVariantList: + result = arrayFromVariantList(*reinterpret_cast<const QVariantList *>(ptr)); + break; + case QMetaType::QVariantMap: + result = objectFromVariantMap(*reinterpret_cast<const QVariantMap *>(ptr)); + break; + case QMetaType::QDateTime: + result = q_func()->newDate(*reinterpret_cast<const QDateTime *>(ptr)); + break; + case QMetaType::QDate: + result = q_func()->newDate(QDateTime(*reinterpret_cast<const QDate *>(ptr))); + break; +#ifndef QT_NO_REGEXP + case QMetaType::QRegExp: + result = q_func()->newRegExp(*reinterpret_cast<const QRegExp *>(ptr)); + break; +#endif +#ifndef QT_NO_QOBJECT + case QMetaType::QObjectStar: + case QMetaType::QWidgetStar: + result = q_func()->newQObject(*reinterpret_cast<QObject* const *>(ptr)); + break; +#endif + default: + if (type == qMetaTypeId<QScriptValue>()) { + result = *reinterpret_cast<const QScriptValue*>(ptr); + if (!result.isValid()) + result = QScriptValue(QScriptValue::UndefinedValue); + } + +#ifndef QT_NO_QOBJECT + // lazy registration of some common list types + else if (type == qMetaTypeId<QObjectList>()) { + qScriptRegisterSequenceMetaType<QObjectList>(q_func()); + return create(type, ptr); + } +#endif + else if (type == qMetaTypeId<QList<int> >()) { + qScriptRegisterSequenceMetaType<QList<int> >(q_func()); + return create(type, ptr); + } + + else { + QByteArray typeName = QMetaType::typeName(type); + if (typeName == "QVariant") + result = scriptValueFromVariant(*reinterpret_cast<const QVariant*>(ptr)); + if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr)) + result = QScriptValue(QScriptValue::NullValue); + else + result = q_func()->newVariant(QVariant(type, ptr)); + } + } + } + if (result.isObject() && info && info->prototype + && JSC::JSValue::strictEqual(scriptValueToJSCValue(result.prototype()), originalGlobalObject()->objectPrototype())) { + result.setPrototype(scriptValueFromJSCValue(info->prototype)); + } + return result; +} + +bool QScriptEnginePrivate::convert(const QScriptValue &value, + int type, void *ptr, + QScriptEnginePrivate *eng) +{ + if (!eng && value.engine()) + eng = QScriptEnginePrivate::get(value.engine()); + if (eng) { + QScriptTypeInfo *info = eng->m_typeInfos.value(type); + if (info && info->demarshal) { + info->demarshal(value, ptr); + return true; + } + } + + // check if it's one of the types we know + switch (QMetaType::Type(type)) { + case QMetaType::Bool: + *reinterpret_cast<bool*>(ptr) = value.toBoolean(); + return true; + case QMetaType::Int: + *reinterpret_cast<int*>(ptr) = value.toInt32(); + return true; + case QMetaType::UInt: + *reinterpret_cast<uint*>(ptr) = value.toUInt32(); + return true; + case QMetaType::LongLong: + *reinterpret_cast<qlonglong*>(ptr) = qlonglong(value.toInteger()); + return true; + case QMetaType::ULongLong: + *reinterpret_cast<qulonglong*>(ptr) = qulonglong(value.toInteger()); + return true; + case QMetaType::Double: + *reinterpret_cast<double*>(ptr) = value.toNumber(); + return true; + case QMetaType::QString: + if (value.isUndefined() || value.isNull()) + *reinterpret_cast<QString*>(ptr) = QString(); + else + *reinterpret_cast<QString*>(ptr) = value.toString(); + return true; + case QMetaType::Float: + *reinterpret_cast<float*>(ptr) = value.toNumber(); + return true; + case QMetaType::Short: + *reinterpret_cast<short*>(ptr) = short(value.toInt32()); + return true; + case QMetaType::UShort: + *reinterpret_cast<unsigned short*>(ptr) = value.toUInt16(); + return true; + case QMetaType::Char: + *reinterpret_cast<char*>(ptr) = char(value.toInt32()); + return true; + case QMetaType::UChar: + *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(value.toInt32()); + return true; + case QMetaType::QChar: + if (value.isString()) { + QString str = value.toString(); + *reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0); + } else { + *reinterpret_cast<QChar*>(ptr) = QChar(value.toUInt16()); + } + return true; + case QMetaType::QDateTime: + if (value.isDate()) { + *reinterpret_cast<QDateTime *>(ptr) = value.toDateTime(); + return true; + } break; + case QMetaType::QDate: + if (value.isDate()) { + *reinterpret_cast<QDate *>(ptr) = value.toDateTime().date(); + return true; + } break; +#ifndef QT_NO_REGEXP + case QMetaType::QRegExp: + if (value.isRegExp()) { + *reinterpret_cast<QRegExp *>(ptr) = value.toRegExp(); + return true; + } break; +#endif +#ifndef QT_NO_QOBJECT + case QMetaType::QObjectStar: + if (value.isQObject() || value.isNull()) { + *reinterpret_cast<QObject* *>(ptr) = value.toQObject(); + return true; + } break; + case QMetaType::QWidgetStar: + if (value.isQObject() || value.isNull()) { + QObject *qo = value.toQObject(); + if (!qo || qo->isWidgetType()) { + *reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo); + return true; + } + } break; +#endif + case QMetaType::QStringList: + if (value.isArray()) { + *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(value); + return true; + } break; + case QMetaType::QVariantList: + if (value.isArray()) { + *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(value); + return true; + } break; + case QMetaType::QVariantMap: + if (value.isObject()) { + *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(value); + return true; + } break; + default: + ; + } + + QByteArray name = QMetaType::typeName(type); +#ifndef QT_NO_QOBJECT + if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(ptr))) + return true; +#endif + if (value.isVariant() && name.endsWith('*')) { + int valueType = QMetaType::type(name.left(name.size()-1)); + QVariant &var = QScriptValuePrivate::get(value)->variantValue(); + if (valueType == var.userType()) { + *reinterpret_cast<void* *>(ptr) = var.data(); + return true; + } else { + // look in the prototype chain + QScriptValue proto = value.prototype(); + while (proto.isObject()) { + bool canCast = false; + if (proto.isVariant()) { + canCast = (type == proto.toVariant().userType()) + || (valueType && (valueType == proto.toVariant().userType())); + } +#ifndef QT_NO_QOBJECT + else if (proto.isQObject()) { + QByteArray className = name.left(name.size()-1); + if (QObject *qobject = proto.toQObject()) + canCast = qobject->qt_metacast(className) != 0; + } +#endif + if (canCast) { + QByteArray varTypeName = QMetaType::typeName(var.userType()); + if (varTypeName.endsWith('*')) + *reinterpret_cast<void* *>(ptr) = *reinterpret_cast<void* *>(var.data()); + else + *reinterpret_cast<void* *>(ptr) = var.data(); + return true; + } + proto = proto.prototype(); + } + } + } else if (value.isNull() && name.endsWith('*')) { + *reinterpret_cast<void* *>(ptr) = 0; + return true; + } else if (type == qMetaTypeId<QScriptValue>()) { + if (!eng) + return false; + *reinterpret_cast<QScriptValue*>(ptr) = value; + return true; + } else if (name == "QVariant") { + *reinterpret_cast<QVariant*>(ptr) = value.toVariant(); + return true; + } + + // lazy registration of some common list types +#ifndef QT_NO_QOBJECT + else if (type == qMetaTypeId<QObjectList>()) { + if (!eng) + return false; + qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func()); + return convert(value, type, ptr, eng); + } +#endif + else if (type == qMetaTypeId<QList<int> >()) { + if (!eng) + return false; + qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func()); + return convert(value, type, ptr, eng); + } + +#if 0 + if (!name.isEmpty()) { + qWarning("QScriptEngine::convert: unable to convert value to type `%s'", + name.constData()); + } +#endif + return false; +} + +bool QScriptEnginePrivate::hasDemarshalFunction(int type) const +{ + QScriptTypeInfo *info = m_typeInfos.value(type); + return info && (info->demarshal != 0); +} + +/*! + \internal +*/ +bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr) +{ + Q_D(QScriptEngine); + return QScriptEnginePrivate::convert(value, type, ptr, d); +} + +/*! + \internal +*/ +bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr) +{ + return QScriptEnginePrivate::convert(value, type, ptr, /*engine=*/0); +} + +/*! + \internal +*/ +void QScriptEngine::registerCustomType(int type, MarshalFunction mf, + DemarshalFunction df, + const QScriptValue &prototype) +{ + Q_D(QScriptEngine); + QScriptTypeInfo *info = d->m_typeInfos.value(type); + if (!info) { + info = new QScriptTypeInfo(); + d->m_typeInfos.insert(type, info); + } + info->marshal = mf; + info->demarshal = df; + info->prototype = d->scriptValueToJSCValue(prototype); +} + +/*! + \since 4.5 + + Installs translator functions on the given \a object, or on the Global + Object if no object is specified. + + The relation between Qt Script translator functions and C++ translator + functions is described in the following table: + + \table + \header \o Script Function \o Corresponding C++ Function + \row \o qsTr() \o QObject::tr() + \row \o QT_TR_NOOP() \o QT_TR_NOOP() + \row \o qsTranslate() \o QCoreApplication::translate() + \row \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP() + \endtable + + \sa {Internationalization with Qt} +*/ +void QScriptEngine::installTranslatorFunctions(const QScriptValue &object) +{ + Q_D(QScriptEngine); + JSC::ExecState* exec = d->currentFrame; + JSC::JSValue jscObject = d->scriptValueToJSCValue(object); + JSC::JSGlobalObject *glob = d->originalGlobalObject(); + if (!jscObject || !jscObject.isObject()) + jscObject = glob; +// unsigned attribs = JSC::DontEnum; + JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate)); + JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp)); + JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr)); + JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp)); + + glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg)); +} + +/*! + Imports the given \a extension into this QScriptEngine. Returns + undefinedValue() if the extension was successfully imported. You + can call hasUncaughtException() to check if an error occurred; in + that case, the return value is the value that was thrown by the + exception (usually an \c{Error} object). + + QScriptEngine ensures that a particular extension is only imported + once; subsequent calls to importExtension() with the same extension + name will do nothing and return undefinedValue(). + + \sa availableExtensions(), QScriptExtensionPlugin, {Creating QtScript Extensions} +*/ +QScriptValue QScriptEngine::importExtension(const QString &extension) +{ +#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS) + Q_UNUSED(extension); +#else + Q_D(QScriptEngine); + if (d->importedExtensions.contains(extension)) + return undefinedValue(); // already imported + + QScriptContext *context = currentContext(); + QCoreApplication *app = QCoreApplication::instance(); + if (!app) + return context->throwError(QLatin1String("No application object")); + + QObjectList staticPlugins = QPluginLoader::staticInstances(); + QStringList libraryPaths = app->libraryPaths(); + QString dot = QLatin1String("."); + QStringList pathComponents = extension.split(dot); + QString initDotJs = QLatin1String("__init__.js"); + + QString ext; + for (int i = 0; i < pathComponents.count(); ++i) { + if (!ext.isEmpty()) + ext.append(dot); + ext.append(pathComponents.at(i)); + if (d->importedExtensions.contains(ext)) + continue; // already imported + + if (d->extensionsBeingImported.contains(ext)) { + return context->throwError(QString::fromLatin1("recursive import of %0") + .arg(extension)); + } + d->extensionsBeingImported.insert(ext); + + QScriptExtensionInterface *iface = 0; + QString initjsContents; + QString initjsFileName; + + // look for the extension in static plugins + for (int j = 0; j < staticPlugins.size(); ++j) { + iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(j)); + if (!iface) + continue; + if (iface->keys().contains(ext)) + break; // use this one + else + iface = 0; // keep looking + } + + { + // look for __init__.js resource + QString path = QString::fromLatin1(":/qtscriptextension"); + for (int j = 0; j <= i; ++j) { + path.append(QLatin1Char('/')); + path.append(pathComponents.at(j)); + } + path.append(QLatin1Char('/')); + path.append(initDotJs); + QFile file(path); + if (file.open(QIODevice::ReadOnly)) { + QTextStream ts(&file); + initjsContents = ts.readAll(); + initjsFileName = path; + file.close(); + } + } + + if (!iface && initjsContents.isEmpty()) { + // look for the extension in library paths + for (int j = 0; j < libraryPaths.count(); ++j) { + QString libPath = libraryPaths.at(j) + QDir::separator() + QLatin1String("script"); + QDir dir(libPath); + if (!dir.exists(dot)) + continue; + + // look for C++ plugin + QFileInfoList files = dir.entryInfoList(QDir::Files); + for (int k = 0; k < files.count(); ++k) { + QFileInfo entry = files.at(k); + QString filePath = entry.canonicalFilePath(); + QPluginLoader loader(filePath); + iface = qobject_cast<QScriptExtensionInterface*>(loader.instance()); + if (iface) { + if (iface->keys().contains(ext)) + break; // use this one + else + iface = 0; // keep looking + } + } + + // look for __init__.js in the corresponding dir + QDir dirdir(libPath); + bool dirExists = dirdir.exists(); + for (int k = 0; dirExists && (k <= i); ++k) + dirExists = dirdir.cd(pathComponents.at(k)); + if (dirExists && dirdir.exists(initDotJs)) { + QFile file(dirdir.canonicalPath() + + QDir::separator() + initDotJs); + if (file.open(QIODevice::ReadOnly)) { + QTextStream ts(&file); + initjsContents = ts.readAll(); + initjsFileName = file.fileName(); + file.close(); + } + } + + if (iface || !initjsContents.isEmpty()) + break; + } + } + + if (!iface && initjsContents.isEmpty()) { + d->extensionsBeingImported.remove(ext); + return context->throwError( + QString::fromLatin1("Unable to import %0: no such extension") + .arg(extension)); + } + + // initialize the extension in a new context + QScriptContext *ctx = pushContext(); + ctx->setThisObject(globalObject()); + ctx->activationObject().setProperty(QLatin1String("__extension__"), ext, + QScriptValue::ReadOnly | QScriptValue::Undeletable); + ctx->activationObject().setProperty(QLatin1String("__setupPackage__"), + newFunction(QScript::__setupPackage__)); + ctx->activationObject().setProperty(QLatin1String("__postInit__"), QScriptValue(QScriptValue::UndefinedValue)); + + // the script is evaluated first + if (!initjsContents.isEmpty()) { + QScriptValue ret = evaluate(initjsContents, initjsFileName); + if (hasUncaughtException()) { + popContext(); + d->extensionsBeingImported.remove(ext); + return ret; + } + } + + // next, the C++ plugin is called + if (iface) { + iface->initialize(ext, this); + if (hasUncaughtException()) { + QScriptValue ret = uncaughtException(); // ctx_p->returnValue(); + popContext(); + d->extensionsBeingImported.remove(ext); + return ret; + } + } + + // if the __postInit__ function has been set, we call it + QScriptValue postInit = ctx->activationObject().property(QLatin1String("__postInit__")); + if (postInit.isFunction()) { + postInit.call(globalObject()); + if (hasUncaughtException()) { + QScriptValue ret = uncaughtException(); // ctx_p->returnValue(); + popContext(); + d->extensionsBeingImported.remove(ext); + return ret; + } + } + + popContext(); + + d->importedExtensions.insert(ext); + d->extensionsBeingImported.remove(ext); + } // for (i) +#endif // QT_NO_QOBJECT + return undefinedValue(); +} + +/*! + \since 4.4 + + Returns a list naming the available extensions that can be + imported using the importExtension() function. This list includes + extensions that have been imported. + + \sa importExtension(), importedExtensions() +*/ +QStringList QScriptEngine::availableExtensions() const +{ +#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS) + return QStringList(); +#else + QCoreApplication *app = QCoreApplication::instance(); + if (!app) + return QStringList(); + + QSet<QString> result; + + QObjectList staticPlugins = QPluginLoader::staticInstances(); + for (int i = 0; i < staticPlugins.size(); ++i) { + QScriptExtensionInterface *iface; + iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(i)); + if (iface) { + QStringList keys = iface->keys(); + for (int j = 0; j < keys.count(); ++j) + result << keys.at(j); + } + } + + QStringList libraryPaths = app->libraryPaths(); + for (int i = 0; i < libraryPaths.count(); ++i) { + QString libPath = libraryPaths.at(i) + QDir::separator() + QLatin1String("script"); + QDir dir(libPath); + if (!dir.exists()) + continue; + + // look for C++ plugins + QFileInfoList files = dir.entryInfoList(QDir::Files); + for (int j = 0; j < files.count(); ++j) { + QFileInfo entry = files.at(j); + QString filePath = entry.canonicalFilePath(); + QPluginLoader loader(filePath); + QScriptExtensionInterface *iface; + iface = qobject_cast<QScriptExtensionInterface*>(loader.instance()); + if (iface) { + QStringList keys = iface->keys(); + for (int k = 0; k < keys.count(); ++k) + result << keys.at(k); + } + } + + // look for scripts + QString initDotJs = QLatin1String("__init__.js"); + QList<QFileInfo> stack; + stack << dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + while (!stack.isEmpty()) { + QFileInfo entry = stack.takeLast(); + QDir dd(entry.canonicalFilePath()); + if (dd.exists(initDotJs)) { + QString rpath = dir.relativeFilePath(dd.canonicalPath()); + QStringList components = rpath.split(QLatin1Char('/')); + result << components.join(QLatin1String(".")); + stack << dd.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + } + } + } + + QStringList lst = result.toList(); + qSort(lst); + return lst; +#endif +} + +/*! + \since 4.4 + + Returns a list naming the extensions that have been imported + using the importExtension() function. + + \sa availableExtensions() +*/ +QStringList QScriptEngine::importedExtensions() const +{ + Q_D(const QScriptEngine); + QStringList lst = d->importedExtensions.toList(); + qSort(lst); + return lst; +} + +/*! \fn QScriptValue QScriptEngine::toScriptValue(const T &value) + + Creates a QScriptValue with the given \a value. + + Note that the template type \c{T} must be known to QMetaType. + + See \l{Conversion Between QtScript and C++ Types} for a + description of the built-in type conversion provided by + QtScript. By default, the types that are not specially handled by + QtScript are represented as QVariants (e.g. the \a value is passed + to newVariant()); you can change this behavior by installing your + own type conversion functions with qScriptRegisterMetaType(). + + \warning This function is not available with MSVC 6. Use + qScriptValueFromValue() instead if you need to support that + version of the compiler. + + \sa fromScriptValue(), qScriptRegisterMetaType() +*/ + +/*! \fn T QScriptEngine::fromScriptValue(const QScriptValue &value) + + Returns the given \a value converted to the template type \c{T}. + + Note that \c{T} must be known to QMetaType. + + See \l{Conversion Between QtScript and C++ Types} for a + description of the built-in type conversion provided by + QtScript. + + \warning This function is not available with MSVC 6. Use + qScriptValueToValue() or qscriptvalue_cast() instead if you need + to support that version of the compiler. + + \sa toScriptValue(), qScriptRegisterMetaType() +*/ + +/*! + \fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value) + \since 4.3 + \relates QScriptEngine + + Creates a QScriptValue using the given \a engine with the given \a + value of template type \c{T}. + + This function is equivalent to QScriptEngine::toScriptValue(). + It is provided as a work-around for MSVC 6, which doesn't support + member template functions. + + \sa qScriptValueToValue() +*/ + +/*! + \fn T qScriptValueToValue(const QScriptValue &value) + \since 4.3 + \relates QScriptEngine + + Returns the given \a value converted to the template type \c{T}. + + This function is equivalent to QScriptEngine::fromScriptValue(). + It is provided as a work-around for MSVC 6, which doesn't + support member template functions. + + \sa qScriptValueFromValue() +*/ + +/*! + \fn QScriptValue qScriptValueFromSequence(QScriptEngine *engine, const Container &container) + \since 4.3 + \relates QScriptEngine + + Creates an array in the form of a QScriptValue using the given \a engine + with the given \a container of template type \c{Container}. + + The \c Container type must provide a \c const_iterator class to enable the + contents of the container to be copied into the array. + + Additionally, the type of each element in the sequence should be suitable + for conversion to a QScriptValue. + See \l{QtScript Module#Conversion Between QtScript and C++ Types} + {Conversion Between QtScript and C++ Types} for more information about the + restrictions on types that can be used with QScriptValue. + + \sa qScriptValueFromValue() +*/ + +/*! + \fn void qScriptValueToSequence(const QScriptValue &value, Container &container) + \since 4.3 + \relates QScriptEngine + + Copies the elements in the sequence specified by \a value to the given + \a container of template type \c{Container}. + + The \a value used is typically an array, but any container can be copied + as long as it provides a \c length property describing how many elements + it contains. + + Additionally, the type of each element in the sequence must be suitable + for conversion to a C++ type from a QScriptValue. + See \l{QtScript Module#Conversion Between QtScript and C++ Types} + {Conversion Between QtScript and C++ Types} for more information about the + restrictions on types that can be used with QScriptValue. + + \sa qscriptvalue_cast() +*/ + +/*! + \fn T qscriptvalue_cast(const QScriptValue &value) + \since 4.3 + \relates QScriptValue + + Returns the given \a value converted to the template type \c{T}. + + \sa qScriptRegisterMetaType(), QScriptEngine::toScriptValue() +*/ + +/*! \fn int qScriptRegisterMetaType( + QScriptEngine *engine, + QScriptValue (*toScriptValue)(QScriptEngine *, const T &t), + void (*fromScriptValue)(const QScriptValue &, T &t), + const QScriptValue &prototype = QScriptValue()) + \relates QScriptEngine + + Registers the type \c{T} in the given \a engine. \a toScriptValue must + be a function that will convert from a value of type \c{T} to a + QScriptValue, and \a fromScriptValue a function that does the + opposite. \a prototype, if valid, is the prototype that's set on + QScriptValues returned by \a toScriptValue. + + Returns the internal ID used by QMetaType. + + You only need to call this function if you want to provide custom + conversion of values of type \c{T}, i.e. if the default + QVariant-based representation and conversion is not + appropriate. (Note that custom QObject-derived types also fall in + this category; e.g. for a QObject-derived class called MyObject, + you probably want to define conversion functions for MyObject* + that utilize QScriptEngine::newQObject() and + QScriptValue::toQObject().) + + If you only want to define a common script interface for values of + type \c{T}, and don't care how those values are represented + (i.e. storing them in QVariants is fine), use + \l{QScriptEngine::setDefaultPrototype()}{setDefaultPrototype}() + instead; this will minimize conversion costs. + + You need to declare the custom type first with + Q_DECLARE_METATYPE(). + + After a type has been registered, you can convert from a + QScriptValue to that type using + \l{QScriptEngine::fromScriptValue()}{fromScriptValue}(), and + create a QScriptValue from a value of that type using + \l{QScriptEngine::toScriptValue()}{toScriptValue}(). The engine + will take care of calling the proper conversion function when + calling C++ slots, and when getting or setting a C++ property; + i.e. the custom type may be used seamlessly on both the C++ side + and the script side. + + The following is an example of how to use this function. We will + specify custom conversion of our type \c{MyStruct}. Here's the C++ + type: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 20 + + We must declare it so that the type will be known to QMetaType: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 21 + + Next, the \c{MyStruct} conversion functions. We represent the + \c{MyStruct} value as a script object and just copy the properties: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 22 + + Now we can register \c{MyStruct} with the engine: + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 23 + + Working with \c{MyStruct} values is now easy: + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 24 + + If you want to be able to construct values of your custom type + from script code, you have to register a constructor function for + the type. For example: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 25 + + \sa qScriptRegisterSequenceMetaType(), qRegisterMetaType() +*/ + +/*! + \macro Q_SCRIPT_DECLARE_QMETAOBJECT(QMetaObject, ArgType) + \since 4.3 + \relates QScriptEngine + + Declares the given \a QMetaObject. Used in combination with + QScriptEngine::scriptValueFromQMetaObject() to make enums and + instantiation of \a QMetaObject available to script code. The + constructor generated by this macro takes a single argument of + type \a ArgType; typically the argument is the parent type of the + new instance, in which case \a ArgType is \c{QWidget*} or + \c{QObject*}. Objects created by the constructor will have + QScriptEngine::AutoOwnership ownership. +*/ + +/*! \fn int qScriptRegisterSequenceMetaType( + QScriptEngine *engine, + const QScriptValue &prototype = QScriptValue()) + \relates QScriptEngine + + Registers the sequence type \c{T} in the given \a engine. This + function provides conversion functions that convert between \c{T} + and Qt Script \c{Array} objects. \c{T} must provide a + const_iterator class and begin(), end() and push_back() + functions. If \a prototype is valid, it will be set as the + prototype of \c{Array} objects due to conversion from \c{T}; + otherwise, the standard \c{Array} prototype will be used. + + Returns the internal ID used by QMetaType. + + You need to declare the container type first with + Q_DECLARE_METATYPE(). If the element type isn't a standard Qt/C++ + type, it must be declared using Q_DECLARE_METATYPE() as well. + Example: + + \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 26 + + \sa qScriptRegisterMetaType() +*/ + +/*! + Runs the garbage collector. + + The garbage collector will attempt to reclaim memory by locating and + disposing of objects that are no longer reachable in the script + environment. + + Normally you don't need to call this function; the garbage collector + will automatically be invoked when the QScriptEngine decides that + it's wise to do so (i.e. when a certain number of new objects have + been created). However, you can call this function to explicitly + request that garbage collection should be performed as soon as + possible. +*/ +void QScriptEngine::collectGarbage() +{ + Q_D(QScriptEngine); + d->collectGarbage(); +} + +/*! + + Sets the interval between calls to QCoreApplication::processEvents + to \a interval milliseconds. + + While the interpreter is running, all event processing is by default + blocked. This means for instance that the gui will not be updated + and timers will not be fired. To allow event processing during + interpreter execution one can specify the processing interval to be + a positive value, indicating the number of milliseconds between each + time QCoreApplication::processEvents() is called. + + The default value is -1, which disables event processing during + interpreter execution. + + You can use QCoreApplication::postEvent() to post an event that + performs custom processing at the next interval. For example, you + could keep track of the total running time of the script and call + abortEvaluation() when you detect that the script has been running + for a long time without completing. + + \sa processEventsInterval() +*/ +void QScriptEngine::setProcessEventsInterval(int interval) +{ + Q_D(QScriptEngine); + d->processEventsInterval = interval; + + if (interval > 0) + d->globalData->timeoutChecker->setCheckInterval(interval); + + d->timeoutChecker()->setShouldProcessEvents(interval > 0); +} + +/*! + + Returns the interval in milliseconds between calls to + QCoreApplication::processEvents() while the interpreter is running. + + \sa setProcessEventsInterval() +*/ +int QScriptEngine::processEventsInterval() const +{ + Q_D(const QScriptEngine); + return d->processEventsInterval; +} + +/*! + \since 4.4 + + Returns true if this engine is currently evaluating a script, + otherwise returns false. + + \sa evaluate(), abortEvaluation() +*/ +bool QScriptEngine::isEvaluating() const +{ + Q_D(const QScriptEngine); + return (d->currentFrame != d->globalExec()) || d->inEval; +} + +/*! + \since 4.4 + + Aborts any script evaluation currently taking place in this engine. + The given \a result is passed back as the result of the evaluation + (i.e. it is returned from the call to evaluate() being aborted). + + If the engine isn't evaluating a script (i.e. isEvaluating() returns + false), this function does nothing. + + Call this function if you need to abort a running script for some + reason, e.g. when you have detected that the script has been + running for several seconds without completing. + + \sa evaluate(), isEvaluating(), setProcessEventsInterval() +*/ +void QScriptEngine::abortEvaluation(const QScriptValue &result) +{ + Q_D(QScriptEngine); + + d->timeoutChecker()->setShouldAbort(true); + d->abortResult = result; +} + +#ifndef QT_NO_QOBJECT + +/*! + \since 4.4 + \relates QScriptEngine + + Creates a connection from the \a signal in the \a sender to the + given \a function. If \a receiver is an object, it will act as the + `this' object when the signal handler function is invoked. Returns + true if the connection succeeds; otherwise returns false. + + \sa qScriptDisconnect(), QScriptEngine::signalHandlerException() +*/ +bool qScriptConnect(QObject *sender, const char *signal, + const QScriptValue &receiver, const QScriptValue &function) +{ + if (!sender || !signal) + return false; + if (!function.isFunction()) + return false; + if (receiver.isObject() && (receiver.engine() != function.engine())) + return false; + QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine()); + JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver); + JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function); + return engine->scriptConnect(sender, signal, jscReceiver, jscFunction, + Qt::AutoConnection); +} + +/*! + \since 4.4 + \relates QScriptEngine + + Disconnects the \a signal in the \a sender from the given (\a + receiver, \a function) pair. Returns true if the connection is + successfully broken; otherwise returns false. + + \sa qScriptConnect() +*/ +bool qScriptDisconnect(QObject *sender, const char *signal, + const QScriptValue &receiver, const QScriptValue &function) +{ + if (!sender || !signal) + return false; + if (!function.isFunction()) + return false; + if (receiver.isObject() && (receiver.engine() != function.engine())) + return false; + QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine()); + JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver); + JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function); + return engine->scriptDisconnect(sender, signal, jscReceiver, jscFunction); +} + +/*! + \since 4.4 + \fn void QScriptEngine::signalHandlerException(const QScriptValue &exception) + + This signal is emitted when a script function connected to a signal causes + an \a exception. + + \sa qScriptConnect() +*/ + +QT_BEGIN_INCLUDE_NAMESPACE +#include "moc_qscriptengine.cpp" +QT_END_INCLUDE_NAMESPACE + +#endif // QT_NO_QOBJECT + +/*! + \since 4.4 + + Installs the given \a agent on this engine. The agent will be + notified of various events pertaining to script execution. This is + useful when you want to find out exactly what the engine is doing, + e.g. when evaluate() is called. The agent interface is the basis of + tools like debuggers and profilers. + + The engine maintains ownership of the \a agent. + + Calling this function will replace the existing agent, if any. + + \sa agent() +*/ +void QScriptEngine::setAgent(QScriptEngineAgent *agent) +{ + Q_D(QScriptEngine); + if (agent && (agent->engine() != this)) { + qWarning("QScriptEngine::setAgent(): " + "cannot set agent belonging to different engine"); + return; + } + if (d->activeAgent) + QScriptEngineAgentPrivate::get(d->activeAgent)->detach(); + d->activeAgent = agent; + if (agent) { + int index = d->ownedAgents.indexOf(agent); + if (index == -1) + d->ownedAgents.append(agent); + QScriptEngineAgentPrivate::get(agent)->attach(); + } +} + +/*! + \since 4.4 + + Returns the agent currently installed on this engine, or 0 if no + agent is installed. + + \sa setAgent() +*/ +QScriptEngineAgent *QScriptEngine::agent() const +{ + Q_D(const QScriptEngine); + return d->activeAgent; +} + +/*! + \since 4.4 + + Returns a handle that represents the given string, \a str. + + QScriptString can be used to quickly look up properties, and + compare property names, of script objects. + + \sa QScriptValue::property() +*/ +QScriptString QScriptEngine::toStringHandle(const QString &str) +{ + Q_D(QScriptEngine); + QScriptString ss; + QScriptStringPrivate::init(ss, this, JSC::Identifier(d->currentFrame, str)); + return ss; +} + +/*! + \since 4.5 + + Converts the given \a value to an object, if such a conversion is + possible; otherwise returns an invalid QScriptValue. The conversion + is performed according to the following table: + + \table + \header \o Input Type \o Result + \row \o Undefined \o An invalid QScriptValue. + \row \o Null \o An invalid QScriptValue. + \row \o Boolean \o A new Boolean object whose internal value is set to the value of the boolean. + \row \o Number \o A new Number object whose internal value is set to the value of the number. + \row \o String \o A new String object whose internal value is set to the value of the string. + \row \o Object \o The result is the object itself (no conversion). + \endtable + + \sa newObject() +*/ +QScriptValue QScriptEngine::toObject(const QScriptValue &value) +{ + Q_D(QScriptEngine); + JSC::JSValue jscValue = d->scriptValueToJSCValue(value); + if (!jscValue || jscValue.isUndefined() || jscValue.isNull()) + return QScriptValue(); + JSC::ExecState* exec = d->currentFrame; + JSC::JSValue result = jscValue.toObject(exec); + return d->scriptValueFromJSCValue(result); +} + +/*! + \internal + + Returns the object with the given \a id, or an invalid + QScriptValue if there is no object with that id. + + \sa QScriptValue::objectId() +*/ +QScriptValue QScriptEngine::objectById(qint64 id) const +{ + Q_D(const QScriptEngine); + // Assumes that the cell was not been garbage collected + return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue((JSC::JSCell*)id); +} + +/*! + \since 4.5 + \class QScriptSyntaxCheckResult + + \brief The QScriptSyntaxCheckResult class provides the result of a script syntax check. + + \ingroup script + \mainclass + + QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to + provide information about the syntactical (in)correctness of a script. +*/ + +/*! + \enum QScriptSyntaxCheckResult::State + + This enum specifies the state of a syntax check. + + \value Error The program contains a syntax error. + \value Intermediate The program is incomplete. + \value Valid The program is a syntactically correct Qt Script program. +*/ + +/*! + Constructs a new QScriptSyntaxCheckResult from the \a other result. +*/ +QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult &other) + : d_ptr(other.d_ptr) +{ + if (d_ptr) + d_ptr->ref.ref(); +} + +/*! + \internal +*/ +QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate *d) + : d_ptr(d) +{ + if (d_ptr) + d_ptr->ref.ref(); +} + +/*! + \internal +*/ +QScriptSyntaxCheckResult::QScriptSyntaxCheckResult() + : d_ptr(0) +{ +} + +/*! + Destroys this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult() +{ + if (d_ptr && !d_ptr->ref.deref()) { + delete d_ptr; + d_ptr = 0; + } +} + +/*! + Returns the state of this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const +{ + Q_D(const QScriptSyntaxCheckResult); + if (!d) + return Valid; + return d->state; +} + +/*! + Returns the error line number of this QScriptSyntaxCheckResult, or -1 if + there is no error. + + \sa state(), errorMessage() +*/ +int QScriptSyntaxCheckResult::errorLineNumber() const +{ + Q_D(const QScriptSyntaxCheckResult); + if (!d) + return -1; + return d->errorLineNumber; +} + +/*! + Returns the error column number of this QScriptSyntaxCheckResult, or -1 if + there is no error. + + \sa state(), errorLineNumber() +*/ +int QScriptSyntaxCheckResult::errorColumnNumber() const +{ + Q_D(const QScriptSyntaxCheckResult); + if (!d) + return -1; + return d->errorColumnNumber; +} + +/*! + Returns the error message of this QScriptSyntaxCheckResult, or an empty + string if there is no error. + + \sa state(), errorLineNumber() +*/ +QString QScriptSyntaxCheckResult::errorMessage() const +{ + Q_D(const QScriptSyntaxCheckResult); + if (!d) + return QString(); + return d->errorMessage; +} + +/*! + Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a + reference to this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult &QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult &other) +{ + if (d_ptr == other.d_ptr) + return *this; + if (d_ptr && !d_ptr->ref.deref()) { + delete d_ptr; + d_ptr = 0; + } + d_ptr = other.d_ptr; + if (d_ptr) + d_ptr->ref.ref(); + return *this; +} + +QT_END_NAMESPACE diff --git a/src/script/qscriptengine.h b/src/script/api/qscriptengine.h index 02ebea7..689c05a 100644 --- a/src/script/qscriptengine.h +++ b/src/script/api/qscriptengine.h @@ -44,8 +44,6 @@ #include <QtCore/qmetatype.h> -#ifndef QT_NO_SCRIPT - #include <QtCore/qvariant.h> #ifndef QT_NO_QOBJECT @@ -117,6 +115,7 @@ private: QScriptSyntaxCheckResultPrivate *d_ptr; Q_DECLARE_PRIVATE(QScriptSyntaxCheckResult) + friend class QScriptEngine; friend class QScriptEnginePrivate; }; @@ -363,7 +362,7 @@ inline bool qscriptvalue_cast_helper(const QScriptValue &value, int type, void * template<typename T> T qscriptvalue_cast(const QScriptValue &value -#if !defined qdoc && defined Q_CC_MSVC && _MSC_VER < 1300 +#ifndef Q_QDOC , T * = 0 #endif ) @@ -379,13 +378,11 @@ T qscriptvalue_cast(const QScriptValue &value return T(); } -#if !defined Q_CC_MSVC || _MSC_VER >= 1300 template <> -inline QVariant qscriptvalue_cast<QVariant>(const QScriptValue &value) +inline QVariant qscriptvalue_cast<QVariant>(const QScriptValue &value, QVariant *) { return value.toVariant(); } -#endif template <typename T> inline T qScriptValueToValue(const QScriptValue &value) @@ -477,5 +474,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT #endif // QSCRIPTENGINE_H diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h new file mode 100644 index 0000000..5979b9b --- /dev/null +++ b/src/script/api/qscriptengine_p.h @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTENGINE_P_H +#define QSCRIPTENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qobject_p.h" + +#include <QtCore/qhash.h> +#include <QtCore/qset.h> + +#include "RefPtr.h" +#include "Structure.h" +#include "JSGlobalObject.h" +#include "JSValue.h" + +QT_BEGIN_NAMESPACE + +namespace JSC +{ + class ExecState; + typedef ExecState CallFrame; + class JSCell; + class JSGlobalObject; + class UString; +} + + +class QString; +class QStringList; +class QScriptContext; +class QScriptValue; +class QScriptValuePrivate; +class QScriptTypeInfo; +class QScriptEngineAgent; +class QScriptEnginePrivate; +class QScriptSyntaxCheckResult; +class QScriptEngine; + +namespace QScript +{ + class QObjectPrototype; + class QMetaObjectPrototype; + class QVariantPrototype; +#ifndef QT_NO_QOBJECT + class QObjectData; +#endif + class TimeoutCheckerProxy; + + //some conversion helper functions + QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec); + bool isFunction(JSC::JSValue value); +} + +class QScriptEnginePrivate +#ifndef QT_NO_QOBJECT + : public QObjectPrivate +#endif +{ + Q_DECLARE_PUBLIC(QScriptEngine) +public: + QScriptEnginePrivate(); + virtual ~QScriptEnginePrivate(); + + static QScriptEnginePrivate *get(QScriptEngine *q) { return q ? q->d_func() : 0; } + static QScriptEngine *get(QScriptEnginePrivate *d) { return d ? d->q_func() : 0; } + + static bool convert(const QScriptValue &value, + int type, void *ptr, + QScriptEnginePrivate *eng); + QScriptValue create(int type, const void *ptr); + bool hasDemarshalFunction(int type) const; + + QScriptValue scriptValueFromJSCValue(JSC::JSValue value); + JSC::JSValue scriptValueToJSCValue(const QScriptValue &value); + + QScriptValue scriptValueFromVariant(const QVariant &value); + QVariant scriptValueToVariant(const QScriptValue &value, int targetType); + + JSC::JSValue jscValueFromVariant(const QVariant &value); + QVariant jscValueToVariant(JSC::JSValue value, int targetType); + + QScriptValue arrayFromStringList(const QStringList &lst); + static QStringList stringListFromArray(const QScriptValue &arr); + + QScriptValue arrayFromVariantList(const QVariantList &lst); + static QVariantList variantListFromArray(const QScriptValue &arr); + + QScriptValue objectFromVariantMap(const QVariantMap &vmap); + static QVariantMap variantMapFromObject(const QScriptValue &obj); + + JSC::JSValue defaultPrototype(int metaTypeId) const; + void setDefaultPrototype(int metaTypeId, JSC::JSValue prototype); + + static QScriptContext *contextForFrame(JSC::ExecState *frame); + static JSC::ExecState *frameForContext(QScriptContext *context); + static const JSC::ExecState *frameForContext(const QScriptContext *context); + + JSC::JSGlobalObject *originalGlobalObject() const; + JSC::JSObject *getOriginalGlobalObjectProxy(); + JSC::JSObject *customGlobalObject() const; + JSC::JSObject *globalObject() const; + void setGlobalObject(JSC::JSObject *object); + JSC::ExecState *globalExec() const; + JSC::JSValue toUsableValue(JSC::JSValue value); + static JSC::JSValue thisForContext(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(); + bool isCollecting() const; + void collectGarbage(); + + //flags that we set on the return value register for native function. (ie when codeBlock is 0) + enum ContextFlags { + NativeContext = 1, + CalledAsConstructorContext = 2, + HasScopeContext = 4 + }; + static uint contextFlags(JSC::ExecState *); + static void setContextFlags(JSC::ExecState *, uint); + + QScript::TimeoutCheckerProxy *timeoutChecker() const; + + void agentDeleted(QScriptEngineAgent *agent); + +#ifndef QT_NO_QOBJECT + JSC::JSValue newQObject(QObject *object, + QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership, + const QScriptEngine:: QObjectWrapOptions &options = 0); + JSC::JSValue newQMetaObject(const QMetaObject *metaObject, + JSC::JSValue ctor); + + static QScriptSyntaxCheckResult checkSyntax(const QString &program); + static bool canEvaluate(const QString &program); + static bool convertToNativeQObject(const QScriptValue &value, + const QByteArray &targetType, + void **result); + + QScript::QObjectData *qobjectData(QObject *object); + void disposeQObject(QObject *object); + void emitSignalHandlerException(); + + bool scriptConnect(QObject *sender, const char *signal, + JSC::JSValue receiver, JSC::JSValue function, + Qt::ConnectionType type); + bool scriptDisconnect(QObject *sender, const char *signal, + JSC::JSValue receiver, JSC::JSValue function); + + bool scriptConnect(QObject *sender, int index, + JSC::JSValue receiver, JSC::JSValue function, + JSC::JSValue senderWrapper, + Qt::ConnectionType type); + bool scriptDisconnect(QObject *sender, int index, + JSC::JSValue receiver, JSC::JSValue function); + + bool scriptConnect(JSC::JSValue signal, JSC::JSValue receiver, + JSC::JSValue function, Qt::ConnectionType type); + bool scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver, + JSC::JSValue function); + + void registerScriptValue(QScriptValuePrivate *value); + void unregisterScriptValue(QScriptValuePrivate *value); + void detachAllRegisteredScriptValues(); + + // private slots + void _q_objectDestroyed(QObject *); +#endif + + JSC::JSGlobalData *globalData; + JSC::JSObject *originalGlobalObjectProxy; + JSC::ExecState *currentFrame; + + WTF::RefPtr<JSC::Structure> scriptObjectStructure; + + QScript::QObjectPrototype *qobjectPrototype; + WTF::RefPtr<JSC::Structure> qobjectWrapperObjectStructure; + + QScript::QMetaObjectPrototype *qmetaobjectPrototype; + WTF::RefPtr<JSC::Structure> qmetaobjectWrapperObjectStructure; + + QScript::QVariantPrototype *variantPrototype; + WTF::RefPtr<JSC::Structure> variantWrapperObjectStructure; + + QList<QScriptEngineAgent*> ownedAgents; + QScriptEngineAgent *activeAgent; + int agentLineNumber; + QScriptValuePrivate *registeredScriptValues; + QHash<int, QScriptTypeInfo*> m_typeInfos; + int processEventsInterval; + QScriptValue abortResult; + bool inEval; + + QSet<QString> importedExtensions; + QSet<QString> extensionsBeingImported; + +#ifndef QT_NO_QOBJECT + QHash<QObject*, QScript::QObjectData*> m_qobjectData; +#endif + +#ifdef QT_NO_QOBJECT + QScriptEngine *q_ptr; +#endif +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/script/qscriptengineagent.cpp b/src/script/api/qscriptengineagent.cpp index b4793ab..6417ed8 100644 --- a/src/script/qscriptengineagent.cpp +++ b/src/script/api/qscriptengineagent.cpp @@ -39,17 +39,14 @@ ** ****************************************************************************/ +#include "config.h" #include "qscriptengineagent.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptvalue.h" #include "qscriptengineagent_p.h" +#include "qscriptengine.h" #include "qscriptengine_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptvalueimpl_p.h" + +#include "CodeBlock.h" +#include "Instruction.h" QT_BEGIN_NAMESPACE @@ -132,17 +129,77 @@ QT_BEGIN_NAMESPACE \sa extension() */ -QScriptEngineAgentPrivate::QScriptEngineAgentPrivate() - : engine(0), q_ptr(0) + +void QScriptEngineAgentPrivate::attach() +{ + if (engine->originalGlobalObject()->debugger()) + engine->originalGlobalObject()->setDebugger(0); + JSC::Debugger::attach(engine->originalGlobalObject()); +} + +void QScriptEngineAgentPrivate::detach() +{ + JSC::Debugger::detach(engine->originalGlobalObject()); +} + +void QScriptEngineAgentPrivate::exceptionThrow(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, bool hasHandler) { + JSC::CallFrame *oldFrame = engine->currentFrame; + engine->currentFrame = frame.callFrame(); + QScriptValue value(engine->scriptValueFromJSCValue(frame.exception())); + q_ptr->exceptionThrow(sourceID, value, hasHandler); + engine->currentFrame = oldFrame; +}; + +void QScriptEngineAgentPrivate::exceptionCatch(const JSC::DebuggerCallFrame& frame, intptr_t sourceID) +{ + JSC::CallFrame *oldFrame = engine->currentFrame; + engine->currentFrame = frame.callFrame(); + QScriptValue value(engine->scriptValueFromJSCValue(frame.exception())); + q_ptr->exceptionCatch(sourceID, value); + engine->currentFrame = oldFrame; +} + +void QScriptEngineAgentPrivate::atStatement(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno, int column) +{ + JSC::CallFrame *oldFrame = engine->currentFrame; + int oldAgentLineNumber = engine->agentLineNumber; + engine->currentFrame = frame.callFrame(); + engine->agentLineNumber = lineno; + q_ptr->positionChange(sourceID, lineno, column); + engine->currentFrame = oldFrame; + engine->agentLineNumber = oldAgentLineNumber; +} + +void QScriptEngineAgentPrivate::functionExit(const JSC::JSValue& returnValue, intptr_t sourceID) +{ + QScriptValue result = engine->scriptValueFromJSCValue(returnValue); + q_ptr->functionExit(sourceID, result); + q_ptr->contextPop(); } -QScriptEngineAgentPrivate::~QScriptEngineAgentPrivate() +void QScriptEngineAgentPrivate::evaluateStop(const JSC::JSValue& returnValue, intptr_t sourceID) { - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - eng_p->agentDeleted(q_ptr); + QScriptValue result = engine->scriptValueFromJSCValue(returnValue); + q_ptr->functionExit(sourceID, result); } +void QScriptEngineAgentPrivate::didReachBreakpoint(const JSC::DebuggerCallFrame& frame, + intptr_t sourceID, int lineno, int column) +{ + if (q_ptr->supportsExtension(QScriptEngineAgent::DebuggerInvocationRequest)) { + JSC::CallFrame *oldFrame = engine->currentFrame; + int oldAgentLineNumber = engine->agentLineNumber; + engine->currentFrame = frame.callFrame(); + engine->agentLineNumber = lineno; + QList<QVariant> args; + args << qint64(sourceID) << lineno << column; + q_ptr->extension(QScriptEngineAgent::DebuggerInvocationRequest, args); + engine->currentFrame = oldFrame; + engine->agentLineNumber = oldAgentLineNumber; + } +}; + /*! Constructs a QScriptEngineAgent object for the given \a engine. @@ -152,10 +209,10 @@ QScriptEngineAgentPrivate::~QScriptEngineAgentPrivate() agent. */ QScriptEngineAgent::QScriptEngineAgent(QScriptEngine *engine) - : d_ptr(new QScriptEngineAgentPrivate) + : d_ptr(new QScriptEngineAgentPrivate()) { d_ptr->q_ptr = this; - d_ptr->engine = engine; + d_ptr->engine = QScriptEnginePrivate::get(engine); } /*! @@ -165,7 +222,7 @@ QScriptEngineAgent::QScriptEngineAgent(QScriptEngineAgentPrivate &dd, QScriptEng : d_ptr(&dd) { d_ptr->q_ptr = this; - d_ptr->engine = engine; + d_ptr->engine = QScriptEnginePrivate::get(engine); } /*! @@ -173,6 +230,7 @@ QScriptEngineAgent::QScriptEngineAgent(QScriptEngineAgentPrivate &dd, QScriptEng */ QScriptEngineAgent::~QScriptEngineAgent() { + d_ptr->engine->agentDeleted(this); delete d_ptr; d_ptr = 0; } @@ -436,9 +494,7 @@ QVariant QScriptEngineAgent::extension(Extension extension, QScriptEngine *QScriptEngineAgent::engine() const { Q_D(const QScriptEngineAgent); - return d->engine; + return QScriptEnginePrivate::get(d->engine); } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptengineagent.h b/src/script/api/qscriptengineagent.h index 00c245b..60c1ed6 100644 --- a/src/script/qscriptengineagent.h +++ b/src/script/api/qscriptengineagent.h @@ -44,8 +44,6 @@ #include <QtCore/qobjectdefs.h> -#ifndef QT_NO_SCRIPT - #include <QtCore/qvariant.h> QT_BEGIN_HEADER @@ -107,6 +105,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/api/qscriptengineagent_p.h b/src/script/api/qscriptengineagent_p.h new file mode 100644 index 0000000..64befc1 --- /dev/null +++ b/src/script/api/qscriptengineagent_p.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTENGINEAGENT_P_H +#define QSCRIPTENGINEAGENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobjectdefs.h> +#include "Debugger.h" +#include "qscriptengineagent.h" + +#include "CallFrame.h" +#include "SourceCode.h" +#include "UString.h" +#include "DebuggerCallFrame.h" + +QT_BEGIN_NAMESPACE + +class QScriptEnginePrivate; + +class QScriptEngineAgent; +class Q_SCRIPT_EXPORT QScriptEngineAgentPrivate : public JSC::Debugger +{ + Q_DECLARE_PUBLIC(QScriptEngineAgent) +public: + static QScriptEngineAgent* get(QScriptEngineAgentPrivate* p) {return p->q_func();} + static QScriptEngineAgentPrivate* get(QScriptEngineAgent* p) {return p->d_func();} + + QScriptEngineAgentPrivate(){} + virtual ~QScriptEngineAgentPrivate(){}; + + void attach(); + void detach(); + + //scripts + virtual void sourceParsed(JSC::ExecState*, const JSC::SourceCode&, int /*errorLine*/, const JSC::UString& /*errorMsg*/) {}; + virtual void scriptUnload(qint64 id) + { + q_ptr->scriptUnload(id); + }; + virtual void scriptLoad(qint64 id, const JSC::UString &program, + const JSC::UString &fileName, int baseLineNumber) + { + q_ptr->scriptLoad(id,program, fileName, baseLineNumber); + }; + + //exceptions + virtual void exception(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno) + { + Q_UNUSED(frame); + Q_UNUSED(sourceID); + Q_UNUSED(lineno); + }; + virtual void exceptionThrow(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, bool hasHandler); + virtual void exceptionCatch(const JSC::DebuggerCallFrame& frame, intptr_t sourceID); + + //statements + virtual void atStatement(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno, int column); + virtual void callEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno) + { + Q_UNUSED(lineno); + q_ptr->contextPush(); + q_ptr->functionEntry(sourceID); + }; + virtual void returnEvent(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno) + { + Q_UNUSED(frame); + Q_UNUSED(sourceID); + Q_UNUSED(lineno); + } + virtual void willExecuteProgram(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno) + { + Q_UNUSED(frame); + Q_UNUSED(sourceID); + Q_UNUSED(lineno); + }; + virtual void didExecuteProgram(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno) + { + Q_UNUSED(frame); + Q_UNUSED(sourceID); + Q_UNUSED(lineno); + }; + virtual void functionExit(const JSC::JSValue& returnValue, intptr_t sourceID); + //others + virtual void didReachBreakpoint(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno, int column); + + virtual void evaluateStart(intptr_t sourceID) + { + q_ptr->functionEntry(sourceID); + } + virtual void evaluateStop(const JSC::JSValue& returnValue, intptr_t sourceID); + + QScriptEnginePrivate *engine; + QScriptEngineAgent *q_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/script/qscriptextensioninterface.h b/src/script/api/qscriptextensioninterface.h index 2e2c66e..e91fec5 100644 --- a/src/script/qscriptextensioninterface.h +++ b/src/script/api/qscriptextensioninterface.h @@ -44,8 +44,6 @@ #include <QtCore/qfactoryinterface.h> -#ifndef QT_NO_SCRIPT - #include <QtCore/qobject.h> QT_BEGIN_HEADER @@ -69,5 +67,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT #endif // QSCRIPTEXTENSIONINTERFACE_H diff --git a/src/script/qscriptextensionplugin.cpp b/src/script/api/qscriptextensionplugin.cpp index 454cceb..38459f4 100644 --- a/src/script/qscriptextensionplugin.cpp +++ b/src/script/api/qscriptextensionplugin.cpp @@ -41,8 +41,6 @@ #include "qscriptextensionplugin.h" -#ifndef QT_NO_SCRIPT - #include "qscriptvalue.h" #include "qscriptengine.h" @@ -143,5 +141,3 @@ QScriptValue QScriptExtensionPlugin::setupPackage( } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptextensionplugin.h b/src/script/api/qscriptextensionplugin.h index 21818d7..94e53f0 100644 --- a/src/script/qscriptextensionplugin.h +++ b/src/script/api/qscriptextensionplugin.h @@ -44,8 +44,6 @@ #include <QtCore/qplugin.h> -#ifndef QT_NO_SCRIPT - #include <QtScript/qscriptextensioninterface.h> QT_BEGIN_HEADER @@ -75,5 +73,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT #endif // QSCRIPTEXTENSIONPLUGIN_H diff --git a/src/script/qscriptstring.cpp b/src/script/api/qscriptstring.cpp index 7d8d4e9..bcafa44 100644 --- a/src/script/qscriptstring.cpp +++ b/src/script/api/qscriptstring.cpp @@ -39,21 +39,14 @@ ** ****************************************************************************/ +#include "config.h" #include "qscriptstring.h" -#ifndef QT_NO_SCRIPT - #include "qscriptstring_p.h" -#include "qscriptnameid_p.h" -#include "qscriptvalue_p.h" -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" QT_BEGIN_NAMESPACE + /*! \since 4.4 \class QScriptString @@ -81,7 +74,6 @@ QT_BEGIN_NAMESPACE \internal */ QScriptStringPrivate::QScriptStringPrivate() - : nameId(0), engine(0), q_ptr(0) { ref = 0; } @@ -89,26 +81,19 @@ QScriptStringPrivate::QScriptStringPrivate() /*! \internal */ -QScriptStringPrivate *QScriptStringPrivate::create() -{ - return new QScriptStringPrivate(); -} - -/*! - \internal -*/ -QScriptStringPrivate *QScriptStringPrivate::get(const QScriptString &q) +QScriptStringPrivate::~QScriptStringPrivate() { - return const_cast<QScriptStringPrivate*>(q.d_func()); } /*! \internal */ -void QScriptStringPrivate::init(QScriptString &q, QScriptStringPrivate *d) +void QScriptStringPrivate::init(QScriptString &q, QScriptEngine *engine, const JSC::Identifier &value) { - Q_ASSERT(q.d_ptr == 0); - q.d_ptr = d; + Q_ASSERT(!q.isValid()); + q.d_ptr = new QScriptStringPrivate(); + q.d_ptr->identifier = value; + q.d_ptr->engine = engine; q.d_ptr->ref.ref(); } @@ -136,12 +121,7 @@ QScriptString::QScriptString(const QScriptString &other) QScriptString::~QScriptString() { if (d_ptr && !d_ptr->ref.deref()) { - if (isValid()) { - d_ptr->engine->uninternString(d_ptr); - } else { - // the engine has already been deleted - delete d_ptr; - } + delete d_ptr; d_ptr = 0; } } @@ -154,12 +134,7 @@ QScriptString &QScriptString::operator=(const QScriptString &other) if (d_ptr == other.d_ptr) return *this; if (d_ptr && !d_ptr->ref.deref()) { - if (isValid()) { - d_ptr->engine->uninternString(d_ptr); - } else { - // the engine has already been deleted - delete d_ptr; - } + delete d_ptr; } d_ptr = other.d_ptr; if (d_ptr) @@ -174,7 +149,7 @@ QScriptString &QScriptString::operator=(const QScriptString &other) bool QScriptString::isValid() const { Q_D(const QScriptString); - return (d && d->nameId); + return (d && d->engine); } /*! @@ -184,7 +159,15 @@ bool QScriptString::isValid() const bool QScriptString::operator==(const QScriptString &other) const { Q_D(const QScriptString); - return (d == other.d_func()); + if (d == other.d_func()) + return true; + if (!d || !other.d_func()) + return false; + if (d->engine != other.d_func()->engine) + return false; + if (!d->engine) + return true; + return d->identifier == other.d_func()->identifier; } /*! @@ -193,8 +176,7 @@ bool QScriptString::operator==(const QScriptString &other) const */ bool QScriptString::operator!=(const QScriptString &other) const { - Q_D(const QScriptString); - return (d != other.d_func()); + return !operator==(other); } /*! @@ -206,9 +188,9 @@ bool QScriptString::operator!=(const QScriptString &other) const QString QScriptString::toString() const { Q_D(const QScriptString); - if (!d || !d->nameId) + if (!d || !d->engine) return QString(); - return d->nameId->s; + return d->identifier.ustring(); } /*! @@ -223,5 +205,3 @@ QScriptString::operator QString() const } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptstring.h b/src/script/api/qscriptstring.h index d0f05cb..e42c3e3 100644 --- a/src/script/qscriptstring.h +++ b/src/script/api/qscriptstring.h @@ -44,8 +44,6 @@ #include <QtCore/qstring.h> -#ifndef QT_NO_SCRIPT - QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -74,7 +72,7 @@ public: private: QScriptStringPrivate *d_ptr; - + friend class QScriptValue; Q_DECLARE_PRIVATE(QScriptString) }; @@ -82,5 +80,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT #endif // QSCRIPTSTRING_H diff --git a/src/script/qscriptstring_p.h b/src/script/api/qscriptstring_p.h index 09e4a0c..74094bf 100644 --- a/src/script/qscriptstring_p.h +++ b/src/script/api/qscriptstring_p.h @@ -42,12 +42,6 @@ #ifndef QSCRIPTSTRING_P_H #define QSCRIPTSTRING_P_H -#include <QtCore/qatomic.h> - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - // // W A R N I N G // ------------- @@ -59,28 +53,36 @@ QT_BEGIN_NAMESPACE // We mean it. // -class QScriptNameIdImpl; -class QScriptEnginePrivate; -class QScriptString; +#include <QtCore/qobjectdefs.h> + +#include <QtCore/qstring.h> +#include <QtCore/qpointer.h> +#include "qscriptengine.h" + +#include "Identifier.h" + +QT_BEGIN_NAMESPACE + +class QScriptString; +class QScriptEngine; class QScriptStringPrivate { - Q_DECLARE_PUBLIC(QScriptString) public: QScriptStringPrivate(); + ~QScriptStringPrivate(); - static QScriptStringPrivate *create(); - static QScriptStringPrivate *get(const QScriptString &q); - static void init(QScriptString &q, QScriptStringPrivate *d); + static void init(QScriptString &q, QScriptEngine *engine, const JSC::Identifier &value); QBasicAtomicInt ref; - QScriptNameIdImpl *nameId; - QScriptEnginePrivate *engine; - QScriptString *q_ptr; +#ifndef QT_NO_QOBJECT + QPointer<QScriptEngine> engine; +#else + void *engine; +#endif + JSC::Identifier identifier; }; QT_END_NAMESPACE -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp new file mode 100644 index 0000000..7b28e37 --- /dev/null +++ b/src/script/api/qscriptvalue.cpp @@ -0,0 +1,2501 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptvalue.h" + +#include "qscriptvalue_p.h" +#include "qscriptengine.h" +#include "qscriptengine_p.h" +#include "qscriptstring_p.h" + +#include "JSArray.h" +#include "JSGlobalObject.h" +#include "JSImmediate.h" +#include "JSObject.h" +#include "JSValue.h" +#include "JSFunction.h" +#include "DateInstance.h" +#include "ErrorInstance.h" +#include "RegExpObject.h" +#include "Identifier.h" +#include "Operations.h" +#include "Arguments.h" + +#include <QtCore/qdatetime.h> +#include <QtCore/qregexp.h> +#include <QtCore/qvariant.h> +#include <QtCore/qnumeric.h> + +#include "utils/qscriptdate_p.h" +#include "bridge/qscriptobject_p.h" +#include "bridge/qscriptclassobject_p.h" +#include "bridge/qscriptvariant_p.h" +#include "bridge/qscriptqobject_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \since 4.3 + \class QScriptValue + + \brief The QScriptValue class acts as a container for the Qt Script data types. + + \ingroup script + \mainclass + + QScriptValue supports the types defined in the \l{ECMA-262} + standard: The primitive types, which are Undefined, Null, Boolean, + Number, and String; and the Object type. Additionally, Qt Script + has built-in support for QVariant, QObject and QMetaObject. + + For the object-based types (including Date and RegExp), use the + newT() functions in QScriptEngine (e.g. QScriptEngine::newObject()) + to create a QScriptValue of the desired type. For the primitive types, + use one of the QScriptValue constructor overloads. + + The methods named isT() (e.g. isBool(), isUndefined()) can be + used to test if a value is of a certain type. The methods named + toT() (e.g. toBool(), toString()) can be used to convert a + QScriptValue to another type. You can also use the generic + qscriptvalue_cast() function. + + Object values have zero or more properties which are themselves + QScriptValues. Use setProperty() to set a property of an object, and + call property() to retrieve the value of a property. + + \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 0 + + Each property can have a set of attributes; these are specified as + the third (optional) argument to setProperty(). The attributes of a + property can be queried by calling the propertyFlags() function. The + following code snippet creates a property that cannot be modified by + script code: + + \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 1 + + If you want to iterate over the properties of a script object, use + the QScriptValueIterator class. + + Object values have an internal \c{prototype} property, which can be + accessed with prototype() and setPrototype(). Properties added to a + prototype are shared by all objects having that prototype; this is + referred to as prototype-based inheritance. In practice, it means + that (by default) the property() function will automatically attempt + to look up look the property in the prototype() (and in the + prototype of the prototype(), and so on), if the object itself does + not have the requested property. Note that this prototype-based + lookup is not performed by setProperty(); setProperty() will always + create the property in the script object itself. For more + information, see the \l{QtScript} documentation. + + Function objects (objects for which isFunction() returns true) can + be invoked by calling call(). Constructor functions can be used to + construct new objects by calling construct(). + + Use equals(), strictlyEquals() and lessThan() to compare a QScriptValue + to another. + + Object values can have custom data associated with them; see the + setData() and data() functions. By default, this data is not + accessible to scripts; it can be used to store any data you want to + associate with the script object. Typically this is used by custom + class objects (see QScriptClass) to store a C++ type that contains + the "native" object data. + + Note that a QScriptValue for which isObject() is true only carries a + reference to an actual object; copying the QScriptValue will only + copy the object reference, not the object itself. If you want to + clone an object (i.e. copy an object's properties to another + object), you can do so with the help of a \c{for-in} statement in + script code, or QScriptValueIterator in C++. + + \sa QScriptEngine, QScriptValueIterator +*/ + +/*! + \enum QScriptValue::SpecialValue + + This enum is used to specify a single-valued type. + + \value UndefinedValue An undefined value. + + \value NullValue A null value. +*/ + +/*! + \enum QScriptValue::PropertyFlag + + This enum describes the attributes of a property. + + \value ReadOnly The property is read-only. Attempts by Qt Script code to write to the property will be ignored. + + \value Undeletable Attempts by Qt Script code to \c{delete} the property will be ignored. + + \value SkipInEnumeration The property is not to be enumerated by a \c{for-in} enumeration. + + \value PropertyGetter The property is defined by a function which will be called to get the property value. + + \value PropertySetter The property is defined by a function which will be called to set the property value. + + \value QObjectMember This flag is used to indicate that an existing property is a QObject member (a property or method). + + \value KeepExistingFlags This value is used to indicate to setProperty() that the property's flags should be left unchanged. If the property doesn't exist, the default flags (0) will be used. + + \value UserRange Flags in this range are not used by Qt Script, and can be used for custom purposes. +*/ + +/*! + \enum QScriptValue::ResolveFlag + + This enum specifies how to look up a property of an object. + + \value ResolveLocal Only check the object's own properties. + + \value ResolvePrototype Check the object's own properties first, then search the prototype chain. This is the default. + + \omitvalue ResolveScope Check the object's own properties first, then search the scope chain. + + \omitvalue ResolveFull Check the object's own properties first, then search the prototype chain, and finally search the scope chain. +*/ + +// ### move + +#include <QtCore/qnumeric.h> +#include <math.h> + +namespace QScript +{ + +static const qsreal D32 = 4294967296.0; + +qint32 ToInt32(qsreal n) +{ + if (qIsNaN(n) || qIsInf(n) || (n == 0)) + return 0; + + double sign = (n < 0) ? -1.0 : 1.0; + qsreal abs_n = fabs(n); + + n = ::fmod(sign * ::floor(abs_n), D32); + const double D31 = D32 / 2.0; + + if (sign == -1 && n < -D31) + n += D32; + + else if (sign != -1 && n >= D31) + n -= D32; + + return qint32 (n); +} + +quint32 ToUint32(qsreal n) +{ + if (qIsNaN(n) || qIsInf(n) || (n == 0)) + return 0; + + double sign = (n < 0) ? -1.0 : 1.0; + qsreal abs_n = fabs(n); + + n = ::fmod(sign * ::floor(abs_n), D32); + + if (n < 0) + n += D32; + + return quint32 (n); +} + +quint16 ToUint16(qsreal n) +{ + static const qsreal D16 = 65536.0; + + if (qIsNaN(n) || qIsInf(n) || (n == 0)) + return 0; + + double sign = (n < 0) ? -1.0 : 1.0; + qsreal abs_n = fabs(n); + + n = ::fmod(sign * ::floor(abs_n), D16); + + if (n < 0) + n += D16; + + return quint16 (n); +} + +qsreal ToInteger(qsreal n) +{ + if (qIsNaN(n)) + return 0; + + if (n == 0 || qIsInf(n)) + return n; + + int sign = n < 0 ? -1 : 1; + return sign * ::floor(::fabs(n)); +} + +} // namespace QScript + +QScriptValuePrivate::QScriptValuePrivate() : engine(0), prev(0), next(0) +{ + ref = 0; +} + +QScriptValuePrivate::~QScriptValuePrivate() +{ +} + +void QScriptValuePrivate::initFrom(JSC::JSValue value) +{ + if (value.isCell()) { + Q_ASSERT(engine != 0); + value = engine->toUsableValue(value); + JSC::JSCell *cell = JSC::asCell(value); + Q_ASSERT(cell != engine->originalGlobalObject()); + } + type = JSC; + jscValue = value; + if (engine) + engine->registerScriptValue(this); +} + +void QScriptValuePrivate::initFrom(double value) +{ + type = Number; + numberValue = value; + if (engine) + engine->registerScriptValue(this); +} + +void QScriptValuePrivate::initFrom(const QString &value) +{ + type = String; + stringValue = value; + if (engine) + engine->registerScriptValue(this); +} + +bool QScriptValuePrivate::isJSC() const +{ + return (type == JSC); +} + +QScriptValue QScriptValuePrivate::property(const QString &name, int resolveMode) const +{ + JSC::ExecState *exec = engine->currentFrame; + return property(JSC::Identifier(exec, name), resolveMode); +} + +QScriptValue QScriptValuePrivate::property(const JSC::Identifier &id, int resolveMode) const +{ + Q_ASSERT(isJSC()); + JSC::ExecState *exec = engine->currentFrame; + JSC::JSObject *object = jscValue.getObject(); + JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object)); + JSC::JSValue result; + if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) { + result = slot.getValue(exec, id); + } else { + if ((resolveMode & QScriptValue::ResolvePrototype) + && const_cast<JSC::JSObject*>(object)->getPropertySlot(exec, id, slot)) { + result = slot.getValue(exec, id); + } else if (resolveMode & QScriptValue::ResolveScope) { + // ### check if it's a function object and look in the scope chain + QScriptValue scope = property(QString::fromLatin1("__qt_scope__"), QScriptValue::ResolveLocal); + if (scope.isObject()) + result = engine->scriptValueToJSCValue(QScriptValuePrivate::get(scope)->property(id, resolveMode)); + } + } + return engine->scriptValueFromJSCValue(result); +} + +QScriptValue QScriptValuePrivate::property(quint32 index, int resolveMode) const +{ + Q_ASSERT(isJSC()); + JSC::ExecState *exec = engine->currentFrame; + JSC::JSObject *object = jscValue.getObject(); + JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object)); + JSC::JSValue result; + if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, index, slot)) { + result = slot.getValue(exec, index); + } else if ((resolveMode & QScriptValue::ResolvePrototype) + && const_cast<JSC::JSObject*>(object)->getPropertySlot(exec, index, slot)) { + result = slot.getValue(exec, index); + } + return engine->scriptValueFromJSCValue(result); +} + +QVariant &QScriptValuePrivate::variantValue() const +{ + Q_ASSERT(jscValue.isObject(&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(); +} + +void QScriptValuePrivate::setVariantValue(const QVariant &value) +{ + Q_ASSERT(jscValue.isObject(&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); +} + +void QScriptValuePrivate::saveException(JSC::ExecState *exec, JSC::JSValue *val) +{ + if (exec) { + *val = exec->exception(); + exec->clearException(); + } else { + *val = JSC::JSValue(); + } +} + +void QScriptValuePrivate::restoreException(JSC::ExecState *exec, JSC::JSValue val) +{ + if (exec && val) + exec->setException(val); +} + +void QScriptValuePrivate::detachFromEngine() +{ + if (isJSC()) + jscValue = JSC::JSValue(); + engine = 0; +} + +/*! + Constructs an invalid QScriptValue. +*/ +QScriptValue::QScriptValue() + : d_ptr(0) +{ +} + +/*! + Destroys this QScriptValue. +*/ +QScriptValue::~QScriptValue() +{ + if (d_ptr && !d_ptr->ref.deref()) { + if (d_ptr->engine) + d_ptr->engine->unregisterScriptValue(d_ptr); + delete d_ptr; + } +} + +/*! + Constructs a new QScriptValue that is a copy of \a other. + + Note that if \a other is an object (i.e., isObject() would return + true), then only a reference to the underlying object is copied into + the new script value (i.e., the object itself is not copied). +*/ +QScriptValue::QScriptValue(const QScriptValue &other) + : d_ptr(other.d_ptr) +{ + if (d_ptr) + d_ptr->ref.ref(); +} + +/*! + \obsolete + + Constructs a new QScriptValue with the special \a value and + registers it with the script \a engine. +*/ +QScriptValue::QScriptValue(QScriptEngine *engine, QScriptValue::SpecialValue value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = QScriptEnginePrivate::get(engine); + switch (value) { + case NullValue: + d_ptr->initFrom(JSC::jsNull()); + break; + case UndefinedValue: + d_ptr->initFrom(JSC::jsUndefined()); + break; + } + d_ptr->ref.ref(); +} + +/*! + \obsolete + + \fn QScriptValue::QScriptValue(QScriptEngine *engine, bool value) + + Constructs a new QScriptValue with the boolean \a value and + registers it with the script \a engine. +*/ +QScriptValue::QScriptValue(QScriptEngine *engine, bool val) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = QScriptEnginePrivate::get(engine); + d_ptr->initFrom(JSC::jsBoolean(val)); + d_ptr->ref.ref(); +} + +/*! + \fn QScriptValue::QScriptValue(QScriptEngine *engine, int value) + \obsolete + + Constructs a new QScriptValue with the integer \a value and + registers it with the script \a engine. +*/ +QScriptValue::QScriptValue(QScriptEngine *engine, int val) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = QScriptEnginePrivate::get(engine); + 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); + } + d_ptr->ref.ref(); +} + +/*! + \fn QScriptValue::QScriptValue(QScriptEngine *engine, uint value) + \obsolete + + Constructs a new QScriptValue with the unsigned integer \a value and + registers it with the script \a engine. + */ +QScriptValue::QScriptValue(QScriptEngine *engine, uint val) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = QScriptEnginePrivate::get(engine); + 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); + } + d_ptr->ref.ref(); +} + +/*! + \fn QScriptValue::QScriptValue(QScriptEngine *engine, qsreal value) + \obsolete + + Constructs a new QScriptValue with the qsreal \a value and + registers it with the script \a engine. +*/ +QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = QScriptEnginePrivate::get(engine); + 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); + } + d_ptr->ref.ref(); +} + +/*! + \fn QScriptValue::QScriptValue(QScriptEngine *engine, const QString &value) + \obsolete + + Constructs a new QScriptValue with the string \a value and + registers it with the script \a engine. +*/ +QScriptValue::QScriptValue(QScriptEngine *engine, const QString &val) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = QScriptEnginePrivate::get(engine); + if (engine) { + JSC::ExecState *exec = d_ptr->engine->currentFrame; + d_ptr->initFrom(JSC::jsString(exec, val)); + } else { + d_ptr->initFrom(val); + } + d_ptr->ref.ref(); +} + +/*! + \fn QScriptValue::QScriptValue(QScriptEngine *engine, const char *value) + \obsolete + + Constructs a new QScriptValue with the string \a value and + registers it with the script \a engine. +*/ + +#ifndef QT_NO_CAST_FROM_ASCII +QScriptValue::QScriptValue(QScriptEngine *engine, const char *val) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = QScriptEnginePrivate::get(engine); + if (engine) { + JSC::ExecState *exec = d_ptr->engine->currentFrame; + d_ptr->initFrom(JSC::jsString(exec, val)); + } else { + d_ptr->initFrom(QString::fromAscii(val)); + } + d_ptr->ref.ref(); +} +#endif + +/*! + \since 4.5 + + Constructs a new QScriptValue with a special \a value. +*/ +QScriptValue::QScriptValue(SpecialValue value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = 0; + switch (value) { + case NullValue: + d_ptr->initFrom(JSC::jsNull()); + break; + case UndefinedValue: + d_ptr->initFrom(JSC::jsUndefined()); + break; + } + d_ptr->ref.ref(); +} + +/*! + \since 4.5 + + Constructs a new QScriptValue with a boolean \a value. +*/ +QScriptValue::QScriptValue(bool value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = 0; + d_ptr->initFrom(JSC::jsBoolean(value)); + d_ptr->ref.ref(); +} + +/*! + \since 4.5 + + Constructs a new QScriptValue with a number \a value. +*/ +QScriptValue::QScriptValue(int value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = 0; + JSC::JSValue immediate = JSC::JSImmediate::from(value); + if (immediate) + d_ptr->initFrom(immediate); + else + d_ptr->initFrom(value); + d_ptr->ref.ref(); +} + +/*! + \since 4.5 + + Constructs a new QScriptValue with a number \a value. +*/ +QScriptValue::QScriptValue(uint value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = 0; + JSC::JSValue immediate = JSC::JSImmediate::from(value); + if (immediate) + d_ptr->initFrom(immediate); + else + d_ptr->initFrom(value); + d_ptr->ref.ref(); +} + +/*! + \since 4.5 + + Constructs a new QScriptValue with a number \a value. +*/ +QScriptValue::QScriptValue(qsreal value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = 0; + JSC::JSValue immediate = JSC::JSImmediate::from(value); + if (immediate) + d_ptr->initFrom(immediate); + else + d_ptr->initFrom(value); + d_ptr->ref.ref(); +} + +/*! + \since 4.5 + + Constructs a new QScriptValue with a string \a value. +*/ +QScriptValue::QScriptValue(const QString &value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = 0; + d_ptr->initFrom(value); + d_ptr->ref.ref(); +} + +/*! + \since 4.5 + + Constructs a new QScriptValue with a string \a value. +*/ +QScriptValue::QScriptValue(const QLatin1String &value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = 0; + d_ptr->initFrom(value); + d_ptr->ref.ref(); +} + +/*! + \since 4.5 + + Constructs a new QScriptValue with a string \a value. +*/ + +#ifndef QT_NO_CAST_FROM_ASCII +QScriptValue::QScriptValue(const char *value) + : d_ptr(new QScriptValuePrivate) +{ + d_ptr->engine = 0; + d_ptr->initFrom(QString::fromAscii(value)); + d_ptr->ref.ref(); +} +#endif + +/*! + Assigns the \a other value to this QScriptValue. + + Note that if \a other is an object (isObject() returns true), + only a reference to the underlying object will be assigned; + the object itself will not be copied. +*/ +QScriptValue &QScriptValue::operator=(const QScriptValue &other) +{ + if (d_ptr == other.d_ptr) + return *this; + if (d_ptr && !d_ptr->ref.deref()) { + if (d_ptr->engine) + d_ptr->engine->unregisterScriptValue(d_ptr); + delete d_ptr; + } + d_ptr = other.d_ptr; + if (d_ptr) + d_ptr->ref.ref(); + return *this; +} + +/*! + Returns true if this QScriptValue is an object of the Error class; + otherwise returns false. + + \sa QScriptContext::throwError() +*/ +bool QScriptValue::isError() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return false; + return d->jscValue.isObject(&JSC::ErrorInstance::info); +} + +/*! + Returns true if this QScriptValue is an object of the Array class; + otherwise returns false. + + \sa QScriptEngine::newArray() +*/ +bool QScriptValue::isArray() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return false; + return d->jscValue.isObject(&JSC::JSArray::info); +} + +/*! + Returns true if this QScriptValue is an object of the Date class; + otherwise returns false. + + \sa QScriptEngine::newDate() +*/ +bool QScriptValue::isDate() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return false; + return d->jscValue.isObject(&JSC::DateInstance::info); +} + +/*! + Returns true if this QScriptValue is an object of the RegExp class; + otherwise returns false. + + \sa QScriptEngine::newRegExp() +*/ +bool QScriptValue::isRegExp() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return false; + return d->jscValue.isObject(&JSC::RegExpObject::info); +} + +/*! + If this QScriptValue is an object, returns the internal prototype + (\c{__proto__} property) of this object; otherwise returns an + invalid QScriptValue. + + \sa setPrototype(), isObject() +*/ +QScriptValue QScriptValue::prototype() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return QScriptValue(); + return d->engine->scriptValueFromJSCValue(JSC::asObject(d->jscValue)->prototype()); +} + +/*! + If this QScriptValue is an object, sets the internal prototype + (\c{__proto__} property) of this object to be \a prototype; + otherwise does nothing. + + The internal prototype should not be confused with the public + property with name "prototype"; the public prototype is usually + only set on functions that act as constructors. + + \sa prototype(), isObject() +*/ +void QScriptValue::setPrototype(const QScriptValue &prototype) +{ + Q_D(QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return; + if (prototype.isValid() && prototype.engine() + && (prototype.engine() != engine())) { + qWarning("QScriptValue::setPrototype() failed: " + "cannot set a prototype created in " + "a different engine"); + return; + } + JSC::JSValue other = d->engine->scriptValueToJSCValue(prototype); + + // check for cycle + JSC::JSValue nextPrototypeValue = other; + while (nextPrototypeValue && nextPrototypeValue.isObject()) { + JSC::JSObject *nextPrototype = JSC::asObject(nextPrototypeValue); + if (nextPrototype == JSC::asObject(d->jscValue)) { + qWarning("QScriptValue::setPrototype() failed: cyclic prototype value"); + return; + } + nextPrototypeValue = nextPrototype->prototype(); + } + JSC::asObject(d->jscValue)->setPrototype(other); +} + +/*! + \internal +*/ +QScriptValue QScriptValue::scope() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return QScriptValue(); + // ### make hidden property + return d->property(QLatin1String("__qt_scope__"), QScriptValue::ResolveLocal); +} + +/*! + \internal +*/ +void QScriptValue::setScope(const QScriptValue &scope) +{ + Q_D(QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return; + if (scope.isValid() && scope.engine() + && (scope.engine() != engine())) { + qWarning("QScriptValue::setScope() failed: " + "cannot set a scope object created in " + "a different engine"); + return; + } + JSC::JSValue other = d->engine->scriptValueToJSCValue(scope); + JSC::ExecState *exec = d->engine->currentFrame; + JSC::Identifier id = JSC::Identifier(exec, "__qt_scope__"); + if (!scope.isValid()) { + JSC::asObject(d->jscValue)->removeDirect(id); + } else { + // ### make hidden property + JSC::asObject(d->jscValue)->putDirect(id, other); + } +} + +/*! + Returns true if this QScriptValue is an instance of + \a other; otherwise returns false. + + This QScriptValue is considered to be an instance of \a other if + \a other is a function and the value of the \c{prototype} + property of \a other is in the prototype chain of this + QScriptValue. +*/ +bool QScriptValue::instanceOf(const QScriptValue &other) const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject() || !other.isObject()) + return false; + if (other.engine() != engine()) { + qWarning("QScriptValue::instanceof: " + "cannot perform operation on a value created in " + "a different engine"); + return false; + } + JSC::JSValue jscProto = d->engine->scriptValueToJSCValue(other.property(QLatin1String("prototype"))); + if (!jscProto) + jscProto = JSC::jsUndefined(); + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSValue jscOther = d->engine->scriptValueToJSCValue(other); + return JSC::asObject(jscOther)->hasInstance(exec, d->jscValue, jscProto); +} + +// ### move + +namespace QScript +{ + +enum Type { + Undefined, + Null, + Boolean, + String, + Number, + Object +}; + +static Type type(const QScriptValue &v) +{ + if (v.isUndefined()) + return Undefined; + else if (v.isNull()) + return Null; + else if (v.isBoolean()) + return Boolean; + else if (v.isString()) + return String; + else if (v.isNumber()) + return Number; + Q_ASSERT(v.isObject()); + return Object; +} + +QScriptValue ToPrimitive(const QScriptValue &object, JSC::PreferredPrimitiveType hint = JSC::NoPreference) +{ + Q_ASSERT(object.isObject()); + QScriptValuePrivate *pp = QScriptValuePrivate::get(object); + Q_ASSERT(pp->engine != 0); + JSC::ExecState *exec = pp->engine->currentFrame; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + JSC::JSValue result = JSC::asObject(pp->jscValue)->toPrimitive(exec, hint); + QScriptValuePrivate::restoreException(exec, savedException); + return pp->engine->scriptValueFromJSCValue(result); +} + +static bool IsNumerical(const QScriptValue &value) +{ + return value.isNumber() || value.isBool(); +} + +static bool LessThan(QScriptValue lhs, QScriptValue rhs) +{ + if (type(lhs) == type(rhs)) { + switch (type(lhs)) { + case Undefined: + case Null: + return false; + + case Number: +#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET + if (qIsNaN(lhs.toNumber()) || qIsNaN(rhs.toNumber())) + return false; +#endif + return lhs.toNumber() < rhs.toNumber(); + + case Boolean: + return lhs.toBool() < rhs.toBool(); + + case String: + return lhs.toString() < rhs.toString(); + + case Object: + break; + } // switch + } + + if (lhs.isObject()) + lhs = ToPrimitive(lhs, JSC::PreferNumber); + + if (rhs.isObject()) + rhs = ToPrimitive(rhs, JSC::PreferNumber); + + if (lhs.isString() && rhs.isString()) + return lhs.toString() < rhs.toString(); + + qsreal n1 = lhs.toNumber(); + qsreal n2 = rhs.toNumber(); +#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET + if (qIsNaN(n1) || qIsNaN(n2)) + return false; +#endif + return n1 < n2; +} + +static bool Equals(QScriptValue lhs, QScriptValue rhs) +{ + if (type(lhs) == type(rhs)) { + switch (type(lhs)) { + case QScript::Undefined: + case QScript::Null: + return true; + + case QScript::Number: + return lhs.toNumber() == rhs.toNumber(); + + case QScript::Boolean: + return lhs.toBool() == rhs.toBool(); + + case QScript::String: + return lhs.toString() == rhs.toString(); + + case QScript::Object: + if (lhs.isVariant()) + return lhs.strictlyEquals(rhs) || (lhs.toVariant() == rhs.toVariant()); +#ifndef QT_NO_QOBJECT + else if (lhs.isQObject()) + return (lhs.strictlyEquals(rhs)) || (lhs.toQObject() == rhs.toQObject()); +#endif + else + return lhs.strictlyEquals(rhs); + } + } + + if (lhs.isNull() && rhs.isUndefined()) + return true; + + else if (lhs.isUndefined() && rhs.isNull()) + return true; + + else if (IsNumerical(lhs) && rhs.isString()) + return lhs.toNumber() == rhs.toNumber(); + + else if (lhs.isString() && IsNumerical(rhs)) + return lhs.toNumber() == rhs.toNumber(); + + else if (lhs.isBool()) + return Equals(lhs.toNumber(), rhs); + + else if (rhs.isBool()) + return Equals(lhs, rhs.toNumber()); + + else if (lhs.isObject() && !rhs.isNull()) { + lhs = ToPrimitive(lhs); + + if (lhs.isValid() && !lhs.isObject()) + return Equals(lhs, rhs); + } + + else if (rhs.isObject() && ! lhs.isNull()) { + rhs = ToPrimitive(rhs); + if (rhs.isValid() && !rhs.isObject()) + return Equals(lhs, rhs); + } + + return false; +} + +} // namespace QScript + +/*! + Returns true if this QScriptValue is less than \a other, otherwise + returns false. The comparison follows the behavior described in + \l{ECMA-262} section 11.8.5, "The Abstract Relational Comparison + Algorithm". + + Note that if this QScriptValue or the \a other value are objects, + calling this function has side effects on the script engine, since + the engine will call the object's valueOf() function (and possibly + toString()) in an attempt to convert the object to a primitive value + (possibly resulting in an uncaught script exception). + + \sa equals() +*/ +bool QScriptValue::lessThan(const QScriptValue &other) const +{ + // no equivalent function in JSC? There's a jsLess() in VM/Machine.cpp + if (!isValid() || !other.isValid()) + return false; + if (other.engine() && engine() && (other.engine() != engine())) { + qWarning("QScriptValue::lessThan: " + "cannot compare to a value created in " + "a different engine"); + return false; + } + return QScript::LessThan(*this, other); +} + +/*! + Returns true if this QScriptValue is equal to \a other, otherwise + returns false. The comparison follows the behavior described in + \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison + Algorithm". + + This function can return true even if the type of this QScriptValue + is different from the type of the \a other value; i.e. the + comparison is not strict. For example, comparing the number 9 to + the string "9" returns true; comparing an undefined value to a null + value returns true; comparing a \c{Number} object whose primitive + value is 6 to a \c{String} object whose primitive value is "6" + returns true; and comparing the number 1 to the boolean value + \c{true} returns true. If you want to perform a comparison + without such implicit value conversion, use strictlyEquals(). + + Note that if this QScriptValue or the \a other value are objects, + calling this function has side effects on the script engine, since + the engine will call the object's valueOf() function (and possibly + toString()) in an attempt to convert the object to a primitive value + (possibly resulting in an uncaught script exception). + + \sa strictlyEquals(), lessThan() +*/ +bool QScriptValue::equals(const QScriptValue &other) const +{ + Q_D(const QScriptValue); + if (!d || !other.d_ptr) + return (d == other.d_ptr); + if (other.engine() && engine() && (other.engine() != engine())) { + qWarning("QScriptValue::equals: " + "cannot compare to a value created in " + "a different engine"); + return false; + } + if (d->isJSC() && other.d_ptr->isJSC()) { + QScriptEnginePrivate *eng_p = d->engine; + if (!eng_p) + eng_p = other.d_ptr->engine; + if (eng_p) { + JSC::ExecState *exec = eng_p->currentFrame; + JSC::JSValue savedException; + 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; + } + } + return QScript::Equals(*this, other); +} + +/*! + Returns true if this QScriptValue is equal to \a other using strict + comparison (no conversion), otherwise returns false. The comparison + follows the behavior described in \l{ECMA-262} section 11.9.6, "The + Strict Equality Comparison Algorithm". + + If the type of this QScriptValue is different from the type of the + \a other value, this function returns false. If the types are equal, + the result depends on the type, as shown in the following table: + + \table + \header \o Type \o Result + \row \o Undefined \o true + \row \o Null \o true + \row \o Boolean \o true if both values are true, false otherwise + \row \o Number \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise + \row \o String \o true if both values are exactly the same sequence of characters, false otherwise + \row \o Object \o true if both values refer to the same object, false otherwise + \endtable + + \sa equals() +*/ +bool QScriptValue::strictlyEquals(const QScriptValue &other) const +{ + Q_D(const QScriptValue); + if (!d || !other.d_ptr) + return (d == other.d_ptr); + if (other.engine() && engine() && (other.engine() != engine())) { + qWarning("QScriptValue::strictlyEquals: " + "cannot compare to a value created in " + "a different engine"); + return false; + } + if (d->type != other.d_ptr->type) + return false; + switch (d->type) { + case QScriptValuePrivate::JSC: + return JSC::JSValue::strictEqual(d->jscValue, other.d_ptr->jscValue); + case QScriptValuePrivate::Number: + return (d->numberValue == other.d_ptr->numberValue); + case QScriptValuePrivate::String: + return (d->stringValue == other.d_ptr->stringValue); + } + return false; +} + +/*! + Returns the string value of this QScriptValue, as defined in + \l{ECMA-262} section 9.8, "ToString". + + Note that if this QScriptValue is an object, calling this function + has side effects on the script engine, since the engine will call + the object's toString() function (and possibly valueOf()) in an + attempt to convert the object to a primitive value (possibly + resulting in an uncaught script exception). + + \sa isString() +*/ +QString QScriptValue::toString() const +{ + Q_D(const QScriptValue); + if (!d) + return QString(); + switch (d->type) { + case QScriptValuePrivate::JSC: { + JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + JSC::UString str = d->jscValue.toString(exec); + if (exec && exec->hadException() && !str.size()) { + JSC::JSValue savedException2; + QScriptValuePrivate::saveException(exec, &savedException2); + str = savedException2.toString(exec); + QScriptValuePrivate::restoreException(exec, savedException2); + } + if (savedException) + QScriptValuePrivate::restoreException(exec, savedException); + return str; + } + case QScriptValuePrivate::Number: + return JSC::UString::from(d->numberValue); + case QScriptValuePrivate::String: + return d->stringValue; + } + return QString(); +} + +/*! + Returns the number value of this QScriptValue, as defined in + \l{ECMA-262} section 9.3, "ToNumber". + + Note that if this QScriptValue is an object, calling this function + has side effects on the script engine, since the engine will call + the object's valueOf() function (and possibly toString()) in an + attempt to convert the object to a primitive value (possibly + resulting in an uncaught script exception). + + \sa isNumber(), toInteger(), toInt32(), toUInt32(), toUInt16() +*/ +qsreal QScriptValue::toNumber() const +{ + Q_D(const QScriptValue); + if (!d) + return 0; + switch (d->type) { + case QScriptValuePrivate::JSC: { + JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + qsreal result = d->jscValue.toNumber(exec); + QScriptValuePrivate::restoreException(exec, savedException); + return result; + } + case QScriptValuePrivate::Number: + return d->numberValue; + case QScriptValuePrivate::String: + return ((JSC::UString)d->stringValue).toDouble(); + } + return 0; +} + +/*! + \obsolete + + Use toBool() instead. +*/ +bool QScriptValue::toBoolean() const +{ + Q_D(const QScriptValue); + if (!d) + return false; + switch (d->type) { + case QScriptValuePrivate::JSC: { + JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + bool result = d->jscValue.toBoolean(exec); + QScriptValuePrivate::restoreException(exec, savedException); + return result; + } + case QScriptValuePrivate::Number: + return (d->numberValue != 0) && !qIsNaN(d->numberValue); + case QScriptValuePrivate::String: + return (!d->stringValue.isEmpty()); + } + return false; +} + +/*! + \since 4.5 + + Returns the boolean value of this QScriptValue, using the conversion + rules described in \l{ECMA-262} section 9.2, "ToBoolean". + + Note that if this QScriptValue is an object, calling this function + has side effects on the script engine, since the engine will call + the object's valueOf() function (and possibly toString()) in an + attempt to convert the object to a primitive value (possibly + resulting in an uncaught script exception). + + \sa isBool() +*/ +bool QScriptValue::toBool() const +{ + Q_D(const QScriptValue); + if (!d) + return false; + switch (d->type) { + case QScriptValuePrivate::JSC: { + JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + bool result = d->jscValue.toBoolean(exec); + QScriptValuePrivate::restoreException(exec, savedException); + return result; + } + case QScriptValuePrivate::Number: + return (d->numberValue != 0) && !qIsNaN(d->numberValue); + case QScriptValuePrivate::String: + return (!d->stringValue.isEmpty()); + } + return false; +} + +/*! + Returns the signed 32-bit integer value of this QScriptValue, using + the conversion rules described in \l{ECMA-262} section 9.5, "ToInt32". + + Note that if this QScriptValue is an object, calling this function + has side effects on the script engine, since the engine will call + the object's valueOf() function (and possibly toString()) in an + attempt to convert the object to a primitive value (possibly + resulting in an uncaught script exception). + + \sa toNumber(), toUInt32() +*/ +qint32 QScriptValue::toInt32() const +{ + Q_D(const QScriptValue); + if (!d) + return 0; + switch (d->type) { + case QScriptValuePrivate::JSC: { + JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + qint32 result = d->jscValue.toInt32(exec); + QScriptValuePrivate::restoreException(exec, savedException); + return result; + } + case QScriptValuePrivate::Number: + return QScript::ToInt32(d->numberValue); + case QScriptValuePrivate::String: + return QScript::ToInt32(((JSC::UString)d->stringValue).toDouble()); + } + return 0; +} + +/*! + Returns the unsigned 32-bit integer value of this QScriptValue, using + the conversion rules described in \l{ECMA-262} section 9.6, "ToUint32". + + Note that if this QScriptValue is an object, calling this function + has side effects on the script engine, since the engine will call + the object's valueOf() function (and possibly toString()) in an + attempt to convert the object to a primitive value (possibly + resulting in an uncaught script exception). + + \sa toNumber(), toInt32() +*/ +quint32 QScriptValue::toUInt32() const +{ + Q_D(const QScriptValue); + if (!d) + return 0; + switch (d->type) { + case QScriptValuePrivate::JSC: { + JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + quint32 result = d->jscValue.toUInt32(exec); + QScriptValuePrivate::restoreException(exec, savedException); + return result; + } + case QScriptValuePrivate::Number: + return QScript::ToUint32(d->numberValue); + case QScriptValuePrivate::String: + return QScript::ToUint32(((JSC::UString)d->stringValue).toDouble()); + } + return 0; +} + +/*! + Returns the unsigned 16-bit integer value of this QScriptValue, using + the conversion rules described in \l{ECMA-262} section 9.7, "ToUint16". + + Note that if this QScriptValue is an object, calling this function + has side effects on the script engine, since the engine will call + the object's valueOf() function (and possibly toString()) in an + attempt to convert the object to a primitive value (possibly + resulting in an uncaught script exception). + + \sa toNumber() +*/ +quint16 QScriptValue::toUInt16() const +{ + Q_D(const QScriptValue); + if (!d) + return 0; + switch (d->type) { + case QScriptValuePrivate::JSC: { + // ### no equivalent function in JSC + return QScript::ToUint16(toNumber()); + } + case QScriptValuePrivate::Number: + return QScript::ToUint16(d->numberValue); + case QScriptValuePrivate::String: + return QScript::ToUint16(((JSC::UString)d->stringValue).toDouble()); + } + return 0; +} + +/*! + Returns the integer value of this QScriptValue, using the conversion + rules described in \l{ECMA-262} section 9.4, "ToInteger". + + Note that if this QScriptValue is an object, calling this function + has side effects on the script engine, since the engine will call + the object's valueOf() function (and possibly toString()) in an + attempt to convert the object to a primitive value (possibly + resulting in an uncaught script exception). + + \sa toNumber() +*/ +qsreal QScriptValue::toInteger() const +{ + Q_D(const QScriptValue); + if (!d) + return 0; + switch (d->type) { + case QScriptValuePrivate::JSC: { + JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + qsreal result = d->jscValue.toInteger(exec); + QScriptValuePrivate::restoreException(exec, savedException); + return result; + } + case QScriptValuePrivate::Number: + return QScript::ToInteger(d->numberValue); + case QScriptValuePrivate::String: + return QScript::ToInteger(((JSC::UString)d->stringValue).toDouble()); + } + return 0; +} + +/*! + Returns the QVariant value of this QScriptValue, if it can be + converted to a QVariant; otherwise returns an invalid QVariant. + The conversion is performed according to the following table: + + \table + \header \o Input Type \o Result + \row \o Undefined \o An invalid QVariant. + \row \o Null \o An invalid QVariant. + \row \o Boolean \o A QVariant containing the value of the boolean. + \row \o Number \o A QVariant containing the value of the number. + \row \o String \o A QVariant containing the value of the string. + \row \o QVariant Object \o The result is the QVariant value of the object (no conversion). + \row \o QObject Object \o A QVariant containing a pointer to the QObject. + \row \o Date Object \o A QVariant containing the date value (toDateTime()). + \row \o RegExp Object \o A QVariant containing the regular expression value (toRegExp()). + \row \o Array Object \o The array is converted to a QVariantList. + \row \o Object \o If the value is primitive, then the result is converted to a QVariant according to the above rules; otherwise, an invalid QVariant is returned. + \endtable + + \sa isVariant() +*/ +QVariant QScriptValue::toVariant() const +{ + Q_D(const QScriptValue); + if (!d) + return QVariant(); + switch (d->type) { + case QScriptValuePrivate::JSC: + if (isObject()) { + if (isVariant()) + return d->variantValue(); +#ifndef QT_NO_QOBJECT + else if (isQObject()) + return qVariantFromValue(toQObject()); +#endif + else if (isDate()) + return QVariant(toDateTime()); +#ifndef QT_NO_REGEXP + else if (isRegExp()) + return QVariant(toRegExp()); +#endif + else if (isArray()) + return QScriptEnginePrivate::variantListFromArray(*this); + // try to convert to primitive + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + JSC::JSValue prim = d->jscValue.toPrimitive(exec); + QScriptValuePrivate::restoreException(exec, savedException); + if (!prim.isObject()) + return d->engine->scriptValueFromJSCValue(prim).toVariant(); + } else if (isNumber()) { + return QVariant(toNumber()); + } else if (isString()) { + return QVariant(toString()); + } else if (isBool()) { + return QVariant(toBool()); + } + return QVariant(); + case QScriptValuePrivate::Number: + return QVariant(d->numberValue); + case QScriptValuePrivate::String: + return QVariant(d->stringValue); + } + return QVariant(); +} + +/*! + \obsolete + + This function is obsolete; use QScriptEngine::toObject() instead. +*/ +QScriptValue QScriptValue::toObject() const +{ + Q_D(const QScriptValue); + if (!d || !d->engine) + return QScriptValue(); + return engine()->toObject(*this); +} + +/*! + Returns a QDateTime representation of this value, in local time. + If this QScriptValue is not a date, or the value of the date is NaN + (Not-a-Number), an invalid QDateTime is returned. + + \sa isDate() +*/ +QDateTime QScriptValue::toDateTime() const +{ + Q_D(const QScriptValue); + if (!isDate()) + return QDateTime(); + qsreal t = static_cast<JSC::DateInstance*>(JSC::asObject(d->jscValue))->internalNumber(); + return QScript::ToDateTime(t, Qt::LocalTime); +} + +#ifndef QT_NO_REGEXP +/*! + Returns the QRegExp representation of this value. + If this QScriptValue is not a regular expression, an empty + QRegExp is returned. + + \sa isRegExp() +*/ +QRegExp QScriptValue::toRegExp() const +{ + Q_D(const QScriptValue); + if (!isRegExp()) + return QRegExp(); + QString pattern = d->property(QLatin1String("source"), QScriptValue::ResolvePrototype).toString(); + Qt::CaseSensitivity kase = Qt::CaseSensitive; + if (d->property(QLatin1String("ignoreCase"), QScriptValue::ResolvePrototype).toBool()) + kase = Qt::CaseInsensitive; + return QRegExp(pattern, kase, QRegExp::RegExp2); +} +#endif // QT_NO_REGEXP + +/*! + If this QScriptValue is a QObject, returns the QObject pointer + that the QScriptValue represents; otherwise, returns 0. + + If the QObject that this QScriptValue wraps has been deleted, + this function returns 0 (i.e. it is possible for toQObject() + to return 0 even when isQObject() returns true). + + \sa isQObject() +*/ +QObject *QScriptValue::toQObject() const +{ + Q_D(const QScriptValue); + if (isQObject()) { + QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); + return static_cast<QScript::QObjectDelegate*>(object->delegate())->value(); + } else if (isVariant()) { + QVariant var = toVariant(); + int type = var.userType(); + if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar)) + return *reinterpret_cast<QObject* const *>(var.constData()); + } + return 0; +} + +/*! + If this QScriptValue is a QMetaObject, returns the QMetaObject pointer + that the QScriptValue represents; otherwise, returns 0. + + \sa isQMetaObject() +*/ +const QMetaObject *QScriptValue::toQMetaObject() const +{ + Q_D(const QScriptValue); + if (isQMetaObject()) + return static_cast<QScript::QMetaObjectWrapperObject*>(JSC::asObject(d->jscValue))->value(); + return 0; +} + +/*! + Sets the value of this QScriptValue's property with the given \a name to + the given \a value. + + If this QScriptValue is not an object, this function does nothing. + + If this QScriptValue does not already have a property with name \a name, + a new property is created; the given \a flags then specify how this + property may be accessed by script code. + + If \a value is invalid, the property is removed. + + If the property is implemented using a setter function (i.e. has the + PropertySetter flag set), calling setProperty() has side-effects on + the script engine, since the setter function will be called with the + given \a value as argument (possibly resulting in an uncaught script + exception). + + Note that you cannot specify custom getter or setter functions for + built-in properties, such as the \c{length} property of Array objects + or meta properties of QObject objects. + + \sa property() +*/ + +void QScriptValue::setProperty(const QString &name, const QScriptValue &value, + const PropertyFlags &flags) +{ + Q_D(QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return; + setProperty(engine()->toStringHandle(name), value, flags); +} + +/*! + Returns the value of this QScriptValue's property with the given \a name, + using the given \a mode to resolve the property. + + If no such property exists, an invalid QScriptValue is returned. + + If the property is implemented using a getter function (i.e. has the + PropertyGetter flag set), calling property() has side-effects on the + script engine, since the getter function will be called (possibly + resulting in an uncaught script exception). If an exception + occurred, property() returns the value that was thrown (typically + an \c{Error} object). + + \sa setProperty(), propertyFlags(), QScriptValueIterator +*/ +QScriptValue QScriptValue::property(const QString &name, + const ResolveFlags &mode) const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return QScriptValue(); + return d->property(name, mode); +} + +/*! + \overload + + Returns the property at the given \a arrayIndex, using the given \a + mode to resolve the property. + + This function is provided for convenience and performance when + working with array objects. + + If this QScriptValue is not an Array object, this function behaves + as if property() was called with the string representation of \a + arrayIndex. +*/ +QScriptValue QScriptValue::property(quint32 arrayIndex, + const ResolveFlags &mode) const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return QScriptValue(); + return d->property(arrayIndex, mode); +} + +/*! + \overload + + Sets the property at the given \a arrayIndex to the given \a value. + + This function is provided for convenience and performance when + working with array objects. + + If this QScriptValue is not an Array object, this function behaves + as if setProperty() was called with the string representation of \a + arrayIndex. +*/ +void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue &value, + const PropertyFlags &flags) +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return; + if (value.engine() && (value.engine() != engine())) { + qWarning("QScriptValue::setProperty() failed: " + "cannot set value created in a different engine"); + return; + } + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSValue jscValue = d->engine->scriptValueToJSCValue(value); + if (!jscValue) { + JSC::asObject(d->jscValue)->deleteProperty(exec, arrayIndex, /*checkDontDelete=*/false); + } else { + if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) { + Q_ASSERT_X(false, Q_FUNC_INFO, "property getters and setters not implemented"); + } else { + if (flags != QScriptValue::KeepExistingFlags) { +// if (JSC::asObject(d->jscValue)->hasOwnProperty(exec, arrayIndex)) +// JSC::asObject(d->jscValue)->deleteProperty(exec, arrayIndex); + 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, arrayIndex, jscValue, attribs); + } else { + JSC::asObject(d->jscValue)->put(exec, arrayIndex, jscValue); + } + } + } +} + +/*! + \since 4.4 + + Returns the value of this QScriptValue's property with the given \a name, + using the given \a mode to resolve the property. + + This overload of property() is useful when you need to look up the + same property repeatedly, since the lookup can be performed faster + when the name is represented as an interned string. + + \sa QScriptEngine::toStringHandle(), setProperty() +*/ +QScriptValue QScriptValue::property(const QScriptString &name, + const ResolveFlags &mode) const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject() || !name.isValid()) + return QScriptValue(); + return d->property(name.d_ptr->identifier, mode); +} + +/*! + \since 4.4 + + Sets the value of this QScriptValue's property with the given \a + name to the given \a value. The given \a flags specify how this + property may be accessed by script code. + + This overload of setProperty() is useful when you need to set the + same property repeatedly, since the operation can be performed + faster when the name is represented as an interned string. + + \sa QScriptEngine::toStringHandle() +*/ +void QScriptValue::setProperty(const QScriptString &name, + const QScriptValue &value, + const PropertyFlags &flags) +{ + Q_D(QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject() || !name.isValid()) + return; + QScriptEngine *valueEngine = value.engine(); + if (valueEngine && (QScriptEnginePrivate::get(valueEngine) != d->engine)) { + qWarning("QScriptValue::setProperty(%s) failed: " + "cannot set value created in a different engine", + qPrintable(name.toString())); + return; + } + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSValue jscValue = d->engine->scriptValueToJSCValue(value); + JSC::Identifier id = name.d_ptr->identifier; + 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, /*checkDontDelete=*/false); + } else if (flags & QScriptValue::PropertyGetter) { + // preserve setter, if there is one + thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + 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, /*checkDontDelete=*/false); + if (getter && getter.isObject()) + thisObject->defineGetter(exec, id, JSC::asObject(getter)); + } + } else { + if (jscValue.isObject()) { // ### should check if it has callData() + // defining getter/setter + if (id == exec->propertyNames().underscoreProto) { + qWarning("QScriptValue::setProperty() failed: " + "cannot set getter or setter of native property `__proto__'"); + } else { + if (flags & QScriptValue::PropertyGetter) + thisObject->defineGetter(exec, id, JSC::asObject(jscValue)); + if (flags & QScriptValue::PropertySetter) + thisObject->defineSetter(exec, id, JSC::asObject(jscValue)); + } + } else { + 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, /*checkDontDelete=*/false); + } else if (flags != QScriptValue::KeepExistingFlags) { + if (thisObject->hasOwnProperty(exec, id)) + thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); // ### 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); + } + } +} + +/*! + Returns the flags of the property with the given \a name, using the + given \a mode to resolve the property. + + \sa property() +*/ +QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString &name, + const ResolveFlags &mode) const +{ + if (!isObject()) + return 0; + return propertyFlags(engine()->toStringHandle(name), mode); + +} + +/*! + \since 4.4 + + Returns the flags of the property with the given \a name, using the + given \a mode to resolve the property. + + \sa property() +*/ +QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString &name, + const ResolveFlags &mode) const +{ + Q_D(const QScriptValue); + if (!isObject()) + return 0; + JSC::ExecState *exec = d->engine->currentFrame; + JSC::JSObject *object = JSC::asObject(d->jscValue); + JSC::Identifier id = name.d_ptr->identifier; + unsigned attribs = 0; + if (!object->getPropertyAttributes(exec, id, attribs)) { + if ((mode & QScriptValue::ResolvePrototype) && object->prototype()) + return d->engine->scriptValueFromJSCValue(object->prototype()).propertyFlags(name, mode); + return 0; + } + QScriptValue::PropertyFlags result = 0; + if (attribs & JSC::ReadOnly) + result |= QScriptValue::ReadOnly; + if (attribs & JSC::DontEnum) + result |= QScriptValue::SkipInEnumeration; + if (attribs & JSC::DontDelete) + result |= QScriptValue::Undeletable; + //We cannot rely on attribs JSC::Setter/Getter because they are not necesserly set by JSC (bug?) + if (attribs & JSC::Getter || !object->lookupGetter(exec, id).isUndefinedOrNull()) + result |= QScriptValue::PropertyGetter; + if (attribs & JSC::Setter || !object->lookupSetter(exec, id).isUndefinedOrNull()) + result |= QScriptValue::PropertySetter; + if (attribs & QScript::QObjectMemberAttribute) + result |= QScriptValue::QObjectMember; + result |= QScriptValue::PropertyFlag(attribs & QScriptValue::UserRange); + return result; +} + +/*! + Calls this QScriptValue as a function, using \a thisObject as + the `this' object in the function call, and passing \a args + as arguments to the function. Returns the value returned from + the function. + + If this QScriptValue is not a function, call() does nothing + and returns an invalid QScriptValue. + + Note that if \a thisObject is not an object, the global object + (see \l{QScriptEngine::globalObject()}) will be used as the + `this' object. + + Calling call() can cause an exception to occur in the script engine; + in that case, call() returns the value that was thrown (typically an + \c{Error} object). You can call + QScriptEngine::hasUncaughtException() to determine if an exception + occurred. + + \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2 + + \sa construct() +*/ +QScriptValue QScriptValue::call(const QScriptValue &thisObject, + const QScriptValueList &args) +{ + Q_D(const QScriptValue); + if (!isFunction()) + return QScriptValue(); + + if (thisObject.engine() && (thisObject.engine() != engine())) { + qWarning("QScriptValue::call() failed: " + "cannot call function with thisObject created in " + "a different engine"); + return QScriptValue(); + } + engine()->currentContext()->activationObject(); //force the creation of a context for native function; + + JSC::ExecState *exec = d->engine->currentFrame; + + JSC::JSValue jscThisObject = d->engine->scriptValueToJSCValue(thisObject); + if (!jscThisObject || !jscThisObject.isObject()) + jscThisObject = d->engine->globalObject(); + + QVector<JSC::JSValue> argsVector; + argsVector.resize(args.size()); + for (int i = 0; i < args.size(); ++i) { + const QScriptValue &arg = args.at(i); + if (!arg.isValid()) { + argsVector[i] = JSC::jsUndefined(); + } else if (arg.engine() && (arg.engine() != engine())) { + qWarning("QScriptValue::call() failed: " + "cannot call function with argument created in " + "a different engine"); + return QScriptValue(); + } else { + argsVector[i] = d->engine->scriptValueToJSCValue(arg); + } + } + JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); + + JSC::JSValue callee = d->jscValue; + JSC::CallData callData; + JSC::CallType callType = callee.getCallData(callData); + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, jscArgs); + if (exec->hadException()) { + result = exec->exception(); + } else { + QScriptValuePrivate::restoreException(exec, savedException); + } + return d->engine->scriptValueFromJSCValue(result); +} + +/*! + Calls this QScriptValue as a function, using \a thisObject as + the `this' object in the function call, and passing \a arguments + as arguments to the function. Returns the value returned from + the function. + + If this QScriptValue is not a function, call() does nothing + and returns an invalid QScriptValue. + + \a arguments can be an arguments object, an array, null or + undefined; any other type will cause a TypeError to be thrown. + + Note that if \a thisObject is not an object, the global object + (see \l{QScriptEngine::globalObject()}) will be used as the + `this' object. + + One common usage of this function is to forward native function + calls to another function: + + \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 3 + + \sa construct(), QScriptContext::argumentsObject() +*/ +QScriptValue QScriptValue::call(const QScriptValue &thisObject, + const QScriptValue &arguments) +{ + Q_D(QScriptValue); + if (!isFunction()) + return QScriptValue(); + + if (thisObject.engine() && (thisObject.engine() != engine())) { + qWarning("QScriptValue::call() failed: " + "cannot call function with thisObject created in " + "a different engine"); + return QScriptValue(); + } + engine()->currentContext()->activationObject(); //force the creation of a context for native function; + + JSC::ExecState *exec = d->engine->currentFrame; + + JSC::JSValue jscThisObject = d->engine->scriptValueToJSCValue(thisObject); + if (!jscThisObject || !jscThisObject.isObject()) + jscThisObject = d->engine->globalObject(); + + JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments); + // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply() + JSC::MarkedArgumentBuffer applyArgs; + if (!array.isUndefinedOrNull()) { + if (!array.isObject()) { + return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError)); + } + if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info) + JSC::asArguments(array)->fillArgList(exec, applyArgs); + else if (JSC::isJSArray(&exec->globalData(), array)) + JSC::asArray(array)->fillArgList(exec, applyArgs); + else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) { + unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec); + for (unsigned i = 0; i < length; ++i) + applyArgs.append(JSC::asArray(array)->get(exec, i)); + } else { + Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); +// return JSC::throwError(exec, JSC::TypeError); + } + } + + JSC::JSValue callee = d->jscValue; + JSC::CallData callData; + JSC::CallType callType = callee.getCallData(callData); + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + JSC::JSValue result = JSC::call(exec, callee, callType, callData, jscThisObject, applyArgs); + if (exec->hadException()) { + result = exec->exception(); + } else { + QScriptValuePrivate::restoreException(exec, savedException); + } + return d->engine->scriptValueFromJSCValue(result); +} + +/*! + Creates a new \c{Object} and calls this QScriptValue as a + constructor, using the created object as the `this' object and + passing \a args as arguments. If the return value from the + constructor call is an object, then that object is returned; + otherwise the default constructed object is returned. + + If this QScriptValue is not a function, construct() does nothing + and returns an invalid QScriptValue. + + Calling construct() can cause an exception to occur in the script + engine; in that case, construct() returns the value that was thrown + (typically an \c{Error} object). You can call + QScriptEngine::hasUncaughtException() to determine if an exception + occurred. + + \sa call(), QScriptEngine::newObject() +*/ +QScriptValue QScriptValue::construct(const QScriptValueList &args) +{ + Q_D(const QScriptValue); + if (!isFunction()) + return QScriptValue(); + engine()->currentContext()->activationObject(); //force the creation of a context for native function; + JSC::ExecState *exec = d->engine->currentFrame; + + QVector<JSC::JSValue> argsVector; + argsVector.resize(args.size()); + for (int i = 0; i < args.size(); ++i) { + if (!args.at(i).isValid()) + argsVector[i] = JSC::jsUndefined(); + else + argsVector[i] = d->engine->scriptValueToJSCValue(args.at(i)); + } + + JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); + + JSC::JSValue callee = d->jscValue; + JSC::ConstructData constructData; + JSC::ConstructType constructType = callee.getConstructData(constructData); + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + JSC::JSObject *result = JSC::construct(exec, callee, constructType, constructData, jscArgs); + if (exec->hadException()) { + result = JSC::asObject(exec->exception()); + } else { + QScriptValuePrivate::restoreException(exec, savedException); + } + return d->engine->scriptValueFromJSCValue(result); +} + +/*! + Creates a new \c{Object} and calls this QScriptValue as a + constructor, using the created object as the `this' object and + passing \a arguments as arguments. If the return value from the + constructor call is an object, then that object is returned; + otherwise the default constructed object is returned. + + If this QScriptValue is not a function, construct() does nothing + and returns an invalid QScriptValue. + + \a arguments can be an arguments object, an array, null or + undefined. Any other type will cause a TypeError to be thrown. + + \sa call(), QScriptEngine::newObject(), QScriptContext::argumentsObject() +*/ +QScriptValue QScriptValue::construct(const QScriptValue &arguments) +{ + Q_D(QScriptValue); + if (!isFunction()) + return QScriptValue(); + engine()->currentContext()->activationObject(); //force the creation of a context for native function; + JSC::ExecState *exec = d->engine->currentFrame; + + JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments); + // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply() + JSC::MarkedArgumentBuffer applyArgs; + if (!array.isUndefinedOrNull()) { + if (!array.isObject()) { + return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array")); + } + if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info) + JSC::asArguments(array)->fillArgList(exec, applyArgs); + else if (JSC::isJSArray(&exec->globalData(), array)) + JSC::asArray(array)->fillArgList(exec, applyArgs); + else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) { + unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec); + for (unsigned i = 0; i < length; ++i) + applyArgs.append(JSC::asArray(array)->get(exec, i)); + } else { + return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array")); + } + } + + JSC::JSValue callee = d->jscValue; + JSC::ConstructData constructData; + JSC::ConstructType constructType = callee.getConstructData(constructData); + JSC::JSValue savedException; + QScriptValuePrivate::saveException(exec, &savedException); + JSC::JSObject *result = JSC::construct(exec, callee, constructType, constructData, applyArgs); + if (exec->hadException()) { + if (exec->exception().isObject()) + result = JSC::asObject(exec->exception()); + } else { + QScriptValuePrivate::restoreException(exec, savedException); + } + return d->engine->scriptValueFromJSCValue(result); +} + +/*! + Returns the QScriptEngine that created this QScriptValue, + or 0 if this QScriptValue is invalid or the value is not + associated with a particular engine. +*/ +QScriptEngine *QScriptValue::engine() const +{ + Q_D(const QScriptValue); + if (!d) + return 0; + return QScriptEnginePrivate::get(d->engine); +} + +/*! + \obsolete + + Use isBool() instead. +*/ +bool QScriptValue::isBoolean() const +{ + Q_D(const QScriptValue); + return d && d->isJSC() && d->jscValue.isBoolean(); +} + +/*! + \since 4.5 + + Returns true if this QScriptValue is of the primitive type Boolean; + otherwise returns false. + + \sa toBool() +*/ +bool QScriptValue::isBool() const +{ + Q_D(const QScriptValue); + return d && d->isJSC() && d->jscValue.isBoolean(); +} + +/*! + Returns true if this QScriptValue is of the primitive type Number; + otherwise returns false. + + \sa toNumber() +*/ +bool QScriptValue::isNumber() const +{ + Q_D(const QScriptValue); + if (!d) + return false; + switch (d->type) { + case QScriptValuePrivate::JSC: + return d->jscValue.isNumber(); + case QScriptValuePrivate::Number: + return true; + case QScriptValuePrivate::String: + return false; + } + return false; +} + +/*! + Returns true if this QScriptValue is of the primitive type String; + otherwise returns false. + + \sa toString() +*/ +bool QScriptValue::isString() const +{ + Q_D(const QScriptValue); + if (!d) + return false; + switch (d->type) { + case QScriptValuePrivate::JSC: + return d->jscValue.isString(); + case QScriptValuePrivate::Number: + return false; + case QScriptValuePrivate::String: + return true; + } + return false; +} + +/*! + Returns true if this QScriptValue is a function; otherwise returns + false. + + \sa call() +*/ +bool QScriptValue::isFunction() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC()) + return false; + return QScript::isFunction(d->jscValue); +} + +/*! + Returns true if this QScriptValue is of the primitive type Null; + otherwise returns false. + + \sa QScriptEngine::nullValue() +*/ +bool QScriptValue::isNull() const +{ + Q_D(const QScriptValue); + return d && d->isJSC() && d->jscValue.isNull(); +} + +/*! + Returns true if this QScriptValue is of the primitive type Undefined; + otherwise returns false. + + \sa QScriptEngine::undefinedValue() +*/ +bool QScriptValue::isUndefined() const +{ + Q_D(const QScriptValue); + return d && d->isJSC() && d->jscValue.isUndefined(); +} + +/*! + Returns true if this QScriptValue is of the Object type; otherwise + returns false. + + Note that function values, variant values, and QObject values are + objects, so this function returns true for such values. + + \sa toObject(), QScriptEngine::newObject() +*/ +bool QScriptValue::isObject() const +{ + Q_D(const QScriptValue); + return d && d->isJSC() && d->jscValue.isObject(); +} + +/*! + Returns true if this QScriptValue is a variant value; + otherwise returns false. + + \sa toVariant(), QScriptEngine::newVariant() +*/ +bool QScriptValue::isVariant() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + return false; + QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); + QScriptObjectDelegate *delegate = object->delegate(); + return (delegate && (delegate->type() == QScriptObjectDelegate::Variant)); +} + +/*! + Returns true if this QScriptValue is a QObject; otherwise returns + false. + + Note: This function returns true even if the QObject that this + QScriptValue wraps has been deleted. + + \sa toQObject(), QScriptEngine::newQObject() +*/ +bool QScriptValue::isQObject() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + return false; + QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); + QScriptObjectDelegate *delegate = object->delegate(); + return (delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); +} + +/*! + Returns true if this QScriptValue is a QMetaObject; otherwise returns + false. + + \sa toQMetaObject(), QScriptEngine::newQMetaObject() +*/ +bool QScriptValue::isQMetaObject() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return false; + return JSC::asObject(d->jscValue)->isObject(&QScript::QMetaObjectWrapperObject::info); + return false; +} + +/*! + Returns true if this QScriptValue is valid; otherwise returns + false. +*/ +bool QScriptValue::isValid() const +{ + Q_D(const QScriptValue); + return d && (!d->isJSC() || !!d->jscValue); +} + +/*! + \since 4.4 + + Returns the internal data of this QScriptValue object. QtScript uses + this property to store the primitive value of Date, String, Number + and Boolean objects. For other types of object, custom data may be + stored using setData(). +*/ +QScriptValue QScriptValue::data() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return QScriptValue(); + if (d->jscValue.isObject(&QScriptObject::info)) { + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); + return d->engine->scriptValueFromJSCValue(scriptObject->data()); + } else { + // ### make hidden property + return d->property(QLatin1String("__qt_data__"), QScriptValue::ResolveLocal); + } +} + +/*! + \since 4.4 + + Sets the internal \a data of this QScriptValue object. You can use + this function to set object-specific data that won't be directly + accessible to scripts, but may be retrieved in C++ using the data() + function. +*/ +void QScriptValue::setData(const QScriptValue &data) +{ + Q_D(QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) + return; + JSC::JSValue other = d->engine->scriptValueToJSCValue(data); + if (d->jscValue.isObject(&QScriptObject::info)) { + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); + scriptObject->setData(other); + } else { + JSC::ExecState *exec = d->engine->currentFrame; + JSC::Identifier id = JSC::Identifier(exec, "__qt_data__"); + if (!data.isValid()) { + JSC::asObject(d->jscValue)->removeDirect(id); + } else { + // ### make hidden property + JSC::asObject(d->jscValue)->putDirect(id, other); + } + } +} + +/*! + \since 4.4 + + Returns the custom script class that this script object is an + instance of, or 0 if the object is not of a custom class. + + \sa setScriptClass() +*/ +QScriptClass *QScriptValue::scriptClass() const +{ + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + return 0; + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) + return 0; + return static_cast<QScript::ClassObjectDelegate*>(delegate)->scriptClass(); +} + +/*! + \since 4.4 + + Sets the custom script class of this script object to \a scriptClass. + This can be used to "promote" a plain script object (e.g. created + by the "new" operator in a script, or by QScriptEngine::newObject() in C++) + to an object of a custom type. + + If \a scriptClass is 0, the object will be demoted to a plain + script object. + + \sa scriptClass(), setData() +*/ +void QScriptValue::setScriptClass(QScriptClass *scriptClass) +{ + Q_D(QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + return; + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) { + delete delegate; + delegate = new QScript::ClassObjectDelegate(scriptClass); + scriptObject->setDelegate(delegate); + } + static_cast<QScript::ClassObjectDelegate*>(delegate)->setScriptClass(scriptClass); +} + +/*! + \internal + + Returns the ID of this object, or -1 if this QScriptValue is not an + object. + + \sa QScriptEngine::objectById() +*/ +qint64 QScriptValue::objectId() const +{ + return d_ptr?d_ptr->objectId():-1; +} +QT_END_NAMESPACE diff --git a/src/script/qscriptvalue.h b/src/script/api/qscriptvalue.h index 5a5cf8b..be59508 100644 --- a/src/script/qscriptvalue.h +++ b/src/script/api/qscriptvalue.h @@ -44,8 +44,6 @@ #include <QtCore/qstring.h> -#ifndef QT_NO_SCRIPT - #include <QtCore/qlist.h> QT_BEGIN_HEADER @@ -233,6 +231,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/qscriptvaluefwd_p.h b/src/script/api/qscriptvalue_p.h index 216f87e..e05259e 100644 --- a/src/script/qscriptvaluefwd_p.h +++ b/src/script/api/qscriptvalue_p.h @@ -34,21 +34,13 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef QSCRIPTVALUEFWD_P_H -#define QSCRIPTVALUEFWD_P_H - -#include <QtCore/qatomic.h> - -#ifndef QT_NO_SCRIPT - -#include "qscriptvalueimplfwd_p.h" - -QT_BEGIN_NAMESPACE +#ifndef QSCRIPTVALUE_P_H +#define QSCRIPTVALUE_P_H // // W A R N I N G @@ -61,29 +53,83 @@ QT_BEGIN_NAMESPACE // We mean it. // -class QScriptValuePrivate -{ -public: - inline QScriptValuePrivate(); - inline ~QScriptValuePrivate(); +#include <QtCore/qobjectdefs.h> - static inline QScriptValuePrivate *create(); - - static inline QScriptValuePrivate *get(const QScriptValue &value); +QT_BEGIN_NAMESPACE - static inline QScriptValueImpl valueOf(const QScriptValue &value); +#include "wtf/Platform.h" +#include "JSValue.h" - static inline void init(QScriptValue &value, QScriptValuePrivate *p); +class QString; +class QScriptEnginePrivate; - inline void invalidate(); +class QScriptValue; +class QScriptValuePrivate +{ + Q_DISABLE_COPY(QScriptValuePrivate); +public: + enum Type { + JSC, + Number, + String + }; + + QScriptValuePrivate(); + ~QScriptValuePrivate(); + + void initFrom(JSC::JSValue value); + void initFrom(double value); + void initFrom(const QString &value); + + bool isJSC() const; + + QVariant &variantValue() const; + void setVariantValue(const QVariant &value); + + static QScriptValuePrivate *get(const QScriptValue &q) + { + return q.d_ptr; + } + + static QScriptValue toPublic(QScriptValuePrivate *d) + { + QScriptValue tmp; + tmp.d_ptr = d; + d->ref.ref(); + return tmp; + } + + QScriptValue property(const JSC::Identifier &id, int resolveMode) const; + QScriptValue property(quint32 index, int resolveMode) const; + QScriptValue property(const QString &, int resolveMode) const; + + void detachFromEngine(); + + qint64 objectId() + { + if ( (type == JSC) && (engine) ) + return (qint64)jscValue.asCell(); + else + return -1; + } + + static void saveException(JSC::ExecState*, JSC::JSValue*); + static void restoreException(JSC::ExecState*, JSC::JSValue); + + QScriptEnginePrivate *engine; + Type type; + JSC::JSValue jscValue; + double numberValue; + QString stringValue; + + // linked list of engine's script values + QScriptValuePrivate *prev; + QScriptValuePrivate *next; - QScriptEngine *engine; - QScriptValueImpl value; QBasicAtomicInt ref; }; -QT_END_NAMESPACE -#endif // QT_NO_SCRIPT +QT_END_NAMESPACE #endif diff --git a/src/script/qscriptvalueiterator.cpp b/src/script/api/qscriptvalueiterator.cpp index 885f9c9..195a23b 100644 --- a/src/script/qscriptvalueiterator.cpp +++ b/src/script/api/qscriptvalueiterator.cpp @@ -39,17 +39,20 @@ ** ****************************************************************************/ +#include "config.h" #include "qscriptvalueiterator.h" -#ifndef QT_NO_SCRIPT - -#include "qscriptvalueiterator_p.h" -#include "qscriptvalueiteratorimpl_p.h" +#include "qscriptstring.h" +#include "qscriptengine.h" #include "qscriptengine_p.h" -#include "qscriptcontext_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" +#include "qscriptvalue_p.h" +#include "qlinkedlist.h" + + +#include "JSObject.h" +#include "PropertyNameArray.h" +#include "JSArray.h" +#include "JSFunction.h" QT_BEGIN_NAMESPACE @@ -93,21 +96,36 @@ QT_BEGIN_NAMESPACE \sa QScriptValue::property() */ -/*! - \internal -*/ -QScriptValueIteratorPrivate::QScriptValueIteratorPrivate() - : q_ptr(0), it(0) +class QScriptValueIteratorPrivate { -} +public: + QScriptValueIteratorPrivate() + : initialized(false) + {} + void ensureInitialized() + { + if (initialized) + return; + QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(object.engine()); + 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::PropertyNameArray::const_iterator propertyNamesIt = propertyNamesArray.begin(); + for(; propertyNamesIt != propertyNamesArray.end(); ++propertyNamesIt) { + propertyNames.append(propertyNamesIt->ustring()); + } + it = propertyNames.begin(); + initialized = true; + } -/*! - \internal -*/ -QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate() -{ - delete it; -} + QScriptValue object; + QLinkedList<JSC::UString> propertyNames; + QLinkedList<JSC::UString>::iterator it; + QLinkedList<JSC::UString>::iterator current; + bool initialized; +}; /*! Constructs an iterator for traversing \a object. The iterator is @@ -116,12 +134,11 @@ QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate() */ QScriptValueIterator::QScriptValueIterator(const QScriptValue &object) { - QScriptValueImpl val = QScriptValuePrivate::valueOf(object); - if (!val.isObject()) { + if (!object.isObject()) { d_ptr = 0; } else { d_ptr = new QScriptValueIteratorPrivate(); - d_ptr->it = new QScriptValueIteratorImpl(val); + d_ptr->object = object; } } @@ -146,7 +163,11 @@ QScriptValueIterator::~QScriptValueIterator() bool QScriptValueIterator::hasNext() const { Q_D(const QScriptValueIterator); - return (d && d->it->hasNext()); + if (!d) + return false; + + const_cast<QScriptValueIteratorPrivate*>(d)->ensureInitialized(); + return d->it != d->propertyNames.end(); } /*! @@ -160,8 +181,12 @@ bool QScriptValueIterator::hasNext() const void QScriptValueIterator::next() { Q_D(QScriptValueIterator); - if (d) - d->it->next(); + if (!d) + return; + d->ensureInitialized(); + + d->current = d->it; + ++(d->it); } /*! @@ -174,7 +199,11 @@ void QScriptValueIterator::next() bool QScriptValueIterator::hasPrevious() const { Q_D(const QScriptValueIterator); - return (d && d->it->hasPrevious()); + if (!d) + return false; + + const_cast<QScriptValueIteratorPrivate*>(d)->ensureInitialized(); + return d->it != d->propertyNames.begin(); } /*! @@ -188,8 +217,11 @@ bool QScriptValueIterator::hasPrevious() const void QScriptValueIterator::previous() { Q_D(QScriptValueIterator); - if (d) - d->it->previous(); + if (!d) + return; + d->ensureInitialized(); + --(d->it); + d->current = d->it; } /*! @@ -201,8 +233,10 @@ void QScriptValueIterator::previous() void QScriptValueIterator::toFront() { Q_D(QScriptValueIterator); - if (d) - d->it->toFront(); + if (!d) + return; + d->ensureInitialized(); + d->it = d->propertyNames.begin(); } /*! @@ -214,8 +248,10 @@ void QScriptValueIterator::toFront() void QScriptValueIterator::toBack() { Q_D(QScriptValueIterator); - if (d) - d->it->toBack(); + if (!d) + return; + d->ensureInitialized(); + d->it = d->propertyNames.end(); } /*! @@ -227,9 +263,9 @@ void QScriptValueIterator::toBack() QString QScriptValueIterator::name() const { Q_D(const QScriptValueIterator); - if (!d) + if (!d || !d->initialized) return QString(); - return d->it->name(); + return *d->current; } /*! @@ -241,10 +277,9 @@ QString QScriptValueIterator::name() const QScriptString QScriptValueIterator::scriptName() const { Q_D(const QScriptValueIterator); - if (!d) + if (!d || !d->initialized) return QScriptString(); - QScriptEnginePrivate *eng = d->it->object().engine(); - return eng->internedString(d->it->nameId()); + return d->object.engine()->toStringHandle(name()); } /*! @@ -256,10 +291,9 @@ QScriptString QScriptValueIterator::scriptName() const QScriptValue QScriptValueIterator::value() const { Q_D(const QScriptValueIterator); - if (!d) + if (!d || !d->initialized) return QScriptValue(); - QScriptEnginePrivate *eng = d->it->object().engine(); - return eng->toPublic(d->it->value()); + return d->object.property(name()); } /*! @@ -270,11 +304,10 @@ QScriptValue QScriptValueIterator::value() const */ void QScriptValueIterator::setValue(const QScriptValue &value) { - Q_D(const QScriptValueIterator); - if (d) { - QScriptEnginePrivate *eng = d->it->object().engine(); - d->it->setValue(eng->toImpl(value)); - } + Q_D(QScriptValueIterator); + if (!d || !d->initialized) + return; + d->object.setProperty(name(), value); } /*! @@ -286,9 +319,9 @@ void QScriptValueIterator::setValue(const QScriptValue &value) QScriptValue::PropertyFlags QScriptValueIterator::flags() const { Q_D(const QScriptValueIterator); - if (!d) + if (!d || !d->initialized) return 0; - return QScriptValue::PropertyFlags(d->it->flags() & ~QScript::Member::InternalRange); + return d->object.propertyFlags(name()); } /*! @@ -299,9 +332,11 @@ QScriptValue::PropertyFlags QScriptValueIterator::flags() const */ void QScriptValueIterator::remove() { - Q_D(const QScriptValueIterator); - if (d) - d->it->remove(); + Q_D(QScriptValueIterator); + if (!d || !d->initialized) + return; + d->object.setProperty(name(), QScriptValue()); + d->propertyNames.erase(d->current); } /*! @@ -315,14 +350,11 @@ QScriptValueIterator& QScriptValueIterator::operator=(QScriptValue &object) delete d_ptr; d_ptr = 0; } - QScriptValueImpl val = QScriptValuePrivate::valueOf(object); - if (val.isObject()) { + if (object.isObject()) { d_ptr = new QScriptValueIteratorPrivate(); - d_ptr->it = new QScriptValueIteratorImpl(val); + d_ptr->object = object; } return *this; } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptvalueiterator.h b/src/script/api/qscriptvalueiterator.h index 6aaf4cd..ce79fe0 100644 --- a/src/script/qscriptvalueiterator.h +++ b/src/script/api/qscriptvalueiterator.h @@ -44,8 +44,6 @@ #include <QtScript/qscriptvalue.h> -#ifndef QT_NO_SCRIPT - QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -94,6 +92,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QT_NO_SCRIPT - #endif // QSCRIPTVALUEITERATOR_H diff --git a/src/script/bridge/bridge.pri b/src/script/bridge/bridge.pri new file mode 100644 index 0000000..666a07e --- /dev/null +++ b/src/script/bridge/bridge.pri @@ -0,0 +1,17 @@ +SOURCES += \ + $$PWD/qscriptfunction.cpp \ + $$PWD/qscriptobject.cpp \ + $$PWD/qscriptclassobject.cpp \ + $$PWD/qscriptvariant.cpp \ + $$PWD/qscriptqobject.cpp \ + $$PWD/qscriptglobalobject.cpp \ + $$PWD/qscriptactivationobject.cpp + +HEADERS += \ + $$PWD/qscriptfunction_p.h \ + $$PWD/qscriptobject_p.h \ + $$PWD/qscriptclassobject_p.h \ + $$PWD/qscriptvariant_p.h \ + $$PWD/qscriptqobject_p.h \ + $$PWD/qscriptglobalobject_p.h \ + $$PWD/qscriptactivationobject_p.h diff --git a/src/script/bridge/qscriptactivationobject.cpp b/src/script/bridge/qscriptactivationobject.cpp new file mode 100644 index 0000000..a8a2181 --- /dev/null +++ b/src/script/bridge/qscriptactivationobject.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptactivationobject_p.h" + +#include "JSVariableObject.h" + +namespace JSC +{ + ASSERT_CLASS_FITS_IN_CELL(QScript::QScriptActivationObject); +} + +QT_BEGIN_NAMESPACE + +/*! +\class QScriptActivationObject +\internal + + Represent a scope for native function call. +*/ + +namespace QScript +{ + +const JSC::ClassInfo QScriptActivationObject::info = { "QScriptActivationObject", 0, 0, 0 }; + +QScriptActivationObject::QScriptActivationObject(JSC::ExecState *callFrame, JSC::JSObject *delegate) + : JSC::JSVariableObject(callFrame->globalData().activationStructure, + new QScriptActivationObjectData(callFrame->registers(), delegate)) +{ +} + +QScriptActivationObject::~QScriptActivationObject() +{ + delete d; +} + +bool QScriptActivationObject::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot) +{ + if (d_ptr()->delegate != 0) + return d_ptr()->delegate->getOwnPropertySlot(exec, propertyName, slot); + return JSC::JSVariableObject::getOwnPropertySlot(exec, propertyName, slot); +} + +bool QScriptActivationObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, unsigned& attributes) const +{ + if (d_ptr()->delegate != 0) + return d_ptr()->delegate->getPropertyAttributes(exec, propertyName, attributes); + return JSC::JSVariableObject::getPropertyAttributes(exec, propertyName, attributes); +} + +void QScriptActivationObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, unsigned listedAttributes) +{ + if (d_ptr()->delegate != 0) { + d_ptr()->delegate->getPropertyNames(exec, propertyNames, listedAttributes); + return; + } + return JSC::JSVariableObject::getPropertyNames(exec, propertyNames, listedAttributes); +} + +void QScriptActivationObject::putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes) +{ + if (d_ptr()->delegate != 0) { + d_ptr()->delegate->putWithAttributes(exec, propertyName, value, attributes); + return; + } + + if (symbolTablePutWithAttributes(propertyName, value, attributes)) + return; + + JSC::PutPropertySlot slot; + JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot); +} + +void QScriptActivationObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot) +{ + if (d_ptr()->delegate != 0) { + d_ptr()->delegate->put(exec, propertyName, value, slot); + return; + } + JSC::JSVariableObject::put(exec, propertyName, value, slot); +} + +void QScriptActivationObject::put(JSC::ExecState* exec, unsigned propertyName, JSC::JSValue value) +{ + if (d_ptr()->delegate != 0) { + d_ptr()->delegate->put(exec, propertyName, value); + return; + } + JSC::JSVariableObject::put(exec, propertyName, value); +} + +bool QScriptActivationObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, bool checkDontDelete) +{ + if (d_ptr()->delegate != 0) + return d_ptr()->delegate->deleteProperty(exec, propertyName, checkDontDelete); + return JSC::JSVariableObject::deleteProperty(exec, propertyName, checkDontDelete); +} + +void QScriptActivationObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction) +{ + if (d_ptr()->delegate != 0) + d_ptr()->delegate->defineGetter(exec, propertyName, getterFunction); + else + JSC::JSVariableObject::defineGetter(exec, propertyName, getterFunction); +} + +void QScriptActivationObject::defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction) +{ + if (d_ptr()->delegate != 0) + d_ptr()->delegate->defineSetter(exec, propertyName, setterFunction); + else + JSC::JSVariableObject::defineSetter(exec, propertyName, setterFunction); +} + +JSC::JSValue QScriptActivationObject::lookupGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName) +{ + if (d_ptr()->delegate != 0) + return d_ptr()->delegate->lookupGetter(exec, propertyName); + return JSC::JSVariableObject::lookupGetter(exec, propertyName); +} + +JSC::JSValue QScriptActivationObject::lookupSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName) +{ + if (d_ptr()->delegate != 0) + return d_ptr()->delegate->lookupSetter(exec, propertyName); + return JSC::JSVariableObject::lookupSetter(exec, propertyName); +} + +} // namespace QScript + +QT_END_NAMESPACE + diff --git a/src/script/bridge/qscriptactivationobject_p.h b/src/script/bridge/qscriptactivationobject_p.h new file mode 100644 index 0000000..cb28341 --- /dev/null +++ b/src/script/bridge/qscriptactivationobject_p.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTACTIVATIONOBJECT_P_H +#define QSCRIPTACTIVATIONOBJECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobjectdefs.h> + +#include "JSVariableObject.h" + +QT_BEGIN_NAMESPACE + +namespace QScript +{ + +class QScriptActivationObject : public JSC::JSVariableObject { +public: + QScriptActivationObject(JSC::ExecState *callFrame, JSC::JSObject *delegate = 0); + virtual ~QScriptActivationObject(); + 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 getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); + + 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 void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction); + virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction); + virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName); + virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName); + + virtual const JSC::ClassInfo* classInfo() const { return &info; } + static const JSC::ClassInfo info; + + struct QScriptActivationObjectData : public JSVariableObjectData { + QScriptActivationObjectData(JSC::Register* registers, JSC::JSObject *dlg) + : JSVariableObjectData(&symbolTable, registers), + delegate(dlg) + { } + JSC::SymbolTable symbolTable; + JSC::JSObject *delegate; + }; + + JSC::JSObject *delegate() const + { return d_ptr()->delegate; } + void setDelegate(JSC::JSObject *delegate) + { d_ptr()->delegate = delegate; } + + QScriptActivationObjectData *d_ptr() const { return static_cast<QScriptActivationObjectData *>(d); } +}; + +} // namespace QScript + +QT_END_NAMESPACE + +#endif diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp new file mode 100644 index 0000000..f6c6792 --- /dev/null +++ b/src/script/bridge/qscriptclassobject.cpp @@ -0,0 +1,273 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptclassobject_p.h" + +#include "../api/qscriptengine.h" +#include "../api/qscriptengine_p.h" +#include "../api/qscriptcontext.h" +#include "../api/qscriptcontext_p.h" +#include "../api/qscriptclass.h" +#include "../api/qscriptclasspropertyiterator.h" + +#include "Error.h" +#include "PropertyNameArray.h" + +Q_DECLARE_METATYPE(QScriptContext*) +Q_DECLARE_METATYPE(QScriptValue) +Q_DECLARE_METATYPE(QScriptValueList) + +QT_BEGIN_NAMESPACE + +namespace QScript +{ + +ClassObjectDelegate::ClassObjectDelegate(QScriptClass *scriptClass) + : m_scriptClass(scriptClass) +{ +} + +ClassObjectDelegate::~ClassObjectDelegate() +{ +} + +QScriptClass *ClassObjectDelegate::scriptClass() const +{ + return m_scriptClass; +} + +void ClassObjectDelegate::setScriptClass(QScriptClass *scriptClass) +{ + m_scriptClass = scriptClass; +} + +QScriptObjectDelegate::Type ClassObjectDelegate::type() const +{ + return ClassObject; +} + +bool ClassObjectDelegate::getOwnPropertySlot(QScriptObject* object, + JSC::ExecState *exec, + const JSC::Identifier &propertyName, + JSC::PropertySlot &slot) +{ + // 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); + QString name(propertyName.ustring()); + QScriptString scriptName = QScriptEnginePrivate::get(engine)->toStringHandle(name); + uint id = 0; + QScriptClass::QueryFlags flags = m_scriptClass->queryProperty( + scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id); + if (flags & QScriptClass::HandlesReadAccess) { + QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id); + slot.setValue(engine->scriptValueToJSCValue(value)); + return true; + } + return false; +} + +void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, + const JSC::Identifier &propertyName, + JSC::JSValue value, JSC::PutPropertySlot &slot) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); + QString name(propertyName.ustring()); + QScriptString scriptName = QScriptEnginePrivate::get(engine)->toStringHandle(name); + uint id = 0; + QScriptClass::QueryFlags flags = m_scriptClass->queryProperty( + scriptObject, scriptName, QScriptClass::HandlesWriteAccess, &id); + if (flags & QScriptClass::HandlesWriteAccess) { + m_scriptClass->setProperty(scriptObject, scriptName, id, engine->scriptValueFromJSCValue(value)); + return; + } + QScriptObjectDelegate::put(object, exec, propertyName, value, slot); +} + +bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec, + const JSC::Identifier &propertyName, + bool checkDontDelete) +{ + // ### avoid duplication of put() + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); + QString name(propertyName.ustring()); + QScriptString scriptName = QScriptEnginePrivate::get(engine)->toStringHandle(name); + uint id = 0; + QScriptClass::QueryFlags flags = m_scriptClass->queryProperty( + scriptObject, scriptName, QScriptClass::HandlesWriteAccess, &id); + if (flags & QScriptClass::HandlesWriteAccess) { + if (m_scriptClass->propertyFlags(scriptObject, scriptName, id) & QScriptValue::Undeletable) + return false; + 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); + QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); + QString name(propertyName.ustring()); + QScriptString scriptName = QScriptEnginePrivate::get(engine)->toStringHandle(name); + 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); +} + +void ClassObjectDelegate::getPropertyNames(QScriptObject* object, JSC::ExecState *exec, + JSC::PropertyNameArray &propertyNames, + unsigned listedAttributes) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); + QScriptClassPropertyIterator *it = m_scriptClass->newIterator(scriptObject); + if (it != 0) { + while (it->hasNext()) { + it->next(); + QString name = it->name().toString(); + propertyNames.add(JSC::Identifier(exec, name)); + } + delete it; + } + QScriptObjectDelegate::getPropertyNames(object, exec, propertyNames, listedAttributes); +} + +JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &callData) +{ + if (!m_scriptClass->supportsExtension(QScriptClass::Callable)) + return JSC::CallTypeNone; + callData.native.function = call; + return JSC::CallTypeHost; +} + +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)) + return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object"); + QScriptObject *obj = static_cast<QScriptObject*>(callee); + QScriptObjectDelegate *delegate = obj->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) + return JSC::throwError(exec, JSC::TypeError, "callee is not a ClassObject object"); + + QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass(); + QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); + + JSC::ExecState *oldFrame = eng_p->currentFrame; + eng_p->pushContext(exec, thisValue, args, callee); + QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); + QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj); + QVariant result = scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx)); + eng_p->popContext(); + eng_p->currentFrame = oldFrame; + return eng_p->jscValueFromVariant(result); +} + +JSC::ConstructType ClassObjectDelegate::getConstructData(QScriptObject*, JSC::ConstructData &constructData) +{ + if (!m_scriptClass->supportsExtension(QScriptClass::Callable)) + return JSC::ConstructTypeNone; + constructData.native.function = construct; + return JSC::ConstructTypeHost; +} + +JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObject *callee, + const JSC::ArgList &args) +{ + Q_ASSERT(callee->isObject(&QScriptObject::info)); + QScriptObject *obj = static_cast<QScriptObject*>(callee); + QScriptObjectDelegate *delegate = obj->delegate(); + QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass(); + + QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); + //JSC::ExecState *oldFrame = eng_p->currentFrame; + eng_p->pushContext(exec, JSC::JSValue(), args, callee, true); + QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); + + QScriptValue defaultObject = ctx->thisObject(); + QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx))); + if (!result.isObject()) + result = defaultObject; + return JSC::asObject(eng_p->scriptValueToJSCValue(result)); +} + +bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec, + JSC::JSValue value, JSC::JSValue proto) +{ + if (!scriptClass()->supportsExtension(QScriptClass::HasInstance)) + return QScriptObjectDelegate::hasInstance(object, exec, value, proto); + QScriptValueList args; + QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); + args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value); + QVariant result = scriptClass()->extension(QScriptClass::HasInstance, qVariantFromValue(args)); + return result.toBool(); +} + +} // namespace QScript + +QT_END_NAMESPACE diff --git a/src/script/qscriptclass_p.h b/src/script/bridge/qscriptclassobject_p.h index d5d8500..38a8585 100644 --- a/src/script/qscriptclass_p.h +++ b/src/script/bridge/qscriptclassobject_p.h @@ -39,14 +39,8 @@ ** ****************************************************************************/ -#ifndef QSCRIPTCLASS_P_H -#define QSCRIPTCLASS_P_H - -#include <QtCore/qobjectdefs.h> - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE +#ifndef QSCRIPTCLASSOBJECT_P_H +#define QSCRIPTCLASSOBJECT_P_H // // W A R N I N G @@ -59,33 +53,59 @@ QT_BEGIN_NAMESPACE // We mean it. // -class QScriptEngine; -class QScriptClassInfo; -class QScriptFunction; +#include <QtCore/qobjectdefs.h> + +#include "qscriptobject_p.h" + +QT_BEGIN_NAMESPACE class QScriptClass; -class QScriptClassPrivate + +namespace QScript +{ + +class ClassObjectDelegate : public QScriptObjectDelegate { - Q_DECLARE_PUBLIC(QScriptClass) public: - QScriptClassPrivate(QScriptClass*); - virtual ~QScriptClassPrivate(); + ClassObjectDelegate(QScriptClass *scriptClass); + ~ClassObjectDelegate(); - static QScriptClassPrivate *get(QScriptClass *klass); + QScriptClass *scriptClass() const; + void setScriptClass(QScriptClass *scriptClass); - QScriptClassInfo *classInfo(); - static QScriptClass *classFromInfo(QScriptClassInfo *info); + virtual Type type() const; - QScriptFunction *newFunction(); + virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertySlot&); + 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; + virtual void getPropertyNames(QScriptObject*, JSC::ExecState*, + JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); - QScriptEngine *engine; - QScriptClassInfo *m_classInfo; + 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&); + static JSC::JSObject* construct(JSC::ExecState*, JSC::JSObject*, + const JSC::ArgList&); - QScriptClass *q_ptr; + virtual bool hasInstance(QScriptObject*, JSC::ExecState*, + JSC::JSValue value, JSC::JSValue proto); + +private: + QScriptClass *m_scriptClass; }; -QT_END_NAMESPACE +} // namespace QScript -#endif // QT_NO_SCRIPT +QT_END_NAMESPACE #endif diff --git a/src/script/bridge/qscriptfunction.cpp b/src/script/bridge/qscriptfunction.cpp new file mode 100644 index 0000000..27ec203 --- /dev/null +++ b/src/script/bridge/qscriptfunction.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptfunction_p.h" + +#include "private/qscriptengine_p.h" +#include "qscriptcontext.h" +#include "private/qscriptcontext_p.h" +#include "private/qscriptvalue_p.h" +#include "qscriptactivationobject_p.h" +#include "qscriptobject_p.h" + +#include "JSGlobalObject.h" +#include "DebuggerCallFrame.h" +#include "Debugger.h" + +namespace JSC +{ +ASSERT_CLASS_FITS_IN_CELL(QScript::FunctionWrapper); +ASSERT_CLASS_FITS_IN_CELL(QScript::FunctionWithArgWrapper); +} + +namespace QScript +{ + +const JSC::ClassInfo FunctionWrapper::info = { "QtNativeFunctionWrapper", &PrototypeFunction::info, 0, 0 }; +const JSC::ClassInfo FunctionWithArgWrapper::info = { "QtNativeFunctionWithArgWrapper", &PrototypeFunction::info, 0, 0 }; + +FunctionWrapper::FunctionWrapper(JSC::ExecState *exec, int length, const JSC::Identifier &name, + QScriptEngine::FunctionSignature function) + : JSC::PrototypeFunction(exec, length, name, proxyCall), + data(new Data()) +{ + data->function = function; +} + +FunctionWrapper::~FunctionWrapper() +{ + delete data; +} + +JSC::ConstructType FunctionWrapper::getConstructData(JSC::ConstructData& consData) +{ + consData.native.function = proxyConstruct; + consData.native.function.doNotCallDebuggerFunctionExit(); + return JSC::ConstructTypeHost; +} + +JSC::JSValue FunctionWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObject *callee, + JSC::JSValue thisObject, const JSC::ArgList &args) +{ + FunctionWrapper *self = static_cast<FunctionWrapper*>(callee); + QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec); + + JSC::ExecState *oldFrame = eng_p->currentFrame; + eng_p->pushContext(exec, thisObject, args, callee); + QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); + + QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p)); + if (!result.isValid()) + result = QScriptValue(QScriptValue::UndefinedValue); + + eng_p->popContext(); + eng_p->currentFrame = oldFrame; + + return eng_p->scriptValueToJSCValue(result); +} + +JSC::JSObject* FunctionWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObject *callee, + const JSC::ArgList &args) +{ + FunctionWrapper *self = static_cast<FunctionWrapper*>(callee); + QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec); + + JSC::ExecState *oldFrame = eng_p->currentFrame; + eng_p->pushContext(exec, JSC::JSValue(), args, callee, true); + QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); + + QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p)); + + if (JSC::Debugger* debugger = eng_p->originalGlobalObject()->debugger()) + debugger->functionExit(QScriptValuePrivate::get(result)->jscValue, -1); + + if (!result.isObject()) + result = ctx->thisObject(); + + eng_p->popContext(); + eng_p->currentFrame = oldFrame; + + return JSC::asObject(eng_p->scriptValueToJSCValue(result)); +} + +FunctionWithArgWrapper::FunctionWithArgWrapper(JSC::ExecState *exec, int length, const JSC::Identifier &name, + QScriptEngine::FunctionWithArgSignature function, void *arg) + : JSC::PrototypeFunction(exec, length, name, proxyCall), + data(new Data()) +{ + data->function = function; + data->arg = arg; +} + +FunctionWithArgWrapper::~FunctionWithArgWrapper() +{ + delete data; +} + +JSC::ConstructType FunctionWithArgWrapper::getConstructData(JSC::ConstructData& consData) +{ + consData.native.function = proxyConstruct; + return JSC::ConstructTypeHost; +} + +JSC::JSValue FunctionWithArgWrapper::proxyCall(JSC::ExecState *exec, JSC::JSObject *callee, + JSC::JSValue thisObject, const JSC::ArgList &args) +{ + FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee); + QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec); + + JSC::ExecState *oldFrame = eng_p->currentFrame; + eng_p->pushContext(exec, thisObject, args, callee); + QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); + + QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p), self->data->arg); + + eng_p->popContext(); + eng_p->currentFrame = oldFrame; + + return eng_p->scriptValueToJSCValue(result); +} + +JSC::JSObject* FunctionWithArgWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObject *callee, + const JSC::ArgList &args) +{ + FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee); + QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec); + + JSC::ExecState *oldFrame = eng_p->currentFrame; + eng_p->pushContext(exec, JSC::JSValue(), args, callee, true); + QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); + + QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p) , self->data->arg); + if (!result.isObject()) + result = ctx->thisObject(); + + eng_p->popContext(); + eng_p->currentFrame = oldFrame; + + return JSC::asObject(eng_p->scriptValueToJSCValue(result)); +} + +} // namespace QScript + +QT_END_NAMESPACE diff --git a/src/script/qscriptmemorypool_p.h b/src/script/bridge/qscriptfunction_p.h index d657ebb..3763645 100644 --- a/src/script/qscriptmemorypool_p.h +++ b/src/script/bridge/qscriptfunction_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QSCRIPTMEMORYPOOL_P_H -#define QSCRIPTMEMORYPOOL_P_H +#ifndef QSCRIPTFUNCTION_P_H +#define QSCRIPTFUNCTIOn_P_H // // W A R N I N G @@ -54,73 +54,80 @@ // #include <QtCore/qglobal.h> -#include <QtCore/qshareddata.h> -#include <string.h> + +#include "qscriptengine.h" + +#include "PrototypeFunction.h" QT_BEGIN_NAMESPACE -namespace QScript { +namespace QScript +{ + +class FunctionWrapper : public JSC::PrototypeFunction // ### subclass InternalFunction instead +{ +public: + // work around CELL_SIZE limitation + struct Data + { + QScriptEngine::FunctionSignature function; + }; + + FunctionWrapper(JSC::ExecState*, int length, const JSC::Identifier&, + QScriptEngine::FunctionSignature); + ~FunctionWrapper(); + + virtual const JSC::ClassInfo* classInfo() const { return &info; } + static const JSC::ClassInfo info; + + QScriptEngine::FunctionSignature function() const + { return data->function; } + +private: + virtual JSC::ConstructType getConstructData(JSC::ConstructData&); + + static JSC::JSValue JSC_HOST_CALL proxyCall(JSC::ExecState *, JSC::JSObject *, + JSC::JSValue, const JSC::ArgList &); + static JSC::JSObject* proxyConstruct(JSC::ExecState *, JSC::JSObject *, + const JSC::ArgList &); + +private: + Data *data; +}; -class MemoryPool : public QSharedData +class FunctionWithArgWrapper : public JSC::PrototypeFunction { public: - enum { maxBlockCount = -1 }; - enum { defaultBlockSize = 1 << 12 }; - - MemoryPool() { - m_blockIndex = maxBlockCount; - m_currentIndex = 0; - m_storage = 0; - m_currentBlock = 0; - m_currentBlockSize = 0; - } - - virtual ~MemoryPool() { - for (int index = 0; index < m_blockIndex + 1; ++index) - qFree(m_storage[index]); - - qFree(m_storage); - } - - char *allocate(int bytes) { - bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment) - if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) { - ++m_blockIndex; - m_currentBlockSize = defaultBlockSize << m_blockIndex; - - m_storage = reinterpret_cast<char**>(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex))); - m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast<char*>(qMalloc(m_currentBlockSize)); - ::memset(m_currentBlock, 0, m_currentBlockSize); - - m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned - Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize); - } - - char *p = reinterpret_cast<char *> - (m_currentBlock + m_currentIndex); - - m_currentIndex += bytes; - - return p; - } - - int bytesAllocated() const { - int bytes = 0; - for (int index = 0; index < m_blockIndex; ++index) - bytes += (defaultBlockSize << index); - bytes += m_currentIndex; - return bytes; - } + // work around CELL_SIZE limitation + struct Data + { + QScriptEngine::FunctionWithArgSignature function; + void *arg; + }; + + FunctionWithArgWrapper(JSC::ExecState*, int length, const JSC::Identifier&, + QScriptEngine::FunctionWithArgSignature, void *); + ~FunctionWithArgWrapper(); + + virtual const JSC::ClassInfo* classInfo() const { return &info; } + static const JSC::ClassInfo info; + + QScriptEngine::FunctionWithArgSignature function() const + { return data->function; } + + void *arg() const + { return data->arg; } private: - int m_blockIndex; - int m_currentIndex; - char *m_currentBlock; - int m_currentBlockSize; - char **m_storage; + virtual JSC::ConstructType getConstructData(JSC::ConstructData&); + + static JSC::JSValue JSC_HOST_CALL proxyCall(JSC::ExecState *, JSC::JSObject *, + JSC::JSValue , const JSC::ArgList &); + static JSC::JSObject* proxyConstruct(JSC::ExecState *, JSC::JSObject *, + const JSC::ArgList &); private: - Q_DISABLE_COPY(MemoryPool) + Data *data; }; } // namespace QScript diff --git a/src/script/bridge/qscriptglobalobject.cpp b/src/script/bridge/qscriptglobalobject.cpp new file mode 100644 index 0000000..eb8673e --- /dev/null +++ b/src/script/bridge/qscriptglobalobject.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptglobalobject_p.h" + +#include "../api/qscriptengine.h" +#include "../api/qscriptengine_p.h" + +QT_BEGIN_NAMESPACE + +namespace JSC +{ + +ASSERT_CLASS_FITS_IN_CELL(QScript::GlobalObject); +ASSERT_CLASS_FITS_IN_CELL(QScript::OriginalGlobalObjectProxy); + +} // namespace JSC + +namespace QScript +{ + +GlobalObject::GlobalObject() + : JSC::JSGlobalObject(), customGlobalObject(0) +{ +} + +GlobalObject::~GlobalObject() +{ +} + +void GlobalObject::mark() +{ + Q_ASSERT(!marked()); + JSC::JSGlobalObject::mark(); + if (customGlobalObject && !customGlobalObject->marked()) + customGlobalObject->mark(); +} + +bool GlobalObject::getOwnPropertySlot(JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::PropertySlot& slot) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + if (propertyName == exec->propertyNames().arguments && engine->currentFrame->argumentCount() > 0) { + JSC::JSValue args = engine->scriptValueToJSCValue(engine->contextForFrame(engine->currentFrame)->argumentsObject()); + slot.setValue(args); + return true; + } + if (customGlobalObject) + return customGlobalObject->getOwnPropertySlot(exec, propertyName, slot); + return JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); +} + +void GlobalObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, + JSC::JSValue value, JSC::PutPropertySlot& slot) +{ + if (customGlobalObject) + customGlobalObject->put(exec, propertyName, value, slot); + else + JSC::JSGlobalObject::put(exec, propertyName, value, slot); +} + +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 +{ + if (customGlobalObject) + return customGlobalObject->getPropertyAttributes(exec, propertyName, attributes); + return JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes); +} + +void GlobalObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, unsigned listedAttributes) +{ + if (customGlobalObject) + customGlobalObject->getPropertyNames(exec, propertyNames, listedAttributes); + else + JSC::JSGlobalObject::getPropertyNames(exec, propertyNames, listedAttributes); +} + +void GlobalObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction) +{ + if (customGlobalObject) + customGlobalObject->defineGetter(exec, propertyName, getterFunction); + else + JSC::JSGlobalObject::defineGetter(exec, propertyName, getterFunction); +} + +void GlobalObject::defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction) +{ + if (customGlobalObject) + customGlobalObject->defineSetter(exec, propertyName, setterFunction); + else + JSC::JSGlobalObject::defineSetter(exec, propertyName, setterFunction); +} + +JSC::JSValue GlobalObject::lookupGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName) +{ + if (customGlobalObject) + return customGlobalObject->lookupGetter(exec, propertyName); + return JSC::JSGlobalObject::lookupGetter(exec, propertyName); +} + +JSC::JSValue GlobalObject::lookupSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName) +{ + if (customGlobalObject) + return customGlobalObject->lookupSetter(exec, propertyName); + return JSC::JSGlobalObject::lookupSetter(exec, propertyName); +} + +} // namespace QScript + +QT_END_NAMESPACE diff --git a/src/script/bridge/qscriptglobalobject_p.h b/src/script/bridge/qscriptglobalobject_p.h new file mode 100644 index 0000000..673f7f6 --- /dev/null +++ b/src/script/bridge/qscriptglobalobject_p.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTGLOBALOBJECT_P_H +#define QSCRIPTGLOBALOBJECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobjectdefs.h> + +#include "JSGlobalObject.h" + +QT_BEGIN_NAMESPACE + +namespace QScript +{ + +class GlobalObject : public JSC::JSGlobalObject +{ +public: + GlobalObject(); + virtual ~GlobalObject(); + virtual JSC::UString className() const { return "global"; } + virtual void mark(); + virtual bool getOwnPropertySlot(JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertySlot&); + 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; + 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 JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName); + virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName); + +public: + JSC::JSObject *customGlobalObject; +}; + +class OriginalGlobalObjectProxy : public JSC::JSObject +{ +public: + explicit OriginalGlobalObjectProxy(WTF::PassRefPtr<JSC::Structure> sid, + JSC::JSGlobalObject *object) + : JSC::JSObject(sid), originalGlobalObject(object) + {} + virtual ~OriginalGlobalObjectProxy() + {} + virtual JSC::UString className() const + { return originalGlobalObject->className(); } + virtual void mark() + { + Q_ASSERT(!marked()); + if (!originalGlobalObject->marked()) + originalGlobalObject->JSC::JSGlobalObject::mark(); + JSC::JSObject::mark(); + } + virtual bool getOwnPropertySlot(JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::PropertySlot& slot) + { return originalGlobalObject->JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); } + 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 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 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 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) + { return originalGlobalObject->JSC::JSGlobalObject::lookupSetter(exec, propertyName); } +private: + JSC::JSGlobalObject *originalGlobalObject; +}; + +} // namespace QScript + +QT_END_NAMESPACE + +#endif diff --git a/src/script/bridge/qscriptobject.cpp b/src/script/bridge/qscriptobject.cpp new file mode 100644 index 0000000..a550d39 --- /dev/null +++ b/src/script/bridge/qscriptobject.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptobject_p.h" +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +namespace JSC +{ +ASSERT_CLASS_FITS_IN_CELL(QScriptObject); +ASSERT_CLASS_FITS_IN_CELL(QScriptObjectPrototype); +} + +// masquerading as JSC::JSObject +const JSC::ClassInfo QScriptObject::info = { "Object", 0, 0, 0 }; + +QScriptObject::Data::~Data() +{ + delete delegate; +} + +QScriptObject::QScriptObject(WTF::PassRefPtr<JSC::Structure> sid) + : JSC::JSObject(sid), d(0) +{ +} + +QScriptObject::~QScriptObject() +{ + delete d; +} + +JSC::JSValue QScriptObject::data() const +{ + if (!d) + return JSC::JSValue(); + return d->data; +} + +void QScriptObject::setData(JSC::JSValue data) +{ + if (!d) + d = new Data(); + d->data = data; +} + +QScriptObjectDelegate *QScriptObject::delegate() const +{ + if (!d) + return 0; + return d->delegate; +} + +void QScriptObject::setDelegate(QScriptObjectDelegate *delegate) +{ + if (!d) + d = new Data(); + d->delegate = delegate; +} + +bool QScriptObject::getOwnPropertySlot(JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::PropertySlot& slot) +{ + if (!d || !d->delegate) + return JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot); + return d->delegate->getOwnPropertySlot(this, exec, propertyName, slot); +} + +void QScriptObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, + JSC::JSValue value, JSC::PutPropertySlot& slot) +{ + if (!d || !d->delegate) { + JSC::JSObject::put(exec, propertyName, value, slot); + return; + } + d->delegate->put(this, exec, propertyName, value, slot); +} + +bool QScriptObject::deleteProperty(JSC::ExecState* exec, + const JSC::Identifier& propertyName, + bool checkDontDelete) +{ + 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); +} + +void QScriptObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, unsigned listedAttributes) +{ + if (!d || !d->delegate) { + JSC::JSObject::getPropertyNames(exec, propertyNames, listedAttributes); + return; + } + d->delegate->getPropertyNames(this, exec, propertyNames, listedAttributes); +} + +void QScriptObject::mark() +{ + 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->delegate) { + JSC::JSObject::mark(); + return; + } + d->delegate->mark(this); +} + +JSC::CallType QScriptObject::getCallData(JSC::CallData &data) +{ + if (!d || !d->delegate) + return JSC::JSObject::getCallData(data); + return d->delegate->getCallData(this, data); +} + +JSC::ConstructType QScriptObject::getConstructData(JSC::ConstructData &data) +{ + if (!d || !d->delegate) + return JSC::JSObject::getConstructData(data); + return d->delegate->getConstructData(this, data); +} + +bool QScriptObject::hasInstance(JSC::ExecState* exec, JSC::JSValue value, JSC::JSValue proto) +{ + if (!d || !d->delegate) + return JSC::JSObject::hasInstance(exec, value, proto); + return d->delegate->hasInstance(this, exec, value, proto); +} + +QScriptObjectPrototype::QScriptObjectPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure> structure, + JSC::Structure* /*prototypeFunctionStructure*/) + : QScriptObject(structure) +{ +} + +QScriptObjectDelegate::QScriptObjectDelegate() +{ +} + +QScriptObjectDelegate::~QScriptObjectDelegate() +{ +} + +bool QScriptObjectDelegate::getOwnPropertySlot(QScriptObject* object, JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::PropertySlot& slot) +{ + return object->JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot); +} + +void QScriptObjectDelegate::put(QScriptObject* object, JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::JSValue value, JSC::PutPropertySlot& slot) +{ + object->JSC::JSObject::put(exec, propertyName, value, slot); +} + +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 +{ + return object->JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); +} + +void QScriptObjectDelegate::getPropertyNames(QScriptObject* object, JSC::ExecState* exec, + JSC::PropertyNameArray& propertyNames, + unsigned listedAttributes) +{ + object->JSC::JSObject::getPropertyNames(exec, propertyNames, listedAttributes); +} + +void QScriptObjectDelegate::mark(QScriptObject* object) +{ + if (!object->marked()) + object->JSC::JSObject::mark(); +} + +JSC::CallType QScriptObjectDelegate::getCallData(QScriptObject* object, JSC::CallData& data) +{ + return object->JSC::JSObject::getCallData(data); +} + +JSC::ConstructType QScriptObjectDelegate::getConstructData(QScriptObject* object, JSC::ConstructData& data) +{ + return object->JSC::JSObject::getConstructData(data); +} + +bool QScriptObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState* exec, + JSC::JSValue value, JSC::JSValue proto) +{ + return object->JSC::JSObject::hasInstance(exec, value, proto); +} + +QT_END_NAMESPACE diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h new file mode 100644 index 0000000..d499c61 --- /dev/null +++ b/src/script/bridge/qscriptobject_p.h @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTOBJECT_P_H +#define QSCRIPTOBJECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobjectdefs.h> + +#include "JSObject.h" + +QT_BEGIN_NAMESPACE + +class QScriptObjectDelegate; + +class QScriptObject : public JSC::JSObject +{ +public: + // work around CELL_SIZE limitation + struct Data + { + JSC::JSValue data; // QScriptValue::data + QScriptObjectDelegate *delegate; + bool isMarking; // recursion guard + + Data() : delegate(0), isMarking(false) {} + ~Data(); + }; + + explicit QScriptObject(WTF::PassRefPtr<JSC::Structure> sid); + virtual ~QScriptObject(); + + virtual bool getOwnPropertySlot(JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertySlot&); + 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; + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = JSC::Structure::Prototype); + virtual void mark(); + virtual JSC::CallType getCallData(JSC::CallData&); + virtual JSC::ConstructType getConstructData(JSC::ConstructData&); + virtual bool hasInstance(JSC::ExecState*, JSC::JSValue value, JSC::JSValue proto); + + virtual const JSC::ClassInfo* classInfo() const { return &info; } + static const JSC::ClassInfo info; + + static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + { + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, JSC::ImplementsHasInstance)); + } + + JSC::JSValue data() const; + void setData(JSC::JSValue data); + + QScriptObjectDelegate *delegate() const; + void setDelegate(QScriptObjectDelegate *delegate); + +protected: + Data *d; +}; + +class QScriptObjectPrototype : public QScriptObject +{ +public: + QScriptObjectPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure>, + JSC::Structure* prototypeFunctionStructure); +}; + +class QScriptObjectDelegate +{ +public: + enum Type { + QtObject, + Variant, + ClassObject + }; + + QScriptObjectDelegate(); + virtual ~QScriptObjectDelegate(); + + virtual Type type() const = 0; + + virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertySlot&); + 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; + virtual void getPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, + unsigned listedAttributes = JSC::Structure::Prototype); + virtual void mark(QScriptObject*); + 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); + +private: + Q_DISABLE_COPY(QScriptObjectDelegate) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp new file mode 100644 index 0000000..b7a0e44 --- /dev/null +++ b/src/script/bridge/qscriptqobject.cpp @@ -0,0 +1,2221 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptqobject_p.h" + +#include <QtCore/qmetaobject.h> +#include <QtCore/qvarlengtharray.h> +#include <QtCore/qdebug.h> +#include <QtScript/qscriptable.h> +#include "../api/qscriptengine_p.h" +#include "../api/qscriptable_p.h" +#include "../api/qscriptcontext_p.h" +#include "qscriptfunction_p.h" + +#include "Error.h" +#include "PrototypeFunction.h" +#include "PropertyNameArray.h" +#include "JSFunction.h" +#include "JSString.h" +#include "JSValue.h" +#include "JSArray.h" +#include "RegExpObject.h" +#include "RegExpConstructor.h" + +QT_BEGIN_NAMESPACE + +namespace JSC +{ +ASSERT_CLASS_FITS_IN_CELL(QScript::QObjectPrototype); +ASSERT_CLASS_FITS_IN_CELL(QScript::QMetaObjectWrapperObject); +ASSERT_CLASS_FITS_IN_CELL(QScript::QMetaObjectPrototype); +ASSERT_CLASS_FITS_IN_CELL(QScript::QtFunction); +ASSERT_CLASS_FITS_IN_CELL(QScript::QtPropertyFunction); +} + +namespace QScript +{ + +struct QObjectConnection +{ + int slotIndex; + JSC::JSValue receiver; + JSC::JSValue slot; + JSC::JSValue senderWrapper; + + QObjectConnection(int i, JSC::JSValue r, JSC::JSValue s, + JSC::JSValue sw) + : slotIndex(i), receiver(r), slot(s), senderWrapper(sw) {} + QObjectConnection() : slotIndex(-1) {} + + bool hasTarget(JSC::JSValue r, JSC::JSValue s) const + { + if ((r && r.isObject()) != (receiver && receiver.isObject())) + return false; + if (((r && r.isObject()) && (receiver && receiver.isObject())) + && (r != receiver)) { + return false; + } + return (s == slot); + } + + void mark() + { + if (senderWrapper && !senderWrapper.marked()) { + // see if the sender should be marked or not + Q_ASSERT(senderWrapper.isObject(&QScriptObject::info)); + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(senderWrapper)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); + QObjectDelegate *inst = static_cast<QObjectDelegate*>(delegate); + if ((inst->ownership() == QScriptEngine::ScriptOwnership) + || ((inst->ownership() == QScriptEngine::AutoOwnership) + && inst->value() && !inst->value()->parent())) { + senderWrapper = JSC::JSValue(); + } else { + senderWrapper.mark(); + } + } + if (receiver && !receiver.marked()) + receiver.mark(); + if (slot && !slot.marked()) + slot.mark(); + } +}; + +class QObjectNotifyCaller : public QObject +{ +public: + void callConnectNotify(const char *signal) + { connectNotify(signal); } + void callDisconnectNotify(const char *signal) + { disconnectNotify(signal); } +}; + +class QObjectConnectionManager: public QObject +{ +public: + QObjectConnectionManager(QScriptEnginePrivate *engine); + ~QObjectConnectionManager(); + + bool addSignalHandler(QObject *sender, int signalIndex, + JSC::JSValue receiver, + JSC::JSValue slot, + JSC::JSValue senderWrapper, + Qt::ConnectionType type); + bool removeSignalHandler(QObject *sender, int signalIndex, + JSC::JSValue receiver, + JSC::JSValue slot); + + static const QMetaObject staticMetaObject; + virtual const QMetaObject *metaObject() const; + virtual void *qt_metacast(const char *); + virtual int qt_metacall(QMetaObject::Call, int, void **argv); + + void execute(int slotIndex, void **argv); + + void mark(); + +private: + QScriptEnginePrivate *engine; + int slotCounter; + QVector<QVector<QObjectConnection> > connections; +}; + +static bool hasMethodAccess(const QMetaMethod &method, int index, const QScriptEngine::QObjectWrapOptions &opt) +{ + return (method.access() != QMetaMethod::Private) + && ((index != 2) || !(opt & QScriptEngine::ExcludeDeleteLater)); +} + +static bool isEnumerableMetaProperty(const QMetaProperty &prop, + const QMetaObject *mo, int index) +{ + return prop.isScriptable() && prop.isValid() + // the following lookup is to ensure that we have the + // "most derived" occurrence of the property with this name + && (mo->indexOfProperty(prop.name()) == index); +} + +static inline QByteArray methodName(const QMetaMethod &method) +{ + QByteArray signature = method.signature(); + return signature.left(signature.indexOf('(')); +} + +static QVariant variantFromValue(QScriptEnginePrivate *eng, + int targetType, const QScriptValue &value) +{ + QVariant v(targetType, (void *)0); + Q_ASSERT(eng); + if (QScriptEnginePrivate::convert(value, targetType, v.data(), eng)) + return v; + if (uint(targetType) == QVariant::LastType) + return value.toVariant(); + if (value.isVariant()) { + v = value.toVariant(); + if (v.canConvert(QVariant::Type(targetType))) { + v.convert(QVariant::Type(targetType)); + return v; + } + QByteArray typeName = v.typeName(); + if (typeName.endsWith('*') + && (QMetaType::type(typeName.left(typeName.size()-1)) == targetType)) { + return QVariant(targetType, *reinterpret_cast<void* *>(v.data())); + } + } + + return QVariant(); +} + +static const bool GeneratePropertyFunctions = true; + +static unsigned flagsForMetaProperty(const QMetaProperty &prop) +{ + return (JSC::DontDelete + | (!prop.isWritable() ? unsigned(JSC::ReadOnly) : unsigned(0)) + | (GeneratePropertyFunctions + ? unsigned(JSC::Getter | JSC::Setter) + : unsigned(0)) + | QObjectMemberAttribute); +} + +static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str) +{ + QByteArray scope; + QByteArray name; + int scopeIdx = str.lastIndexOf("::"); + if (scopeIdx != -1) { + scope = str.left(scopeIdx); + name = str.mid(scopeIdx + 2); + } else { + name = str; + } + for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { + QMetaEnum m = meta->enumerator(i); + if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) + return i; + } + return -1; +} + +static inline QScriptable *scriptableFromQObject(QObject *qobj) +{ + void *ptr = qobj->qt_metacast("QScriptable"); + return reinterpret_cast<QScriptable*>(ptr); +} + +QtFunction::QtFunction(JSC::JSValue object, int initialIndex, bool maybeOverloaded, + JSC::JSGlobalData *data, WTF::PassRefPtr<JSC::Structure> sid, + const JSC::Identifier &ident) + : JSC::InternalFunction(data, sid, ident), + data(new Data(object, initialIndex, maybeOverloaded)) +{ +} + +QtFunction::~QtFunction() +{ + delete data; +} + +JSC::CallType QtFunction::getCallData(JSC::CallData &callData) +{ + callData.native.function = call; + return JSC::CallTypeHost; +} + +void QtFunction::mark() +{ + Q_ASSERT(!marked()); + if (data->object && !data->object.marked()) + data->object.mark(); + JSC::InternalFunction::mark(); +} + +QScriptObject *QtFunction::wrapperObject() const +{ + Q_ASSERT(JSC::asObject(data->object)->inherits(&QScriptObject::info)); + return static_cast<QScriptObject*>(JSC::asObject(data->object)); +} + +QObject *QtFunction::qobject() const +{ + QScriptObject *scriptObject = wrapperObject(); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); + return static_cast<QScript::QObjectDelegate*>(delegate)->value(); +} + +const QMetaObject *QtFunction::metaObject() const +{ + QObject *qobj = qobject(); + if (!qobj) + return 0; + return qobj->metaObject(); +} + +int QtFunction::initialIndex() const +{ + return data->initialIndex; +} + +bool QtFunction::maybeOverloaded() const +{ + return data->maybeOverloaded; +} + +int QtFunction::mostGeneralMethod(QMetaMethod *out) const +{ + const QMetaObject *meta = metaObject(); + if (!meta) + return -1; + int index = initialIndex(); + QMetaMethod method = meta->method(index); + if (maybeOverloaded() && (method.attributes() & QMetaMethod::Cloned)) { + // find the most general method + do { + method = meta->method(--index); + } while (method.attributes() & QMetaMethod::Cloned); + } + if (out) + *out = method; + return index; +} + +QList<int> QScript::QtFunction::overloadedIndexes() const +{ + if (!maybeOverloaded()) + return QList<int>(); + QList<int> result; + QString name = functionName(); + const QMetaObject *meta = metaObject(); + for (int index = mostGeneralMethod() - 1; index >= 0; --index) { + QString otherName = QString::fromLatin1(methodName(meta->method(index))); + if (otherName == name) + 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: + enum Kind { + Invalid, + Variant, + MetaType, + Unresolved, + MetaEnum + }; + + inline QScriptMetaType() + : m_kind(Invalid) { } + + inline Kind kind() const + { return m_kind; } + + int typeId() const; + + inline bool isValid() const + { return (m_kind != Invalid); } + + inline bool isVariant() const + { return (m_kind == Variant); } + + inline bool isMetaType() const + { return (m_kind == MetaType); } + + inline bool isUnresolved() const + { return (m_kind == Unresolved); } + + inline bool isMetaEnum() const + { return (m_kind == MetaEnum); } + + QByteArray name() const; + + inline int enumeratorIndex() const + { Q_ASSERT(isMetaEnum()); return m_typeId; } + + inline bool operator==(const QScriptMetaType &other) const + { + return (m_kind == other.m_kind) && (m_typeId == other.m_typeId); + } + + static inline QScriptMetaType variant() + { return QScriptMetaType(Variant); } + + static inline QScriptMetaType metaType(int typeId, const QByteArray &name) + { return QScriptMetaType(MetaType, typeId, name); } + + static inline QScriptMetaType metaEnum(int enumIndex, const QByteArray &name) + { return QScriptMetaType(MetaEnum, enumIndex, name); } + + static inline QScriptMetaType unresolved(const QByteArray &name) + { return QScriptMetaType(Unresolved, /*typeId=*/0, name); } + +private: + inline QScriptMetaType(Kind kind, int typeId = 0, const QByteArray &name = QByteArray()) + : m_kind(kind), m_typeId(typeId), m_name(name) { } + + Kind m_kind; + int m_typeId; + QByteArray m_name; +}; + +int QScriptMetaType::typeId() const +{ + if (isVariant()) + return QMetaType::type("QVariant"); + return isMetaEnum() ? 2/*int*/ : m_typeId; +} + +QByteArray QScriptMetaType::name() const +{ + if (!m_name.isEmpty()) + return m_name; + else if (m_kind == Variant) + return "QVariant"; + return QMetaType::typeName(typeId()); +} + +class QScriptMetaMethod +{ +public: + inline QScriptMetaMethod() + { } + inline QScriptMetaMethod(const QByteArray &name, const QVector<QScriptMetaType> &types) + : m_name(name), m_types(types), m_firstUnresolvedIndex(-1) + { + QVector<QScriptMetaType>::const_iterator it; + for (it = m_types.constBegin(); it != m_types.constEnd(); ++it) { + if ((*it).kind() == QScriptMetaType::Unresolved) { + m_firstUnresolvedIndex = it - m_types.constBegin(); + break; + } + } + } + inline bool isValid() const + { return !m_types.isEmpty(); } + + QByteArray name() const + { return m_name; } + + inline QScriptMetaType returnType() const + { return m_types.at(0); } + + inline int argumentCount() const + { return m_types.count() - 1; } + + inline QScriptMetaType argumentType(int arg) const + { return m_types.at(arg + 1); } + + inline bool fullyResolved() const + { return m_firstUnresolvedIndex == -1; } + + inline bool hasUnresolvedReturnType() const + { return (m_firstUnresolvedIndex == 0); } + + inline int firstUnresolvedIndex() const + { return m_firstUnresolvedIndex; } + + inline int count() const + { return m_types.count(); } + + inline QScriptMetaType type(int index) const + { return m_types.at(index); } + + inline QVector<QScriptMetaType> types() const + { return m_types; } + +private: + QByteArray m_name; + QVector<QScriptMetaType> m_types; + int m_firstUnresolvedIndex; +}; + +struct QScriptMetaArguments +{ + int matchDistance; + int index; + QScriptMetaMethod method; + QVarLengthArray<QVariant, 9> args; + + inline QScriptMetaArguments(int dist, int idx, const QScriptMetaMethod &mtd, + const QVarLengthArray<QVariant, 9> &as) + : matchDistance(dist), index(idx), method(mtd), args(as) { } + inline QScriptMetaArguments() + : index(-1) { } + + inline bool isValid() const + { return (index != -1); } +}; + +static QMetaMethod metaMethod(const QMetaObject *meta, + QMetaMethod::MethodType type, + int index) +{ + if (type != QMetaMethod::Constructor) + return meta->method(index); + else + return meta->constructor(index); +} + +static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType callType, + QObject *thisQObject, const JSC::ArgList &scriptArgs, + const QMetaObject *meta, int initialIndex, + bool maybeOverloaded) +{ + QByteArray funName; + QScriptMetaMethod chosenMethod; + int chosenIndex = -1; + QVarLengthArray<QVariant, 9> args; + QVector<QScriptMetaArguments> candidates; + QVector<QScriptMetaArguments> unresolved; + QVector<int> tooFewArgs; + QVector<int> conversionFailed; + int index; + 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) + continue; + } + + QVector<QScriptMetaType> types; + // 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)); + } + } else { + if (callType == QMetaMethod::Constructor) + types.append(QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*")); + else if (returnTypeName == "QVariant") + types.append(QScriptMetaType::variant()); + else + types.append(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()); + else + types.append(QScriptMetaType::metaType(atype, argTypeName)); + } + } + + QScriptMetaMethod mtd = QScriptMetaMethod(methodName(method), types); + + if (int(scriptArgs.size()) < mtd.argumentCount()) { + tooFewArgs.append(index); + continue; + } + + if (!mtd.fullyResolved()) { + // remember it so we can give an error message later, if necessary + unresolved.append(QScriptMetaArguments(/*matchDistance=*/INT_MAX, index, + mtd, QVarLengthArray<QVariant, 9>())); + if (mtd.hasUnresolvedReturnType()) + continue; + } + + if (args.count() != mtd.count()) + args.resize(mtd.count()); + + QScriptMetaType retType = mtd.returnType(); + args[0] = QVariant(retType.typeId(), (void *)0); // the result + + // try to convert arguments + bool converted = true; + int matchDistance = 0; + for (int i = 0; converted && i < mtd.argumentCount(); ++i) { + QScriptValue actual; + if (i < (int)scriptArgs.size()) + actual = engine->scriptValueFromJSCValue(scriptArgs.at(i)); + else + actual = QScriptValue::QScriptValue(QScriptValue::UndefinedValue); + 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())); + } else if (argType.isVariant()) { + if (actual.isVariant()) { + v = actual.toVariant(); + } else { + v = actual.toVariant(); + converted = v.isValid() || actual.isUndefined() || actual.isNull(); + } + } else { + tid = argType.typeId(); + v = QVariant(tid, (void *)0); + converted = QScriptEnginePrivate::convert(actual, tid, v.data(), engine); + if (exec->hadException()) + return exec->exception(); + } + + if (!converted) { + if (actual.isVariant()) { + if (tid == -1) + tid = argType.typeId(); + QVariant vv = actual.toVariant(); + if (vv.canConvert(QVariant::Type(tid))) { + v = vv; + converted = v.convert(QVariant::Type(tid)); + if (converted && (vv.userType() != tid)) + matchDistance += 10; + } else { + QByteArray vvTypeName = vv.typeName(); + if (vvTypeName.endsWith('*') + && (vvTypeName.left(vvTypeName.size()-1) == argType.name())) { + v = QVariant(tid, *reinterpret_cast<void* *>(vv.data())); + converted = true; + matchDistance += 10; + } + } + } else if (actual.isNumber() || actual.isString()) { + // see if it's an enum value + QMetaEnum m; + if (argType.isMetaEnum()) { + m = meta->enumerator(argType.enumeratorIndex()); + } else { + int mi = indexOfMetaEnum(meta, argType.name()); + if (mi != -1) + m = meta->enumerator(mi); + } + if (m.isValid()) { + if (actual.isNumber()) { + int ival = actual.toInt32(); + if (m.valueToKey(ival) != 0) { + qVariantSetValue(v, ival); + converted = true; + matchDistance += 10; + } + } else { + QString sval = actual.toString(); + int ival = m.keyToValue(sval.toLatin1()); + if (ival != -1) { + qVariantSetValue(v, ival); + converted = true; + matchDistance += 10; + } + } + } + } + } else { + // determine how well the conversion matched + if (actual.isNumber()) { + switch (tid) { + case QMetaType::Double: + // perfect + break; + case QMetaType::Float: + matchDistance += 1; + break; + case QMetaType::LongLong: + case QMetaType::ULongLong: + matchDistance += 2; + break; + case QMetaType::Long: + case QMetaType::ULong: + matchDistance += 3; + break; + case QMetaType::Int: + case QMetaType::UInt: + matchDistance += 4; + break; + case QMetaType::Short: + case QMetaType::UShort: + matchDistance += 5; + break; + case QMetaType::Char: + case QMetaType::UChar: + matchDistance += 6; + break; + default: + matchDistance += 10; + break; + } + } else if (actual.isString()) { + switch (tid) { + case QMetaType::QString: + // perfect + break; + default: + matchDistance += 10; + break; + } + } else if (actual.isBoolean()) { + switch (tid) { + case QMetaType::Bool: + // perfect + break; + default: + matchDistance += 10; + break; + } + } else if (actual.isDate()) { + switch (tid) { + case QMetaType::QDateTime: + // perfect + break; + case QMetaType::QDate: + matchDistance += 1; + break; + case QMetaType::QTime: + matchDistance += 2; + break; + default: + matchDistance += 10; + break; + } + } else if (actual.isRegExp()) { + switch (tid) { + case QMetaType::QRegExp: + // perfect + break; + default: + matchDistance += 10; + break; + } + } else if (actual.isVariant()) { + if (argType.isVariant() + || (actual.toVariant().userType() == tid)) { + // perfect + } else { + matchDistance += 10; + } + } else if (actual.isArray()) { + switch (tid) { + case QMetaType::QStringList: + case QMetaType::QVariantList: + matchDistance += 5; + break; + default: + matchDistance += 10; + break; + } + } else if (actual.isQObject()) { + switch (tid) { + case QMetaType::QObjectStar: + case QMetaType::QWidgetStar: + // perfect + break; + default: + matchDistance += 10; + break; + } + } else if (actual.isNull()) { + switch (tid) { + case QMetaType::VoidStar: + case QMetaType::QObjectStar: + case QMetaType::QWidgetStar: + // perfect + break; + default: + if (!argType.name().endsWith('*')) + matchDistance += 10; + break; + } + } else { + matchDistance += 10; + } + } + + if (converted) + args[i+1] = v; + } + + if (converted) { + if ((scriptArgs.size() == (size_t)mtd.argumentCount()) + && (matchDistance == 0)) { + // perfect match, use this one + chosenMethod = mtd; + chosenIndex = index; + break; + } else { + bool redundant = false; + if ((callType != QMetaMethod::Constructor) + && (index < meta->methodOffset())) { + // it is possible that a virtual method is redeclared in a subclass, + // in which case we want to ignore the superclass declaration + for (int i = 0; i < candidates.size(); ++i) { + const QScriptMetaArguments &other = candidates.at(i); + if (mtd.types() == other.method.types()) { + redundant = true; + break; + } + } + } + if (!redundant) { + QScriptMetaArguments metaArgs(matchDistance, index, mtd, args); + if (candidates.isEmpty()) { + candidates.append(metaArgs); + } else { + const QScriptMetaArguments &otherArgs = candidates.at(0); + if ((args.count() > otherArgs.args.count()) + || ((args.count() == otherArgs.args.count()) + && (matchDistance <= otherArgs.matchDistance))) { + candidates.prepend(metaArgs); + } else { + candidates.append(metaArgs); + } + } + } + } + } else if (mtd.fullyResolved()) { + conversionFailed.append(index); + } + + if (!maybeOverloaded) + break; + } + + JSC::JSValue result; + if ((chosenIndex == -1) && candidates.isEmpty()) { +// context->calleeMetaIndex = initialIndex; +//#ifndef Q_SCRIPT_NO_EVENT_NOTIFY +// engine->notifyFunctionEntry(context); +//#endif + if (!conversionFailed.isEmpty()) { + QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n") + .arg(QLatin1String(funName)); + for (int i = 0; i < conversionFailed.size(); ++i) { + if (i > 0) + message += QLatin1String("\n"); + QMetaMethod mtd = metaMethod(meta, callType, conversionFailed.at(i)); + message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); + } + result = JSC::throwError(exec, JSC::TypeError, message); + } else if (!unresolved.isEmpty()) { + QScriptMetaArguments argsInstance = unresolved.first(); + int unresolvedIndex = argsInstance.method.firstUnresolvedIndex(); + Q_ASSERT(unresolvedIndex != -1); + QScriptMetaType unresolvedType = argsInstance.method.type(unresolvedIndex); + QString unresolvedTypeName = QString::fromLatin1(unresolvedType.name()); + QString message = QString::fromLatin1("cannot call %0(): ") + .arg(QString::fromLatin1(funName)); + if (unresolvedIndex > 0) { + message.append(QString::fromLatin1("argument %0 has unknown type `%1'"). + arg(unresolvedIndex).arg(unresolvedTypeName)); + } else { + message.append(QString::fromLatin1("unknown return type `%0'") + .arg(unresolvedTypeName)); + } + message.append(QString::fromLatin1(" (register the type with qScriptRegisterMetaType())")); + 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)); + for (int i = 0; i < tooFewArgs.size(); ++i) { + if (i > 0) + message += QLatin1String("\n"); + QMetaMethod mtd = metaMethod(meta, callType, tooFewArgs.at(i)); + message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); + } + result = JSC::throwError(exec, JSC::SyntaxError, message); + } + } else { + if (chosenIndex == -1) { + QScriptMetaArguments metaArgs = candidates.at(0); + if ((candidates.size() > 1) + && (metaArgs.args.count() == candidates.at(1).args.count()) + && (metaArgs.matchDistance == candidates.at(1).matchDistance)) { + // ambiguous call + QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n") + .arg(QLatin1String(funName)); + for (int i = 0; i < candidates.size(); ++i) { + if (i > 0) + message += QLatin1String("\n"); + QMetaMethod mtd = metaMethod(meta, callType, candidates.at(i).index); + message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); + } + result = JSC::throwError(exec, JSC::TypeError, message); + } else { + chosenMethod = metaArgs.method; + chosenIndex = metaArgs.index; + args = metaArgs.args; + } + } + + if (chosenIndex != -1) { + // call it +// context->calleeMetaIndex = chosenIndex; + + QVarLengthArray<void*, 9> array(args.count()); + void **params = array.data(); + for (int i = 0; i < args.count(); ++i) { + const QVariant &v = args[i]; + switch (chosenMethod.type(i).kind()) { + case QScriptMetaType::Variant: + params[i] = const_cast<QVariant*>(&v); + break; + case QScriptMetaType::MetaType: + case QScriptMetaType::MetaEnum: + case QScriptMetaType::Unresolved: + params[i] = const_cast<void*>(v.constData()); + break; + default: + Q_ASSERT(0); + } + } + + QScriptable *scriptable = 0; + if (thisQObject) + scriptable = scriptableFromQObject(thisQObject); + QScriptEngine *oldEngine = 0; + if (scriptable) { + oldEngine = QScriptablePrivate::get(scriptable)->engine; + QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine); + } + +// ### fixme +//#ifndef Q_SCRIPT_NO_EVENT_NOTIFY +// engine->notifyFunctionEntry(context); +//#endif + + if (callType == QMetaMethod::Constructor) { + Q_ASSERT(meta != 0); + meta->static_metacall(QMetaObject::CreateInstance, chosenIndex, params); + } else { + QMetaObject::metacall(thisQObject, QMetaObject::InvokeMetaMethod, chosenIndex, params); + } + + if (scriptable) + QScriptablePrivate::get(scriptable)->engine = oldEngine; + + if (exec->hadException()) { + result = exec->exception() ; // propagate + } else { + QScriptMetaType retType = chosenMethod.returnType(); + if (retType.isVariant()) { + result = engine->jscValueFromVariant(*(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); + } + } else { + result = JSC::jsUndefined(); + } + } + } + } + + return result; +} + +JSC::JSValue QtFunction::execute(JSC::ExecState *exec, JSC::JSValue thisValue, + const JSC::ArgList &scriptArgs) +{ + Q_ASSERT(data->object.isObject(&QScriptObject::info)); + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(data->object)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); + QObject *qobj = static_cast<QScript::QObjectDelegate*>(delegate)->value(); + Q_ASSERT_X(qobj != 0, "QtFunction::call", "handle the case when QObject has been deleted"); + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + + const QMetaObject *meta = qobj->metaObject(); + QObject *thisQObject = 0; + thisValue = engine->toUsableValue(thisValue); + if (thisValue.isObject(&QScriptObject::info)) { + delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate(); + if (delegate && (delegate->type() == QScriptObjectDelegate::QtObject)) + thisQObject = static_cast<QScript::QObjectDelegate*>(delegate)->value(); + } + if (!thisQObject) + thisQObject = qobj; // ### TypeError + + if (!meta->cast(thisQObject)) { + // invoking a function in the prototype + thisQObject = qobj; + } + + return callQtMethod(exec, QMetaMethod::Method, thisQObject, scriptArgs, + meta, data->initialIndex, data->maybeOverloaded); +} + +const JSC::ClassInfo QtFunction::info = { "QtFunction", &InternalFunction::info, 0, 0 }; + +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)) + return throwError(exec, JSC::TypeError, "callee is not a QtFunction object"); + QtFunction *qfun = static_cast<QtFunction*>(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; +} + +const JSC::ClassInfo QtPropertyFunction::info = { "QtPropertyFunction", &InternalFunction::info, 0, 0 }; + +QtPropertyFunction::QtPropertyFunction(const QMetaObject *meta, int index, + JSC::JSGlobalData *data, + WTF::PassRefPtr<JSC::Structure> sid, + const JSC::Identifier &ident) + : JSC::InternalFunction(data, sid, ident), + data(new Data(meta, index)) +{ +} + +QtPropertyFunction::~QtPropertyFunction() +{ + delete data; +} + +JSC::CallType QtPropertyFunction::getCallData(JSC::CallData &callData) +{ + callData.native.function = call; + return JSC::CallTypeHost; +} + +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)) + 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; +} + +JSC::JSValue QtPropertyFunction::execute(JSC::ExecState *exec, + JSC::JSValue thisValue, + const JSC::ArgList &args) +{ + 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(); + while ((!qobject || (qobject->metaObject() != data->meta)) + && object.prototype().isObject()) { + object = object.prototype(); + qobject = object.toQObject(); + } + Q_ASSERT_X(qobject, Q_FUNC_INFO, "this-object must be a QObject"); + + QMetaProperty prop = data->meta->property(data->index); + Q_ASSERT(prop.isScriptable()); + if (args.size() == 0) { + // get + if (prop.isValid()) { + QScriptable *scriptable = scriptableFromQObject(qobject); + QScriptEngine *oldEngine = 0; + if (scriptable) { + oldEngine = QScriptablePrivate::get(scriptable)->engine; + QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine); + } + + QVariant v = prop.read(qobject); + + if (scriptable) + QScriptablePrivate::get(scriptable)->engine = oldEngine; + + result = engine->jscValueFromVariant(v); + } + } else { + // set + JSC::JSValue arg = args.at(0); + QVariant v; + if (prop.isEnumType() && arg.isString() + && !engine->hasDemarshalFunction(prop.userType())) { + // give QMetaProperty::write() a chance to convert from + // 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); + } + + QScriptable *scriptable = scriptableFromQObject(qobject); + QScriptEngine *oldEngine = 0; + if (scriptable) { + oldEngine = QScriptablePrivate::get(scriptable)->engine; + QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine); + } + + prop.write(qobject, v); + + if (scriptable) + QScriptablePrivate::get(scriptable)->engine = oldEngine; + + result = arg; + } + return result; +} + +const QMetaObject *QtPropertyFunction::metaObject() const +{ + return data->meta; +} + +int QtPropertyFunction::propertyIndex() const +{ + return data->index; +} + + +QObjectDelegate::QObjectDelegate( + QObject *object, QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options) + : data(new Data(object, ownership, options)) +{ +} + +QObjectDelegate::~QObjectDelegate() +{ + switch (data->ownership) { + case QScriptEngine::QtOwnership: + break; + case QScriptEngine::ScriptOwnership: + if (data->value) + delete data->value; // ### fixme +// eng->disposeQObject(value); + break; + case QScriptEngine::AutoOwnership: + if (data->value && !data->value->parent()) + delete data->value; // ### fixme +// eng->disposeQObject(value); + break; + } + delete data; +} + +QScriptObjectDelegate::Type QObjectDelegate::type() const +{ + return QtObject; +} + +bool QObjectDelegate::getOwnPropertySlot(QScriptObject *object, JSC::ExecState *exec, + const JSC::Identifier &propertyName, + JSC::PropertySlot &slot) +{ + QByteArray name = QString(propertyName.ustring()).toLatin1(); + QObject *qobject = data->value; + if (!qobject) { + QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject") + .arg(QString::fromLatin1(name)); + slot.setValue(JSC::throwError(exec, JSC::GeneralError, message)); + return true; + } + + const QMetaObject *meta = qobject->metaObject(); + { + QHash<QByteArray, JSC::JSValue>::const_iterator it = data->cachedMembers.constFind(name); + if (it != data->cachedMembers.constEnd()) { + if (GeneratePropertyFunctions && (meta->indexOfProperty(name) != -1)) + slot.setGetterSlot(JSC::asObject(it.value())); + else + slot.setValue(it.value()); + return true; + } + } + + const QScriptEngine::QObjectWrapOptions &opt = data->options; + QScriptEnginePrivate *eng = scriptEngineFromExec(exec); + 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())) { + QtFunction *fun = new (exec)QtFunction( + object, index, /*maybeOverloaded=*/false, + &exec->globalData(), eng->originalGlobalObject()->functionStructure(), + propertyName); + slot.setValue(fun); + data->cachedMembers.insert(name, fun); + return true; + } + } + } + } + + index = meta->indexOfProperty(name); + if (index != -1) { + QMetaProperty prop = meta->property(index); + if (prop.isScriptable()) { + if (!(opt & QScriptEngine::ExcludeSuperClassProperties) + || (index >= meta->propertyOffset())) { + if (GeneratePropertyFunctions) { + QtPropertyFunction *fun = new (exec)QtPropertyFunction( + meta, index, &exec->globalData(), + eng->originalGlobalObject()->functionStructure(), + propertyName); + data->cachedMembers.insert(name, fun); + slot.setGetterSlot(fun); + } else { + JSC::JSValue val; + if (!prop.isValid()) + val = JSC::jsUndefined(); + else + val = eng->jscValueFromVariant(prop.read(qobject)); + slot.setValue(val); + } + return true; + } + } + } + + index = qobject->dynamicPropertyNames().indexOf(name); + if (index != -1) { + JSC::JSValue val = eng->jscValueFromVariant(qobject->property(name)); + slot.setValue(val); + 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)) { + QtFunction *fun = new (exec)QtFunction( + object, index, /*maybeOverloaded=*/true, + &exec->globalData(), eng->originalGlobalObject()->functionStructure(), + propertyName); + slot.setValue(fun); + data->cachedMembers.insert(name, fun); + 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())) { + QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; + QScriptValue tmp = QScriptEnginePrivate::get(eng)->newQObject(child, QScriptEngine::QtOwnership, opt); + slot.setValue(eng->scriptValueToJSCValue(tmp)); + return true; + } + } + } + + return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot); +} + +void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::JSValue value, JSC::PutPropertySlot &slot) +{ + QByteArray name = ((QString)propertyName.ustring()).toLatin1(); + QObject *qobject = data->value; + if (!qobject) { + QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject") + .arg(QString::fromLatin1(name)); + JSC::throwError(exec, JSC::GeneralError, message); + return; + } + + const QScriptEngine::QObjectWrapOptions &opt = data->options; + const QMetaObject *meta = qobject->metaObject(); + QScriptEnginePrivate *eng = scriptEngineFromExec(exec); + 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())) { + data->cachedMembers.insert(name, value); + return; + } + } + } + } + + index = meta->indexOfProperty(name); + if (index != -1) { + QMetaProperty prop = meta->property(index); + if (prop.isScriptable()) { + if (!(opt & QScriptEngine::ExcludeSuperClassProperties) + || (index >= meta->propertyOffset())) { + if (GeneratePropertyFunctions) { + // ### ideally JSC would do this for us already, i.e. find out + // that the property is a setter and call the setter. + // Maybe QtPropertyFunction needs to inherit JSC::GetterSetter. + JSC::JSValue fun; + QHash<QByteArray, JSC::JSValue>::const_iterator it; + it = data->cachedMembers.constFind(name); + if (it != data->cachedMembers.constEnd()) { + fun = it.value(); + } else { + fun = new (exec)QtPropertyFunction( + meta, index, &exec->globalData(), + eng->originalGlobalObject()->functionStructure(), + propertyName); + data->cachedMembers.insert(name, fun); + } + JSC::CallData callData; + JSC::CallType callType = fun.getCallData(callData); + JSC::JSValue argv[1] = { value }; + JSC::ArgList args(argv, 1); + (void)JSC::call(exec, fun, callType, callData, object, args); + } else { + QVariant v; + if (prop.isEnumType() && value.isString() + && !eng->hasDemarshalFunction(prop.userType())) { + // give QMetaProperty::write() a chance to convert from + // string to enum value + v = (QString)value.toString(exec); + } else { + v = eng->jscValueToVariant(value, prop.userType()); + } + (void)prop.write(qobject, v); + } + return; + } + } + } + + 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)) { + data->cachedMembers.insert(name, value); + return; + } + } + + index = qobject->dynamicPropertyNames().indexOf(name); + if ((index != -1) || (opt & QScriptEngine::AutoCreateDynamicProperties)) { + QVariant v = eng->scriptValueFromJSCValue(value).toVariant(); + (void)qobject->setProperty(name, v); + return; + } + + QScriptObjectDelegate::put(object, exec, propertyName, value, slot); +} + +bool QObjectDelegate::deleteProperty(QScriptObject *object, JSC::ExecState *exec, + const JSC::Identifier& propertyName, + bool checkDontDelete) +{ + QByteArray name = ((QString)propertyName.ustring()).toLatin1(); + QObject *qobject = data->value; + if (!qobject) { + QString message = QString::fromLatin1("cannot access member `%0' of deleted QObject") + .arg(QString::fromLatin1(name)); + JSC::throwError(exec, JSC::GeneralError, message); + return false; + } + + const QMetaObject *meta = qobject->metaObject(); + { + QHash<QByteArray, JSC::JSValue>::iterator it = data->cachedMembers.find(name); + if (it != data->cachedMembers.end()) { + if (GeneratePropertyFunctions && (meta->indexOfProperty(name) != -1)) + return false; + data->cachedMembers.erase(it); + return true; + } + } + + const QScriptEngine::QObjectWrapOptions &opt = data->options; + int index = meta->indexOfProperty(name); + if (index != -1) { + QMetaProperty prop = meta->property(index); + if (prop.isScriptable() && + (!(opt & QScriptEngine::ExcludeSuperClassProperties) + || (index >= meta->propertyOffset()))) { + return false; + } + } + + index = qobject->dynamicPropertyNames().indexOf(name); + if (index != -1) { + (void)qobject->setProperty(name, QVariant()); + return true; + } + + return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete); +} + +bool QObjectDelegate::getPropertyAttributes(const QScriptObject *object, + JSC::ExecState *exec, + const JSC::Identifier &propertyName, + unsigned &attributes) const +{ + // ### try to avoid duplicating logic from 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); +} + +void QObjectDelegate::getPropertyNames(QScriptObject *object, JSC::ExecState *exec, + JSC::PropertyNameArray &propertyNames, + unsigned listedAttributes) +{ + QObject *qobject = data->value; + if (!qobject) { + QString message = QString::fromLatin1("cannot get property names of deleted QObject"); + JSC::throwError(exec, JSC::GeneralError, message); + return; + } + + const QScriptEngine::QObjectWrapOptions &opt = data->options; + const QMetaObject *meta = qobject->metaObject(); + { + int i = (opt & QScriptEngine::ExcludeSuperClassProperties) + ? meta->propertyOffset() : 0; + for ( ; i < meta->propertyCount(); ++i) { + QMetaProperty prop = meta->property(i); + if (isEnumerableMetaProperty(prop, meta, i)) { + QString name = QString::fromLatin1(prop.name()); + propertyNames.add(JSC::Identifier(exec, name)); + } + } + } + + { + QList<QByteArray> dpNames = qobject->dynamicPropertyNames(); + for (int i = 0; i < dpNames.size(); ++i) { + QString name = QString::fromLatin1(dpNames.at(i)); + propertyNames.add(JSC::Identifier(exec, name)); + } + } + + if (!(opt & QScriptEngine::SkipMethodsInEnumeration)) { + int i = (opt & QScriptEngine::ExcludeSuperClassMethods) + ? meta->methodOffset() : 0; + for ( ; i < meta->methodCount(); ++i) { + QMetaMethod method = meta->method(i); + if (hasMethodAccess(method, i, opt)) { + QMetaMethod method = meta->method(i); + QString sig = QString::fromLatin1(method.signature()); + propertyNames.add(JSC::Identifier(exec, sig)); + } + } + } + + QScriptObjectDelegate::getPropertyNames(object, exec, propertyNames, listedAttributes); +} + +void QObjectDelegate::mark(QScriptObject *object) +{ + 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(); + } + + QScriptObjectDelegate::mark(object); +} + +static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec, JSC::JSObject*, + JSC::JSValue thisValue, const JSC::ArgList &args) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + thisValue = engine->toUsableValue(thisValue); + if (!thisValue.isObject(&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(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject)) + return throwError(exec, JSC::TypeError, "this object is not a QObject"); + QObject *obj = static_cast<QObjectDelegate*>(delegate)->value(); + QString name; + if (args.size() != 0) + name = args.at(0).toString(exec); + QObject *child = qFindChild<QObject*>(obj, name); + QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; + return engine->newQObject(child, QScriptEngine::QtOwnership, opt); +} + +static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *exec, JSC::JSObject*, + JSC::JSValue thisValue, const JSC::ArgList &args) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + thisValue = engine->toUsableValue(thisValue); + // extract the QObject + if (!thisValue.isObject(&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(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject)) + return throwError(exec, JSC::TypeError, "this object is not a QObject"); + const QObject *const obj = static_cast<QObjectDelegate*>(delegate)->value(); + + // find the children + QList<QObject *> children; + if (args.size() != 0) { + const JSC::JSValue arg = args.at(0); + if (arg.isObject(&JSC::RegExpObject::info)) { + const QObjectList allChildren= obj->children(); + + JSC::RegExpObject *const regexp = JSC::asRegExpObject(arg); + + const int allChildrenCount = allChildren.size(); + for (int i = 0; i < allChildrenCount; ++i) { + QObject *const child = allChildren.at(i); + const JSC::UString childName = child->objectName(); + JSC::RegExpConstructor* regExpConstructor = engine->originalGlobalObject()->regExpConstructor(); + int position; + int length; + regExpConstructor->performMatch(regexp->regExp(), childName, 0, position, length); + if (position >= 0) + children.append(child); + } + } else { + const QString name(args.at(0).toString(exec)); + children = qFindChildren<QObject*>(obj, name); + } + } else { + children = qFindChildren<QObject*>(obj, QString()); + } + // create the result array with the children + const int length = children.size(); + JSC::JSArray *const result = JSC::constructEmptyArray(exec, length); + + QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; + for (int i = 0; i < length; ++i) { + QObject *const child = children.at(i); + result->put(exec, i, engine->newQObject(child, QScriptEngine::QtOwnership, opt)); + } + return JSC::JSValue(result); +} + +static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncToString(JSC::ExecState *exec, JSC::JSObject*, + JSC::JSValue thisValue, const JSC::ArgList&) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + thisValue = engine->toUsableValue(thisValue); + if (!thisValue.isObject(&QScriptObject::info)) + return JSC::jsUndefined(); + QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(thisValue)); + QScriptObjectDelegate *delegate = scriptObject->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::QtObject)) + return JSC::jsUndefined(); + QObject *obj = static_cast<QObjectDelegate*>(delegate)->value(); + const QMetaObject *meta = obj ? obj->metaObject() : &QObject::staticMetaObject; + QString name = obj ? obj->objectName() : QString::fromUtf8("unnamed"); + QString str = QString::fromUtf8("%0(name = \"%1\")") + .arg(QLatin1String(meta->className())).arg(name); + return JSC::jsString(exec, str); +} + +QObjectPrototype::QObjectPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure, + JSC::Structure* prototypeFunctionStructure) + : QScriptObject(structure) +{ + setDelegate(new QObjectDelegate(new QObjectPrototypeObject(), QScriptEngine::AutoOwnership, + QScriptEngine::ExcludeSuperClassMethods + | QScriptEngine::ExcludeSuperClassProperties + | QScriptEngine::ExcludeChildObjects)); + + putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/0, exec->propertyNames().toString, qobjectProtoFuncToString), JSC::DontEnum); + putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChild"), qobjectProtoFuncFindChild), JSC::DontEnum); + putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/1, JSC::Identifier(exec, "findChildren"), qobjectProtoFuncFindChildren), JSC::DontEnum); +} + +const JSC::ClassInfo QMetaObjectWrapperObject::info = { "QMetaObject", 0, 0, 0 }; + +QMetaObjectWrapperObject::QMetaObjectWrapperObject( + JSC::ExecState *exec, const QMetaObject *metaObject, JSC::JSValue ctor, + WTF::PassRefPtr<JSC::Structure> sid) + : JSC::JSObject(sid), + data(new Data(metaObject, ctor)) +{ + if (!ctor) + data->prototype = new (exec)JSC::JSObject(exec->lexicalGlobalObject()->emptyObjectStructure()); +} + +QMetaObjectWrapperObject::~QMetaObjectWrapperObject() +{ + delete data; +} + +bool QMetaObjectWrapperObject::getOwnPropertySlot( + JSC::ExecState *exec, const JSC::Identifier& propertyName, + JSC::PropertySlot &slot) +{ + const QMetaObject *meta = data->value; + if (!meta) + return false; + + if (propertyName == exec->propertyNames().prototype) { + if (data->ctor) + slot.setValue(data->ctor.get(exec, propertyName)); + else + slot.setValue(data->prototype); + 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())) { + slot.setValue(JSC::JSValue(exec, e.value(j))); + return true; + } + } + } + + return JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot); +} + +void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, + JSC::JSValue value, JSC::PutPropertySlot &slot) +{ + if (propertyName == exec->propertyNames().prototype) { + if (data->ctor) + data->ctor.put(exec, propertyName, value, slot); + else + data->prototype = value; + return; + } + 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())) + return; + } + } + } + JSC::JSObject::put(exec, propertyName, value, slot); +} + +bool QMetaObjectWrapperObject::deleteProperty( + JSC::ExecState *exec, const JSC::Identifier& propertyName, + bool checkDontDelete) +{ + if (propertyName == exec->propertyNames().prototype) + return false; + 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())) + return false; + } + } + } + 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); +} + +void QMetaObjectWrapperObject::getPropertyNames(JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, unsigned listedAttributes) +{ + const QMetaObject *meta = data->value; + if (!meta) + return; + for (int i = 0; i < meta->enumeratorCount(); ++i) { + QMetaEnum e = meta->enumerator(i); + for (int j = 0; j < e.keyCount(); ++j) + propertyNames.add(JSC::Identifier(exec, e.key(j))); + } + JSC::JSObject::getPropertyNames(exec, propertyNames, listedAttributes); +} + +void QMetaObjectWrapperObject::mark() +{ + Q_ASSERT(!marked()); + if (data->ctor && !data->ctor.marked()) + data->ctor.mark(); + if (data->prototype && !data->prototype.marked()) + data->prototype.mark(); + JSC::JSObject::mark(); +} + +JSC::CallType QMetaObjectWrapperObject::getCallData(JSC::CallData& callData) +{ + callData.native.function = call; + return JSC::CallTypeHost; +} + +JSC::ConstructType QMetaObjectWrapperObject::getConstructData(JSC::ConstructData& constructData) +{ + constructData.native.function = construct; + return JSC::ConstructTypeHost; +} + +JSC::JSValue JSC_HOST_CALL QMetaObjectWrapperObject::call( + JSC::ExecState *exec, JSC::JSObject *callee, + JSC::JSValue thisValue, const JSC::ArgList &args) +{ + QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); + thisValue = eng_p->toUsableValue(thisValue); + if (!callee->isObject(&QMetaObjectWrapperObject::info)) + return throwError(exec, JSC::TypeError, "callee is not a QMetaObject"); + QMetaObjectWrapperObject *self = static_cast<QMetaObjectWrapperObject*>(callee); + JSC::ExecState *previousFrame = eng_p->currentFrame; + eng_p->pushContext(exec, thisValue, args, callee); + JSC::JSValue result = self->execute(eng_p->currentFrame, args); + eng_p->popContext(); + eng_p->currentFrame = previousFrame; + return result; +} + +JSC::JSObject* QMetaObjectWrapperObject::construct(JSC::ExecState *exec, JSC::JSObject *callee, const JSC::ArgList &args) +{ + QMetaObjectWrapperObject *self = static_cast<QMetaObjectWrapperObject*>(callee); + QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); + JSC::ExecState *previousFrame = eng_p->currentFrame; + eng_p->pushContext(exec, JSC::JSValue(), args, callee, true); + JSC::JSValue result = self->execute(eng_p->currentFrame, args); + eng_p->popContext(); + eng_p->currentFrame = previousFrame; + if (!result || !result.isObject()) + return 0; + return JSC::asObject(result); +} + +JSC::JSValue QMetaObjectWrapperObject::execute(JSC::ExecState *exec, + const JSC::ArgList &args) +{ + if (data->ctor) { + QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec); + QScriptContext *ctx = eng_p->contextForFrame(exec); + JSC::CallData callData; + JSC::CallType callType = data->ctor.getCallData(callData); + Q_ASSERT_X(callType == JSC::CallTypeHost, Q_FUNC_INFO, "script constructors not supported"); + if (data->ctor.isObject(&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)); + FunctionWrapper *wrapper = static_cast<FunctionWrapper*>(JSC::asObject(data->ctor)); + QScriptValue result = wrapper->function()(ctx, QScriptEnginePrivate::get(eng_p)); + return eng_p->scriptValueToJSCValue(result); + } + } else { + const QMetaObject *meta = data->value; + if (meta->constructorCount() > 0) { + 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)); + QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(result)); + QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(object->delegate()); + delegate->setOwnership(QScriptEngine::AutoOwnership); + if (data->prototype) + object->setPrototype(data->prototype); + } + return result; + } else { + QString message = QString::fromLatin1("no constructor for %0") + .arg(QLatin1String(meta->className())); + return JSC::throwError(exec, JSC::TypeError, message); + } + } +} + +struct StaticQtMetaObject : public QObject +{ + static const QMetaObject *get() + { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; } +}; + +static JSC::JSValue JSC_HOST_CALL qmetaobjectProtoFuncClassName( + JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisValue, const JSC::ArgList&) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + thisValue = engine->toUsableValue(thisValue); + if (!thisValue.isObject(&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()); +} + +QMetaObjectPrototype::QMetaObjectPrototype( + JSC::ExecState *exec, WTF::PassRefPtr<JSC::Structure> structure, + JSC::Structure* prototypeFunctionStructure) + : QMetaObjectWrapperObject(exec, StaticQtMetaObject::get(), /*ctor=*/JSC::JSValue(), structure) +{ + putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, /*length=*/0, JSC::Identifier(exec, "className"), qmetaobjectProtoFuncClassName), JSC::DontEnum); +} + +static const uint qt_meta_data_QObjectConnectionManager[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 1, 10, // methods + 0, 0, // properties + 0, 0, // enums/sets + + // slots: signature, parameters, type, tag, flags + 35, 34, 34, 34, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_QObjectConnectionManager[] = { + "QScript::QObjectConnectionManager\0\0execute()\0" +}; + +const QMetaObject QObjectConnectionManager::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_QObjectConnectionManager, + qt_meta_data_QObjectConnectionManager, 0 } +}; + +const QMetaObject *QObjectConnectionManager::metaObject() const +{ + return &staticMetaObject; +} + +void *QObjectConnectionManager::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_QObjectConnectionManager)) + return static_cast<void*>(const_cast<QObjectConnectionManager*>(this)); + return QObject::qt_metacast(_clname); +} + +int QObjectConnectionManager::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + execute(_id, _a); + _id -= slotCounter; + } + return _id; +} + +void QObjectConnectionManager::execute(int slotIndex, void **argv) +{ + JSC::JSValue receiver; + JSC::JSValue slot; + JSC::JSValue senderWrapper; + int signalIndex = -1; + for (int i = 0; i < connections.size(); ++i) { + const QVector<QObjectConnection> &cs = connections.at(i); + for (int j = 0; j < cs.size(); ++j) { + const QObjectConnection &c = cs.at(j); + if (c.slotIndex == slotIndex) { + receiver = c.receiver; + slot = c.slot; + senderWrapper = c.senderWrapper; + signalIndex = i; + break; + } + } + } + Q_ASSERT(slot && slot.isObject()); + + if (engine->isCollecting()) { + qWarning("QtScript: can't execute signal handler during GC"); + // we can't do a script function call during GC, + // so we're forced to ignore this signal + return; + } + +#if 0 + QScriptFunction *fun = engine->convertToNativeFunction(slot); + if (fun == 0) { + // the signal handler has been GC'ed. This can only happen when + // a QObject is owned by the engine, the engine is destroyed, and + // there is a script function connected to the destroyed() signal + Q_ASSERT(signalIndex <= 1); // destroyed(QObject*) + return; + } +#endif + + const QMetaObject *meta = sender()->metaObject(); + const QMetaMethod method = meta->method(signalIndex); + + QList<QByteArray> parameterTypes = method.parameterTypes(); + int argc = parameterTypes.count(); + + JSC::ExecState *exec = engine->currentFrame; + QVector<JSC::JSValue> argsVector; + argsVector.resize(argc); + for (int i = 0; i < argc; ++i) { + // ### optimize -- no need to convert via QScriptValue + QScriptValue 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); + } + } else { + actual = engine->create(argType, arg); + } + argsVector[i] = engine->scriptValueToJSCValue(actual); + } + JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); + + JSC::JSValue senderObject; + if (senderWrapper && senderWrapper.isObject(&QScriptObject::info)) // ### check if it's actually a QObject wrapper + senderObject = senderWrapper; + else { + QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; + senderObject = engine->newQObject(sender(), QScriptEngine::QtOwnership, opt); + } + + JSC::JSValue thisObject; + if (receiver && receiver.isObject()) + thisObject = receiver; + else + thisObject = engine->globalObject(); + + JSC::CallData callData; + JSC::CallType callType = slot.getCallData(callData); + if (exec->hadException()) + exec->clearException(); // ### otherwise JSC asserts + JSC::call(exec, slot, callType, callData, thisObject, jscArgs); + + if (exec->hadException()) { + engine->emitSignalHandlerException(); + } +} + +QObjectConnectionManager::QObjectConnectionManager(QScriptEnginePrivate *eng) + : engine(eng), slotCounter(0) +{ +} + +QObjectConnectionManager::~QObjectConnectionManager() +{ +} + +void QObjectConnectionManager::mark() +{ + for (int i = 0; i < connections.size(); ++i) { + QVector<QObjectConnection> &cs = connections[i]; + for (int j = 0; j < cs.size(); ++j) + cs[j].mark(); + } +} + +bool QObjectConnectionManager::addSignalHandler( + QObject *sender, int signalIndex, JSC::JSValue receiver, + JSC::JSValue function, JSC::JSValue senderWrapper, + Qt::ConnectionType type) +{ + if (connections.size() <= signalIndex) + connections.resize(signalIndex+1); + QVector<QObjectConnection> &cs = connections[signalIndex]; + int absSlotIndex = slotCounter + metaObject()->methodOffset(); + bool ok = QMetaObject::connect(sender, signalIndex, this, absSlotIndex, type); + if (ok) { + cs.append(QObjectConnection(slotCounter++, receiver, function, senderWrapper)); + QMetaMethod signal = sender->metaObject()->method(signalIndex); + QByteArray signalString; + signalString.append('2'); // signal code + signalString.append(signal.signature()); + static_cast<QObjectNotifyCaller*>(sender)->callConnectNotify(signalString); + } + return ok; +} + +bool QObjectConnectionManager::removeSignalHandler( + QObject *sender, int signalIndex, + JSC::JSValue receiver, JSC::JSValue slot) +{ + if (connections.size() <= signalIndex) + return false; + QVector<QObjectConnection> &cs = connections[signalIndex]; + for (int i = 0; i < cs.size(); ++i) { + const QObjectConnection &c = cs.at(i); + if (c.hasTarget(receiver, slot)) { + int absSlotIndex = c.slotIndex + metaObject()->methodOffset(); + bool ok = QMetaObject::disconnect(sender, signalIndex, this, absSlotIndex); + if (ok) { + cs.remove(i); + QMetaMethod signal = sender->metaObject()->method(signalIndex); + QByteArray signalString; + signalString.append('2'); // signal code + signalString.append(signal.signature()); + static_cast<QScript::QObjectNotifyCaller*>(sender)->callDisconnectNotify(signalString); + } + return ok; + } + } + return false; +} + +QObjectData::QObjectData(QScriptEnginePrivate *eng) + : engine(eng), connectionManager(0) +{ +} + +QObjectData::~QObjectData() +{ + if (connectionManager) { + delete connectionManager; + connectionManager = 0; + } +} + +void QObjectData::mark() +{ + if (connectionManager) + connectionManager->mark(); + { + 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); + } + } + } +} + +bool QObjectData::addSignalHandler(QObject *sender, + int signalIndex, + JSC::JSValue receiver, + JSC::JSValue slot, + JSC::JSValue senderWrapper, + Qt::ConnectionType type) +{ + if (!connectionManager) + connectionManager = new QObjectConnectionManager(engine); + return connectionManager->addSignalHandler( + sender, signalIndex, receiver, slot, senderWrapper, type); +} + +bool QObjectData::removeSignalHandler(QObject *sender, + int signalIndex, + JSC::JSValue receiver, + JSC::JSValue slot) +{ + if (!connectionManager) + return false; + return connectionManager->removeSignalHandler( + sender, signalIndex, receiver, slot); +} + +QScriptObject *QObjectData::findWrapper(QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options) const +{ + for (int i = 0; i < wrappers.size(); ++i) { + const QObjectWrapperInfo &info = wrappers.at(i); + if ((info.ownership == ownership) && (info.options == options)) + return info.object; + } + return 0; +} + +void QObjectData::registerWrapper(QScriptObject *wrapper, + QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options) +{ + wrappers.append(QObjectWrapperInfo(wrapper, ownership, options)); +} + +} // namespace QScript + +namespace JSC +{ + ASSERT_CLASS_FITS_IN_CELL(QScript::QtFunction); +} + +QT_END_NAMESPACE + +#include "moc_qscriptqobject_p.cpp" + diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h new file mode 100644 index 0000000..64853ff --- /dev/null +++ b/src/script/bridge/qscriptqobject_p.h @@ -0,0 +1,337 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTQOBJECT_P_H +#define QSCRIPTQOBJECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qscriptobject_p.h" + +#include "qscriptengine.h" +#include <QtCore/qpointer.h> + +#include "InternalFunction.h" + +QT_BEGIN_NAMESPACE + +namespace QScript +{ + +enum AttributeExtension { + // ### Make sure there's no conflict with JSC::Attribute + QObjectMemberAttribute = 1 << 12 +}; + +class QObjectDelegate : public QScriptObjectDelegate +{ +public: + struct Data + { + QPointer<QObject> value; + QScriptEngine::ValueOwnership ownership; + QScriptEngine::QObjectWrapOptions options; + + QHash<QByteArray, JSC::JSValue> cachedMembers; + + Data(QObject *o, QScriptEngine::ValueOwnership own, + QScriptEngine::QObjectWrapOptions opt) + : value(o), ownership(own), options(opt) {} + }; + + QObjectDelegate( + QObject *object, QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options); + ~QObjectDelegate(); + + virtual Type type() const; + + virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertySlot&); + 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; + virtual void getPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, + unsigned listedAttributes = JSC::Structure::Prototype); + virtual void mark(QScriptObject*); + + inline QObject *value() const { return data->value; } + inline void setValue(QObject* value) { data->value = value; } + + inline QScriptEngine::ValueOwnership ownership() const + { return data->ownership; } + inline void setOwnership(QScriptEngine::ValueOwnership ownership) + { data->ownership = ownership; } + + inline QScriptEngine::QObjectWrapOptions options() const + { return data->options; } + inline void setOptions(QScriptEngine::QObjectWrapOptions options) + { data->options = options; } + +protected: + Data *data; +}; + +class QObjectPrototypeObject : public QObject +{ + Q_OBJECT +public: + QObjectPrototypeObject(QObject *parent = 0) + : QObject(parent) { } + ~QObjectPrototypeObject() { } +}; + +class QObjectPrototype : public QScriptObject +{ +public: + QObjectPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure>, + JSC::Structure* prototypeFunctionStructure); +}; + +class QObjectConnectionManager; + +struct QObjectWrapperInfo +{ + QObjectWrapperInfo(QScriptObject *obj, + QScriptEngine::ValueOwnership own, + const QScriptEngine::QObjectWrapOptions &opt) + : object(obj), ownership(own), options(opt) {} + + QScriptObject *object; + QScriptEngine::ValueOwnership ownership; + QScriptEngine::QObjectWrapOptions options; +}; + +class QObjectData // : public QObjectUserData +{ +public: + QObjectData(QScriptEnginePrivate *engine); + ~QObjectData(); + + bool addSignalHandler(QObject *sender, + int signalIndex, + JSC::JSValue receiver, + JSC::JSValue slot, + JSC::JSValue senderWrapper, + Qt::ConnectionType type); + bool removeSignalHandler(QObject *sender, + int signalIndex, + JSC::JSValue receiver, + JSC::JSValue slot); + + QScriptObject *findWrapper(QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options) const; + void registerWrapper(QScriptObject *wrapper, + QScriptEngine::ValueOwnership ownership, + const QScriptEngine::QObjectWrapOptions &options); + + void mark(); + +private: + QScriptEnginePrivate *engine; + QScript::QObjectConnectionManager *connectionManager; + QList<QScript::QObjectWrapperInfo> wrappers; +}; + +class QtFunction: public JSC::InternalFunction +{ +public: + // work around CELL_SIZE limitation + struct Data + { + JSC::JSValue object; + int initialIndex; + bool maybeOverloaded; + + Data(JSC::JSValue o, int ii, bool mo) + : object(o), initialIndex(ii), maybeOverloaded(mo) {} + }; + + QtFunction(JSC::JSValue object, int initialIndex, bool maybeOverloaded, + JSC::JSGlobalData*, WTF::PassRefPtr<JSC::Structure>, const JSC::Identifier&); + virtual ~QtFunction(); + + virtual JSC::CallType getCallData(JSC::CallData&); + virtual void mark(); + + virtual const JSC::ClassInfo* classInfo() const { return &info; } + static const JSC::ClassInfo info; + + static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*, + JSC::JSValue, const JSC::ArgList&); + + JSC::JSValue execute(JSC::ExecState *exec, JSC::JSValue thisValue, + const JSC::ArgList &args); + + QScriptObject *wrapperObject() const; + QObject *qobject() const; + const QMetaObject *metaObject() const; + int initialIndex() const; + bool maybeOverloaded() const; + int mostGeneralMethod(QMetaMethod *out = 0) const; + QList<int> overloadedIndexes() const; + QString functionName() const; + +private: + Data *data; +}; + +class QtPropertyFunction: public JSC::InternalFunction +{ +public: + // work around CELL_SIZE limitation + struct Data + { + const QMetaObject *meta; + int index; + + Data(const QMetaObject *m, int i) + : meta(m), index(i) {} + }; + + QtPropertyFunction(const QMetaObject *meta, int index, + JSC::JSGlobalData*, WTF::PassRefPtr<JSC::Structure>, + const JSC::Identifier&); + virtual ~QtPropertyFunction(); + + virtual JSC::CallType getCallData(JSC::CallData&); + + virtual const JSC::ClassInfo* classInfo() const { return &info; } + static const JSC::ClassInfo info; + + static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*, + JSC::JSValue, const JSC::ArgList&); + + JSC::JSValue execute(JSC::ExecState *exec, JSC::JSValue thisValue, + const JSC::ArgList &args); + + const QMetaObject *metaObject() const; + int propertyIndex() const; + +private: + Data *data; +}; + +class QMetaObjectWrapperObject : public JSC::JSObject +{ +public: + // work around CELL_SIZE limitation + struct Data + { + const QMetaObject *value; + JSC::JSValue ctor; + JSC::JSValue prototype; + + Data(const QMetaObject *mo, JSC::JSValue c) + : value(mo), ctor(c) {} + }; + + explicit QMetaObjectWrapperObject( + JSC::ExecState *, const QMetaObject *metaobject, JSC::JSValue ctor, + WTF::PassRefPtr<JSC::Structure> sid); + ~QMetaObjectWrapperObject(); + + virtual bool getOwnPropertySlot(JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertySlot&); + 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; + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, + unsigned listedAttributes = JSC::Structure::Prototype); + virtual void mark(); + + virtual JSC::CallType getCallData(JSC::CallData&); + virtual JSC::ConstructType getConstructData(JSC::ConstructData&); + + virtual const JSC::ClassInfo* classInfo() const { return &info; } + static const JSC::ClassInfo info; + + static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*, + JSC::JSValue, const JSC::ArgList&); + static JSC::JSObject* construct(JSC::ExecState *, JSC::JSObject *, const JSC::ArgList &); + + JSC::JSValue execute(JSC::ExecState *exec, const JSC::ArgList &args); + + inline const QMetaObject *value() const { return data->value; } + inline void setValue(const QMetaObject* value) { data->value = value; } + + static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + { + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); + } + +protected: + Data *data; +}; + +class QMetaObjectPrototype : public QMetaObjectWrapperObject +{ +public: + QMetaObjectPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure>, + JSC::Structure* prototypeFunctionStructure); +}; + +} // namespace QScript + +QT_END_NAMESPACE + +#endif diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp new file mode 100644 index 0000000..ee59e4f --- /dev/null +++ b/src/script/bridge/qscriptvariant.cpp @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptvariant_p.h" + +#include "../api/qscriptengine.h" +#include "../api/qscriptengine_p.h" + +#include "Error.h" +#include "PrototypeFunction.h" +#include "JSString.h" + +QT_BEGIN_NAMESPACE + +namespace JSC +{ +ASSERT_CLASS_FITS_IN_CELL(QScript::QVariantPrototype); +} + +namespace QScript +{ + +QVariantDelegate::QVariantDelegate(const QVariant &value) + : m_value(value) +{ +} + +QVariantDelegate::~QVariantDelegate() +{ +} + +QVariant &QVariantDelegate::value() +{ + return m_value; +} + +void QVariantDelegate::setValue(const QVariant &value) +{ + m_value = value; +} + +QScriptObjectDelegate::Type QVariantDelegate::type() const +{ + return Variant; +} + +static JSC::JSValue JSC_HOST_CALL variantProtoFuncValueOf(JSC::ExecState *exec, JSC::JSObject*, + JSC::JSValue thisValue, const JSC::ArgList&) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + thisValue = engine->toUsableValue(thisValue); + if (!thisValue.isObject(&QScriptObject::info)) + return throwError(exec, JSC::TypeError); + QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(thisValue))->delegate(); + if (!delegate || (delegate->type() != QScriptObjectDelegate::Variant)) + return throwError(exec, JSC::TypeError); + const QVariant &v = static_cast<QVariantDelegate*>(delegate)->value(); + switch (v.type()) { + case QVariant::Invalid: + return JSC::jsUndefined(); + case QVariant::String: + return JSC::jsString(exec, v.toString()); + + case QVariant::Int: + return JSC::jsNumber(exec, v.toInt()); + + case QVariant::Bool: + return JSC::jsBoolean(v.toBool()); + + case QVariant::Double: + return JSC::jsNumber(exec, v.toDouble()); + +// case QVariant::Char: +// return JSC::jsNumber(exec, v.toChar().unicode()); + + case QVariant::UInt: + return JSC::jsNumber(exec, v.toUInt()); + + default: + ; + } + return thisValue; +} + +static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, JSC::JSObject *callee, + JSC::JSValue thisValue, const JSC::ArgList &args) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + thisValue = engine->toUsableValue(thisValue); + if (!thisValue.isObject(&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)) + return throwError(exec, JSC::TypeError, "This object is not a QVariant"); + const QVariant &v = static_cast<QVariantDelegate*>(delegate)->value(); + JSC::UString result; + JSC::JSValue value = variantProtoFuncValueOf(exec, callee, thisValue, args); + if (value.isObject()) { + result = v.toString(); + if (result.isEmpty()) { + result = "QVariant("; + result += v.typeName(); + result += ")"; + } + } else { + result = value.toString(exec); + } + return JSC::jsString(exec, result); +} + +QVariantPrototype::QVariantPrototype(JSC::ExecState* exec, WTF::PassRefPtr<JSC::Structure> structure, + JSC::Structure* prototypeFunctionStructure) + : QScriptObject(structure) +{ + setDelegate(new QVariantDelegate(QVariant())); + + putDirectFunction(exec, new (exec) JSC::PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, variantProtoFuncToString), JSC::DontEnum); + 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/qscriptrepository_p.h b/src/script/bridge/qscriptvariant_p.h index 3c2f63e..4a97ba3 100644 --- a/src/script/qscriptrepository_p.h +++ b/src/script/bridge/qscriptvariant_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QSCRIPTREPOSITORY_P_H -#define QSCRIPTREPOSITORY_P_H +#ifndef QSCRIPTVARIANT_P_H +#define QSCRIPTVARIANT_P_H // // W A R N I N G @@ -53,35 +53,35 @@ // We mean it. // -#include "qscriptbuffer_p.h" +#include <QtCore/qvariant.h> + +#include "qscriptobject_p.h" QT_BEGIN_NAMESPACE -namespace QScript { +namespace QScript +{ -template <typename Tp, typename Factory> -class Repository +class QVariantDelegate : public QScriptObjectDelegate { public: - inline Repository() { cache.reserve(32); } - inline ~Repository() { qDeleteAll(cache); } + QVariantDelegate(const QVariant &value); + ~QVariantDelegate(); - inline Tp *get() - { - if (cache.isEmpty()) - return Factory::create(); + QVariant &value(); + void setValue(const QVariant &value); - return cache.takeLast(); - } - - inline void release(Tp *item) - { cache.append(item); } + Type type() const; private: - Buffer<Tp*> cache; + QVariant m_value; +}; -private: - Q_DISABLE_COPY(Repository) +class QVariantPrototype : public QScriptObject +{ +public: + QVariantPrototype(JSC::ExecState*, WTF::PassRefPtr<JSC::Structure>, + JSC::Structure* prototypeFunctionStructure); }; } // namespace QScript diff --git a/src/script/instruction.table b/src/script/instruction.table deleted file mode 100644 index 389db18..0000000 --- a/src/script/instruction.table +++ /dev/null @@ -1,87 +0,0 @@ -Q_SCRIPT_DEFINE_OPERATOR(Add) -Q_SCRIPT_DEFINE_OPERATOR(Assign) -Q_SCRIPT_DEFINE_OPERATOR(BitAnd) -Q_SCRIPT_DEFINE_OPERATOR(BitOr) -Q_SCRIPT_DEFINE_OPERATOR(BitXor) -Q_SCRIPT_DEFINE_OPERATOR(BitNot) -Q_SCRIPT_DEFINE_OPERATOR(Branch) -Q_SCRIPT_DEFINE_OPERATOR(BranchTrue) -Q_SCRIPT_DEFINE_OPERATOR(BranchFalse) -Q_SCRIPT_DEFINE_OPERATOR(Call) -Q_SCRIPT_DEFINE_OPERATOR(DeclareLocal) -Q_SCRIPT_DEFINE_OPERATOR(Decr) -Q_SCRIPT_DEFINE_OPERATOR(Delete) -Q_SCRIPT_DEFINE_OPERATOR(Div) -Q_SCRIPT_DEFINE_OPERATOR(Duplicate) -Q_SCRIPT_DEFINE_OPERATOR(EnterWith) -Q_SCRIPT_DEFINE_OPERATOR(Equal) -Q_SCRIPT_DEFINE_OPERATOR(Fetch) -Q_SCRIPT_DEFINE_OPERATOR(FetchField) -Q_SCRIPT_DEFINE_OPERATOR(LazyArguments) -Q_SCRIPT_DEFINE_OPERATOR(GreatOrEqual) -Q_SCRIPT_DEFINE_OPERATOR(GreatThan) -Q_SCRIPT_DEFINE_OPERATOR(HasNextElement) -Q_SCRIPT_DEFINE_OPERATOR(In) -Q_SCRIPT_DEFINE_OPERATOR(Incr) -Q_SCRIPT_DEFINE_OPERATOR(InplaceAdd) -Q_SCRIPT_DEFINE_OPERATOR(InplaceAnd) -Q_SCRIPT_DEFINE_OPERATOR(InplaceDiv) -Q_SCRIPT_DEFINE_OPERATOR(InplaceLeftShift) -Q_SCRIPT_DEFINE_OPERATOR(InplaceMod) -Q_SCRIPT_DEFINE_OPERATOR(InplaceMul) -Q_SCRIPT_DEFINE_OPERATOR(InplaceOr) -Q_SCRIPT_DEFINE_OPERATOR(InplaceRightShift) -Q_SCRIPT_DEFINE_OPERATOR(InplaceSub) -Q_SCRIPT_DEFINE_OPERATOR(InplaceURightShift) -Q_SCRIPT_DEFINE_OPERATOR(InstanceOf) -Q_SCRIPT_DEFINE_OPERATOR(LeaveWith) -Q_SCRIPT_DEFINE_OPERATOR(LeftShift) -Q_SCRIPT_DEFINE_OPERATOR(LessOrEqual) -Q_SCRIPT_DEFINE_OPERATOR(LessThan) -Q_SCRIPT_DEFINE_OPERATOR(LoadFalse) -Q_SCRIPT_DEFINE_OPERATOR(LoadString) -Q_SCRIPT_DEFINE_OPERATOR(LoadNumber) -Q_SCRIPT_DEFINE_OPERATOR(LoadThis) -Q_SCRIPT_DEFINE_OPERATOR(LoadActivation) -Q_SCRIPT_DEFINE_OPERATOR(LoadNull) -Q_SCRIPT_DEFINE_OPERATOR(LoadTrue) -Q_SCRIPT_DEFINE_OPERATOR(LoadUndefined) -Q_SCRIPT_DEFINE_OPERATOR(Mod) -Q_SCRIPT_DEFINE_OPERATOR(Mul) -Q_SCRIPT_DEFINE_OPERATOR(New) -Q_SCRIPT_DEFINE_OPERATOR(NewArray) -Q_SCRIPT_DEFINE_OPERATOR(NewClosure) -Q_SCRIPT_DEFINE_OPERATOR(NewEnumeration) -Q_SCRIPT_DEFINE_OPERATOR(NewObject) -Q_SCRIPT_DEFINE_OPERATOR(NewRegExp) -Q_SCRIPT_DEFINE_OPERATOR(NextElement) -Q_SCRIPT_DEFINE_OPERATOR(Nop) -Q_SCRIPT_DEFINE_OPERATOR(Not) -Q_SCRIPT_DEFINE_OPERATOR(NotEqual) -Q_SCRIPT_DEFINE_OPERATOR(Pop) -Q_SCRIPT_DEFINE_OPERATOR(PostDecr) -Q_SCRIPT_DEFINE_OPERATOR(PostIncr) -Q_SCRIPT_DEFINE_OPERATOR(PutField) -Q_SCRIPT_DEFINE_OPERATOR(Receive) -Q_SCRIPT_DEFINE_OPERATOR(Resolve) -Q_SCRIPT_DEFINE_OPERATOR(Ret) -Q_SCRIPT_DEFINE_OPERATOR(RightShift) -Q_SCRIPT_DEFINE_OPERATOR(StrictEqual) -Q_SCRIPT_DEFINE_OPERATOR(StrictNotEqual) -Q_SCRIPT_DEFINE_OPERATOR(Sub) -Q_SCRIPT_DEFINE_OPERATOR(Swap) -Q_SCRIPT_DEFINE_OPERATOR(ToFirstElement) -Q_SCRIPT_DEFINE_OPERATOR(Throw) -Q_SCRIPT_DEFINE_OPERATOR(TypeOf) -Q_SCRIPT_DEFINE_OPERATOR(UnaryMinus) -Q_SCRIPT_DEFINE_OPERATOR(UnaryPlus) -Q_SCRIPT_DEFINE_OPERATOR(URightShift) -Q_SCRIPT_DEFINE_OPERATOR(InplaceXor) -Q_SCRIPT_DEFINE_OPERATOR(Line) -Q_SCRIPT_DEFINE_OPERATOR(Sync) -Q_SCRIPT_DEFINE_OPERATOR(Halt) -Q_SCRIPT_DEFINE_OPERATOR(BeginCatch) -Q_SCRIPT_DEFINE_OPERATOR(EndCatch) -Q_SCRIPT_DEFINE_OPERATOR(MakeReference) -Q_SCRIPT_DEFINE_OPERATOR(NewString) -Q_SCRIPT_DEFINE_OPERATOR(Debugger) diff --git a/src/script/parser/parser.pri b/src/script/parser/parser.pri new file mode 100644 index 0000000..4839ed2 --- /dev/null +++ b/src/script/parser/parser.pri @@ -0,0 +1,19 @@ +SOURCES += \ + $$PWD/qscriptast.cpp \ + $$PWD/qscriptastvisitor.cpp \ + $$PWD/qscriptgrammar.cpp \ + $$PWD/qscriptsyntaxchecker.cpp \ + $$PWD/qscriptlexer.cpp \ + #$$PWD/qscriptparser.cpp + +HEADERS += \ + $$PWD/qscriptastfwd_p.h \ + $$PWD/qscriptast_p.h \ + $$PWD/qscriptastvisitor_p.h \ + $$PWD/qscriptgrammar_p.h \ + $$PWD/qscriptsyntaxchecker_p.h \ + $$PWD/qscriptlexer_p.h \ + #$$PWD/qscriptparser_p.h + +INCLUDEPATH += \ + $$PWD diff --git a/src/script/qscript.g b/src/script/parser/qscript.g index adce274..39900a8 100644 --- a/src/script/qscript.g +++ b/src/script/parser/qscript.g @@ -89,21 +89,6 @@ ** ** This file is part of the QtScript module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** ** In addition, as a special exception, Nokia gives you certain ** additional rights. These rights are described in the Nokia Qt LGPL ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this @@ -125,8 +110,6 @@ #include <QtCore/QtDebug> -#ifndef QT_NO_SCRIPT - #include <string.h> #include "qscriptengine.h" @@ -156,34 +139,6 @@ ** ** This file is part of the QtScript module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** $QT_END_LICENSE$ @@ -211,8 +166,6 @@ #include "qscriptgrammar_p.h" -#ifndef QT_NO_SCRIPT - #include "qscriptastfwd_p.h" QT_BEGIN_NAMESPACE @@ -331,9 +284,7 @@ QScriptParser::QScriptParser(): stack_size(0), sym_stack(0), state_stack(0), - location_stack(0), - error_lineno(0), - error_column(0) + location_stack(0) { } @@ -2111,13 +2062,9 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT ./ /: QT_END_NAMESPACE -#endif // QT_NO_SCRIPT - #endif // QSCRIPTPARSER_P_H :/ diff --git a/src/script/qscriptast.cpp b/src/script/parser/qscriptast.cpp index 0866d74..b0cc171 100644 --- a/src/script/qscriptast.cpp +++ b/src/script/parser/qscriptast.cpp @@ -41,8 +41,6 @@ #include "qscriptast_p.h" -#ifndef QT_NO_SCRIPT - #include "qscriptastvisitor_p.h" QT_BEGIN_NAMESPACE @@ -785,5 +783,3 @@ void DebuggerStatement::accept0(Visitor *visitor) } } // namespace QScript::AST QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptast_p.h b/src/script/parser/qscriptast_p.h index b23bd16..d0e534a 100644 --- a/src/script/qscriptast_p.h +++ b/src/script/parser/qscriptast_p.h @@ -55,8 +55,6 @@ #include <QtCore/QString> -#ifndef QT_NO_SCRIPT - #include "qscriptastvisitor_p.h" QT_BEGIN_NAMESPACE @@ -1495,8 +1493,6 @@ public: } } // namespace AST -#endif // QT_NO_SCRIPT - QT_END_NAMESPACE #endif diff --git a/src/script/qscriptastfwd_p.h b/src/script/parser/qscriptastfwd_p.h index 84c1c24..84c1c24 100644 --- a/src/script/qscriptastfwd_p.h +++ b/src/script/parser/qscriptastfwd_p.h diff --git a/src/script/qscriptastvisitor.cpp b/src/script/parser/qscriptastvisitor.cpp index 196c906..196c906 100644 --- a/src/script/qscriptastvisitor.cpp +++ b/src/script/parser/qscriptastvisitor.cpp diff --git a/src/script/qscriptastvisitor_p.h b/src/script/parser/qscriptastvisitor_p.h index c199e5e..c199e5e 100644 --- a/src/script/qscriptastvisitor_p.h +++ b/src/script/parser/qscriptastvisitor_p.h diff --git a/src/script/qscriptgrammar.cpp b/src/script/parser/qscriptgrammar.cpp index ab1aa19..a2971a0 100644 --- a/src/script/qscriptgrammar.cpp +++ b/src/script/parser/qscriptgrammar.cpp @@ -42,8 +42,6 @@ #include "qscriptgrammar_p.h" -#ifndef QT_NO_SCRIPT - QT_BEGIN_NAMESPACE const char *const QScriptGrammar::spell [] = { @@ -971,5 +969,3 @@ const int QScriptGrammar::action_check [] = { -1, -1, -1, -1, -1, -1, -1, -1}; QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptgrammar_p.h b/src/script/parser/qscriptgrammar_p.h index 80f22d5..43e8b67 100644 --- a/src/script/qscriptgrammar_p.h +++ b/src/script/parser/qscriptgrammar_p.h @@ -57,8 +57,6 @@ #include <QtCore/qglobal.h> -#ifndef QT_NO_SCRIPT - QT_BEGIN_NAMESPACE class QScriptGrammar @@ -203,6 +201,4 @@ public: QT_END_NAMESPACE -#endif // QT_NO_SCRIPT - #endif // QSCRIPTGRAMMAR_P_H diff --git a/src/script/qscriptlexer.cpp b/src/script/parser/qscriptlexer.cpp index 058e659..ea7578f 100644 --- a/src/script/qscriptlexer.cpp +++ b/src/script/parser/qscriptlexer.cpp @@ -39,21 +39,9 @@ ** ****************************************************************************/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "qscriptengine_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" #include "qscriptlexer_p.h" -#include "qscriptgrammar_p.h" +#include "qscriptgrammar_p.h" #include <ctype.h> #include <stdlib.h> #include <stdio.h> @@ -72,6 +60,8 @@ extern double qstrtod(const char *s00, char const **se, bool *ok); } \ while (0) +typedef double qsreal; // ### + namespace QScript { extern qsreal integerFromString(const char *buf, int size, int radix); } @@ -79,25 +69,14 @@ extern qsreal integerFromString(const char *buf, int size, int radix); QScript::Lexer::Lexer(QScriptEnginePrivate *eng) : driver(eng), yylineno(0), - done(false), - size8(128), size16(128), - pos8(0), pos16(0), - terminator(false), - restrKeyword(false), - delimited(false), - stackToken(-1), - state(Start), - pos(0), + size8(128), size16(128), restrKeyword(false), + stackToken(-1), pos(0), code(0), length(0), - yycolumn(0), - startlineno(0), startcolumn(0), bol(true), current(0), next1(0), next2(0), next3(0), err(NoError), - wantRx(false), check_reserved(true), parenthesesState(IgnoreParentheses), - parenthesesCount(0), prohibitAutomaticSemicolon(false) { // allocate space for read buffers @@ -790,9 +769,10 @@ int QScript::Lexer::lex() case Identifier: if ((token = findReservedWord(buffer16, pos16)) < 0) { /* TODO: close leak on parse error. same holds true for String */ - if (driver) - qsyylval.ustr = driver->intern(buffer16, pos16); - else + if (driver) { + Q_ASSERT_X(false, Q_FUNC_INFO, "not implemented"); + qsyylval.ustr = 0; // driver->intern(buffer16, pos16); + } else qsyylval.ustr = 0; return QScriptGrammar::T_IDENTIFIER; } @@ -808,9 +788,10 @@ int QScript::Lexer::lex() } return token; case String: - if (driver) - qsyylval.ustr = driver->intern(buffer16, pos16); - else + if (driver) { + Q_ASSERT_X(false, Q_FUNC_INFO, "not implemented"); + qsyylval.ustr = 0; // driver->intern(buffer16, pos16); + } else qsyylval.ustr = 0; return QScriptGrammar::T_STRING_LITERAL; case Number: @@ -1077,9 +1058,10 @@ bool QScript::Lexer::scanRegExp(RegExpBodyPrefix prefix) lastWasEscape = !lastWasEscape && (current == '\\'); } else { - if (driver) - pattern = driver->intern(buffer16, pos16); - else + if (driver) { + Q_ASSERT_X(false, Q_FUNC_INFO, "not implemented"); + pattern = 0; // driver->intern(buffer16, pos16); + } else pattern = 0; pos16 = 0; shift(1); @@ -1090,7 +1072,16 @@ bool QScript::Lexer::scanRegExp(RegExpBodyPrefix prefix) flags = 0; while (isIdentLetter(current)) { - int flag = QScript::Ecma::RegExp::flagFromChar(current); + // current version was remade from this line: + //int flag = QScript::Ecma::RegExp::flagFromChar(current); + //code was "inlined" because it was only one call to this function + int flag; + switch (current) { + case 'g': flag = 0x01; break; + case 'm': flag = 0x02; break; + case 'i': flag = 0x04; break; + default: flag = 0; + } if (flag == 0) { errmsg = QString::fromLatin1("Invalid regular expression flag '%0'") .arg(QChar(current)); @@ -1118,5 +1109,3 @@ void QScript::Lexer::syncProhibitAutomaticSemicolon() } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptlexer_p.h b/src/script/parser/qscriptlexer_p.h index 7a8651c..2d7d3b5 100644 --- a/src/script/qscriptlexer_p.h +++ b/src/script/parser/qscriptlexer_p.h @@ -55,8 +55,6 @@ #include <QtCore/QString> -#ifndef QT_NO_SCRIPT - QT_BEGIN_NAMESPACE class QScriptEnginePrivate; @@ -241,6 +239,4 @@ private: QT_END_NAMESPACE -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/qscriptparser.cpp b/src/script/parser/qscriptparser.cpp index e14aace..b3880af 100644 --- a/src/script/qscriptparser.cpp +++ b/src/script/parser/qscriptparser.cpp @@ -43,19 +43,9 @@ #include <QtCore/QtDebug> -#ifndef QT_NO_SCRIPT - #include <string.h> -#include "qscriptengine.h" -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptlexer_p.h" #include "qscriptast_p.h" -#include "qscriptnodepool_p.h" #define Q_SCRIPT_UPDATE_POSITION(node, startloc, endloc) do { \ node->startLine = startloc.startLine; \ @@ -88,9 +78,7 @@ QScriptParser::QScriptParser(): stack_size(0), sym_stack(0), state_stack(0), - location_stack(0), - error_lineno(0), - error_column(0) + location_stack(0) { } @@ -1168,5 +1156,3 @@ case 266: { } QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptparser_p.h b/src/script/parser/qscriptparser_p.h index 56736f5..cd463aa 100644 --- a/src/script/qscriptparser_p.h +++ b/src/script/parser/qscriptparser_p.h @@ -62,8 +62,6 @@ #include "qscriptgrammar_p.h" -#ifndef QT_NO_SCRIPT - #include "qscriptastfwd_p.h" QT_BEGIN_NAMESPACE @@ -162,6 +160,4 @@ inline void QScriptParser::reallocateStack() QT_END_NAMESPACE -#endif // QT_NO_SCRIPT - #endif // QSCRIPTPARSER_P_H diff --git a/src/script/qscriptsyntaxchecker.cpp b/src/script/parser/qscriptsyntaxchecker.cpp index b7c4905..ee91c52 100644 --- a/src/script/qscriptsyntaxchecker.cpp +++ b/src/script/parser/qscriptsyntaxchecker.cpp @@ -41,8 +41,6 @@ #include "qscriptsyntaxchecker_p.h" -#ifndef QT_NO_SCRIPT - #include "qscriptlexer_p.h" #include "qscriptparser_p.h" @@ -214,5 +212,3 @@ SyntaxChecker::Result SyntaxChecker::checkSyntax(const QString &code) } // namespace QScript QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptsyntaxchecker_p.h b/src/script/parser/qscriptsyntaxchecker_p.h index 853bb76..5609cc2 100644 --- a/src/script/qscriptsyntaxchecker_p.h +++ b/src/script/parser/qscriptsyntaxchecker_p.h @@ -55,8 +55,6 @@ #include <QtCore/qstring.h> -#ifndef QT_NO_SCRIPT - #include "qscriptgrammar_p.h" QT_BEGIN_NAMESPACE @@ -71,7 +69,7 @@ public: enum State { Error, Intermediate, - Valid + Valid, }; struct Result { @@ -113,6 +111,4 @@ inline void SyntaxChecker::reallocateStack() QT_END_NAMESPACE -#endif // QT_NO_SCRIPT - #endif diff --git a/src/script/qscriptarray_p.h b/src/script/qscriptarray_p.h deleted file mode 100644 index cabac9e..0000000 --- a/src/script/qscriptarray_p.h +++ /dev/null @@ -1,428 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTARRAY_P_H -#define QSCRIPTARRAY_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QMap> - -#ifndef QT_NO_SCRIPT - -#include <QtCore/QVector> - -#include "qscriptvalueimplfwd_p.h" -#include "qscriptenginefwd_p.h" - -QT_BEGIN_NAMESPACE - -namespace QScript { - -class Array -{ -public: - inline Array(QScriptEnginePrivate *engine); - inline Array(const Array &other); - inline ~Array(); - - inline Array &operator = (const Array &other); - - inline bool isEmpty() const; - inline uint size() const; - inline uint count() const; - inline QScriptValueImpl at(uint index) const; - inline void assign(uint index, const QScriptValueImpl &v); - inline void clear(); - inline void mark(int generation); - inline void resize(uint size); - inline void concat(const Array &other); - inline QScriptValueImpl pop(); - inline void sort(const QScriptValueImpl &comparefn); - inline void splice(qsreal start, qsreal deleteCount, - const QVector<QScriptValueImpl> &items, - Array &other); - inline QList<uint> keys() const; - -private: - enum Mode { - VectorMode, - MapMode - }; - - QScriptEnginePrivate *m_engine; - Mode m_mode; - int m_instances; - - union { - QMap<uint, QScriptValueImpl> *to_map; - QVector<QScriptValueImpl> *to_vector; - }; -}; - -class ArrayElementLessThan -{ -public: - inline ArrayElementLessThan(const QScriptValueImpl &comparefn) - : m_comparefn(comparefn) {} - - inline bool operator()(const QScriptValueImpl &v1, const QScriptValueImpl &v2) const - { - if (!v1.isValid() || v1.isUndefined()) - return false; - if (!v2.isValid() || v2.isUndefined()) - return true; - if (!m_comparefn.isUndefined()) { - ArrayElementLessThan *that = const_cast<ArrayElementLessThan*>(this); - QScriptValueImpl result = that->m_comparefn.call(QScriptValueImpl(), - QScriptValueImplList() << v1 << v2); - return result.toNumber() <= 0; - } - return v1.toString() < v2.toString(); - } - -private: - QScriptValueImpl m_comparefn; -}; - -} // namespace QScript - -inline QScript::Array::Array(QScriptEnginePrivate *engine): - m_engine(engine), - m_mode(VectorMode), - m_instances(0) -{ - to_vector = new QVector<QScriptValueImpl>(); -} - -inline QScript::Array::Array(const Array &other): - m_engine(other.m_engine), - m_mode(other.m_mode), - m_instances(other.m_instances) -{ - if (m_mode == VectorMode) - to_vector = new QVector<QScriptValueImpl> (*other.to_vector); - else - to_map = new QMap<uint, QScriptValueImpl> (*other.to_map); -} - -inline QScript::Array::~Array() -{ - if (m_mode == VectorMode) - delete to_vector; - else - delete to_map; -} - -inline QScript::Array &QScript::Array::operator = (const Array &other) -{ - m_engine = other.m_engine; - m_instances = other.m_instances; - if (m_mode != other.m_mode) { - if (m_mode == VectorMode) - delete to_vector; - else - delete to_map; - m_mode = other.m_mode; - - if (m_mode == VectorMode) - to_vector = new QVector<QScriptValueImpl> (*other.to_vector); - else - to_map = new QMap<uint, QScriptValueImpl> (*other.to_map); - } - - if (m_mode == VectorMode) - *to_vector = *other.to_vector; - else - *to_map = *other.to_map; - - return *this; -} - -inline bool QScript::Array::isEmpty() const -{ - if (m_mode == VectorMode) - return to_vector->isEmpty(); - - return to_map->isEmpty(); -} - -inline uint QScript::Array::size() const -{ - if (m_mode == VectorMode) - return to_vector->size(); - - if (to_map->isEmpty()) - return 0; - - return (--to_map->constEnd()).key(); -} - -inline uint QScript::Array::count() const -{ - return size(); -} - -inline QScriptValueImpl QScript::Array::at(uint index) const -{ - if (m_mode == VectorMode) { - if (index < uint(to_vector->size())) - return to_vector->at(index); - return QScriptValueImpl(); - } else { - return to_map->value(index, QScriptValueImpl()); - } -} - -inline void QScript::Array::assign(uint index, const QScriptValueImpl &v) -{ - if (index >= size()) { - resize(index + 1); - if (v.isValid() && m_engine) - m_engine->adjustBytesAllocated(sizeof(QScriptValueImpl) * (size() - index)); - } - - const QScriptValueImpl &oldv = at(index); - if (oldv.isValid() && (oldv.isObject() || oldv.isString())) - --m_instances; - - if (v.isValid() && (v.isObject() || v.isString())) - ++m_instances; - - if (m_mode == VectorMode) { - to_vector->replace(index, v); - } else { - if (!v.isValid()) - to_map->remove(index); - else - to_map->insert(index, v); - } -} - -inline void QScript::Array::clear() -{ - m_instances = 0; - - if (m_mode == VectorMode) - to_vector->clear(); - - else - to_map->clear(); -} - -inline void QScript::Array::mark(int generation) -{ - if (! m_instances) - return; - - if (m_mode == VectorMode) { - for (int i = 0; i < to_vector->size(); ++i) - to_vector->at(i).mark(generation); - } else { - QMap<uint, QScriptValueImpl>::const_iterator it = to_map->constBegin(); - for (; it != to_map->constEnd(); ++it) - it.value().mark(generation); - } -} - -inline void QScript::Array::resize(uint s) -{ - const uint oldSize = size(); - if (oldSize == s) - return; - - const uint N = 10 * 1024; - - if (m_mode == VectorMode) { - if (s < N) { - to_vector->resize (s); - } else { - // switch to MapMode - QMap<uint, QScriptValueImpl> *m = new QMap<uint, QScriptValueImpl>(); - for (uint i = 0; i < oldSize; ++i) { - if (to_vector->at(i).isValid()) - m->insert(i, to_vector->at(i)); - } - m->insert(s, QScriptValueImpl()); - delete to_vector; - to_map = m; - m_mode = MapMode; - } - } - - else { - if (s < N) { - // switch to VectorMode - QVector<QScriptValueImpl> *v = new QVector<QScriptValueImpl> (s); - QMap<uint, QScriptValueImpl>::const_iterator it = to_map->constBegin(); - for ( ; (it != to_map->constEnd()) && (it.key() < s); ++it) - (*v) [it.key()] = it.value(); - delete to_map; - to_vector = v; - m_mode = VectorMode; - } else { - if (!to_map->isEmpty()) { - QMap<uint, QScriptValueImpl>::iterator it = --to_map->end(); - if (oldSize > s) { - // shrink - while ((it != to_map->end()) && (it.key() >= s)) { - it = to_map->erase(it); - --it; - } - } else { - if ((it.key() == oldSize) && !it.value().isValid()) - to_map->erase(it); - } - } - to_map->insert(s, QScriptValueImpl()); - } - } -} - -inline void QScript::Array::concat(const QScript::Array &other) -{ - uint k = size(); - resize (k + other.size()); - for (uint i = 0; i < other.size(); ++i) { - QScriptValueImpl v = other.at(i); - if (! v.isValid()) - continue; - - assign(k + i, v); - } -} - -inline QScriptValueImpl QScript::Array::pop() -{ - if (isEmpty()) - return QScriptValueImpl(); - - QScriptValueImpl v; - - if (m_mode == VectorMode) - v = to_vector->last(); - else - v = *--to_map->end(); - - resize(size() - 1); - - return v; -} - -inline void QScript::Array::sort(const QScriptValueImpl &comparefn) -{ - ArrayElementLessThan lessThan(comparefn); - if (m_mode == VectorMode) { - qSort(to_vector->begin(), to_vector->end(), lessThan); - } else { - QList<uint> keys = to_map->keys(); - QList<QScriptValueImpl> values = to_map->values(); - qStableSort(values.begin(), values.end(), lessThan); - const uint len = keys.size(); - for (uint i = 0; i < len; ++i) - to_map->insert(keys.at(i), values.at(i)); - } -} - -inline void QScript::Array::splice(qsreal start, qsreal deleteCount, - const QVector<QScriptValueImpl> &items, - Array &other) -{ - const qsreal len = size(); - if (start < 0) - start = qMax(len + start, qsreal(0)); - else if (start > len) - start = len; - deleteCount = qMax(qMin(deleteCount, len - start), qsreal(0)); - - const uint st = uint(start); - const uint dc = uint(deleteCount); - other.resize(dc); - - const uint itemsSize = uint(items.size()); - - if (m_mode == VectorMode) { - for (uint i = 0; i < dc; ++i) - other.assign(i, to_vector->at(st + i)); - if (itemsSize > dc) - to_vector->insert(st, itemsSize - dc, QScriptValueImpl()); - else if (itemsSize < dc) - to_vector->remove(st, dc - itemsSize); - for (uint i = 0; i < itemsSize; ++i) - to_vector->replace(st + i, items.at(i)); - } else { - for (uint i = 0; i < dc; ++i) - other.assign(i, to_map->take(st + i)); - uint del = itemsSize - dc; - if (del != 0) { - for (uint i = st; i < uint(len); ++i) { - if (to_map->contains(i)) - to_map->insert(i + del, to_map->take(i)); - } - resize(uint(len) + del); - } - for (uint i = 0; i < itemsSize; ++i) - to_map->insert(st + i, items.at(i)); - } -} - -inline QList<uint> QScript::Array::keys() const -{ - if (m_mode == VectorMode) - return QList<uint>(); - else - return to_map->keys(); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif // QSCRIPTARRAY_P_H diff --git a/src/script/qscriptasm.cpp b/src/script/qscriptasm.cpp deleted file mode 100644 index 08a44a7..0000000 --- a/src/script/qscriptasm.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/QTextStream> - -#ifndef QT_NO_SCRIPT - -#include "qscriptasm_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptengine_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -QT_BEGIN_NAMESPACE - -const char *QScriptInstruction::opcode[] = { -#define STR(a) #a -#define Q_SCRIPT_DEFINE_OPERATOR(op) STR(i##op) , -#include "instruction.table" -#undef Q_SCRIPT_DEFINE_OPERATOR -#undef STR -}; - -void QScriptInstruction::print(QTextStream &out) const -{ - out << opcode[op]; - - if (! operand[0].isValid()) - return; - - out << '(' << operand[0].toString(); - - if (operand[1].isValid()) - out << ", " << operand[1].toString(); - - out << ')'; -} - -namespace QScript { - -Code::Code(): - optimized(false), - firstInstruction(0), - lastInstruction(0), - astPool(0) -{ -} - -Code::~Code() -{ - delete[] firstInstruction; -} - -void Code::init(const CompilationUnit &compilation, NodePool *pool) -{ - optimized = false; - const QVector<QScriptInstruction> ilist = compilation.instructions(); - firstInstruction = new QScriptInstruction[ilist.count()]; - lastInstruction = firstInstruction + ilist.count(); - qCopy(ilist.begin(), ilist.end(), firstInstruction); - exceptionHandlers = compilation.exceptionHandlers(); - astPool = pool; -} - -} // namespace QScript - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptasm_p.h b/src/script/qscriptasm_p.h deleted file mode 100644 index 6b01d64..0000000 --- a/src/script/qscriptasm_p.h +++ /dev/null @@ -1,183 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTASM_P_H -#define QSCRIPTASM_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -#ifndef QT_NO_SCRIPT - -#include <QtCore/qvector.h> - -#include "qscriptvalueimplfwd_p.h" - -QT_BEGIN_NAMESPACE - -class QTextStream; - -class QScriptInstruction -{ -public: - enum Operator { -#define Q_SCRIPT_DEFINE_OPERATOR(op) OP_##op, -#include "instruction.table" -#undef Q_SCRIPT_DEFINE_OPERATOR - OP_Dummy - }; - -public: - Operator op; - QScriptValueImpl operand[2]; -#if defined(Q_SCRIPT_DIRECT_CODE) - void *code; -#endif - - void print(QTextStream &out) const; - - static const char *opcode[]; -}; - -namespace QScript { - -class NodePool; - -class ExceptionHandlerDescriptor -{ -public: - ExceptionHandlerDescriptor() - : m_startInstruction(0), - m_endInstruction(0), - m_handlerInstruction(0) {} - - ExceptionHandlerDescriptor( - int startInstruction, - int endInstruction, - int handlerInstruction) - : m_startInstruction(startInstruction), - m_endInstruction(endInstruction), - m_handlerInstruction(handlerInstruction) {} - - inline int startInstruction() const { return m_startInstruction; } - inline int endInstruction() const { return m_endInstruction; } - inline int handlerInstruction() const { return m_handlerInstruction; } - -private: - int m_startInstruction; - int m_endInstruction; - int m_handlerInstruction; -}; - -class CompilationUnit -{ -public: - CompilationUnit(): m_valid(true), - m_errorLineNumber(-1) {} - - bool isValid() const { return m_valid; } - - void setError(const QString &message, int lineNumber) - { - m_errorMessage = message; - m_errorLineNumber = lineNumber; - m_valid = false; - } - - QString errorMessage() const - { return m_errorMessage; } - int errorLineNumber() const - { return m_errorLineNumber; } - - QVector<QScriptInstruction> instructions() const - { return m_instructions; } - void setInstructions(const QVector<QScriptInstruction> &instructions) - { m_instructions = instructions; } - - QVector<ExceptionHandlerDescriptor> exceptionHandlers() const - { return m_exceptionHandlers; } - void setExceptionHandlers(const QVector<ExceptionHandlerDescriptor> &exceptionHandlers) - { m_exceptionHandlers = exceptionHandlers; } - -private: - bool m_valid; - QString m_errorMessage; - int m_errorLineNumber; - QVector<QScriptInstruction> m_instructions; - QVector<ExceptionHandlerDescriptor> m_exceptionHandlers; -}; - -class Code -{ -public: - Code(); - ~Code(); - - void init(const CompilationUnit &compilation, NodePool *astPool); - -public: // attributes - bool optimized; - QScriptInstruction *firstInstruction; - QScriptInstruction *lastInstruction; - QVector<ExceptionHandlerDescriptor> exceptionHandlers; - NodePool *astPool; - -private: - Q_DISABLE_COPY(Code) -}; - - -} // namespace QScript - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif // QSCRIPTASM_P_H diff --git a/src/script/qscriptbuffer_p.h b/src/script/qscriptbuffer_p.h deleted file mode 100644 index 0551451..0000000 --- a/src/script/qscriptbuffer_p.h +++ /dev/null @@ -1,211 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTBUFFER_P_H -#define QSCRIPTBUFFER_P_H - -#include <QtCore/qglobal.h> - -#if defined(Q_OS_VXWORKS) && defined(m_data) -# undef m_data -#endif - - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -namespace QScript -{ - template <typename T> class Buffer - { - public: - typedef T *iterator; - typedef const T *const_iterator; - - Buffer() : m_data(0), m_capacity(0), m_size(0) { } - ~Buffer() { delete [] m_data; } - - inline void reserve(int num); - inline void reset(); - inline void clear(); - inline void append(const T &t); - - inline iterator begin(); - inline iterator end(); - - inline const_iterator begin() const; - inline const_iterator end() const; - - inline int size() const; - inline void resize(int s); - - inline int capacity() const; - inline T *data(); - inline const T *constData() const; - - inline T &last(); - inline T &takeLast(); - - inline T &at(int i) { return (*this)[i]; } - inline const T &at(int i) const { return (*this)[i]; } - - inline T &operator[](int i); - inline const T &operator[](int i) const; - - inline bool isEmpty() const; - - private: - T *m_data; - int m_capacity; - int m_size; - - private: - Q_DISABLE_COPY(Buffer) - }; - -} // namespace QScript - -template <typename T> T *QScript::Buffer<T>::data() { return m_data; } -template <typename T> const T *QScript::Buffer<T>::constData() const { return m_data; } -template <typename T> void QScript::Buffer<T>::reset() { m_size = 0; } -template <typename T> int QScript::Buffer<T>::capacity() const { return m_capacity; } - -template <typename T> int QScript::Buffer<T>::size() const { return m_size; } -template <typename T> void QScript::Buffer<T>::resize(int s) -{ - if (m_capacity < s) - reserve (s << 1); - - m_size = s; -} - -template <typename T> void QScript::Buffer<T>::clear() -{ - delete [] m_data; - m_data = 0; - m_size = 0; - m_capacity = 0; -} - -template <typename T> void QScript::Buffer<T>::reserve(int x) -{ - // its an ever expanding buffer so it never gets smaller.. - if (x < m_capacity) - return; - m_capacity = x; - T *new_data = new T[m_capacity]; - for (int i=0; i<m_size; ++i) - new_data[i] = m_data[i]; - delete [] m_data; - m_data = new_data; -} - -template <typename T> void QScript::Buffer<T>::append(const T &t) -{ - if (m_size == m_capacity) - reserve(m_capacity + 32); - m_data[m_size++] = t; -} - -template <typename T> T &QScript::Buffer<T>::operator[](int i) -{ - Q_ASSERT(i >= 0); - Q_ASSERT(i < m_size); - return m_data[i]; -} - -template <typename T> const T &QScript::Buffer<T>::operator[](int i) const -{ - Q_ASSERT(i >= 0); - Q_ASSERT(i < m_size); - return m_data[i]; -} - -template <typename T> bool QScript::Buffer<T>::isEmpty() const -{ - return m_size == 0; -} - -template <typename T> T &QScript::Buffer<T>::takeLast() -{ - Q_ASSERT(!isEmpty()); - --m_size; - return m_data[m_size]; -} - -template <typename T> T &QScript::Buffer<T>::last() -{ - return m_data[m_size - 1]; -} - -template <typename T> typename QScript::Buffer<T>::iterator QScript::Buffer<T>::begin() -{ - return m_data; -} - -template <typename T> typename QScript::Buffer<T>::iterator QScript::Buffer<T>::end() -{ - return m_data + m_size; -} - -template <typename T> typename QScript::Buffer<T>::const_iterator QScript::Buffer<T>::begin() const -{ - return m_data; -} - -template <typename T> typename QScript::Buffer<T>::const_iterator QScript::Buffer<T>::end() const -{ - return m_data + m_size; -} - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptclassdata.cpp b/src/script/qscriptclassdata.cpp deleted file mode 100644 index 29e03d9..0000000 --- a/src/script/qscriptclassdata.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptclassdata_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -QScriptClassData::QScriptClassData() -{ -} - -QScriptClassData::~QScriptClassData() -{ -} - -void QScriptClassData::mark(const QScriptValueImpl &, int) -{ -} - -bool QScriptClassData:: resolve(const QScriptValueImpl &, QScriptNameIdImpl *, - QScript::Member *, QScriptValueImpl *, - QScript::AccessMode) -{ - return false; -} - -bool QScriptClassData::get(const QScriptValueImpl &, const QScript::Member &, - QScriptValueImpl *) -{ - Q_ASSERT_X(false, "QScriptClassData::get()", - "implement if resolveMember is implemented"); - return false; -} - -bool QScriptClassData::put(QScriptValueImpl *, const QScript::Member &, - const QScriptValueImpl &) -{ - Q_ASSERT_X(false, "QScriptClassData::put()", - "implement if resolveMember is implemented"); - return false; -} - -bool QScriptClassData::removeMember(const QScriptValueImpl &, - const QScript::Member &) -{ - return true; -} - -bool QScriptClassData::implementsHasInstance(const QScriptValueImpl &) -{ - return false; -} - -bool QScriptClassData::hasInstance(const QScriptValueImpl &, - const QScriptValueImpl &) -{ - Q_ASSERT_X(false, "QScriptClassData::hasInstance()", - "implement if implementsHasInstance() returns true"); - return false; -} - -QScriptClassDataIterator *QScriptClassData::newIterator(const QScriptValueImpl &) -{ - return 0; -} - -QScriptClassDataIterator::QScriptClassDataIterator() -{ -} - -QScriptClassDataIterator::~QScriptClassDataIterator() -{ -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptclassdata_p.h b/src/script/qscriptclassdata_p.h deleted file mode 100644 index 69093ba..0000000 --- a/src/script/qscriptclassdata_p.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTCLASSDATA_P_H -#define QSCRIPTCLASSDATA_P_H - -#include "qscriptglobals_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -class QScriptValueImpl; -class QScriptNameIdImpl; -class QScriptClassDataIterator; - -namespace QScript { - class Member; -} - -class QScriptClassData -{ -protected: - QScriptClassData(); - -public: - virtual ~QScriptClassData(); - - virtual void mark(const QScriptValueImpl &object, int generation); - virtual bool resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode access); - virtual bool get(const QScriptValueImpl &obj, const QScript::Member &m, - QScriptValueImpl *result); - virtual bool put(QScriptValueImpl *object, const QScript::Member &member, - const QScriptValueImpl &value); - virtual bool removeMember(const QScriptValueImpl &object, - const QScript::Member &member); - virtual bool implementsHasInstance(const QScriptValueImpl &object); - virtual bool hasInstance(const QScriptValueImpl &object, - const QScriptValueImpl &value); - virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object); - -private: - Q_DISABLE_COPY(QScriptClassData) -}; - -class QScriptClassDataIterator -{ -protected: - QScriptClassDataIterator(); - -public: - virtual ~QScriptClassDataIterator(); - - virtual bool hasNext() const = 0; - virtual void next(QScript::Member *member) = 0; - - virtual bool hasPrevious() const = 0; - virtual void previous(QScript::Member *member) = 0; - - virtual void toFront() = 0; - virtual void toBack() = 0; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif // QSCRIPTCLASSDATA_P_H diff --git a/src/script/qscriptclassinfo_p.h b/src/script/qscriptclassinfo_p.h deleted file mode 100644 index 6f7b761..0000000 --- a/src/script/qscriptclassinfo_p.h +++ /dev/null @@ -1,126 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTCLASSINFO_P_H -#define QSCRIPTCLASSINFO_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#if defined(Q_OS_VXWORKS) && defined(m_type) -# undef m_type -#endif - -#include "qscriptclassdata_p.h" - -#ifndef QT_NO_SCRIPT - -#include <QtCore/qstring.h> - -QT_BEGIN_NAMESPACE - -class QScriptClassInfo -{ -public: - enum Type { - FunctionBased = 0x40000000, - - ObjectType = 1, - FunctionType = 2 | FunctionBased, - ArrayType = 3, - StringType = 4, - BooleanType = 5, - NumberType = 6, - DateType = 7, - RegExpType = 8, - ErrorType = 9, - - VariantType = 10, - QObjectType = 11, - QMetaObjectType = 12 | FunctionBased, - - // Types used by the runtime - ActivationType = 100, - EnumerationType = 101, - - CustomType = 1000, - - TypeMask = 0x0000FFFF - }; - - inline QScriptClassInfo(QScriptEnginePrivate *engine, Type type, const QString &name) - : m_engine(engine), m_type(type), m_name(name), m_data(0) { } - inline ~QScriptClassInfo() { delete m_data; } - - inline QScriptEnginePrivate *engine() const - { return m_engine; } - inline Type type() const - { return m_type; } - inline QString name() const - { return m_name; } - - inline void setData(QScriptClassData *data) - { m_data = data; } - QScriptClassData *data() const - { return m_data; } - -private: - QScriptEnginePrivate *m_engine; - Type m_type; - QString m_name; - QScriptClassData *m_data; - -private: - Q_DISABLE_COPY(QScriptClassInfo) -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif // QSCRIPTCLASSINFO_P_H diff --git a/src/script/qscriptclasspropertyiterator_p.h b/src/script/qscriptclasspropertyiterator_p.h deleted file mode 100644 index 8fe42aa..0000000 --- a/src/script/qscriptclasspropertyiterator_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTCLASSPROPERTYITERATOR_P_H -#define QSCRIPTCLASSPROPERTYITERATOR_P_H - -#include <QtCore/qobjectdefs.h> - -#ifndef QT_NO_SCRIPT - -#include "qscriptvalue.h" - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -class QScriptClassPropertyIterator; -class QScriptClassPropertyIteratorPrivate -{ - Q_DECLARE_PUBLIC(QScriptClassPropertyIterator) -public: - QScriptClassPropertyIteratorPrivate(QScriptClassPropertyIterator*); - virtual ~QScriptClassPropertyIteratorPrivate(); - - QScriptValue object; - - QScriptClassPropertyIterator *q_ptr; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptcompiler.cpp b/src/script/qscriptcompiler.cpp deleted file mode 100644 index 9f60db0..0000000 --- a/src/script/qscriptcompiler.cpp +++ /dev/null @@ -1,2111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptcompiler_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptast_p.h" -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -namespace QScript { - -class Compare : protected AST::Visitor -{ -public: - bool operator()(AST::ExpressionNode *e1, AST::ExpressionNode *e2) - { - if (!e1 || !e2) - return (e1 == e2); - - if (e1->kind != e2->kind) - return false; - - m_e2 = e2; - m_equal = false; - e1->accept(this); - return m_equal; - } - -protected: - virtual bool visit(AST::ThisExpression *) - { - m_equal = true; - return false; - } - virtual bool visit(AST::NullExpression *) - { - m_equal = true; - return false; - } - virtual bool visit(AST::VoidExpression *) - { - m_equal = true; - return false; - } - virtual bool visit(AST::FalseLiteral *) - { - m_equal = true; - return false; - } - virtual bool visit(AST::TrueLiteral *) - { - m_equal = true; - return false; - } - virtual bool visit(AST::NumericLiteral *e1) - { - AST::NumericLiteral *e2 = static_cast<AST::NumericLiteral*>(m_e2); - m_equal = (e1->value == e2->value); - return false; - } - virtual bool visit(AST::RegExpLiteral *e1) - { - AST::RegExpLiteral *e2 = static_cast<AST::RegExpLiteral*>(m_e2); - m_equal = (e1->pattern == e2->pattern) - && (e1->flags == e2->flags); - return false; - } - virtual bool visit(AST::StringLiteral *e1) - { - AST::StringLiteral *e2 = static_cast<AST::StringLiteral*>(m_e2); - m_equal = (e1->value == e2->value); - return false; - } - virtual bool visit(AST::IdentifierExpression *e1) - { - AST::IdentifierExpression *e2 = static_cast<AST::IdentifierExpression*>(m_e2); - m_equal = (e1->name == e2->name); - return false; - } - virtual bool visit(AST::ArrayMemberExpression *e1) - { - AST::ArrayMemberExpression *e2 = static_cast<AST::ArrayMemberExpression*>(m_e2); - m_equal = operator()(e1->base, e2->base) - && operator()(e1->expression, e2->expression); - return false; - } - virtual bool visit(AST::FieldMemberExpression *e1) - { - AST::FieldMemberExpression *e2 = static_cast<AST::FieldMemberExpression*>(m_e2); - m_equal = (e1->name == e2->name) && operator()(e1->base, e2->base); - return false; - } - virtual bool visit(AST::BinaryExpression *e1) - { - AST::BinaryExpression *e2 = static_cast<AST::BinaryExpression*>(m_e2); - m_equal = (e1->op == e2->op) && operator()(e1->left, e2->left) - && operator()(e1->right, e2->right); - return false; - } - virtual bool visit(AST::ConditionalExpression *e1) - { - AST::ConditionalExpression *e2 = static_cast<AST::ConditionalExpression*>(m_e2); - m_equal = operator()(e1->expression, e2->expression) - && operator()(e1->ok, e2->ok) - && operator()(e1->ko, e2->ko); - return false; - } - virtual bool visit(AST::TypeOfExpression *e1) - { - AST::TypeOfExpression *e2 = static_cast<AST::TypeOfExpression*>(m_e2); - m_equal = operator()(e1->expression, e2->expression); - return false; - } - virtual bool visit(AST::UnaryPlusExpression *e1) - { - AST::UnaryPlusExpression *e2 = static_cast<AST::UnaryPlusExpression*>(m_e2); - m_equal = operator()(e1->expression, e2->expression); - return false; - } - virtual bool visit(AST::UnaryMinusExpression *e1) - { - AST::UnaryMinusExpression *e2 = static_cast<AST::UnaryMinusExpression*>(m_e2); - m_equal = operator()(e1->expression, e2->expression); - return false; - } - virtual bool visit(AST::TildeExpression *e1) - { - AST::TildeExpression *e2 = static_cast<AST::TildeExpression*>(m_e2); - m_equal = operator()(e1->expression, e2->expression); - return false; - } - virtual bool visit(AST::NotExpression *e1) - { - AST::NotExpression *e2 = static_cast<AST::NotExpression*>(m_e2); - m_equal = operator()(e1->expression, e2->expression); - return false; - } - virtual bool visit(AST::Expression *) - { return false; } - virtual bool visit(AST::ArrayLiteral *) - { return false; } - virtual bool visit(AST::ObjectLiteral *) - { return false; } - virtual bool visit(AST::CallExpression *) - { return false; } - virtual bool visit(AST::DeleteExpression *) - { return false; } - virtual bool visit(AST::FunctionExpression *) - { return false; } - virtual bool visit(AST::NewExpression *) - { return false; } - virtual bool visit(AST::NewMemberExpression *) - { return false; } - virtual bool visit(AST::PostDecrementExpression *) - { return false; } - virtual bool visit(AST::PostIncrementExpression *) - { return false; } - virtual bool visit(AST::PreDecrementExpression *) - { return false; } - virtual bool visit(AST::PreIncrementExpression *) - { return false; } - -private: - AST::ExpressionNode *m_e2; - bool m_equal; -}; - -class FetchName: protected AST::Visitor -{ -public: - inline FetchName(QScriptEnginePrivate *e): - eng(e), name(0) {} - - QScriptNameIdImpl *operator() (AST::PropertyName *node) - { - name = 0; - node->accept(this); - return name; - } - -protected: - virtual bool visit(AST::IdentifierPropertyName *node) - { - name = node->id; - return false; - } - - virtual bool visit(AST::StringLiteralPropertyName *node) - { - name = node->id; - return false; - } - - virtual bool visit(AST::NumericLiteralPropertyName *node) - { - name = eng->nameId(QString::number(node->id), /*persistent=*/false); // ### don't use QString::number - name->persistent = true; // ### remove - return false; - } - -private: - QScriptEnginePrivate *eng; - QScriptNameIdImpl *name; -}; - -class EmptySourceElements: protected AST::Visitor -{ -public: - EmptySourceElements(QScriptEngine *d): - driver(d), empty(false) {} - - inline bool operator () (AST::Node *) - { - empty = false; - return empty; - } - -private: - QScriptEngine *driver; - bool empty; -}; - -class DeclareLocals: protected AST::Visitor -{ -public: - DeclareLocals(Compiler *c): - compiler(c), - eng(c->engine()) - { - } - - void operator () (AST::Node *node) - { - if (node) - node->accept(this); - } - -protected: - virtual bool visit(AST::FunctionDeclaration *node) - { - compiler->iDeclareLocal(node->name, /*readOnly=*/false); - return false; - } - - virtual bool visit(AST::FunctionExpression *) - { return false; } - - virtual bool visit(AST::VariableDeclaration *node) - { - compiler->iDeclareLocal(node->name, node->readOnly); - return false; - } - -private: - Compiler *compiler; - QScriptEnginePrivate *eng; -}; - -Compiler::Compiler(QScriptEnginePrivate *eng): - m_eng(eng), - m_generateReferences(0), m_iterationStatement(0), - m_switchStatement(0), m_withStatement(0), - m_generateLeaveWithOnBreak(0), m_generateFastArgumentLookup(0), - m_parseStatements(0), m_pad(0), - m_topLevelCompiler(false), - m_activeLoop(0) -{ -} - -Compiler::~Compiler() -{ -} - -bool Compiler::topLevelCompiler() const -{ - return m_topLevelCompiler; -} - -void Compiler::setTopLevelCompiler(bool b) -{ - m_topLevelCompiler = b; -} - - CompilationUnit Compiler::compile(AST::Node *node, const QList<QScriptNameIdImpl *> &formals) -{ - m_formals = formals; - m_generateReferences = 0; - m_iterationStatement = 0; - m_switchStatement = 0; - m_withStatement = 0; - m_generateLeaveWithOnBreak = 0; - m_generateFastArgumentLookup = 0; - m_parseStatements = 0; - m_pad = 0; - m_instructions.clear(); - m_exceptionHandlers.clear(); - m_generateFastArgumentLookup = false; // ### !formals.isEmpty(); // ### disabled for now.. it's buggy :( - - m_compilationUnit = CompilationUnit(); - - if (node) - node->accept(this); - - // add a terminator - if (topLevelCompiler()) { - iHalt(); - } else if (m_instructions.isEmpty() || m_instructions.last().op != QScriptInstruction::OP_Ret) { - iLoadUndefined(); - iRet(); - } - - m_compilationUnit.setInstructions(m_instructions); - m_compilationUnit.setExceptionHandlers(m_exceptionHandlers); - return m_compilationUnit; -} - -bool Compiler::preVisit(AST::Node *) -{ - return m_compilationUnit.isValid(); -} - -bool Compiler::visit(AST::SourceElements *node) -{ - DeclareLocals declareLocals(this); - declareLocals(node); - - bool was = changeParseStatements(false); - - for (AST::SourceElements *it = node; it != 0; it = it->next) - it->element->accept(this); - - changeParseStatements(true); - - for (AST::SourceElements *it = node; it != 0; it = it->next) - it->element->accept(this); - - changeParseStatements(was); - - return false; -} - -bool Compiler::visit(AST::StatementList *) -{ - return true; -} - -bool Compiler::visit(AST::FunctionSourceElement *) -{ - return m_parseStatements == 0; -} - -bool Compiler::visit(AST::StatementSourceElement *) -{ - return m_parseStatements; -} - -bool Compiler::visit(AST::ThisExpression *) -{ - iLoadThis(); - return false; -} - -bool Compiler::visit(AST::NullExpression *) -{ - iLoadNull(); - return false; -} - -bool Compiler::visit(AST::RegExpLiteral *node) -{ - Q_ASSERT(node->pattern != 0); - - if (node->flags) - iNewRegExp(node->pattern, node->flags); - else - iNewRegExp(node->pattern); - - return false; -} - -bool Compiler::visit(AST::NumericLiteral *node) -{ - iLoadNumber(node->value); - return false; -} - -bool Compiler::visit(AST::StringLiteral *node) -{ - iNewString(node->value); - - return false; -} - -bool Compiler::visit(AST::ObjectLiteral *node) -{ - iNewObject(); - - FetchName fetchName(m_eng); - bool was = generateReferences(false); - for (AST::PropertyNameAndValueList *it = node->properties; it != 0; it = it->next) { - iLine(it->value); - iDuplicate(); - - QScriptNameIdImpl *name = fetchName(it->name); - Q_ASSERT(name != 0); - iLoadString(name); - iMakeReference(); - - it->value->accept(this); - iPutField(); - } - generateReferences(was); - - return false; -} - -bool Compiler::visit(AST::IdentifierExpression *node) -{ - Q_ASSERT(node->name != 0); - - if (node->name == m_eng->idTable()->id_arguments) - iLazyArguments(); - if (m_generateReferences) - iResolve(node->name); - else - iFetch(node->name); - - return false; -} - -bool Compiler::visit(AST::FunctionDeclaration *node) -{ - iLoadActivation(); - iLoadString(node->name); - iMakeReference(); - iNewClosure(node); - iPutField(); - return false; -} - -bool Compiler::visit(AST::FunctionExpression *node) -{ - iNewClosure(node); - if (node->name) { - iDuplicate(); - iLoadActivation(); - iSwap(); - iLoadString(node->name); - iSwap(); - iMakeReference(); - iSwap(); - iPutField(); - } - return false; -} - -bool Compiler::visit(AST::CallExpression *node) -{ - bool was = generateReferences(true); - node->base->accept(this); - generateReferences(false); - - int argc = 0; - for (AST::ArgumentList *it = node->arguments; it != 0; it = it->next) { - it->expression->accept(this); - ++argc; - } - - generateReferences(was); - - iCall(argc); - return false; -} - -bool Compiler::visit(AST::NewExpression *node) -{ - bool was = generateReferences(true); - node->expression->accept(this); - generateReferences(was); - iNew(0); - return false; -} - -bool Compiler::visit(AST::NewMemberExpression *node) -{ - bool was = generateReferences(true); - node->base->accept(this); - generateReferences(false); - - int argc = 0; - for (AST::ArgumentList *it = node->arguments; it != 0; it = it->next) { - it->expression->accept(this); - ++argc; - } - - generateReferences(was); - - iNew(argc); - return false; -} - -bool Compiler::visit(AST::FieldMemberExpression *node) -{ - bool was = generateReferences(false); - node->base->accept(this); - generateReferences(was); - - iLoadString(node->name); - - if (! was) - iFetchField(); - else - iMakeReference(); - - return false; -} - -bool Compiler::visit(AST::ArrayMemberExpression *node) -{ - bool was = generateReferences(false); - node->base->accept(this); - node->expression->accept(this); - generateReferences(was); - - if (! was) - iFetchField(); - else - iMakeReference(); - - return false; -} - -bool Compiler::visit(AST::PostIncrementExpression *node) -{ - bool was = generateReferences(true); - node->base->accept(this); - generateReferences(was); - iPostIncr(); - - return false; -} - -bool Compiler::visit(AST::PostDecrementExpression *node) -{ - bool was = generateReferences(true); - node->base->accept(this); - generateReferences(was); - iPostDecr(); - - return false; -} - -bool Compiler::visit(AST::PreIncrementExpression *node) -{ - bool was = generateReferences(true); - node->expression->accept(this); - generateReferences(was); - iIncr(); - return false; -} - -bool Compiler::visit(AST::PreDecrementExpression *node) -{ - bool was = generateReferences(true); - node->expression->accept(this); - generateReferences(was); - iDecr(); - return false; -} - -void Compiler::endVisit(AST::NotExpression *) -{ - iNot(); -} - -void Compiler::endVisit(AST::TildeExpression *) -{ - iBitNot(); -} - -bool Compiler::visit(AST::ThrowStatement *node) -{ - iLine(node); - return true; -} - -bool Compiler::visit(AST::TryStatement *node) -{ - int start = nextInstructionOffset(); - if (node->statement) - node->statement->accept(this); - int end = nextInstructionOffset(); - if (node->catchExpression) { - iBranch(0); // skip the catch if no exception - ExceptionHandlerDescriptor ehd(start, end, nextInstructionOffset()); - m_exceptionHandlers.append(ehd); - iBeginCatch(node->catchExpression->name); - node->catchExpression->statement->accept(this); - iEndCatch(); - patchInstruction(end, nextInstructionOffset() - end); - } - if (node->finallyExpression) { - if (!node->catchExpression) { - ExceptionHandlerDescriptor ehd(start, end, nextInstructionOffset()); - m_exceptionHandlers.prepend(ehd); - } - node->finallyExpression->statement->accept(this); - } - return false; -} - -void Compiler::endVisit(AST::ThrowStatement *node) -{ - if (! node->expression) - iLoadUndefined(); - - iThrow(); -} - -void Compiler::endVisit(AST::VoidExpression *) -{ - iPop(); - iLoadUndefined(); -} - -bool Compiler::visit(AST::TypeOfExpression *node) -{ - bool was = generateReferences(true); - node->expression->accept(this); - generateReferences(was); - iTypeOf(); - return false; -} - -bool Compiler::visit(AST::DeleteExpression *node) -{ - bool was = generateReferences(true); - node->expression->accept(this); - generateReferences(was); - iDelete(); - return false; -} - -bool Compiler::visit(AST::ReturnStatement *node) -{ - if (topLevelCompiler()) { - m_compilationUnit.setError(QString::fromUtf8("return outside function body"), - node->startLine); - return false; - } - iLine(node); - return true; -} - -void Compiler::endVisit(AST::ReturnStatement *node) -{ - if (! node->expression) - iLoadUndefined(); - - iRet(); -} - -bool Compiler::visit(AST::VariableStatement *node) -{ - AST::VariableDeclarationList *lst = node->declarations; - while (lst) { - if (lst->declaration->expression) { - iLine(node); - break; - } - lst = lst->next; - } - return true; -} - -bool Compiler::visit(AST::VariableDeclaration *node) -{ - if (node->expression != 0) { - iResolve(node->name); - node->expression->accept(this); - iAssign(); - iPop(); - } - - return false; -} - -bool Compiler::visit(AST::ConditionalExpression *node) -{ - node->expression->accept(this); - - int cond = nextInstructionOffset(); - iBranchFalse(0); - - node->ok->accept(this); - - if (! node->ko) { - patchInstruction(cond, nextInstructionOffset() - cond); - } else { - int terminator = nextInstructionOffset(); - iBranch(0); - node->ko->accept(this); - - patchInstruction(cond, terminator + 1 - cond); - patchInstruction(terminator, nextInstructionOffset() - terminator); - } - - return false; -} - -bool Compiler::visit(AST::IfStatement *node) -{ - iLine(node); - node->expression->accept(this); - - int cond = nextInstructionOffset(); - iBranchFalse(0); - - node->ok->accept(this); - - if (! node->ko) { - patchInstruction(cond, nextInstructionOffset() - cond); - } else { - int terminator = nextInstructionOffset(); - iBranch(0); - node->ko->accept(this); - - patchInstruction(cond, terminator + 1 - cond); - patchInstruction(terminator, nextInstructionOffset() - terminator); - } - if (!m_instructions.isEmpty() && m_instructions.last().op == QScriptInstruction::OP_Ret) - iNop(); - - return false; -} - -bool Compiler::visit(AST::Block *node) -{ - if (node->statements && m_loops.contains(node)) { - Loop &loop = m_loops[node]; - - node->statements->accept(this); - - loop.breakLabel.offset = nextInstructionOffset(); - - foreach (int index, loop.breakLabel.uses) { - patchInstruction(index, loop.breakLabel.offset - index); - } - - return false; - } - - return true; -} - -bool Compiler::visit(AST::WhileStatement *node) -{ - Loop *previousLoop = changeActiveLoop(&m_loops[node]); - m_activeLoop->continueLabel.offset = nextInstructionOffset(); - - iLine(node); - int again = nextInstructionOffset(); - node->expression->accept(this); - - int cond = nextInstructionOffset(); - iBranchFalse(0); - - bool was = iterationStatement(true); - bool was2 = generateLeaveOnBreak(false); - node->statement->accept(this); - generateLeaveOnBreak(was2); - iterationStatement(was); - - iBranch(again - nextInstructionOffset()); - patchInstruction(cond, nextInstructionOffset() - cond); - - m_activeLoop->breakLabel.offset = nextInstructionOffset(); - - foreach (int index, m_activeLoop->breakLabel.uses) { - patchInstruction(index, m_activeLoop->breakLabel.offset - index); - } - - foreach (int index, m_activeLoop->continueLabel.uses) { - patchInstruction(index, m_activeLoop->continueLabel.offset - index); - } - - changeActiveLoop(previousLoop); - m_loops.remove(node); - - return false; -} - -bool Compiler::visit(AST::DoWhileStatement *node) -{ - Loop *previousLoop = changeActiveLoop(&m_loops[node]); - int again = nextInstructionOffset(); - iLine(node); - bool was = iterationStatement(true); - node->statement->accept(this); - iterationStatement(was); - - m_activeLoop->continueLabel.offset = nextInstructionOffset(); - - node->expression->accept(this); - - iBranchTrue(again - nextInstructionOffset()); - m_activeLoop->breakLabel.offset = nextInstructionOffset(); - - foreach (int index, m_activeLoop->breakLabel.uses) { - patchInstruction(index, m_activeLoop->breakLabel.offset - index); - } - - foreach (int index, m_activeLoop->continueLabel.uses) { - patchInstruction(index, m_activeLoop->continueLabel.offset - index); - } - - changeActiveLoop(previousLoop); - m_loops.remove(node); - - return false; -} - -bool Compiler::visit(AST::ForEachStatement *node) -{ - Loop *previousLoop = changeActiveLoop(&m_loops[node]); - - iLine(node); - node->expression->accept(this); - iNewEnumeration(); - iDuplicate(); - iToFirstElement(); - - int again = nextInstructionOffset(); - m_activeLoop->continueLabel.offset = again; - iDuplicate(); - iHasNextElement(); - int cond = nextInstructionOffset(); - iBranchFalse(0); - bool was = generateReferences(true); - node->initialiser->accept(this); - generateReferences(was); - iNextElement(); - iAssign(); - iPop(); - was = iterationStatement(true); - node->statement->accept(this); - iterationStatement(was); - iBranch(again - nextInstructionOffset()); - patchInstruction(cond, nextInstructionOffset() - cond); - - m_activeLoop->breakLabel.offset = nextInstructionOffset(); - iPop(); // pop the Enumeration - - foreach (int index, m_activeLoop->breakLabel.uses) { - patchInstruction(index, m_activeLoop->breakLabel.offset - index); - } - - foreach (int index, m_activeLoop->continueLabel.uses) { - patchInstruction(index, m_activeLoop->continueLabel.offset - index); - } - - changeActiveLoop(previousLoop); - m_loops.remove(node); - - return false; -} - -bool Compiler::visit(AST::LocalForEachStatement *node) -{ - Loop *previousLoop = changeActiveLoop(&m_loops[node]); - - iLine(node); - node->declaration->accept(this); - node->expression->accept(this); - iNewEnumeration(); - iDuplicate(); - iToFirstElement(); - - int again = nextInstructionOffset(); - m_activeLoop->continueLabel.offset = again; - iDuplicate(); - iHasNextElement(); - int cond = nextInstructionOffset(); - iBranchFalse(0); - iResolve(node->declaration->name); - iNextElement(); - iAssign(); - iPop(); - bool was = iterationStatement(true); - node->statement->accept(this); - iterationStatement(was); - iBranch(again - nextInstructionOffset()); - patchInstruction(cond, nextInstructionOffset() - cond); - - m_activeLoop->breakLabel.offset = nextInstructionOffset(); - iPop(); // pop the Enumeration - - foreach (int index, m_activeLoop->breakLabel.uses) { - patchInstruction(index, m_activeLoop->breakLabel.offset - index); - } - - foreach (int index, m_activeLoop->continueLabel.uses) { - patchInstruction(index, m_activeLoop->continueLabel.offset - index); - } - - changeActiveLoop(previousLoop); - m_loops.remove(node); - - return false; -} - -void Compiler::visitForInternal(AST::Statement *node, AST::ExpressionNode *condition, AST::Statement *statement, AST::ExpressionNode *expression) -{ - Q_ASSERT(statement != 0); - - int again = nextInstructionOffset(); - if (condition != 0) { -// iLine(condition); - condition->accept(this); - } else { -// iLine(node); - iLoadNumber(1); - } - - int cond = nextInstructionOffset(); - iBranchFalse(0); - - Loop *previousLoop = changeActiveLoop(&m_loops[node]); - - bool was = iterationStatement(true); - statement->accept(this); - iterationStatement(was); - - m_activeLoop->continueLabel.offset = nextInstructionOffset(); - - if (expression != 0) { - expression->accept(this); - iPop(); - } - - iBranch(again - nextInstructionOffset()); - patchInstruction(cond, nextInstructionOffset() - cond); - - m_activeLoop->breakLabel.offset = nextInstructionOffset(); - - foreach (int index, m_activeLoop->breakLabel.uses) { - patchInstruction(index, m_activeLoop->breakLabel.offset - index); - } - - foreach (int index, m_activeLoop->continueLabel.uses) { - patchInstruction(index, m_activeLoop->continueLabel.offset - index); - } - - changeActiveLoop(previousLoop); - m_loops.remove(node); -} - -bool Compiler::visit(AST::ForStatement *node) -{ - iLine(node); - - if (node->initialiser != 0) { - node->initialiser->accept(this); - iPop(); - } - - visitForInternal(node, node->condition, node->statement, node->expression); - return false; -} - -bool Compiler::visit(AST::LocalForStatement *node) -{ - iLine(node); - - if (node->declarations) - node->declarations->accept(this); - - visitForInternal(node, node->condition, node->statement, node->expression); - return false; -} - -bool Compiler::isAssignmentOperator(int op) const -{ - switch (op) { - - case QSOperator::Assign: - case QSOperator::InplaceAnd: - case QSOperator::InplaceSub: - case QSOperator::InplaceDiv: - case QSOperator::InplaceAdd: - case QSOperator::InplaceLeftShift: - case QSOperator::InplaceMod: - case QSOperator::InplaceMul: - case QSOperator::InplaceOr: - case QSOperator::InplaceRightShift: - case QSOperator::InplaceURightShift: - case QSOperator::InplaceXor: - return true; - - default: - break; - - } - - return false; -} - -int Compiler::inplaceAssignmentOperator(int op) const -{ - switch (op) { - case QSOperator::BitAnd: - return QSOperator::InplaceAnd; - case QSOperator::Sub: - return QSOperator::InplaceSub; - case QSOperator::Div: - return QSOperator::InplaceDiv; - case QSOperator::Add: - return QSOperator::InplaceAdd; - case QSOperator::LShift: - return QSOperator::InplaceLeftShift; - case QSOperator::Mod: - return QSOperator::InplaceMod; - case QSOperator::Mul: - return QSOperator::InplaceMul; - case QSOperator::BitOr: - return QSOperator::InplaceOr; - case QSOperator::RShift: - return QSOperator::InplaceRightShift; - case QSOperator::URShift: - return QSOperator::InplaceURightShift; - case QSOperator::BitXor: - return QSOperator::InplaceXor; - - default: - break; - - } - - return(-1); -} - -bool Compiler::visit(AST::Expression *node) -{ - node->left->accept(this); - iPop(); // ### or iSync? - node->right->accept(this); - return false; -} - -bool Compiler::visit(AST::BinaryExpression *node) -{ - if (isAssignmentOperator(node->op)) { - bool was = generateReferences(true); - node->left->accept(this); - generateReferences(was); - } else { - node->left->accept(this); - } - - int address = 0; - if (node->op == QSOperator::Or || node->op == QSOperator::And) { - iDuplicate(); - address = nextInstructionOffset(); - if (node->op == QSOperator::Or) - iBranchTrue(0); - else - iBranchFalse(0); - iPop(); - } - - int op = node->op; - Compare compare; - if ((op == QSOperator::Assign) && node->right->binaryExpressionCast() - && (inplaceAssignmentOperator(node->right->binaryExpressionCast()->op) != -1) - && compare(node->left, node->right->binaryExpressionCast()->left)) { - // node->left is equivalent to node->right->left, so we generate - // x op= y rather than x = x op y - op = inplaceAssignmentOperator(node->right->binaryExpressionCast()->op); - node->right->binaryExpressionCast()->right->accept(this); - } else { - node->right->accept(this); - } - - switch (op) { - - case QSOperator::Assign: - iAssign(); - break; - - case QSOperator::InplaceAnd: - iInplaceAnd(); - break; - - case QSOperator::InplaceSub: - iInplaceSub(); - break; - - case QSOperator::InplaceDiv: - iInplaceDiv(); - break; - - case QSOperator::InplaceAdd: - iInplaceAdd(); - break; - - case QSOperator::InplaceLeftShift: - iInplaceLeftShift(); - break; - - case QSOperator::InplaceMod: - iInplaceMod(); - break; - - case QSOperator::InplaceMul: - iInplaceMul(); - break; - - case QSOperator::InplaceOr: - iInplaceOr(); - break; - - case QSOperator::InplaceRightShift: - iInplaceRightShift(); - break; - - case QSOperator::InplaceURightShift: - iInplaceURightShift(); - break; - - case QSOperator::InplaceXor: - iInplaceXor(); - break; - - case QSOperator::BitAnd: - iBitAnd(); - break; - - case QSOperator::BitOr: - iBitOr(); - break; - - case QSOperator::BitXor: - iBitXor(); - break; - - case QSOperator::LShift: - iLeftShift(); - break; - - case QSOperator::Mod: - iMod(); - break; - - case QSOperator::RShift: - iRightShift(); - break; - - case QSOperator::URShift: - iURightShift(); - break; - - case QSOperator::InstanceOf: - iInstanceOf(); - break; - - case QSOperator::Add: - iAdd(); - break; - - case QSOperator::And: - patchInstruction(address, nextInstructionOffset() - address); - break; - - case QSOperator::Div: - iDiv(); - break; - - case QSOperator::Equal: - iEqual(); - break; - - case QSOperator::Ge: - iGreatOrEqual(); - break; - - case QSOperator::Gt: - iGreatThan(); - break; - - case QSOperator::Le: - iLessOrEqual(); - break; - - case QSOperator::Lt: - iLessThan(); - break; - - case QSOperator::Mul: - iMul(); - break; - - case QSOperator::NotEqual: - iNotEqual(); - break; - - case QSOperator::Or: - patchInstruction(address, nextInstructionOffset() - address); - break; - - case QSOperator::Sub: - iSub(); - break; - - case QSOperator::StrictEqual: - iStrictEqual(); - break; - - case QSOperator::StrictNotEqual: - iStrictNotEqual(); - break; - - case QSOperator::In: - iIn(); - break; - } - - return false; -} - -bool Compiler::visit(AST::TrueLiteral *) -{ - iLoadTrue(); - return false; -} - -bool Compiler::visit(AST::FalseLiteral *) -{ - iLoadFalse(); - return false; -} - -bool Compiler::visit(AST::SwitchStatement *node) -{ - iLine(node); - Loop *previousLoop = changeActiveLoop(&m_loops[node]); - - node->expression->accept(this); - - bool was = switchStatement(true); - - AST::CaseClauses *clauses; - int skipIndex = -1; - int fallthroughIndex = -1; - // ### make a function for this - for (clauses = node->block->clauses; clauses != 0; clauses = clauses->next) { - AST::CaseClause *clause = clauses->clause; - if (skipIndex != -1) - patchInstruction(skipIndex, nextInstructionOffset() - skipIndex); - - iDuplicate(); // expression - clause->expression->accept(this); - iStrictEqual(); - skipIndex = nextInstructionOffset(); - iBranchFalse(0); // next case - - if (fallthroughIndex != -1) // previous case falls through to here - patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex); - - int breaksBefore = m_activeLoop->breakLabel.uses.count(); - if (clause->statements) - clause->statements->accept(this); - int breaksAfter = m_activeLoop->breakLabel.uses.count(); - if (breaksAfter == breaksBefore) { // fallthrough - fallthroughIndex = nextInstructionOffset(); - iBranch(0); - } else { // no fallthrough (break) - fallthroughIndex = -1; - } - } - - if (fallthroughIndex != -1) { - patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex); - fallthroughIndex = -1; - } - - int defaultIndex = -1; - if (node->block->defaultClause) { - int skipDefaultIndex = -1; - if (!node->block->clauses && node->block->moreClauses) { - skipDefaultIndex = nextInstructionOffset(); - iBranch(0); - } - defaultIndex = nextInstructionOffset(); - int breaksBefore = m_activeLoop->breakLabel.uses.count(); - if (node->block->defaultClause->statements) - node->block->defaultClause->statements->accept(this); - int breaksAfter = m_activeLoop->breakLabel.uses.count(); - if (breaksAfter == breaksBefore) { // fallthrough - fallthroughIndex = nextInstructionOffset(); - iBranch(0); - } else { // no fallthrough (break) - fallthroughIndex = -1; - } - if (skipDefaultIndex != -1) - patchInstruction(skipDefaultIndex, nextInstructionOffset() - skipDefaultIndex); - } - - for (clauses = node->block->moreClauses; clauses != 0; clauses = clauses->next) { - AST::CaseClause *clause = clauses->clause; - if (skipIndex != -1) - patchInstruction(skipIndex, nextInstructionOffset() - skipIndex); - - iDuplicate(); // expression - clause->expression->accept(this); - iStrictEqual(); - skipIndex = nextInstructionOffset(); - iBranchFalse(0); // next case - - if (fallthroughIndex != -1) // previous case falls through to here - patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex); - - int breaksBefore = m_activeLoop->breakLabel.uses.count(); - if (clause->statements) - clause->statements->accept(this); - int breaksAfter = m_activeLoop->breakLabel.uses.count(); - if (breaksAfter == breaksBefore) { // fallthrough - fallthroughIndex = nextInstructionOffset(); - iBranch(0); - } else { // no fallthrough (break) - fallthroughIndex = -1; - } - } - - if (skipIndex != -1) { - patchInstruction(skipIndex, nextInstructionOffset() - skipIndex); - if (defaultIndex != -1) - iBranch(defaultIndex - nextInstructionOffset()); // goto default - } - - if (fallthroughIndex != -1) - patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex); - - // backpatch the breaks - int term = nextInstructionOffset(); - foreach (int index, m_activeLoop->breakLabel.uses) { - patchInstruction(index, term - index); - } - - iPop(); // expression - - if (previousLoop && !m_activeLoop->continueLabel.uses.isEmpty()) { - // join the continues and add to outer loop - iBranch(3); - foreach (int index, m_activeLoop->continueLabel.uses) { - patchInstruction(index, nextInstructionOffset() - index); - } - iPop(); - iBranch(0); - previousLoop->continueLabel.uses.append(nextInstructionOffset() - 1); - } - - switchStatement(was); - changeActiveLoop(previousLoop); - m_loops.remove(node); - return false; -} - -bool Compiler::visit(AST::LabelledStatement *node) -{ - Loop *loop = findLoop(node->label); - if (loop != 0) { - QString str = m_eng->toString(node->label); - m_compilationUnit.setError(QString::fromUtf8("duplicate label `%1'").arg(str), - node->startLine); - return false; - } - - loop = &m_loops[node->statement]; - loop->name = node->label; - node->statement->accept(this); - if (m_loops.contains(node->statement)) { - loop->breakLabel.offset = nextInstructionOffset(); - foreach (int index, loop->breakLabel.uses) { - patchInstruction(index, loop->breakLabel.offset - index); - } - m_loops.remove(node->statement); - } - return false; -} - -bool Compiler::visit(AST::ExpressionStatement *node) -{ - if (node->expression) - iLine(node->expression); - return true; -} - -void Compiler::endVisit(AST::ExpressionStatement *) -{ - if (topLevelCompiler()) - iSync(); - else - iPop(); -} - -void Compiler::endVisit(AST::UnaryPlusExpression *) -{ - iUnaryPlus(); -} - -void Compiler::endVisit(AST::UnaryMinusExpression *) -{ - iUnaryMinus(); -} - -bool Compiler::visit(AST::ContinueStatement *node) -{ - iLine(node); - return true; -} - -void Compiler::endVisit(AST::ContinueStatement *node) -{ - int offset = nextInstructionOffset(); - iBranch(0); - - Loop *loop = findLoop(node->label); - if (!loop || !m_iterationStatement) { - m_compilationUnit.setError(QString::fromUtf8("label not found"), - node->startLine); - return; - } - - loop->continueLabel.uses.append(offset); -} - -bool Compiler::visit(AST::BreakStatement *node) -{ - iLine(node); - return true; -} - -void Compiler::endVisit(AST::BreakStatement *node) -{ - Loop *loop = findLoop(node->label); - if (! loop) { - m_compilationUnit.setError(QString::fromUtf8("label not found"), - node->startLine); - return; - } - - if (m_generateLeaveWithOnBreak) - iLeaveWith(); - int offset = nextInstructionOffset(); - iBranch(0); - loop->breakLabel.uses.append(offset); -} - -void Compiler::endVisit(AST::EmptyStatement *node) -{ - iLine(node); -} - -bool Compiler::visit(AST::DebuggerStatement *node) -{ - iLine(node); - iDebugger(); - return false; -} - -void Compiler::patchInstruction(int index, int offset) -{ - QScriptInstruction &i = m_instructions[index]; - - switch (i.op) { - case QScriptInstruction::OP_Branch: - case QScriptInstruction::OP_BranchFalse: - case QScriptInstruction::OP_BranchTrue: - m_eng->newInteger(&i.operand[0], offset); - break; - - default: - Q_ASSERT_X(0, "Compiler::patchInstruction()", "expected a branch instruction"); - break; - } -} - -bool Compiler::visit(AST::WithStatement *node) -{ - iLine(node); - node->expression->accept(this); - iEnterWith(); - bool was = withStatement(true); - bool was2 = generateLeaveOnBreak(true); - node->statement->accept(this); - generateLeaveOnBreak(was2); - withStatement(was); - iLeaveWith(); - return false; -} - -bool Compiler::visit(AST::ArrayLiteral *node) -{ - iNewArray(); - - int length = 0; - - for (AST::ElementList *it = node->elements; it != 0; it = it->next) { - for (AST::Elision *eit = it->elision; eit != 0; eit = eit->next) { - iDuplicate(); - iLoadNumber(length); - iMakeReference(); - iLoadUndefined(); - iAssign(); - iPop(); - ++length; - } - - if (it->expression) { - iDuplicate(); - iLoadNumber(length); - iMakeReference(); - it->expression->accept(this); - iAssign(); - iPop(); - ++length; - } - } - - for (AST::Elision *eit = node->elision; eit != 0; eit = eit->next) { - iDuplicate(); - iLoadNumber(length); - iMakeReference(); - iLoadUndefined(); - iAssign(); - iPop(); - ++length; - } - - return false; -} - -void Compiler::iLoadUndefined() -{ - pushInstruction(QScriptInstruction::OP_LoadUndefined); -} - -void Compiler::iLoadThis() -{ - pushInstruction(QScriptInstruction::OP_LoadThis); -} - -void Compiler::iLoadActivation() -{ - pushInstruction(QScriptInstruction::OP_LoadActivation); -} - -void Compiler::iLoadNull() -{ - pushInstruction(QScriptInstruction::OP_LoadNull); -} - -void Compiler::iLoadNumber(double number) -{ - QScriptValueImpl arg0(number); - pushInstruction(QScriptInstruction::OP_LoadNumber, arg0); -} - -void Compiler::iLoadString(QScriptNameIdImpl *id) -{ - QScriptValueImpl arg0; - id->persistent = true; - m_eng->newNameId(&arg0, id); - pushInstruction(QScriptInstruction::OP_LoadString, arg0); -} - -void Compiler::iDuplicate() -{ - pushInstruction(QScriptInstruction::OP_Duplicate); -} - -void Compiler::iSwap() -{ - pushInstruction(QScriptInstruction::OP_Swap); -} - -void Compiler::iResolve(QScriptNameIdImpl *id) -{ - QScriptValueImpl arg0; - id->persistent = true; - m_eng->newNameId(&arg0, id); - pushInstruction(QScriptInstruction::OP_Resolve, arg0); -} - -void Compiler::iPutField() -{ - pushInstruction(QScriptInstruction::OP_PutField); -} - -void Compiler::iCall(int argc) -{ - QScriptValueImpl arg0; - m_eng->newInteger(&arg0, argc); - pushInstruction(QScriptInstruction::OP_Call, arg0); -} - -void Compiler::iNew(int argc) -{ - QScriptValueImpl arg0; - m_eng->newInteger(&arg0, argc); - pushInstruction(QScriptInstruction::OP_New, arg0); -} - -void Compiler::iFetchField() -{ - pushInstruction(QScriptInstruction::OP_FetchField); -} - -void Compiler::iLazyArguments() -{ - pushInstruction(QScriptInstruction::OP_LazyArguments); -} - -void Compiler::iRet() -{ - pushInstruction(QScriptInstruction::OP_Ret); -} - -void Compiler::iDeclareLocal(QScriptNameIdImpl *id, bool readOnly) -{ - QScriptValueImpl arg0; - id->persistent = true; - m_eng->newNameId(&arg0, id); - QScriptValueImpl arg1; - m_eng->newInteger(&arg1, readOnly); - pushInstruction(QScriptInstruction::OP_DeclareLocal, arg0, arg1); -} - -void Compiler::iAssign() -{ - pushInstruction(QScriptInstruction::OP_Assign); -} - -void Compiler::iBitAnd() -{ - pushInstruction(QScriptInstruction::OP_BitAnd); -} - -void Compiler::iBitOr() -{ - pushInstruction(QScriptInstruction::OP_BitOr); -} - -void Compiler::iBitXor() -{ - pushInstruction(QScriptInstruction::OP_BitXor); -} - -void Compiler::iLeftShift() -{ - pushInstruction(QScriptInstruction::OP_LeftShift); -} - -void Compiler::iMod() -{ - pushInstruction(QScriptInstruction::OP_Mod); -} - -void Compiler::iRightShift() -{ - pushInstruction(QScriptInstruction::OP_RightShift); -} - -void Compiler::iURightShift() -{ - pushInstruction(QScriptInstruction::OP_URightShift); -} - -void Compiler::iAdd() -{ - pushInstruction(QScriptInstruction::OP_Add); -} - -void Compiler::iDiv() -{ - pushInstruction(QScriptInstruction::OP_Div); -} - -void Compiler::iEqual() -{ - pushInstruction(QScriptInstruction::OP_Equal); -} - -void Compiler::iGreatOrEqual() -{ - pushInstruction(QScriptInstruction::OP_GreatOrEqual); -} - -void Compiler::iGreatThan() -{ - pushInstruction(QScriptInstruction::OP_GreatThan); -} - -void Compiler::iLessOrEqual() -{ - pushInstruction(QScriptInstruction::OP_LessOrEqual); -} - -void Compiler::iLessThan() -{ - pushInstruction(QScriptInstruction::OP_LessThan); -} - -void Compiler::iMul() -{ - pushInstruction(QScriptInstruction::OP_Mul); -} - -void Compiler::iNotEqual() -{ - pushInstruction(QScriptInstruction::OP_NotEqual); -} - -void Compiler::iSub() -{ - pushInstruction(QScriptInstruction::OP_Sub); -} - -void Compiler::iStrictEqual() -{ - pushInstruction(QScriptInstruction::OP_StrictEqual); -} - -void Compiler::iStrictNotEqual() -{ - pushInstruction(QScriptInstruction::OP_StrictNotEqual); -} - -void Compiler::iBranch(int index) -{ - QScriptValueImpl arg0; - m_eng->newInteger(&arg0, index); - pushInstruction(QScriptInstruction::OP_Branch, arg0); -} - -void Compiler::iBranchFalse(int index) -{ - QScriptValueImpl arg0; - m_eng->newInteger(&arg0, index); - pushInstruction(QScriptInstruction::OP_BranchFalse, arg0); -} - -void Compiler::iBranchTrue(int index) -{ - QScriptValueImpl arg0; - m_eng->newInteger(&arg0, index); - pushInstruction(QScriptInstruction::OP_BranchTrue, arg0); -} - -void Compiler::iNewClosure(AST::FunctionExpression *expr) -{ - QScriptValueImpl arg0; - m_eng->newPointer(&arg0, expr); - - pushInstruction(QScriptInstruction::OP_NewClosure, arg0); -} - -void Compiler::iIncr() -{ - pushInstruction(QScriptInstruction::OP_Incr); -} - -void Compiler::iDecr() -{ - pushInstruction(QScriptInstruction::OP_Decr); -} - -void Compiler::iPop() -{ - pushInstruction(QScriptInstruction::OP_Pop); -} - -void Compiler::iFetch(QScriptNameIdImpl *id) -{ - if (m_generateFastArgumentLookup) { - int index = m_formals.indexOf(id); - - if (index != -1) { - QScriptValueImpl arg0; - m_eng->newInteger(&arg0, index); - pushInstruction(QScriptInstruction::OP_Receive, arg0); - return; - } - } - - QScriptValueImpl arg0; - id->persistent = true; - m_eng->newNameId(&arg0, id); - pushInstruction(QScriptInstruction::OP_Fetch, arg0); -} - -void Compiler::iLoadTrue() -{ - pushInstruction(QScriptInstruction::OP_LoadTrue); -} - -void Compiler::iLoadFalse() -{ - pushInstruction(QScriptInstruction::OP_LoadFalse); -} - -void Compiler::iUnaryMinus() -{ - pushInstruction(QScriptInstruction::OP_UnaryMinus); -} - -void Compiler::iUnaryPlus() -{ - pushInstruction(QScriptInstruction::OP_UnaryPlus); -} - -void Compiler::iPostIncr() -{ - pushInstruction(QScriptInstruction::OP_PostIncr); -} - -void Compiler::iPostDecr() -{ - pushInstruction(QScriptInstruction::OP_PostDecr); -} - -void Compiler::iNewArray() -{ - pushInstruction(QScriptInstruction::OP_NewArray); -} - -void Compiler::iNewObject() -{ - pushInstruction(QScriptInstruction::OP_NewObject); -} - -void Compiler::iTypeOf() -{ - pushInstruction(QScriptInstruction::OP_TypeOf); -} - -void Compiler::iDelete() -{ - pushInstruction(QScriptInstruction::OP_Delete); -} - -void Compiler::iInstanceOf() -{ - pushInstruction(QScriptInstruction::OP_InstanceOf); -} - -void Compiler::iInplaceAnd() -{ - pushInstruction(QScriptInstruction::OP_InplaceAnd); -} - -void Compiler::iInplaceSub() -{ - pushInstruction(QScriptInstruction::OP_InplaceSub); -} - -void Compiler::iInplaceDiv() -{ - pushInstruction(QScriptInstruction::OP_InplaceDiv); -} - -void Compiler::iInplaceAdd() -{ - pushInstruction(QScriptInstruction::OP_InplaceAdd); -} - -void Compiler::iInplaceLeftShift() -{ - pushInstruction(QScriptInstruction::OP_InplaceLeftShift); -} - -void Compiler::iInplaceMod() -{ - pushInstruction(QScriptInstruction::OP_InplaceMod); -} - -void Compiler::iInplaceMul() -{ - pushInstruction(QScriptInstruction::OP_InplaceMul); -} - -void Compiler::iInplaceOr() -{ - pushInstruction(QScriptInstruction::OP_InplaceOr); -} - -void Compiler::iInplaceRightShift() -{ - pushInstruction(QScriptInstruction::OP_InplaceRightShift); -} - -void Compiler::iInplaceURightShift() -{ - pushInstruction(QScriptInstruction::OP_InplaceURightShift); -} - -void Compiler::iInplaceXor() -{ - pushInstruction(QScriptInstruction::OP_InplaceXor); -} - -void Compiler::iThrow() -{ - pushInstruction(QScriptInstruction::OP_Throw); -} - -void Compiler::iLine(AST::Node *node) -{ - if (! node) - return; - - QScriptValueImpl arg0; - m_eng->newInteger(&arg0, node->startLine); - - QScriptValueImpl arg1; - m_eng->newInteger(&arg1, node->startColumn); - - pushInstruction(QScriptInstruction::OP_Line, arg0, arg1); -} - -void Compiler::iBitNot() -{ - pushInstruction(QScriptInstruction::OP_BitNot); -} - -void Compiler::iNot() -{ - pushInstruction(QScriptInstruction::OP_Not); -} - -void Compiler::iNewRegExp(QScriptNameIdImpl *pattern) -{ - QScriptValueImpl arg0; - pattern->persistent = true; - m_eng->newNameId(&arg0, pattern); - pushInstruction(QScriptInstruction::OP_NewRegExp, arg0); -} - -void Compiler::iNewRegExp(QScriptNameIdImpl *pattern, int flags) -{ - QScriptValueImpl arg0; - pattern->persistent = true; - m_eng->newNameId(&arg0, pattern); - - QScriptValueImpl arg1; - m_eng->newInteger(&arg1, flags); - - pushInstruction(QScriptInstruction::OP_NewRegExp, arg0, arg1); -} - -void Compiler::iNewEnumeration() -{ - pushInstruction(QScriptInstruction::OP_NewEnumeration); -} - -void Compiler::iToFirstElement() -{ - pushInstruction(QScriptInstruction::OP_ToFirstElement); -} - -void Compiler::iHasNextElement() -{ - pushInstruction(QScriptInstruction::OP_HasNextElement); -} - -void Compiler::iNextElement() -{ - pushInstruction(QScriptInstruction::OP_NextElement); -} - -void Compiler::iEnterWith() -{ - pushInstruction(QScriptInstruction::OP_EnterWith); -} - -void Compiler::iLeaveWith() -{ - pushInstruction(QScriptInstruction::OP_LeaveWith); -} - -void Compiler::iBeginCatch(QScriptNameIdImpl *id) -{ - QScriptValueImpl arg0; - id->persistent = true; - m_eng->newNameId(&arg0, id); - pushInstruction(QScriptInstruction::OP_BeginCatch, arg0); -} - -void Compiler::iEndCatch() -{ - pushInstruction(QScriptInstruction::OP_EndCatch); -} - -void Compiler::iSync() -{ - pushInstruction(QScriptInstruction::OP_Sync); -} - -void Compiler::iHalt() -{ - pushInstruction(QScriptInstruction::OP_Halt); -} - -void Compiler::iMakeReference() -{ - pushInstruction(QScriptInstruction::OP_MakeReference); -} - -void Compiler::iIn() -{ - pushInstruction(QScriptInstruction::OP_In); -} - -void Compiler::iNop() -{ - pushInstruction(QScriptInstruction::OP_Nop); -} - -void Compiler::iNewString(QScriptNameIdImpl *id) -{ - QScriptValueImpl arg0; - id->persistent = true; - m_eng->newNameId(&arg0, id); - pushInstruction(QScriptInstruction::OP_NewString, arg0); -} - -void Compiler::iDebugger() -{ - pushInstruction(QScriptInstruction::OP_Debugger); -} - -Compiler::Loop *Compiler::findLoop(QScriptNameIdImpl *name) -{ - if (! name) - return m_activeLoop; - - QMap<AST::Statement*, Loop>::iterator it = m_loops.begin(); - - for (; it != m_loops.end(); ++it) { - Loop &loop = *it; - - if (loop.name == name) - return &loop; - } - - return 0; -} - - -} // namespace QScript - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptcompiler_p.h b/src/script/qscriptcompiler_p.h deleted file mode 100644 index 397abf1..0000000 --- a/src/script/qscriptcompiler_p.h +++ /dev/null @@ -1,377 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTCOMPILER_P_H -#define QSCRIPTCOMPILER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QMap> - -#ifndef QT_NO_SCRIPT - -#include <QtCore/QVector> - -#include "qscriptastvisitor_p.h" -#include "qscriptasm_p.h" - -QT_BEGIN_NAMESPACE - -class QScriptEnginePrivate; - -namespace QScript { - -class Compiler: protected AST::Visitor -{ -public: - Compiler(QScriptEnginePrivate *eng); - virtual ~Compiler(); - - inline QScriptEnginePrivate *engine() const { return m_eng; } - - bool topLevelCompiler() const; - void setTopLevelCompiler(bool b); - - CompilationUnit compile(AST::Node *node, const QList<QScriptNameIdImpl *> &formals - = QList<QScriptNameIdImpl *>()); - - struct Label { - Label(int o = 0): - offset (o) {} - - int offset; - QVector<int> uses; - }; - -// instruction set - void iAdd(); - void iAssign(); - void iBitAnd(); - void iBitOr(); - void iBitXor(); - void iBitNot(); - void iBranch(int index); - void iBranchTrue(int index); - void iBranchFalse(int index); - void iCall(int argc); - void iDeclareLocal(QScriptNameIdImpl *id, bool readOnly); - void iDecr(); - void iDelete(); - void iDiv(); - void iDuplicate(); - void iEqual(); - void iFetch(QScriptNameIdImpl *id); - void iFetchField(); - void iLazyArguments(); - void iGreatOrEqual(); - void iGreatThan(); - void iIncr(); - void iInplaceAdd(); - void iInplaceAnd(); - void iInplaceDecr(); - void iInplaceDiv(); - void iInplaceLeftShift(); - void iInplaceMod(); - void iInplaceMul(); - void iInplaceOr(); - void iInplaceRightShift(); - void iInplaceSub(); - void iInplaceURightShift(); - void iInstanceOf(); - void iLeftShift(); - void iLessOrEqual(); - void iLessThan(); - void iLoadFalse(); - void iLoadNumber(double number); - void iLoadString(QScriptNameIdImpl *id); - void iNewString(QScriptNameIdImpl *id); - void iLoadThis(); - void iLoadActivation(); - void iLoadNull(); - void iLoadTrue(); - void iLoadUndefined(); - void iMod(); - void iMul(); - void iUnaryPlus(); - void iUnaryMinus(); - void iNew(int argc); - void iNewArray(); - void iNewClosure(AST::FunctionExpression *expr); - void iNewObject(); - void iNewRegExp(QScriptNameIdImpl *pattern); - void iNewRegExp(QScriptNameIdImpl *pattern, int flags); - void iNot(); - void iNotEqual(); - void iPop(); - void iPostDecr(); - void iPostIncr(); - void iPutField(); - void iResolve(QScriptNameIdImpl *id); - void iRet(); - void iRightShift(); - void iSub(); - void iStrictEqual(); - void iStrictNotEqual(); - void iSwap(); - void iThrow(); - void iTypeOf(); - void iURightShift(); - void iInplaceXor(); - void iLine(AST::Node *node); - void iNewEnumeration(); - void iToFirstElement(); - void iHasNextElement(); - void iNextElement(); - void iEnterWith(); - void iLeaveWith(); - void iBeginCatch(QScriptNameIdImpl *id); - void iEndCatch(); - void iSync(); - void iHalt(); - void iMakeReference(); - void iIn(); - void iNop(); - void iDebugger(); - -protected: - virtual bool preVisit(AST::Node *node); - - virtual bool visit(AST::ArrayLiteral *node); - virtual bool visit(AST::ArrayMemberExpression *node); - virtual bool visit(AST::Expression *node); - virtual bool visit(AST::BinaryExpression *node); - virtual bool visit(AST::BreakStatement *node); - virtual bool visit(AST::CallExpression *node); - virtual bool visit(AST::ConditionalExpression *node); - virtual bool visit(AST::ContinueStatement *node); - virtual bool visit(AST::DeleteExpression *node); - virtual bool visit(AST::DoWhileStatement *node); - virtual bool visit(AST::ExpressionStatement *node); - virtual bool visit(AST::FalseLiteral *node); - virtual bool visit(AST::FieldMemberExpression *node); - virtual bool visit(AST::ForEachStatement *node); - virtual bool visit(AST::LocalForEachStatement *node); - virtual bool visit(AST::ForStatement *node); - virtual bool visit(AST::FunctionDeclaration *node); - virtual bool visit(AST::FunctionExpression *node); - virtual bool visit(AST::FunctionSourceElement *node); - virtual bool visit(AST::IdentifierExpression *node); - virtual bool visit(AST::IfStatement *node); - virtual bool visit(AST::LabelledStatement *node); - virtual bool visit(AST::LocalForStatement *node); - virtual bool visit(AST::NewExpression *node); - virtual bool visit(AST::NewMemberExpression *node); - virtual bool visit(AST::NumericLiteral *node); - virtual bool visit(AST::ObjectLiteral *node); - virtual bool visit(AST::PostDecrementExpression *node); - virtual bool visit(AST::PostIncrementExpression *node); - virtual bool visit(AST::PreDecrementExpression *node); - virtual bool visit(AST::PreIncrementExpression *node); - virtual bool visit(AST::RegExpLiteral *node); - virtual bool visit(AST::ReturnStatement *node); - virtual bool visit(AST::SourceElements *node); - virtual bool visit(AST::StatementList *node); - virtual bool visit(AST::StatementSourceElement *node); - virtual bool visit(AST::StringLiteral *node); - virtual bool visit(AST::SwitchStatement *node); - virtual bool visit(AST::ThisExpression *node); - virtual bool visit(AST::NullExpression *node); - virtual bool visit(AST::ThrowStatement *node); - virtual bool visit(AST::TryStatement *node); - virtual bool visit(AST::TrueLiteral *node); - virtual bool visit(AST::VariableStatement *node); - virtual bool visit(AST::VariableDeclaration *node); - virtual bool visit(AST::WhileStatement *node); - virtual bool visit(AST::WithStatement *node); - virtual bool visit(AST::Block *node); - virtual bool visit(AST::TypeOfExpression *node); - virtual bool visit(AST::DebuggerStatement *node); - - virtual void endVisit(AST::BreakStatement *node); - virtual void endVisit(AST::ContinueStatement *node); - virtual void endVisit(AST::ExpressionStatement *node); - virtual void endVisit(AST::NotExpression *node); - virtual void endVisit(AST::ReturnStatement *node); - virtual void endVisit(AST::ThrowStatement *node); - virtual void endVisit(AST::TildeExpression *node); - virtual void endVisit(AST::UnaryPlusExpression *node); - virtual void endVisit(AST::UnaryMinusExpression *node); - virtual void endVisit(AST::VoidExpression *node); - virtual void endVisit(AST::EmptyStatement *node); - - void visitForInternal(AST::Statement *node, AST::ExpressionNode *condition, - AST::Statement *statement, AST::ExpressionNode *expression); - - bool isAssignmentOperator(int op) const; - int inplaceAssignmentOperator(int op) const; - - inline int nextInstructionOffset() const - { return m_instructions.count(); } - - inline void pushInstruction(QScriptInstruction::Operator op) - { - pushInstruction(op, QScriptValueImpl(), QScriptValueImpl()); - } - - inline void pushInstruction(QScriptInstruction::Operator op, - const QScriptValueImpl &arg1) - { - pushInstruction(op, arg1, QScriptValueImpl()); - } - - inline void pushInstruction(QScriptInstruction::Operator op, - const QScriptValueImpl &arg1, - const QScriptValueImpl &arg2) - { - QScriptInstruction i; - i.op = op; - i.operand[0] = arg1; - i.operand[1] = arg2; - m_instructions.append(i); - } - - inline bool generateReferences(bool b) - { - bool was = m_generateReferences; - m_generateReferences = b; - return was; - } - - inline bool generateFastArgumentLookup(bool b) - { - bool was = m_generateFastArgumentLookup; - m_generateFastArgumentLookup= b; - return was; - } - - inline bool iterationStatement(bool b) - { - bool was = m_iterationStatement; - m_iterationStatement = b; - return was; - } - - inline bool switchStatement(bool b) - { - bool was = m_switchStatement; - m_switchStatement = b; - return was; - } - - inline bool changeParseStatements(bool b) - { - bool was = m_parseStatements; - m_parseStatements = b; - return was; - } - - inline bool withStatement(bool b) - { - bool was = m_withStatement; - m_withStatement = b; - return was; - } - - inline bool generateLeaveOnBreak(bool b) - { - bool was = m_generateLeaveWithOnBreak; - m_generateLeaveWithOnBreak = b; - return was; - } - - void patchInstruction(int index, int offset); - -private: - QScriptEnginePrivate *m_eng; - - uint m_generateReferences: 1; - uint m_iterationStatement: 1; - uint m_switchStatement: 1; - uint m_withStatement: 1; - uint m_generateLeaveWithOnBreak: 1; - uint m_generateFastArgumentLookup: 1; - uint m_parseStatements: 1; - uint m_pad: 25; - - bool m_topLevelCompiler; // bit - QVector<QScriptInstruction> m_instructions; - QVector<ExceptionHandlerDescriptor> m_exceptionHandlers; - QList<QScriptNameIdImpl *> m_formals; - - struct Loop { - Loop(QScriptNameIdImpl *n = 0): - name(n) {} - - QScriptNameIdImpl *name; - Label breakLabel; - Label continueLabel; - }; - - inline Loop *changeActiveLoop(Loop *activeLoop) - { - Loop *was = m_activeLoop; - m_activeLoop = activeLoop; - return was; - } - - Loop *findLoop(QScriptNameIdImpl *name = 0); - - Loop *m_activeLoop; - QMap<AST::Statement*, Loop> m_loops; - CompilationUnit m_compilationUnit; -}; - -} // namespace QScript - -#endif // QT_NO_SCRIPT - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptcontext.cpp b/src/script/qscriptcontext.cpp deleted file mode 100644 index aed69d3..0000000 --- a/src/script/qscriptcontext.cpp +++ /dev/null @@ -1,571 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptcontext.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptcontextinfo.h" -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \since 4.3 - \class QScriptContext - - \brief The QScriptContext class represents a Qt Script function invocation. - - \ingroup script - - - A QScriptContext provides access to the `this' object and arguments - passed to a script function. You typically want to access this - information when you're writing a native (C++) function (see - QScriptEngine::newFunction()) that will be called from script - code. For example, when the script code - - \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 0 - - is evaluated, a QScriptContext will be created, and the context will - carry the arguments as QScriptValues; in this particular case, the - arguments will be one QScriptValue containing the number 20.5, a second - QScriptValue containing the string \c{"hello"}, and a third QScriptValue - containing a Qt Script object. - - Use argumentCount() to get the number of arguments passed to the - function, and argument() to get an argument at a certain index. The - argumentsObject() function returns a Qt Script array object - containing all the arguments; you can use the QScriptValueIterator - to iterate over its elements, or pass the array on as arguments to - another script function using QScriptValue::call(). - - Use thisObject() to get the `this' object associated with the function call, - and setThisObject() to set the `this' object. If you are implementing a - native "instance method", you typically fetch the thisObject() and access - one or more of its properties: - - \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 1 - - Use isCalledAsConstructor() to determine if the function was called - as a constructor (e.g. \c{"new foo()"} (as constructor) or just - \c{"foo()"}). When a function is called as a constructor, the - thisObject() contains the newly constructed object that the function - is expected to initialize. - - Use throwValue() or throwError() to throw an exception. - - Use callee() to obtain the QScriptValue that represents the function being - called. This can for example be used to call the function recursively. - - Use parentContext() to get a pointer to the context that precedes - this context in the activation stack. This is mostly useful for - debugging purposes (e.g. when constructing some form of backtrace). - - The activationObject() function returns the object that is used to - hold the local variables associated with this function call. You can - replace the activation object by calling setActivationObject(). A - typical usage of these functions is when you want script code to be - evaluated in the context of the parent context, e.g. to implement an - include() function: - - \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 2 - - Use backtrace() to get a human-readable backtrace associated with - this context. This can be useful for debugging purposes when - implementing native functions. The toString() function provides a - string representation of the context. (QScriptContextInfo provides - more detailed debugging-related information about the - QScriptContext.) - - Use engine() to obtain a pointer to the QScriptEngine that this context - resides in. - - \sa QScriptContextInfo, QScriptEngine::newFunction(), QScriptable -*/ - -/*! - \enum QScriptContext::ExecutionState - - This enum specifies the execution state of the context. - - \value NormalState The context is in a normal state. - - \value ExceptionState The context is in an exceptional state. -*/ - -/*! - \enum QScriptContext::Error - - This enum specifies types of error. - - \value ReferenceError A reference error. - - \value SyntaxError A syntax error. - - \value TypeError A type error. - - \value RangeError A range error. - - \value URIError A URI error. - - \value UnknownError An unknown error. -*/ - -/*! - Throws an exception with the given \a value. - Returns the value thrown (the same as the argument). - - \sa throwError(), state() -*/ -QScriptValue QScriptContext::throwValue(const QScriptValue &value) -{ - Q_D(QScriptContext); - d->m_result = d->engine()->toImpl(value); - d->m_state = QScriptContext::ExceptionState; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - d->engine()->notifyException(d); -#endif - return value; -} - -/*! - Throws an \a error with the given \a text. - Returns the created error object. - - The \a text will be stored in the \c{message} property of the error - object. - - The error object will be initialized to contain information about - the location where the error occurred; specifically, it will have - properties \c{lineNumber}, \c{fileName} and \c{stack}. These - properties are described in \l {QtScript Extensions to ECMAScript}. - - \sa throwValue(), state() -*/ -QScriptValue QScriptContext::throwError(Error error, const QString &text) -{ - Q_D(QScriptContext); - return d->engine()->toPublic(d->throwError(error, text)); -} - -/*! - \overload - - Throws an error with the given \a text. - Returns the created error object. - - \sa throwValue(), state() -*/ -QScriptValue QScriptContext::throwError(const QString &text) -{ - Q_D(QScriptContext); - return d->engine()->toPublic(d->throwError(text)); -} - -/*! - \internal -*/ -QScriptContext::QScriptContext(): - d_ptr(new QScriptContextPrivate()) -{ - d_ptr->q_ptr = this; -} - -/*! - Destroys this QScriptContext. -*/ -QScriptContext::~QScriptContext() -{ - delete d_ptr; - d_ptr = 0; -} - -/*! - Returns the QScriptEngine that this QScriptContext belongs to. -*/ -QScriptEngine *QScriptContext::engine() const -{ - Q_D(const QScriptContext); - return QScriptEnginePrivate::get(d->engine()); -} - -/*! - Returns the function argument at the given \a index. - - If \a index >= argumentCount(), a QScriptValue of - the primitive type Undefined is returned. - - \sa argumentCount() -*/ -QScriptValue QScriptContext::argument(int index) const -{ - Q_D(const QScriptContext); - if (index < 0) - return QScriptValue(); - return d->engine()->toPublic(d->argument(index)); -} - -/*! - Returns the callee. The callee is the function object that this - QScriptContext represents an invocation of. -*/ -QScriptValue QScriptContext::callee() const -{ - Q_D(const QScriptContext); - return d->engine()->toPublic(d->m_callee); -} - -/*! - Returns the arguments object of this QScriptContext. - - The arguments object has properties \c callee (equal to callee()) - and \c length (equal to argumentCount()), and properties \c 0, \c 1, - ..., argumentCount() - 1 that provide access to the argument - values. Initially, property \c P (0 <= \c P < argumentCount()) has - the same value as argument(\c P). In the case when \c P is less - than the number of formal parameters of the function, \c P shares - its value with the corresponding property of the activation object - (activationObject()). This means that changing this property changes - the corresponding property of the activation object and vice versa. - - \sa argument(), activationObject() -*/ -QScriptValue QScriptContext::argumentsObject() const -{ - Q_D(const QScriptContext); - return d->engine()->toPublic(d->argumentsObject()); -} - -/*! - Returns true if the function was called as a constructor - (e.g. \c{"new foo()"}); otherwise returns false. - - When a function is called as constructor, the thisObject() - contains the newly constructed object to be initialized. -*/ -bool QScriptContext::isCalledAsConstructor() const -{ - Q_D(const QScriptContext); - return d->m_calledAsConstructor; -} - -/*! - Returns the parent context of this QScriptContext. -*/ -QScriptContext *QScriptContext::parentContext() const -{ - Q_D(const QScriptContext); - return QScriptContextPrivate::get(d->previous); -} - -/*! - Returns the number of arguments passed to the function - in this invocation. - - Note that the argument count can be different from the - formal number of arguments (the \c{length} property of - callee()). - - \sa argument() -*/ -int QScriptContext::argumentCount() const -{ - Q_D(const QScriptContext); - return d->argc; -} - -/*! - \internal -*/ -QScriptValue QScriptContext::returnValue() const -{ - Q_D(const QScriptContext); - return d->engine()->toPublic(d->m_result); -} - -/*! - \internal -*/ -void QScriptContext::setReturnValue(const QScriptValue &result) -{ - Q_D(QScriptContext); - d->m_result = d->engine()->toImpl(result); -} - -/*! - Returns the activation object of this QScriptContext. The activation - object provides access to the local variables associated with this - context. - - \sa argument(), argumentsObject() -*/ -QScriptValue QScriptContext::activationObject() const -{ - Q_D(const QScriptContext); - return d->engine()->toPublic(d->activationObject()); -} - -/*! - Sets the activation object of this QScriptContext to be the given \a - activation. - - If \a activation is not an object, this function does nothing. -*/ -void QScriptContext::setActivationObject(const QScriptValue &activation) -{ - Q_D(QScriptContext); - if (!activation.isObject()) { - return; - } else if (activation.engine() != engine()) { - qWarning("QScriptContext::setActivationObject() failed: " - "cannot set an object created in " - "a different engine"); - } else { - d->m_activation = d->engine()->toImpl(activation); - } -} - -/*! - Returns the `this' object associated with this QScriptContext. -*/ -QScriptValue QScriptContext::thisObject() const -{ - Q_D(const QScriptContext); - return d->engine()->toPublic(d->m_thisObject); -} - -/*! - Sets the `this' object associated with this QScriptContext to be - \a thisObject. - - If \a thisObject is not an object, this function does nothing. -*/ -void QScriptContext::setThisObject(const QScriptValue &thisObject) -{ - Q_D(QScriptContext); - if (!thisObject.isObject()) { - } else if (thisObject.engine() != engine()) { - qWarning("QScriptContext::setThisObject() failed: " - "cannot set an object created in " - "a different engine"); - } else { - d->m_thisObject = d->engine()->toImpl(thisObject); - } -} - -/*! - Returns the execution state of this QScriptContext. -*/ -QScriptContext::ExecutionState QScriptContext::state() const -{ - Q_D(const QScriptContext); - return d->m_state; -} - -/*! - Returns a human-readable backtrace of this QScriptContext. - - Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}. - - To access individual pieces of debugging-related information (for - example, to construct your own backtrace representation), use - QScriptContextInfo. - - \sa QScriptEngine::uncaughtExceptionBacktrace(), QScriptContextInfo, toString() -*/ -QStringList QScriptContext::backtrace() const -{ - Q_D(const QScriptContext); - return d->backtrace(); -} - -static QString safeValueToString(const QScriptValue &value) -{ - if (value.isObject()) - return QLatin1String("[object Object]"); - else - return value.toString(); -} - -/*! - \since 4.4 - - Returns a string representation of this context. - This is useful for debugging. - - \sa backtrace() -*/ -QString QScriptContext::toString() const -{ - QScriptContextInfo info(this); - QString result; - - QString functionName = info.functionName(); - if (functionName.isEmpty()) { - if (parentContext()) { - if (info.functionType() == QScriptContextInfo::ScriptFunction) - result.append(QLatin1String("<anonymous>")); - else - result.append(QLatin1String("<native>")); - } else { - result.append(QLatin1String("<global>")); - } - } else { - result.append(functionName); - } - - QStringList parameterNames = info.functionParameterNames(); - result.append(QLatin1String(" (")); - for (int i = 0; i < argumentCount(); ++i) { - if (i > 0) - result.append(QLatin1String(", ")); - if (i < parameterNames.count()) { - result.append(parameterNames.at(i)); - result.append(QLatin1Char('=')); - } - QScriptValue arg = argument(i); - result.append(safeValueToString(arg)); - } - result.append(QLatin1Char(')')); - - QString fileName = info.fileName(); - int lineNumber = info.lineNumber(); - result.append(QLatin1String(" at ")); - if (!fileName.isEmpty()) { - result.append(fileName); - result.append(QLatin1Char(':')); - } - result.append(QString::number(lineNumber)); - return result; -} - -/*! - \internal - \since 4.5 - - Returns the scope chain of this QScriptContext. -*/ -QScriptValueList QScriptContext::scopeChain() const -{ - Q_D(const QScriptContext); - // make sure arguments properties are initialized - const QScriptContextPrivate *ctx = d; - while (ctx) { - (void)ctx->activationObject(); - ctx = ctx->previous; - } - QScriptValueList result; - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine()); - QScriptValueImpl scope = d->m_scopeChain; - while (scope.isObject()) { - if (scope.classInfo() == eng_p->m_class_with) - result.append(eng_p->toPublic(scope.prototype())); - else - result.append(eng_p->toPublic(scope)); - scope = scope.scope(); - } - return result; -} - -/*! - \internal - \since 4.5 - - Adds the given \a object to the front of this context's scope chain. - - If \a object is not an object, this function does nothing. -*/ -void QScriptContext::pushScope(const QScriptValue &object) -{ - Q_D(QScriptContext); - if (!object.isObject()) { - return; - } else if (object.engine() != engine()) { - qWarning("QScriptContext::pushScope() failed: " - "cannot push an object created in " - "a different engine"); - return; - } - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine()); - if (!d->m_scopeChain.isValid()) { - d->m_scopeChain = eng_p->toImpl(object); - } else { - QScriptValueImpl withObject; - eng_p->newObject(&withObject, eng_p->toImpl(object), eng_p->m_class_with); - withObject.m_object_value->m_scope = d->m_scopeChain; - withObject.setInternalValue(1); // to differentiate from with-statement objects - d->m_scopeChain = withObject; - } -} - -/*! - \internal - \since 4.5 - - Removes the front object from this context's scope chain, and - returns the removed object. - - If the scope chain is already empty, this function returns an - invalid QScriptValue. -*/ -QScriptValue QScriptContext::popScope() -{ - Q_D(QScriptContext); - if (!d->m_scopeChain.isObject()) - return QScriptValue(); - QScriptValueImpl result; - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine()); - if (d->m_scopeChain.classInfo() != eng_p->m_class_with) - result = d->m_scopeChain; - else - result = d->m_scopeChain.prototype(); - d->m_scopeChain = d->m_scopeChain.m_object_value->m_scope; - return eng_p->toPublic(result); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptcontext_p.cpp b/src/script/qscriptcontext_p.cpp deleted file mode 100644 index ba0783b..0000000 --- a/src/script/qscriptcontext_p.cpp +++ /dev/null @@ -1,2598 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/QtDebug> - -#ifndef QT_NO_SCRIPT - -#include "qscriptcontext_p.h" -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptprettypretty_p.h" -#include "qscriptast_p.h" -#include "qscriptnodepool_p.h" -#include "qscriptcompiler_p.h" -#include "qscriptextenumeration_p.h" - -#include <math.h> // floor & friends... - -QT_BEGIN_NAMESPACE - -#define Q_SCRIPT_NO_PRINT_GENERATED_CODE - -#define Q_SCRIPT_NO_JOINED_FUNCTION - -#define CHECK_TEMPSTACK(needed) do { \ - if (stackPtr + needed >= eng->tempStackEnd) { \ - throwError(QLatin1String("out of memory")); \ - HandleException(); \ - } \ -} while (0) - -#ifndef Q_SCRIPT_NO_PRINT_GENERATED_CODE -static QTextStream qout(stderr, QIODevice::WriteOnly); -#endif - -static inline void qscript_uint_to_string_helper(uint i, QString &s) -{ - switch (i) { - case 0: case 1: case 2: case 3: case 4: - case 5: case 6: case 7: case 8: case 9: - s += QLatin1Char('0' + i); - break; - - default: - qscript_uint_to_string_helper(i / 10, s); - s += QLatin1Char('0' + (i % 10)); - } -} - -static inline void qscript_uint_to_string(qsreal i, QString &s) -{ - if ((i < 0) || (i > 0xFFFFFFFF)) - return; // nothing to do - - qsreal x = ::fmod(i, 10); - - if (x != 0.0 && x != 1.0 - && x != 2.0 && x != 3.0 - && x != 4.0 && x != 5.0 - && x != 6.0 && x != 7.0 - && x != 8.0 && x != 9.0) - return; // nothing to do - - qscript_uint_to_string_helper(uint(i), s); -} - -static inline quint32 toArrayIndex(const QScriptValueImpl &v) -{ - if (v.isNumber()) { - quint32 ui = v.toUInt32(); - if (qsreal(ui) == v.m_number_value) - return ui; - } else if (v.isString()) { - QByteArray bytes = v.m_string_value->s.toUtf8(); - char *eptr; - quint32 pos = strtoul(bytes.constData(), &eptr, 10); - if ((eptr == bytes.constData() + bytes.size()) - && (QByteArray::number(pos) == bytes)) { - return pos; - } - } - return 0xFFFFFFFF; -} - -#define CREATE_MEMBER(__obj__, __name__, __member__, __flags__) do { \ - (__obj__).createMember(__name__, __member__, __flags__); \ - eng->adjustBytesAllocated(sizeof(QScript::Member) + sizeof(QScriptValueImpl)); \ -} while (0) - -#define BEGIN_PREFIX_OPERATOR \ - QScriptValue::ResolveFlags mode; \ - mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value) \ - | QScriptValue::ResolvePrototype; \ - --stackPtr; \ - QScriptValueImpl object = eng->toObject(stackPtr[-1]); \ - if (!object.isObject()) { \ - stackPtr -= 2; \ - throwTypeError(QLatin1String("not an object")); \ - HandleException(); \ - } \ - QScriptNameIdImpl *memberName = 0; \ - if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique) \ - memberName = stackPtr[0].m_string_value; \ - else \ - memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false); \ - QScript::Member member; \ - QScriptValueImpl base; \ - QScriptValueImpl value; \ - QScriptValueImpl getter; \ - QScriptValueImpl setter; \ - const bool isMemberAssignment = (object.m_object_value != m_scopeChain.m_object_value); \ - if (object.resolve(memberName, &member, &base, mode, QScript::ReadWrite)) { \ - base.get(member, &value); \ - if (hasUncaughtException()) { \ - stackPtr -= 2; \ - HandleException(); \ - } else if (member.isGetterOrSetter()) { \ - if (member.isGetter()) { \ - getter = value; \ - if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { \ - stackPtr -= 2; \ - throwError(QLatin1String("No setter defined")); \ - HandleException(); \ - } \ - base.get(member, &setter); \ - } else { \ - setter = value; \ - QScript::Member tmp = member; \ - if (!base.m_object_value->findGetter(&member)) { \ - stackPtr -= 2; \ - throwError(QLatin1String("No getter defined")); \ - HandleException(); \ - } \ - base.get(member, &getter); \ - member = tmp; \ - } \ - value = getter.call(object); \ - if (hasUncaughtException()) { \ - stackPtr -= 2; \ - Done(); \ - } \ - } \ - } else if (!isMemberAssignment) { \ - stackPtr -= 2; \ - throwNotDefined(memberName); \ - HandleException(); \ - } else { \ - base = object; \ - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \ - value = undefined; \ - } - -#define END_PREFIX_OPERATOR \ - if (member.isSetter()) { \ - setter.call(object, QScriptValueImplList() << value); \ - if (hasUncaughtException()) { \ - stackPtr -= 2; \ - Done(); \ - } \ - } else { \ - if (member.isWritable()) { \ - if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { \ - base = object; \ - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \ - } \ - base.put(member, value); \ - if (hasUncaughtException()) { \ - stackPtr -= 2; \ - HandleException(); \ - } \ - } \ - } \ - *--stackPtr = value; \ - ++iPtr; - -#define BEGIN_INPLACE_OPERATOR \ - if (! stackPtr[-1].isReference()) { \ - stackPtr -= 2; \ - throwSyntaxError(QLatin1String("invalid assignment lvalue")); \ - HandleException(); \ - } \ - QScriptValue::ResolveFlags mode; \ - mode = QScriptValue::ResolveFlags(stackPtr[-1].m_int_value) \ - | QScriptValue::ResolvePrototype; \ - QScriptValueImpl object = eng->toObject(stackPtr[-3]); \ - if (! object.isValid()) { \ - stackPtr -= 4; \ - throwTypeError(QLatin1String("not an object")); \ - HandleException(); \ - } \ - QScriptNameIdImpl *memberName = 0; \ - if (stackPtr[-2].isString() && stackPtr[-2].m_string_value->unique) \ - memberName = stackPtr[-2].m_string_value; \ - else \ - memberName = eng->nameId(stackPtr[-2].toString(), /*persistent=*/false); \ - QScriptValueImpl lhs; \ - QScriptValueImpl base; \ - QScript::Member member; \ - QScriptValueImpl getter; \ - QScriptValueImpl setter; \ - const bool isMemberAssignment = (object.m_object_value != m_scopeChain.m_object_value); \ - if (object.resolve(memberName, &member, &base, mode, QScript::ReadWrite)) { \ - base.get(member, &lhs); \ - if (hasUncaughtException()) { \ - stackPtr -= 4; \ - HandleException(); \ - } else if (member.isGetterOrSetter()) { \ - if (member.isGetter()) { \ - getter = lhs; \ - if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { \ - stackPtr -= 4; \ - throwError(QLatin1String("No setter defined")); \ - HandleException(); \ - } \ - base.get(member, &setter); \ - } else { \ - setter = lhs; \ - QScript::Member tmp = member; \ - if (!base.m_object_value->findGetter(&member)) { \ - stackPtr -= 4; \ - throwError(QLatin1String("No getter defined")); \ - HandleException(); \ - } \ - base.get(member, &getter); \ - member = tmp; \ - } \ - lhs = getter.call(object); \ - if (hasUncaughtException()) { \ - stackPtr -= 4; \ - Done(); \ - } \ - } \ - } else if (!isMemberAssignment) { \ - stackPtr -= 4; \ - throwNotDefined(memberName); \ - HandleException(); \ - } else { \ - base = object; \ - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \ - lhs = undefined; \ - } \ - QScriptValueImpl rhs = stackPtr[0]; - -#define END_INPLACE_OPERATOR \ - if (member.isSetter()) { \ - setter.call(object, QScriptValueImplList() << *stackPtr); \ - if (hasUncaughtException()) { \ - stackPtr -= 1; \ - Done(); \ - } \ - } else { \ - if (member.isWritable()) { \ - if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { \ - base = object; \ - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); \ - } \ - base.put(member, *stackPtr); \ - if (hasUncaughtException()) { \ - stackPtr -= 1; \ - HandleException(); \ - } \ - } \ - } \ - ++iPtr; - -namespace QScript { - -void ScriptFunction::execute(QScriptContextPrivate *context) -{ - if (! m_compiledCode) { - QScriptEnginePrivate *eng = context->engine(); - Compiler compiler(eng); - - CompilationUnit unit = compiler.compile(m_definition->body, formals); - if (! unit.isValid()) { - context->throwError(unit.errorMessage()); - return; - } - - m_compiledCode = m_astPool->createCompiledCode(m_definition->body, unit); - } - - context->execute(m_compiledCode); -} - -QString ScriptFunction::toString(QScriptContextPrivate *) const -{ - QString str; - QTextStream out(&str, QIODevice::WriteOnly); - PrettyPretty pp(out); - pp(m_definition, /*indent=*/ 0); - return str; -} - -QString ScriptFunction::fileName() const -{ - return m_astPool->fileName(); -} - -QString ScriptFunction::functionName() const -{ - if (!m_definition->name) - return QString(); - return m_definition->name->s; -} - -int ScriptFunction::startLineNumber() const -{ - return m_definition->startLine; -} - -int ScriptFunction::endLineNumber() const -{ - return m_definition->endLine; -} - -} // namespace QScript - -/*! - \internal - - Resolves and gets the value specified by \a stackPtr. - stackPtr[0] contains the member specifier, stackPtr[-1] contains the object. - If the member can be resolved, sets \a value to the value of that member, - otherwise returns false. -*/ -bool QScriptContextPrivate::resolveField(QScriptEnginePrivate *eng, - QScriptValueImpl *stackPtr, - QScriptValueImpl *value) -{ - const QScriptValueImpl &m = stackPtr[0]; - QScriptValueImpl &object = stackPtr[-1]; - - if (! object.isObject()) - object = eng->toObject(object); - - if (! object.isValid()) - return false; - - if (QScript::Ecma::Array::Instance *arrayInstance = eng->arrayConstructor->get(object)) { - quint32 pos = toArrayIndex(m); - if (pos != 0xFFFFFFFF) { - *value = arrayInstance->value.at(pos); - - if (! value->isValid()) - *value = eng->undefinedValue(); - - return true; - } - } - - QScriptNameIdImpl *nameId = m.isString() ? m.m_string_value : 0; - - if (! nameId || ! nameId->unique) - nameId = eng->nameId(QScriptEnginePrivate::convertToNativeString(m), /*persistent=*/false); // ### slow! - - QScript::Member member; - QScriptValueImpl base; - - if (! object.resolve(nameId, &member, &base, QScriptValue::ResolveFull, QScript::Read)) // ### ... - return false; - - if (QScriptEnginePrivate::strictlyEquals(base, eng->m_globalObject)) - stackPtr[-1] = base; - else if (object.classInfo() == eng->m_class_with) - stackPtr[-1] = object.prototype(); - - base.get(member, value); - - if (member.isGetterOrSetter()) { - // call the getter function - QScriptValueImpl getter; - if (member.isGetter()) { - getter = *value; - } else { - if (!base.m_object_value->findGetter(&member)) { - *value = eng->undefinedValue(); - return true; - } - base.get(member, &getter); - } - *value = getter.call(object); - } - - return true; -} - -void QScriptContextPrivate::execute(QScript::Code *code) -{ - int oldCurrentLine = currentLine; - int oldCurrentColumn = currentColumn; - QScript::Code *oldCode = m_code; - m_code = code; - -#ifndef Q_SCRIPT_NO_PRINT_GENERATED_CODE - qout << QLatin1String("function:") << endl; - for (QScriptInstruction *current = code->firstInstruction; current != code->lastInstruction; ++current) { - qout << int(current - code->firstInstruction) << QLatin1String(":\t"); - current->print(qout); - qout << endl; - } - qout << endl; -#endif - - QScriptEnginePrivate *eng = engine(); - - bool wasEvaluating = eng->m_evaluating; - if (!wasEvaluating) { - eng->setupProcessEvents(); - eng->resetAbortFlag(); - } - eng->m_evaluating = true; - - // set up the temp stack - if (! tempStack) - stackPtr = tempStack = eng->tempStackBegin; - - QScriptValueImpl undefined(eng->undefinedValue()); - - catching = false; - m_state = QScriptContext::NormalState; - m_result = undefined; - firstInstruction = code->firstInstruction; - lastInstruction = code->lastInstruction; - iPtr = code->firstInstruction; - - if (!m_scopeChain.isValid()) - m_scopeChain = m_activation; - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng->notifyFunctionEntry(this); -#endif - -#ifndef Q_SCRIPT_DIRECT_CODE - -# define I(opc) case QScriptInstruction::OP_##opc -# define Next() goto Lfetch -# define Done() goto Ldone -# define HandleException() goto Lhandle_exception -# define Abort() goto Labort - -Lfetch: - - -#else - -# define I(opc) qscript_execute_##opc -# define Next() goto *iPtr->code -# define Done() goto Ldone -# define HandleException() goto Lhandle_exception -# define Abort() goto Labort - - static void * const jump_table[] = { - -# define Q_SCRIPT_DEFINE_OPERATOR(op) &&I(op), -# include "instruction.table" -# undef Q_SCRIPT_DEFINE_OPERATOR - }; // jump_table - - - if (!code->optimized) { - for (QScriptInstruction *current = code->firstInstruction; current != code->lastInstruction; ++current) { - current->code = jump_table[current->op]; - } - - code->optimized = true; - } - -#endif -Ltop: - -#ifndef Q_SCRIPT_DIRECT_CODE - switch (iPtr->op) { -#else - goto *iPtr->code; -#endif - - I(Nop): - { - ++iPtr; - } Next(); - - I(LoadUndefined): - { - CHECK_TEMPSTACK(1); - *(++stackPtr) = undefined; - ++iPtr; - } Next(); - - I(LoadTrue): - { - CHECK_TEMPSTACK(1); - *(++stackPtr) = QScriptValueImpl(true); - ++iPtr; - } Next(); - - I(LoadFalse): - { - CHECK_TEMPSTACK(1); - *(++stackPtr) = QScriptValueImpl(false); - ++iPtr; - } Next(); - - I(LoadThis): - { - CHECK_TEMPSTACK(1); - Q_ASSERT(m_thisObject.isObject()); - *++stackPtr = m_thisObject; - ++iPtr; - } Next(); - - I(LoadActivation): - { - CHECK_TEMPSTACK(1); - *++stackPtr = m_activation; - ++iPtr; - } Next(); - - I(LoadNull): - { - CHECK_TEMPSTACK(1); - *(++stackPtr) = eng->nullValue(); - ++iPtr; - } Next(); - - I(LoadNumber): - { - CHECK_TEMPSTACK(1); - *++stackPtr = iPtr->operand[0]; - ++iPtr; - } Next(); - - - I(LoadString): - { - CHECK_TEMPSTACK(1); - *++stackPtr = iPtr->operand[0]; - ++iPtr; - } Next(); - - I(NewString): - { - CHECK_TEMPSTACK(1); - eng->newNameId(++stackPtr, iPtr->operand[0].m_string_value); - ++iPtr; - } Next(); - - I(Duplicate): - { - CHECK_TEMPSTACK(1); - ++stackPtr; - *stackPtr = stackPtr[-1]; - ++iPtr; - } Next(); - - I(Swap): - { - QScriptValueImpl tmp = stackPtr[0]; - *stackPtr = stackPtr[-1]; - stackPtr[-1] = tmp; - ++iPtr; - } Next(); - - - I(Receive): - { - int n = iPtr->operand[0].m_int_value; - - if (n >= argc) { - throwError(QLatin1String("invalid argument")); - HandleException(); - } - - CHECK_TEMPSTACK(1); - *++stackPtr = argument(n); - ++iPtr; - } Next(); - - I(Fetch): - { - CHECK_TEMPSTACK(1); - - QScriptNameIdImpl *memberName = iPtr->operand[0].m_string_value; - - QScriptValueImpl base; - QScript::Member member; - - QScriptObject *instance = m_scopeChain.m_object_value; - if (instance->findMember(memberName, &member)) { - instance->get(member, ++stackPtr); - base = m_scopeChain; - } else { - if (m_scopeChain.resolve_helper(memberName, &member, &base, QScriptValue::ResolveFull, QScript::Read)) { - base.get(member, ++stackPtr); - if (hasUncaughtException()) { - stackPtr -= 1; - HandleException(); - } - } else { - throwNotDefined(memberName); - HandleException(); - } - } - if (member.isGetterOrSetter()) { - // locate the getter function - QScriptValueImpl getter; - if (member.isGetter()) { - getter = *stackPtr; - } else { - if (!base.m_object_value->findGetter(&member)) { - stackPtr -= 1; - throwError(QLatin1String("No getter defined")); - HandleException(); - } - base.get(member, &getter); - } - // decide the this-object. This is the object that actually - // has the getter (in its prototype chain). - QScriptValueImpl object = m_scopeChain; - while (!object.resolve(memberName, &member, &base, QScriptValue::ResolvePrototype, QScript::Read)) - object = object.scope(); - if (object.classInfo() == eng->m_class_with) - object = object.prototype(); - - *stackPtr = getter.call(object); - if (hasUncaughtException()) { - stackPtr -= 1; - Done(); - } - } - ++iPtr; - } Next(); - - I(Resolve): - { - Q_ASSERT(iPtr->operand[0].isString()); - - CHECK_TEMPSTACK(2); - *++stackPtr = m_scopeChain; - *++stackPtr = iPtr->operand[0]; - eng->newReference(++stackPtr, QScriptValue::ResolveScope); - ++iPtr; - } Next(); - - I(PutField): - { - Q_ASSERT(stackPtr[-1].isReference()); - - const QScriptValueImpl &object = stackPtr[-3]; - QScriptNameIdImpl *memberName = stackPtr[-2].m_string_value; - const QScriptValueImpl &value = stackPtr[0]; - - QScript::Member member; - QScriptValueImpl base; - - if (! object.resolve(memberName, &member, &base, QScriptValue::ResolveLocal, QScript::Write)) { - base = object; - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); - } - - base.put(member, value); - stackPtr -= 4; - if (hasUncaughtException()) - HandleException(); - ++iPtr; - } Next(); - - I(Call): - { - int argc = iPtr->operand[0].m_int_value; - QScriptValueImpl *argp = stackPtr - argc; - - QScriptValueImpl base; - QScriptValueImpl callee; - - bool isReference = argp[0].isReference(); - - if (! isReference) { // we have a value - base = eng->m_globalObject; - callee = argp[0]; - } else if (resolveField(eng, &argp[-1], &callee)) { - if (hasUncaughtException()) { - stackPtr = argp - 3; - HandleException(); - } - base = argp[-2]; - } else { - QScriptValueImpl member = argp[-1]; - stackPtr = argp - 1; - Q_ASSERT(isReference); - stackPtr -= 2; - - if (member.isString()) - throwNotDefined(member.toString()); - else - throwNotDefined(QLatin1String("function")); - HandleException(); - } - - Q_ASSERT(base.isValid()); - Q_ASSERT(callee.isValid()); - - QScriptFunction *function = QScriptEnginePrivate::convertToNativeFunction(callee); - if (! function) { - QScriptValueImpl member = argp[-1]; - QString message; - if (member.isString()) { - message = QString::fromLatin1("%0 is not a function") - .arg(member.toString()); - } else { - message = QLatin1String("not a function"); - } - throwTypeError(message); - HandleException(); - } - - if (++eng->m_callDepth == eng->m_maxCallDepth) { - throwError(QLatin1String("call stack overflow")); - HandleException(); - } - - QScriptContextPrivate *nested_data = eng->pushContext(); - nested_data->m_thisObject = base; - nested_data->m_callee = callee; - - // create the activation - eng->newActivation(&nested_data->m_activation); - QScriptObject *activation_data = nested_data->m_activation.m_object_value; - - int formalCount = function->formals.count(); - int mx = qMax(formalCount, argc); - activation_data->m_members.resize(mx); - activation_data->m_values.resize(mx); - for (int i = 0; i < mx; ++i) { - QScriptNameIdImpl *nameId = 0; - if (i < formalCount) - nameId = function->formals.at(i); - - activation_data->m_members[i].object(nameId, i, - QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration); - activation_data->m_values[i] = (i < argc) ? argp[i + 1] : undefined; - } - - nested_data->argc = argc; - if (callee.m_object_value->m_scope.isValid()) - activation_data->m_scope = callee.m_object_value->m_scope; - else - activation_data->m_scope = eng->m_globalObject; - nested_data->tempStack = stackPtr; - nested_data->args = &argp[1]; - - function->execute(nested_data); - - --eng->m_callDepth; - - stackPtr = argp - 1; - if (isReference) - stackPtr -= 2; - - if (nested_data->m_state == QScriptContext::ExceptionState) { - eng->popContext(); - if (eng->shouldAbort()) - Abort(); - else - Done(); - } - - CHECK_TEMPSTACK(1); - *++stackPtr = nested_data->m_result; - - eng->popContext(); - - if (eng->shouldAbort()) - Abort(); - - if (eng->m_processEventsInterval > 0) - eng->processEvents(); - - ++iPtr; - } Next(); - - - I(NewArray): - { - CHECK_TEMPSTACK(1); - eng->arrayConstructor->newArray(++stackPtr, QScript::Array(eng)); - ++iPtr; - } Next(); - - I(NewRegExp): - { - CHECK_TEMPSTACK(1); - - QString pattern = eng->toString(iPtr->operand[0].m_string_value); -#ifndef QT_NO_REGEXP - QString literal = pattern; -#endif - int flags = 0; - if (iPtr->operand[1].isValid()) { - flags = iPtr->operand[1].m_int_value; -#ifndef QT_NO_REGEXP - if (flags != 0) { - literal += QLatin1Char('/'); - literal += QString::number(flags); - } -#endif - } - -#ifndef QT_NO_REGEXP - QRegExp rx; - // lazy compilation of regexp literals - QHash<QString, QRegExp>::const_iterator it; - it = eng->m_regExpLiterals.constFind(literal); - if (it == eng->m_regExpLiterals.constEnd()) { - rx = QScript::Ecma::RegExp::toRegExp(pattern, flags); - eng->m_regExpLiterals.insert(literal, rx); - } else { - rx = *it; - } - eng->regexpConstructor->newRegExp(++stackPtr, rx, flags); -#else - eng->regexpConstructor->newRegExp(++stackPtr, pattern, flags); -#endif - ++iPtr; - } Next(); - - I(NewObject): - { - CHECK_TEMPSTACK(1); - eng->objectConstructor->newObject(++stackPtr); - ++iPtr; - } Next(); - - I(New): - { - int argc = iPtr->operand[0].m_int_value; - QScriptValueImpl *argp = stackPtr - argc; - - // QScriptValueImpl base; - QScriptValueImpl callee; - - bool isReference = argp[0].isReference(); - - if (! isReference) { // we have a value - // base = eng->globalObject; - callee = argp[0]; - } else if (resolveField(eng, &argp[-1], &callee)) { - // base = argp[-2]; - if (hasUncaughtException()) { - stackPtr = argp - 3; - HandleException(); - } - } else { - QScriptValueImpl member = argp[-1]; - stackPtr = argp - 1; - Q_ASSERT(isReference); - stackPtr -= 2; - - if (member.isString()) - throwNotDefined(member.toString()); - else - throwNotDefined(QLatin1String("constructor")); - HandleException(); - } - - // Q_ASSERT(base.isValid()); - Q_ASSERT(callee.isValid()); - - QScriptFunction *function = QScriptEnginePrivate::convertToNativeFunction(callee); - if (! function) { - QScriptValueImpl member = argp[-1]; - QString message; - if (member.isString()) { - message = QString::fromLatin1("%0 is not a constructor") - .arg(member.toString()); - } else { - message = QLatin1String("not a constructor"); - } - throwTypeError(message); - HandleException(); - } - - if (++eng->m_callDepth == eng->m_maxCallDepth) { - throwError(QLatin1String("call stack overflow")); - HandleException(); - } - - QScriptContextPrivate *nested_data = eng->pushContext(); - nested_data->m_callee = callee; - nested_data->m_calledAsConstructor = true; - - // create the activation - eng->newActivation(&nested_data->m_activation); - QScriptObject *activation_data = nested_data->m_activation.m_object_value; - - int formalCount = function->formals.count(); - int mx = qMax(formalCount, argc); - activation_data->m_members.resize(mx); - activation_data->m_values.resize(mx); - for (int i = 0; i < mx; ++i) { - QScriptNameIdImpl *nameId = 0; - if (i < formalCount) - nameId = function->formals.at(i); - - activation_data->m_members[i].object(nameId, i, - QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration); - activation_data->m_values[i] = (i < argc) ? argp[i + 1] : undefined; - } - - eng->objectConstructor->newObject(&nested_data->m_thisObject); - nested_data->argc = argc; - if (callee.m_object_value->m_scope.isValid()) - activation_data->m_scope = callee.m_object_value->m_scope; - else - activation_data->m_scope = eng->m_globalObject; - nested_data->tempStack = stackPtr; - nested_data->args = &argp[1]; - nested_data->m_result = undefined; - - QScriptObject *instance = nested_data->m_thisObject.m_object_value; - - // set [[prototype]] - QScriptValueImpl dummy; - QScript::Member proto; - if (callee.resolve(eng->idTable()->id_prototype, &proto, &dummy, QScriptValue::ResolveLocal, QScript::Read)) - callee.get(proto, &instance->m_prototype); - if (!instance->m_prototype.isObject()) - instance->m_prototype = eng->objectConstructor->publicPrototype; - - function->execute(nested_data); - - --eng->m_callDepth; - - stackPtr = argp - 1; - if (isReference) - stackPtr -= 2; - - if (! nested_data->m_result.isValid()) - nested_data->m_result = undefined; - else if (! nested_data->m_result.isObject()) - nested_data->m_result = nested_data->m_thisObject; - - if (nested_data->m_state == QScriptContext::ExceptionState) { - eng->popContext(); - if (eng->shouldAbort()) - Abort(); - else - Done(); - } - - CHECK_TEMPSTACK(1); - - *++stackPtr = nested_data->m_result; - - eng->popContext(); - - if (eng->shouldAbort()) - Abort(); - - if (eng->m_processEventsInterval > 0) - eng->processEvents(); - - ++iPtr; - } Next(); - - I(FetchField): - { - QScriptValueImpl object = eng->toObject(stackPtr[-1]); - if (! object.isValid()) { - stackPtr -= 2; - throwTypeError(QLatin1String("not an object")); - HandleException(); - } - - QScriptValueImpl m = stackPtr[0]; - - QScript::Ecma::Array::Instance *arrayInstance = 0; - if (object.classInfo() == eng->arrayConstructor->classInfo()) - arrayInstance = static_cast<QScript::Ecma::Array::Instance *> (object.m_object_value->m_data); - - if (arrayInstance) { - quint32 pos = toArrayIndex(m); - if (pos != 0xFFFFFFFF) { - QScriptValueImpl val = arrayInstance->value.at(pos); - if (val.isValid()) { - *--stackPtr = val; - ++iPtr; - Next(); - } - } - } - - QScriptNameIdImpl *nameId = m.isString() ? m.m_string_value : 0; - - if (! nameId || ! nameId->unique) { - QString str; - - if (m.isNumber()) - qscript_uint_to_string(m.m_number_value, str); - - if (str.isEmpty()) - str = QScriptEnginePrivate::convertToNativeString(m); - - nameId = eng->nameId(str, /*persistent=*/false); - } - - QScript::Member member; - QScriptValueImpl base; - - if (object.resolve(nameId, &member, &base, QScriptValue::ResolvePrototype, QScript::Read)) { - base.get(member, --stackPtr); - if (hasUncaughtException()) { - stackPtr -= 1; - HandleException(); - } else if (member.isGetterOrSetter()) { - // call the getter function - QScriptValueImpl getter; - if (member.isGetter()) { - getter = *stackPtr; - } else { - if (!base.m_object_value->findGetter(&member)) { - stackPtr -= 1; - throwError(QLatin1String("No getter defined")); - HandleException(); - } - base.get(member, &getter); - } - *stackPtr = getter.call(object); - if (hasUncaughtException()) { - stackPtr -= 1; - Done(); - } - } - } else { - *(--stackPtr) = undefined; - } - - ++iPtr; - } Next(); - - I(LazyArguments): - { - QScript::Member member; - QScriptValueImpl base; - QScriptNameIdImpl *arguments = eng->idTable()->id_arguments; - if (!m_activation.resolve(arguments, &member, &base, QScriptValue::ResolveLocal, QScript::Read)) { - CREATE_MEMBER(m_activation, arguments, &member, QScriptValue::Undeletable); - if (!m_arguments.isValid()) { - if (eng->strictlyEquals(m_activation, eng->globalObject())) - m_arguments = undefined; - else - eng->newArguments(&m_arguments, m_activation, argc, m_callee); - } - m_activation.put(member, m_arguments); - } - ++iPtr; - } Next(); - - I(DeclareLocal): - { - QScriptValueImpl &act = m_activation; - - QScriptNameIdImpl *memberName = iPtr->operand[0].m_string_value; - bool readOnly = iPtr->operand[1].m_int_value != 0; - QScript::Member member; - QScriptValueImpl object; - - if (! act.resolve(memberName, &member, &object, QScriptValue::ResolveLocal, QScript::ReadWrite)) { - uint flags = QScriptValue::Undeletable; - if (readOnly) - flags |= QScript::Member::UninitializedConst | QScriptValue::ReadOnly; - CREATE_MEMBER(act, memberName, &member, flags); - act.put(member, undefined); - } - ++iPtr; - } Next(); - - I(Assign): - { - if (! stackPtr[-1].isReference()) { - stackPtr -= 2; - throwSyntaxError(QLatin1String("invalid assignment lvalue")); - HandleException(); - } - - QScriptValue::ResolveFlags mode; - mode = QScriptValue::ResolveFlags(stackPtr[-1].m_int_value) - | QScriptValue::ResolvePrototype; - - QScriptValueImpl object = eng->toObject(stackPtr[-3]); - if (! object.isValid()) { - stackPtr -= 4; - throwTypeError(QLatin1String("invalid assignment lvalue")); - HandleException(); - } - - QScriptValueImpl m = stackPtr[-2]; - QScriptValueImpl value = stackPtr[0]; - - quint32 pos = 0xFFFFFFFF; - - QScript::Ecma::Array::Instance *arrayInstance = eng->arrayConstructor->get(object); - if (arrayInstance) - pos = toArrayIndex(m); - - stackPtr -= 3; - - if (pos != 0xFFFFFFFF) - arrayInstance->value.assign(pos, value); - - else { - QScriptNameIdImpl *memberName; - - if (m.isString() && m.m_string_value->unique) - memberName = m.m_string_value; - else - memberName = eng->nameId(QScriptEnginePrivate::convertToNativeString(m), /*persistent=*/false); - - QScriptValueImpl base; - QScript::Member member; - - const bool isMemberAssignment = (object.m_object_value != m_scopeChain.m_object_value); - if (! object.resolve(memberName, &member, &base, mode, QScript::Write)) { - if (isMemberAssignment) - base = object; - else - base = eng->m_globalObject; - - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); - } - - if (value.isString() && ! value.m_string_value->unique) - eng->newNameId(&value, value.m_string_value->s); - - if (member.isGetterOrSetter()) { - // find and call setter(value) - QScriptValueImpl setter; - if (!member.isSetter()) { - if (!base.m_object_value->findSetter(&member)) { - stackPtr -= 1; - throwError(QLatin1String("no setter defined")); - HandleException(); - } - } - base.get(member, &setter); - - if (!isMemberAssignment) { - // decide the this-object. This is the object that actually - // has the setter (in its prototype chain). - while (!object.resolve(memberName, &member, &base, QScriptValue::ResolvePrototype, QScript::Write)) - object = object.scope(); - if (object.classInfo() == eng->m_class_with) - object = object.prototype(); - } - - value = setter.call(object, QScriptValueImplList() << value); - if (hasUncaughtException()) { - stackPtr -= 1; - Done(); - } - } else { - if (object.classInfo() == eng->m_class_with) - object = object.prototype(); - - if (member.isWritable()) { - if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { - base = object; - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); - } - base.put(member, value); - } else if (member.isUninitializedConst()) { - base.put(member, value); - if (member.isObjectProperty()) { - base.m_object_value->m_members[member.id()] - .unsetFlags(QScript::Member::UninitializedConst); - } - } - if (hasUncaughtException()) { - stackPtr -= 1; - HandleException(); - } - } - } - - *stackPtr = value; - ++iPtr; - } Next(); - - I(BitAnd): - { - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]); - *(--stackPtr) = QScriptValueImpl(v1 & v2); - ++iPtr; - } Next(); - - I(BitOr): - { - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]); - *(--stackPtr) = QScriptValueImpl(v1 | v2); - ++iPtr; - } Next(); - - I(BitXor): - { - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]); - *(--stackPtr) = QScriptValueImpl(v1 ^ v2); - ++iPtr; - } Next(); - - I(BitNot): - { - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]); - *stackPtr = QScriptValueImpl(~v1); - ++iPtr; - } Next(); - - I(Not): - { - bool v1 = QScriptEnginePrivate::convertToNativeBoolean(stackPtr[0]); - *stackPtr = QScriptValueImpl(!v1); - ++iPtr; - } Next(); - - I(LeftShift): - { - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]) & 0x1f; - *(--stackPtr) = QScriptValueImpl(v1 << v2); - ++iPtr; - } Next(); - - I(Mod): - { - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]); - qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]); - - *(--stackPtr) = QScriptValueImpl(::fmod(v1, v2)); - ++iPtr; - } Next(); - - I(RightShift): - { - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[-1]); - quint32 v2 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(stackPtr[0])) & 0x1f; - *(--stackPtr) = QScriptValueImpl(v1 >> v2); - ++iPtr; - } Next(); - - I(URightShift): - { - quint32 v1 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(stackPtr[-1])); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(stackPtr[0]) & 0x1f; - *(--stackPtr) = QScriptValueImpl(v1 >> v2); - ++iPtr; - } Next(); - - I(InstanceOf): - { - QScriptValueImpl object = stackPtr[-1]; - QScriptValueImpl ctor = stackPtr[0]; - - if (!ctor.isObject() || !ctor.implementsHasInstance()) { - stackPtr -= 2; - throwTypeError(QLatin1String("invalid 'instanceof' operand")); - HandleException(); - } - - bool result = ctor.hasInstance(object); - if (eng->hasUncaughtException()) { - stackPtr -= 2; - HandleException(); - } - - *(--stackPtr) = QScriptValueImpl(result); - ++iPtr; - } Next(); - - I(In): - { - QScriptValueImpl object = stackPtr[0]; - if (!object.isObject()) { - stackPtr -= 2; - throwTypeError(QLatin1String("invalid 'in' operand")); - HandleException(); - } - QString propertyName = QScriptEnginePrivate::convertToNativeString(stackPtr[-1]); - bool result = object.property(propertyName, QScriptValue::ResolvePrototype).isValid(); // ### hasProperty() - *(--stackPtr) = QScriptValueImpl(result); - ++iPtr; - } Next(); - - I(Add): - { - QScriptValueImpl lhs = eng->toPrimitive(stackPtr[-1], QScriptValueImpl::NoTypeHint); - QScriptValueImpl rhs = eng->toPrimitive(stackPtr[0], QScriptValueImpl::NoTypeHint); - - if (lhs.isString() || rhs.isString()) { - QString tmp = QScriptEnginePrivate::convertToNativeString(lhs); - tmp += QScriptEnginePrivate::convertToNativeString(rhs); - eng->newString(--stackPtr, tmp); - } else { - qsreal tmp = QScriptEnginePrivate::convertToNativeDouble(lhs); - tmp += QScriptEnginePrivate::convertToNativeDouble(rhs); - *(--stackPtr) = QScriptValueImpl(tmp); - } - - ++iPtr; - } Next(); - - I(Div): - { - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]); - qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]); - *(--stackPtr) = QScriptValueImpl(v1 / v2); - ++iPtr; - } Next(); - - I(Equal): - { - QScriptValueImpl v1 = stackPtr[-1]; - QScriptValueImpl v2 = stackPtr[0]; - *(--stackPtr) = QScriptValueImpl(eq_cmp(v1, v2)); - ++iPtr; - } Next(); - - I(GreatOrEqual): - { - QScriptValueImpl v1 = stackPtr[0]; - QScriptValueImpl v2 = stackPtr[-1]; - *(--stackPtr) = QScriptValueImpl(le_cmp(v1, v2)); - ++iPtr; - } Next(); - - I(GreatThan): - { - QScriptValueImpl v1 = stackPtr[0]; - QScriptValueImpl v2 = stackPtr[-1]; - *(--stackPtr) = QScriptValueImpl(lt_cmp(v1, v2)); - ++iPtr; - } Next(); - - I(LessOrEqual): - { - QScriptValueImpl v1 = stackPtr[-1]; - QScriptValueImpl v2 = stackPtr[0]; - *(--stackPtr) = QScriptValueImpl(le_cmp(v1, v2)); - ++iPtr; - } Next(); - - I(LessThan): - { - QScriptValueImpl v1 = stackPtr[-1]; - QScriptValueImpl v2 = stackPtr[0]; - *(--stackPtr) = QScriptValueImpl(lt_cmp(v1, v2)); - ++iPtr; - } Next(); - - I(NotEqual): - { - QScriptValueImpl v1 = stackPtr[-1]; - QScriptValueImpl v2 = stackPtr[0]; - *(--stackPtr) = QScriptValueImpl(!eq_cmp(v1, v2)); - ++iPtr; - } Next(); - - I(Mul): - { - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]); - qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]); - *(--stackPtr) = QScriptValueImpl(v1 * v2); - ++iPtr; - } Next(); - - I(StrictEqual): - { - QScriptValueImpl v1 = stackPtr[-1]; - QScriptValueImpl v2 = stackPtr[0]; - *(--stackPtr) = strict_eq_cmp(v1, v2); - ++iPtr; - } Next(); - - I(StrictNotEqual): - { - QScriptValueImpl v1 = stackPtr[-1]; - QScriptValueImpl v2 = stackPtr[0]; - *(--stackPtr) = ! strict_eq_cmp(v1, v2); - ++iPtr; - } Next(); - - I(Sub): - { - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[-1]); - qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(stackPtr[0]); - *(--stackPtr) = QScriptValueImpl(v1 - v2); - ++iPtr; - } Next(); - - I(UnaryMinus): - { - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(*stackPtr); - *stackPtr = QScriptValueImpl(-v1); - ++iPtr; - } Next(); - - I(UnaryPlus): - { - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(*stackPtr); - *stackPtr = QScriptValueImpl(+v1); - ++iPtr; - } Next(); - - I(Branch): - { - eng->maybeProcessEvents(); - if (hasUncaughtException()) - HandleException(); - if (eng->shouldAbort()) - Abort(); - iPtr += iPtr->operand[0].m_int_value; - } Next(); - - I(BranchFalse): - { - if (! QScriptEnginePrivate::convertToNativeBoolean(*stackPtr--)) - iPtr += iPtr->operand[0].m_int_value; - else - ++iPtr; - } Next(); - - I(BranchTrue): - { - if (eng->convertToNativeBoolean(*stackPtr--)) - iPtr += iPtr->operand[0].m_int_value; - else - ++iPtr; - } Next(); - - I(NewClosure): - { - CHECK_TEMPSTACK(1); - - QScript::AST::FunctionExpression *expr = static_cast<QScript::AST::FunctionExpression *> (iPtr->operand[0].m_ptr_value); - -#ifndef Q_SCRIPT_NO_JOINED_FUNCTION - if (QScript::Code *code = eng->findCode(functionBody)) { - QScriptValueImpl value = code->value; - - if (isValid(value)) { - QScriptObject *instance = value.m_object_value; - Q_ASSERT(instance != 0); - - if (instance->m_scope.m_object_value == m_scopeChain.m_object_value) - { - *++stackPtr = value; - ++iPtr; - Next(); - } - } - } -#endif - - QScript::ScriptFunction *function = new QScript::ScriptFunction(expr, code->astPool); - - // update the formals - for (QScript::AST::FormalParameterList *it = expr->formals; it != 0; it = it->next) { - function->formals.append(it->name); - } - function->length = function->formals.count(); - - eng->functionConstructor->newFunction(++stackPtr, function); - - QScriptObject *instance = stackPtr->m_object_value; - // initialize [[scope]] - instance->m_scope = m_scopeChain; - - // create and initialize `prototype' - QScriptValueImpl proto; - eng->objectConstructor->newObject(&proto); - - QScript::Member member; - CREATE_MEMBER(proto, eng->idTable()->id_constructor, &member, - QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration); - proto.put(member, *stackPtr); - - stackPtr->createMember(eng->idTable()->id_prototype, &member, - QScriptValue::Undeletable); - stackPtr->put(member, proto); - - ++iPtr; - } Next(); - - I(Incr): - { - if (! stackPtr[0].isReference()) { - stackPtr -= 1; - throwSyntaxError(QLatin1String("invalid increment operand")); - HandleException(); - } - - BEGIN_PREFIX_OPERATOR - - qsreal x = QScriptEnginePrivate::convertToNativeDouble(value); - value = QScriptValueImpl(x + 1); - - END_PREFIX_OPERATOR - } Next(); - - I(Decr): - { - if (! stackPtr[0].isReference()) { - stackPtr -= 1; - throwSyntaxError(QLatin1String("invalid decrement operand")); - HandleException(); - } - - BEGIN_PREFIX_OPERATOR - - qsreal x = QScriptEnginePrivate::convertToNativeDouble(value); - value = QScriptValueImpl(x - 1); - - END_PREFIX_OPERATOR - } Next(); - - I(PostIncr): - { - if (! stackPtr[0].isReference()) { - stackPtr -= 1; - throwSyntaxError(QLatin1String("invalid increment operand")); - HandleException(); - } - - QScriptValue::ResolveFlags mode; - mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value) - | QScriptValue::ResolvePrototype; - - --stackPtr; - - QScriptValueImpl object = eng->toObject(stackPtr[-1]); - if (!object.isObject()) { - stackPtr -= 2; - throwTypeError(QLatin1String("not an object")); - HandleException(); - } - - QScriptNameIdImpl *memberName = 0; - if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique) - memberName = stackPtr[0].m_string_value; - else - memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false); - - QScript::Member member; - QScriptValueImpl base; - QScriptValueImpl value; - QScriptObject *instance = object.m_object_value; - const bool isMemberAssignment = (instance != m_scopeChain.m_object_value); - if (instance->findMember(memberName, &member)) { - if (!member.isGetterOrSetter()) { - QScriptValueImpl &r = instance->reference(member); - if (r.isNumber()) { - *(--stackPtr) = QScriptValueImpl(r.m_number_value); - r.incr(); - ++iPtr; - Next(); - } - } - base = object; - } else if (!object.resolve_helper(memberName, &member, &base, mode, QScript::ReadWrite)) { - if (!isMemberAssignment) { - stackPtr -= 2; - throwNotDefined(memberName); - HandleException(); - } - base = object; - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); - base.put(member, undefined); - } - - QScriptValueImpl getter; - QScriptValueImpl setter; - base.get(member, &value); - if (hasUncaughtException()) { - stackPtr -= 2; - HandleException(); - } else if (member.isGetterOrSetter()) { - if (member.isGetter()) { - getter = value; - if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { - stackPtr -= 2; - throwError(QLatin1String("No setter defined")); - HandleException(); - } - base.get(member, &setter); - } else { - setter = value; - QScript::Member tmp = member; - if (!base.m_object_value->findGetter(&member)) { - stackPtr -= 2; - throwError(QLatin1String("No getter defined")); - HandleException(); - } - base.get(member, &getter); - member = tmp; - } - value = getter.call(object); - if (hasUncaughtException()) { - stackPtr -= 2; - Done(); - } - } - - qsreal x = QScriptEnginePrivate::convertToNativeDouble(value); - - value = QScriptValueImpl(x + 1); - - if (member.isSetter()) { - setter.call(object, QScriptValueImplList() << value); - if (hasUncaughtException()) { - stackPtr -= 2; - Done(); - } - } else { - if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { - base = object; - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); - } - if (member.isWritable()) { - base.put(member, value); - if (hasUncaughtException()) { - stackPtr -= 2; - HandleException(); - } - } - } - - *(--stackPtr) = QScriptValueImpl(x); - - ++iPtr; - } Next(); - - I(PostDecr): - { - // ### most of the code is duplicated from PostIncr -- try to merge - if (! stackPtr[0].isReference()) { - stackPtr -= 1; - throwSyntaxError(QLatin1String("invalid decrement operand")); - HandleException(); - } - - QScriptValue::ResolveFlags mode = QScriptValue::ResolveFlags(stackPtr[0].m_int_value) - | QScriptValue::ResolvePrototype; - - --stackPtr; - - QScriptValueImpl object = eng->toObject(stackPtr[-1]); - if (!object.isObject()) { - stackPtr -= 2; - throwTypeError(QLatin1String("not an object")); - HandleException(); - } - - QScriptNameIdImpl *memberName = 0; - if (stackPtr[0].isString() && stackPtr[0].m_string_value->unique) - memberName = stackPtr[0].m_string_value; - else - memberName = eng->nameId(stackPtr[0].toString(), /*persistent=*/false); - - QScript::Member member; - QScriptValueImpl base; - QScriptValueImpl value; - QScriptObject *instance = object.m_object_value; - const bool isMemberAssignment = (instance != m_scopeChain.m_object_value); - if (instance->findMember(memberName, &member)) { - if (!member.isGetterOrSetter()) { - QScriptValueImpl &r = instance->reference(member); - if (r.isNumber()) { - *(--stackPtr) = QScriptValueImpl(r.m_number_value); - r.decr(); - ++iPtr; - Next(); - } - } - base = object; - } else if (! object.resolve_helper(memberName, &member, &base, mode, QScript::ReadWrite)) { - if (!isMemberAssignment) { - stackPtr -= 2; - throwNotDefined(memberName); - HandleException(); - } - base = object; - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); - base.put(member, undefined); - } - - QScriptValueImpl getter; - QScriptValueImpl setter; - base.get(member, &value); - if (hasUncaughtException()) { - stackPtr -= 2; - HandleException(); - } else if (member.isGetterOrSetter()) { - if (member.isGetter()) { - getter = value; - if (!member.isSetter() && !base.m_object_value->findSetter(&member)) { - stackPtr -= 2; - throwError(QLatin1String("No setter defined")); - HandleException(); - } - base.get(member, &setter); - } else { - setter = value; - QScript::Member tmp = member; - if (!base.m_object_value->findGetter(&member)) { - stackPtr -= 2; - throwError(QLatin1String("No getter defined")); - HandleException(); - } - base.get(member, &getter); - member = tmp; - } - value = getter.call(object); - if (hasUncaughtException()) { - stackPtr -= 2; - Done(); - } - } - - qsreal x = QScriptEnginePrivate::convertToNativeDouble(value); - - value = QScriptValueImpl(x - 1); - - if (member.isSetter()) { - setter.call(object, QScriptValueImplList() << value); - if (hasUncaughtException()) { - stackPtr -= 2; - Done(); - } - } else { - if (isMemberAssignment && (base.m_object_value != object.m_object_value)) { - base = object; - CREATE_MEMBER(base, memberName, &member, /*flags=*/0); - } - if (member.isWritable()) { - base.put(member, value); - if (hasUncaughtException()) { - stackPtr -= 2; - HandleException(); - } - } - } - - *(--stackPtr) = QScriptValueImpl(x); - - ++iPtr; - } Next(); - - I(InplaceAdd): - { - BEGIN_INPLACE_OPERATOR - - lhs = eng->toPrimitive(lhs); - rhs = eng->toPrimitive(rhs); - if (lhs.isString() || rhs.isString()) { - if (lhs.isString() && !lhs.m_string_value->unique) { - lhs.m_string_value->s += QScriptEnginePrivate::convertToNativeString(rhs); - stackPtr -= 3; - *stackPtr = lhs; - } else { - QString tmp = QScriptEnginePrivate::convertToNativeString(lhs); - tmp += QScriptEnginePrivate::convertToNativeString(rhs); - stackPtr -= 3; - eng->newString(stackPtr, tmp); - } - } else { - qsreal tmp = QScriptEnginePrivate::convertToNativeDouble(lhs); - tmp += QScriptEnginePrivate::convertToNativeDouble(rhs); - stackPtr -= 3; - *stackPtr = QScriptValueImpl(tmp); - } - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceSub): - { - BEGIN_INPLACE_OPERATOR - - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs); - qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 - v2); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceAnd): - { - BEGIN_INPLACE_OPERATOR - - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 & v2); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceDiv): - { - BEGIN_INPLACE_OPERATOR - - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs); - qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 / v2); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceLeftShift): - { - BEGIN_INPLACE_OPERATOR - - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 << v2); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceMod): - { - BEGIN_INPLACE_OPERATOR - - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs); - qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(::fmod (v1, v2)); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceMul): - { - BEGIN_INPLACE_OPERATOR - - qsreal v1 = QScriptEnginePrivate::convertToNativeDouble(lhs); - qsreal v2 = QScriptEnginePrivate::convertToNativeDouble(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 * v2); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceOr): - { - BEGIN_INPLACE_OPERATOR - - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 | v2); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceRightShift): - { - BEGIN_INPLACE_OPERATOR - - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 >> v2); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceURightShift): - { - BEGIN_INPLACE_OPERATOR - - quint32 v1 = QScriptEnginePrivate::toUint32 (eng->convertToNativeDouble(lhs)); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 >> v2); - - END_INPLACE_OPERATOR - } Next(); - - I(InplaceXor): - { - BEGIN_INPLACE_OPERATOR - - qint32 v1 = QScriptEnginePrivate::convertToNativeInt32(lhs); - qint32 v2 = QScriptEnginePrivate::convertToNativeInt32(rhs); - - stackPtr -= 3; - *stackPtr = QScriptValueImpl(v1 ^ v2); - - END_INPLACE_OPERATOR - } Next(); - - I(MakeReference): - { - CHECK_TEMPSTACK(1); - eng->newReference(++stackPtr, QScriptValue::ResolveLocal); - ++iPtr; - } Next(); - - I(TypeOf): - { - QScriptValueImpl value; - - bool isReference = stackPtr[0].isReference(); - - if (! isReference) { // we have a value - value = stackPtr[0]; - } else if (resolveField(eng, &stackPtr[-1], &value)) { - stackPtr -= 2; - if (hasUncaughtException()) { - stackPtr -= 1; - HandleException(); - } - } else { - value = undefined; - stackPtr -= 2; - } - - QString typeName; - - switch (value.type()) { - case QScript::InvalidType: - typeName = QLatin1String("invalid"); - break; - - case QScript::UndefinedType: - typeName = QLatin1String("undefined"); - break; - - case QScript::NullType: - typeName = QLatin1String("object"); - break; - - case QScript::BooleanType: - typeName = QLatin1String("boolean"); - break; - - case QScript::IntegerType: - case QScript::NumberType: - typeName = QLatin1String("number"); - break; - - case QScript::StringType: - case QScript::LazyStringType: - typeName = QLatin1String("string"); - break; - - case QScript::ReferenceType: - typeName = QLatin1String("reference"); - break; - - case QScript::PointerType: - typeName = QLatin1String("pointer"); - break; - - case QScript::ObjectType: - if (value.isFunction()) - typeName = QLatin1String("function"); - else - typeName = QLatin1String("object"); - break; - } - - eng->newString(stackPtr, typeName); - ++iPtr; - } Next(); - - I(Line): - { - eng->maybeGC(); - eng->maybeProcessEvents(); - if (hasUncaughtException()) - HandleException(); - if (eng->shouldAbort()) - Abort(); - currentLine = iPtr->operand[0].m_int_value; - currentColumn = iPtr->operand[1].m_int_value; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - if (eng->shouldNotify()) { - eng->notifyPositionChange(this); - if (hasUncaughtException()) - HandleException(); - if (eng->shouldAbort()) - Abort(); - } -#endif - ++iPtr; - } Next(); - - I(Delete): - { - bool result; - if (! stackPtr[0].isReference()) - result = true; - - else { - QScriptValueImpl object = stackPtr[-2]; - if (!object.isObject()) - object = eng->toObject(object); - - QScriptNameIdImpl *nameId = 0; - if (stackPtr[-1].isString() && stackPtr[-1].m_string_value->unique) { - nameId = stackPtr[-1].m_string_value; - } else { - nameId = eng->nameId(QScriptEnginePrivate::convertToNativeString(stackPtr[-1]), - /*persistent=*/false); - } - if (object.classInfo() == eng->m_class_with) - object = object.prototype(); - result = object.deleteProperty(nameId, QScriptValue::ResolveScope); - stackPtr -= 2; - } - - *stackPtr = QScriptValueImpl(result); - - ++iPtr; - } Next(); - - - I(NewEnumeration): { - QScriptValueImpl e; - QScriptValueImpl object = eng->toObject(stackPtr[0]); - eng->enumerationConstructor->newEnumeration(&e, object); - *stackPtr = e; - ++iPtr; - } Next(); - - - I(ToFirstElement): { - QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[0]); - Q_ASSERT(e != 0); - e->toFront(); - --stackPtr; - ++iPtr; - } Next(); - - - I(HasNextElement): { - QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[0]); - Q_ASSERT(e != 0); - e->hasNext(this, stackPtr); - ++iPtr; - } Next(); - - - I(NextElement): { - // the Enumeration should be located below the result of I(Resolve) - if (! stackPtr[0].isReference()) { - throwTypeError(QLatin1String("QScript.VM.NextElement")); - HandleException(); - } - - QScript::Ext::Enumeration::Instance *e = eng->enumerationConstructor->get(stackPtr[-3]); - if (! e) { - throwTypeError(QLatin1String("QScript.VM.NextElement")); - HandleException(); - } - e->next(this, ++stackPtr); - ++iPtr; - } Next(); - - - I(Pop): - { - --stackPtr; - ++iPtr; - } Next(); - - I(Sync): - { - m_result = *stackPtr; - --stackPtr; - ++iPtr; - } Next(); - - I(Throw): - { - Q_ASSERT(stackPtr->isValid()); - m_result = *stackPtr--; - if (!m_result.isError() && !exceptionHandlerContext()) - eng->m_exceptionBacktrace = backtrace(); - m_state = QScriptContext::ExceptionState; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng->notifyException(this); -#endif - } HandleException(); - - I(Ret): - { - Q_ASSERT(stackPtr->isValid()); - m_result = *stackPtr--; - ++iPtr; - } Done(); - - I(Halt): - { - ++iPtr; - } Done(); - - I(EnterWith): - { - QScriptValueImpl object = eng->toObject(*stackPtr--); - if (! object.isValid()) { - throwTypeError(QLatin1String("value has no properties")); - HandleException(); - } - QScriptValueImpl withObject; - eng->newObject(&withObject, object, eng->m_class_with); - withObject.m_object_value->m_scope = m_scopeChain; - m_scopeChain = withObject; - ++iPtr; - } Next(); - - I(LeaveWith): - { - QScriptValueImpl withObject = m_scopeChain; - m_scopeChain = withObject.m_object_value->m_scope; - ++iPtr; - } Next(); - - I(BeginCatch): - { - // result contains the thrown object - QScriptValueImpl object; - eng->newObject(&object, undefined); // ### prototype - QScript::Member member; - CREATE_MEMBER(object, iPtr->operand[0].m_string_value, &member, /*flags=*/0); - object.put(member, m_result); - // make catch-object head of scopechain - object.m_object_value->m_scope = m_scopeChain; - m_scopeChain = object; - - catching = true; - ++iPtr; - } Next(); - - I(EndCatch): - { - // remove catch-object from scopechain - QScriptValueImpl object = m_scopeChain; - m_scopeChain = object.m_object_value->m_scope; - - catching = false; - ++iPtr; - } Next(); - - I(Debugger): - { -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng->notifyDebugger(this); -#endif - ++iPtr; - } Next(); - -#ifndef Q_SCRIPT_DIRECT_CODE - I(Dummy): - { ; } - - } // end switch -#endif - -Lhandle_exception: - errorLineNumber = currentLine; - -Ldone: - Q_ASSERT(m_result.isValid()); - - if (m_state == QScriptContext::ExceptionState) { - if (catching) { - // exception thrown in catch -- clean up scopechain - QScriptValueImpl object = m_scopeChain; - m_scopeChain = object.m_object_value->m_scope; - catching = false; - } - - // see if we have an exception handler in this context - const QScriptInstruction *exPtr = findExceptionHandler(iPtr); - if (exPtr) { - if (m_scopeChain.classInfo() == eng->m_class_with) { - // clean up effects of with-statements if necessary - int withLevel = 0; - for (++iPtr; iPtr != exPtr; ++iPtr) { - if (iPtr->op == QScriptInstruction::OP_EnterWith) { - ++withLevel; - } else if (iPtr->op == QScriptInstruction::OP_LeaveWith) { - --withLevel; - if (withLevel < 0) { - QScriptValueImpl withObject = m_scopeChain; - m_scopeChain = withObject.m_object_value->m_scope; - } - } - } - } else { - iPtr = exPtr; - } - // go to the handler - recover(); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng->notifyExceptionCatch(this); -#endif - goto Ltop; - } else { - if (!parentContext()) { - // pop all the top-level with-objects - while ((m_scopeChain.classInfo() == eng->m_class_with) - && !m_scopeChain.internalValue().isValid()) { - QScriptValueImpl withObject = m_scopeChain; - m_scopeChain = withObject.m_object_value->m_scope; - } - } - } - } - -Labort: -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng->notifyFunctionExit(this); -#endif - - eng->maybeGC(); - - currentLine = oldCurrentLine; - currentColumn = oldCurrentColumn; - m_code = oldCode; - - eng->m_evaluating = wasEvaluating; -} - -QScriptValueImpl QScriptContextPrivate::throwError(QScriptContext::Error error, const QString &text) -{ - QScriptEnginePrivate *eng_p = engine(); - QScript::Ecma::Error *ctor = eng_p->errorConstructor; - m_result.invalidate(); - switch (error) { - case QScriptContext::ReferenceError: - ctor->newReferenceError(&m_result, text); - break; - case QScriptContext::SyntaxError: - ctor->newSyntaxError(&m_result, text); - break; - case QScriptContext::TypeError: - ctor->newTypeError(&m_result, text); - break; - case QScriptContext::RangeError: - ctor->newRangeError(&m_result, text); - break; - case QScriptContext::URIError: - ctor->newURIError(&m_result, text); - break; - case QScriptContext::UnknownError: - default: - ctor->newError(&m_result, text); - } - setDebugInformation(&m_result); - m_state = QScriptContext::ExceptionState; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyException(this); -#endif - return m_result; -} - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY -qint64 QScriptContextPrivate::scriptId() const -{ - if (!m_code) - return -1; - return m_code->astPool->id(); -} -#endif - -QString QScriptContextPrivate::fileName() const -{ - if (!m_code) - return QString(); - return m_code->astPool->fileName(); -} - -QString QScriptContextPrivate::functionName() const -{ - if (!m_callee.isValid()) - return QString(); - QScriptFunction *fun = m_callee.toFunction(); - if (fun) - return fun->functionName(); - return QString(); -} - -void QScriptContextPrivate::setDebugInformation(QScriptValueImpl *error) const -{ - QScriptEnginePrivate *eng_p = engine(); - error->setProperty(QLatin1String("lineNumber"), QScriptValueImpl(currentLine)); - if (!fileName().isEmpty()) - error->setProperty(QLatin1String("fileName"), QScriptValueImpl(eng_p, fileName())); - - const QScriptContextPrivate *ctx = this; - QScriptValueImpl stackArray = eng_p->newArray(); - int i = 0; - while (ctx) { - QScriptValueImpl obj = eng_p->newObject(); - obj.setProperty(QLatin1String("frame"), ctx->activationObject()); - obj.setProperty(QLatin1String("lineNumber"), QScriptValueImpl(ctx->currentLine)); - if (!ctx->fileName().isEmpty()) - obj.setProperty(QLatin1String("fileName"), QScriptValueImpl(eng_p, ctx->fileName())); - if (!ctx->functionName().isEmpty()) - obj.setProperty(QLatin1String("functionName"), QScriptValueImpl(eng_p, ctx->functionName())); - stackArray.setProperty(i, obj); - ctx = ctx->parentContext(); - ++i; - } - error->setProperty(QLatin1String("stack"), stackArray); -} - -QStringList QScriptContextPrivate::backtrace() const -{ - QStringList result; - const QScriptContextPrivate *ctx = this; - while (ctx) { - QString s; - QString functionName = ctx->functionName(); - if (!functionName.isEmpty()) - s += functionName; - else { - if (ctx->parentContext()) { - if (ctx->callee().isFunction() - && ctx->callee().toFunction()->type() != QScriptFunction::Script) { - s += QLatin1String("<native>"); - } else { - s += QLatin1String("<anonymous>"); - } - } else { - s += QLatin1String("<global>"); - } - } - s += QLatin1Char('('); - for (int i = 0; i < ctx->argc; ++i) { - if (i > 0) - s += QLatin1Char(','); - QScriptValueImpl arg = ctx->args[i]; - if (arg.isObject()) - s += QLatin1String("[object Object]"); // don't do a function call - else - s += arg.toString(); - } - s += QLatin1String(")@"); - s += ctx->fileName(); - s += QString::fromLatin1(":%0").arg(ctx->currentLine); - result.append(s); - ctx = ctx->parentContext(); - } - return result; -} - -QScriptValueImpl QScriptContextPrivate::throwError(const QString &text) -{ - return throwError(QScriptContext::UnknownError, text); -} - -QScriptValueImpl QScriptContextPrivate::throwNotImplemented(const QString &name) -{ - return throwTypeError(QString::fromUtf8("%1 is not implemented").arg(name)); -} - -QScriptValueImpl QScriptContextPrivate::throwNotDefined(const QString &name) -{ - return throwError(QScriptContext::ReferenceError, - QString::fromUtf8("%1 is not defined").arg(name)); -} - -QScriptValueImpl QScriptContextPrivate::throwNotDefined(QScriptNameIdImpl *nameId) -{ - return throwNotDefined(QScriptEnginePrivate::toString(nameId)); -} - -bool QScriptContextPrivate::eq_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs) -{ - if (lhs.isNull() && rhs.isUndefined()) - return true; - - else if (lhs.isUndefined() && rhs.isNull()) - return true; - - else if (isNumerical(lhs) && rhs.isString()) - return QScriptEnginePrivate::convertToNativeDouble(lhs) == QScriptEnginePrivate::convertToNativeDouble(rhs); - - else if (lhs.isString() && isNumerical(rhs)) - return QScriptEnginePrivate::convertToNativeDouble(lhs) == QScriptEnginePrivate::convertToNativeDouble(rhs); - - else if (lhs.isBoolean()) - return eq_cmp(QScriptValueImpl(QScriptEnginePrivate::convertToNativeDouble(lhs)), rhs); - - else if (rhs.isBoolean()) - return eq_cmp(lhs, QScriptValueImpl(QScriptEnginePrivate::convertToNativeDouble(rhs))); - - else if (lhs.isObject() && ! rhs.isNull()) { - lhs = lhs.engine()->toPrimitive(lhs); - - if (lhs.isValid() && ! lhs.isObject()) - return eq_cmp(lhs, rhs); - } - - else if (rhs.isObject() && ! lhs.isNull()) { - rhs = rhs.engine()->toPrimitive(rhs); - - if (rhs.isValid() && ! rhs.isObject()) - return eq_cmp(lhs, rhs); - } - - return false; -} - -#if defined(Q_CC_GNU) && __GNUC__ <= 3 -bool QScriptContextPrivate::lt_cmp(QScriptValueImpl lhs, QScriptValueImpl rhs) -{ - if (lhs.type() == rhs.type()) { - switch (lhs.type()) { - case QScript::InvalidType: - case QScript::UndefinedType: - case QScript::NullType: - return false; - - case QScript::NumberType: - return lhs.m_number_value < rhs.m_number_value; - - case QScript::IntegerType: - return lhs.m_int_value < rhs.m_int_value; - - case QScript::BooleanType: - return lhs.m_bool_value < rhs.m_bool_value; - - default: - break; - } // switch - } -#else -bool QScriptContextPrivate::lt_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs) -{ -#endif - if ((lhs.type() == rhs.type()) && (lhs.type() == QScript::StringType)) - return lhs.m_string_value->s < rhs.m_string_value->s; - - if (lhs.isObject()) - lhs = lhs.engine()->toPrimitive(lhs, QScriptValueImpl::NumberTypeHint); - - if (rhs.isObject()) - rhs = rhs.engine()->toPrimitive(rhs, QScriptValueImpl::NumberTypeHint); - - if (lhs.isString() && rhs.isString()) - return QScriptEnginePrivate::convertToNativeString(lhs) < QScriptEnginePrivate::convertToNativeString(rhs); - - qsreal n1 = QScriptEnginePrivate::convertToNativeDouble(lhs); - qsreal n2 = QScriptEnginePrivate::convertToNativeDouble(rhs); -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - if (qIsNaN(n1) || qIsNaN(n2)) - return false; -#endif - return n1 < n2; -} - -bool QScriptContextPrivate::le_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs) -{ - if ((lhs.type() == rhs.type()) && (lhs.type() == QScript::StringType)) - return lhs.m_string_value->s <= rhs.m_string_value->s; - - if (lhs.isObject()) - lhs = lhs.engine()->toPrimitive(lhs, QScriptValueImpl::NumberTypeHint); - - if (rhs.isObject()) - rhs = rhs.engine()->toPrimitive(rhs, QScriptValueImpl::NumberTypeHint); - - if (lhs.isString() && rhs.isString()) - return QScriptEnginePrivate::convertToNativeString(lhs) <= QScriptEnginePrivate::convertToNativeString(rhs); - - qsreal n1 = QScriptEnginePrivate::convertToNativeDouble(lhs); - qsreal n2 = QScriptEnginePrivate::convertToNativeDouble(rhs); - return n1 <= n2; -} - -const QScriptInstruction *QScriptContextPrivate::findExceptionHandler( - const QScriptInstruction *ip) const -{ - Q_ASSERT(m_code); - int offset = ip - m_code->firstInstruction; - for (int i = 0; i < m_code->exceptionHandlers.count(); ++i) { - QScript::ExceptionHandlerDescriptor e = m_code->exceptionHandlers.at(i); - if (offset >= e.startInstruction() && offset <= e.endInstruction()) { - return m_code->firstInstruction + e.handlerInstruction(); - } - } - return 0; -} - -const QScriptInstruction *QScriptContextPrivate::findExceptionHandlerRecursive( - const QScriptInstruction *ip, QScriptContextPrivate **handlerContext) const -{ - const QScriptContextPrivate *ctx = this; - const QScriptInstruction *iip = ip; - while (ctx) { - if (ctx->m_code) { - const QScriptInstruction *ep = ctx->findExceptionHandler(iip); - if (ep) { - Q_ASSERT(handlerContext); - *handlerContext = const_cast<QScriptContextPrivate*>(ctx); - return ep; - } - } - ctx = ctx->parentContext(); - if (ctx) - iip = ctx->iPtr; - } - return 0; -} - -/*! - Requires that iPtr in current context is in sync -*/ -QScriptContextPrivate *QScriptContextPrivate::exceptionHandlerContext() const -{ - QScriptContextPrivate *handlerContext; - if (findExceptionHandlerRecursive(iPtr, &handlerContext)) - return handlerContext; - return 0; -} - -QScriptContext *QScriptContextPrivate::get(QScriptContextPrivate *d) -{ - if (d) - return d->q_func(); - return 0; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptcontext_p.h b/src/script/qscriptcontext_p.h deleted file mode 100644 index 22e7c6b..0000000 --- a/src/script/qscriptcontext_p.h +++ /dev/null @@ -1,361 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTCONTEXT_P_H -#define QSCRIPTCONTEXT_P_H - -#include "qscriptcontextfwd_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptenginefwd_p.h" -#include "qscriptnameid_p.h" - -#include <QtCore/qnumeric.h> - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -inline QScriptContextPrivate::QScriptContextPrivate() - : previous(0), - argc(0), - m_state(QScriptContext::NormalState), - args(0), - tempStack(0), - stackPtr(0), - m_code(0), - iPtr(0), - firstInstruction(0), - lastInstruction(0), - currentLine(0), - currentColumn(0), - errorLineNumber(0), - catching(false), - m_calledAsConstructor(false), - calleeMetaIndex(0), - q_ptr(0) -{ -} - -inline QScriptContextPrivate *QScriptContextPrivate::get(QScriptContext *q) -{ - if (q) - return q->d_func(); - return 0; -} - -inline const QScriptContextPrivate *QScriptContextPrivate::get(const QScriptContext *q) -{ - if (q) - return q->d_func(); - return 0; -} - -inline QScriptContext *QScriptContextPrivate::create() -{ - return new QScriptContext; -} - -inline QScriptEnginePrivate *QScriptContextPrivate::engine() const -{ - return m_activation.engine(); -} - -inline QScriptContextPrivate *QScriptContextPrivate::parentContext() const -{ - return previous; -} - -inline void QScriptContextPrivate::init(QScriptContextPrivate *parent) -{ - m_state = QScriptContext::NormalState; - previous = parent; - args = 0; - argc = 0; - m_code = 0; - iPtr = firstInstruction = lastInstruction = 0; - stackPtr = tempStack = (parent != 0) ? parent->stackPtr : 0; - m_activation.invalidate(); - m_thisObject.invalidate(); - m_result.invalidate(); - m_scopeChain.invalidate(); - m_callee.invalidate(); - m_arguments.invalidate(); - currentLine = -1; - currentColumn = -1; - errorLineNumber = -1; - m_calledAsConstructor = false; -} - -inline QScriptValueImpl QScriptContextPrivate::argument(int index) const -{ - if (index >= argc) - return engine()->undefinedValue(); - - Q_ASSERT(args != 0); - return args[index]; -} - -inline int QScriptContextPrivate::argumentCount() const -{ - return argc; -} - -inline QScriptValueImpl QScriptContextPrivate::argumentsObject() const -{ - if (!m_arguments.isValid() && m_activation.isValid()) { - QScriptContextPrivate *dd = const_cast<QScriptContextPrivate*>(this); - engine()->newArguments(&dd->m_arguments, m_activation, - argc, m_callee); - } - return m_arguments; -} - -inline void QScriptContextPrivate::throwException() -{ - m_state = QScriptContext::ExceptionState; -} - -inline bool QScriptContextPrivate::hasUncaughtException() const -{ - return m_state == QScriptContext::ExceptionState; -} - -inline void QScriptContextPrivate::recover() -{ - m_state = QScriptContext::NormalState; - errorLineNumber = -1; -} - -inline bool QScriptContextPrivate::isNumerical(const QScriptValueImpl &v) -{ - switch (v.type()) { - case QScript::BooleanType: - case QScript::IntegerType: - case QScript::NumberType: - return true; - - default: - return false; - } -} - -inline bool QScriptContextPrivate::eq_cmp(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs) -{ - if (lhs.type() == rhs.type()) { - switch (lhs.type()) { - case QScript::InvalidType: - case QScript::UndefinedType: - case QScript::NullType: - return true; - - case QScript::NumberType: - return lhs.m_number_value == rhs.m_number_value; - - case QScript::ReferenceType: - case QScript::IntegerType: - return lhs.m_int_value == rhs.m_int_value; - - case QScript::BooleanType: - return lhs.m_bool_value == rhs.m_bool_value; - - case QScript::StringType: - if (lhs.m_string_value->unique && rhs.m_string_value->unique) - return lhs.m_string_value == rhs.m_string_value; - return lhs.m_string_value->s == rhs.m_string_value->s; - - case QScript::PointerType: - return lhs.m_ptr_value == rhs.m_ptr_value; - - case QScript::ObjectType: - if (lhs.isVariant()) - return lhs.m_object_value == rhs.m_object_value || lhs.toVariant() == rhs.toVariant(); -#ifndef QT_NO_QOBJECT - else if (lhs.isQObject()) - return lhs.m_object_value == rhs.m_object_value || lhs.toQObject() == rhs.toQObject(); -#endif - else - return lhs.m_object_value == rhs.m_object_value; - - case QScript::LazyStringType: - return *lhs.m_lazy_string_value == *rhs.m_lazy_string_value; - } - } - - return eq_cmp_helper(lhs, rhs); -} - -inline bool QScriptContextPrivate::strict_eq_cmp( const QScriptValueImpl &lhs, const QScriptValueImpl &rhs) -{ - if (lhs.type() != rhs.type()) - return false; - - switch (lhs.type()) { - case QScript::InvalidType: - case QScript::UndefinedType: - case QScript::NullType: - return true; - - case QScript::NumberType: - if (qIsNaN(lhs.m_number_value) || qIsNaN(rhs.m_number_value)) - return false; - return lhs.m_number_value == rhs.m_number_value; - - case QScript::IntegerType: - return lhs.m_int_value == rhs.m_int_value; - - case QScript::BooleanType: - return lhs.m_bool_value == rhs.m_bool_value; - - case QScript::StringType: - if (lhs.m_string_value->unique && rhs.m_string_value->unique) - return lhs.m_string_value == rhs.m_string_value; - return lhs.m_string_value->s == rhs.m_string_value->s; - - case QScript::ObjectType: - return lhs.m_object_value == rhs.m_object_value; - - case QScript::ReferenceType: - return lhs.m_int_value == rhs.m_int_value; - - case QScript::PointerType: - return lhs.m_ptr_value == rhs.m_ptr_value; - - case QScript::LazyStringType: - return *lhs.m_lazy_string_value == *rhs.m_lazy_string_value; - } - - return false; -} - -inline QScriptValueImpl QScriptContextPrivate::throwTypeError(const QString &text) -{ - return throwError(QScriptContext::TypeError, text); -} - -inline QScriptValueImpl QScriptContextPrivate::throwSyntaxError(const QString &text) -{ - return throwError(QScriptContext::SyntaxError, text); -} - -inline QScriptValueImpl QScriptContextPrivate::thisObject() const -{ - return m_thisObject; -} - -inline void QScriptContextPrivate::setThisObject(const QScriptValueImpl &object) -{ - m_thisObject = object; -} - -inline QScriptValueImpl QScriptContextPrivate::callee() const -{ - return m_callee; -} - -inline bool QScriptContextPrivate::isCalledAsConstructor() const -{ - return m_calledAsConstructor; -} - -inline QScriptValueImpl QScriptContextPrivate::returnValue() const -{ - return m_result; -} - -inline void QScriptContextPrivate::setReturnValue(const QScriptValueImpl &value) -{ - m_result = value; -} - -inline QScriptValueImpl QScriptContextPrivate::activationObject() const -{ - if (previous && !m_activation.property(QLatin1String("arguments")).isValid()) { - QScriptContextPrivate *dd = const_cast<QScriptContextPrivate*>(this); - dd->m_activation.setProperty(QLatin1String("arguments"), argumentsObject()); - } - return m_activation; -} - -inline void QScriptContextPrivate::setActivationObject(const QScriptValueImpl &activation) -{ - m_activation = activation; -} - -inline const QScriptInstruction *QScriptContextPrivate::instructionPointer() -{ - return iPtr; -} - -inline void QScriptContextPrivate::setInstructionPointer(const QScriptInstruction *instructionPointer) -{ - iPtr = instructionPointer; -} - -inline const QScriptValueImpl *QScriptContextPrivate::baseStackPointer() const -{ - return tempStack; -} - -inline const QScriptValueImpl *QScriptContextPrivate::currentStackPointer() const -{ - return stackPtr; -} - -inline QScriptContext::ExecutionState QScriptContextPrivate::state() const -{ - return m_state; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif diff --git a/src/script/qscriptcontextfwd_p.h b/src/script/qscriptcontextfwd_p.h deleted file mode 100644 index 6b0c954..0000000 --- a/src/script/qscriptcontextfwd_p.h +++ /dev/null @@ -1,257 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTCONTEXTFWD_P_H -#define QSCRIPTCONTEXTFWD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptvalueimplfwd_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptcontext.h" - -#include <QtCore/qobjectdefs.h> - -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET -#include <QtCore/qnumeric.h> -#endif - -QT_BEGIN_NAMESPACE - -namespace QScript { - namespace AST { - class Node; - } -class Code; -} - -class QScriptInstruction; - -class QScriptContextPrivate -{ - Q_DECLARE_PUBLIC(QScriptContext) -public: - inline QScriptContextPrivate(); - - static inline QScriptContextPrivate *get(QScriptContext *q); - static inline const QScriptContextPrivate *get(const QScriptContext *q); - static QScriptContext *get(QScriptContextPrivate *d); - - static inline QScriptContext *create(); - - inline QScriptEnginePrivate *engine() const; - inline QScriptContextPrivate *parentContext() const; - - inline void init(QScriptContextPrivate *parent); - inline QScriptValueImpl argument(int index) const; - inline int argumentCount() const; - inline QScriptValueImpl argumentsObject() const; - - inline void throwException(); - inline bool hasUncaughtException() const; - const QScriptInstruction *findExceptionHandler(const QScriptInstruction *ip) const; - const QScriptInstruction *findExceptionHandlerRecursive( - const QScriptInstruction *ip, QScriptContextPrivate **handlerContext) const; - QScriptContextPrivate *exceptionHandlerContext() const; - inline void recover(); - QStringList backtrace() const; - - static inline bool isNumerical(const QScriptValueImpl &v); - - static inline bool eq_cmp(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs); - - static bool eq_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs); - -#if defined(Q_CC_GNU) && __GNUC__ <= 3 - static bool lt_cmp(QScriptValueImpl lhs, QScriptValueImpl rhs); -#else - static bool lt_cmp(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs) - { - if (lhs.type() == rhs.type()) { - switch (lhs.type()) { - case QScript::UndefinedType: - case QScript::NullType: - return false; - - case QScript::NumberType: -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - if (qIsNaN(lhs.m_number_value) || qIsNaN(rhs.m_number_value)) - return false; -#endif - return lhs.m_number_value < rhs.m_number_value; - - case QScript::IntegerType: - return lhs.m_int_value < rhs.m_int_value; - - case QScript::BooleanType: - return lhs.m_bool_value < rhs.m_bool_value; - - default: - break; - } // switch - } - - return lt_cmp_helper(lhs, rhs); - } - - static bool lt_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs); -#endif - - static bool le_cmp(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs) - { - if (lhs.type() == rhs.type()) { - switch (lhs.type()) { - case QScript::UndefinedType: - case QScript::NullType: - return true; - - case QScript::NumberType: - return lhs.m_number_value <= rhs.m_number_value; - - case QScript::IntegerType: - return lhs.m_int_value <= rhs.m_int_value; - - case QScript::BooleanType: - return lhs.m_bool_value <= rhs.m_bool_value; - - default: - break; - } // switch - } - - return le_cmp_helper(lhs, rhs); - } - - static bool le_cmp_helper(QScriptValueImpl lhs, QScriptValueImpl rhs); - - static inline bool strict_eq_cmp(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs); - - bool resolveField(QScriptEnginePrivate *eng, QScriptValueImpl *stackPtr, - QScriptValueImpl *value); - - void execute(QScript::Code *code); - - QScriptValueImpl throwError(QScriptContext::Error error, const QString &text); - QScriptValueImpl throwError(const QString &text); - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - qint64 scriptId() const; -#endif - QString fileName() const; - QString functionName() const; - void setDebugInformation(QScriptValueImpl *error) const; - - QScriptValueImpl throwNotImplemented(const QString &name); - QScriptValueImpl throwNotDefined(const QString &name); - QScriptValueImpl throwNotDefined(QScriptNameIdImpl *nameId); - - inline QScriptValueImpl throwTypeError(const QString &text); - inline QScriptValueImpl throwSyntaxError(const QString &text); - - inline QScriptValueImpl thisObject() const; - inline void setThisObject(const QScriptValueImpl &object); - - inline QScriptValueImpl callee() const; - inline bool isCalledAsConstructor() const; - - inline QScriptValueImpl returnValue() const; - inline void setReturnValue(const QScriptValueImpl &value); - - inline QScriptValueImpl activationObject() const; - inline void setActivationObject(const QScriptValueImpl &activation); - - inline const QScriptInstruction *instructionPointer(); - inline void setInstructionPointer(const QScriptInstruction *instructionPointer); - - inline const QScriptValueImpl *baseStackPointer() const; - inline const QScriptValueImpl *currentStackPointer() const; - - inline QScriptContext::ExecutionState state() const; - -public: - QScriptContextPrivate *previous; - int argc; - QScriptContext::ExecutionState m_state; - - QScriptValueImpl m_activation; - QScriptValueImpl m_thisObject; - QScriptValueImpl m_result; - QScriptValueImpl m_scopeChain; - QScriptValueImpl m_callee; - QScriptValueImpl m_arguments; - - QScriptValueImpl *args; - QScriptValueImpl *tempStack; - QScriptValueImpl *stackPtr; - - QScript::Code *m_code; - const QScriptInstruction *iPtr; - const QScriptInstruction *firstInstruction; - const QScriptInstruction *lastInstruction; - - int currentLine; - int currentColumn; - - int errorLineNumber; - - bool catching; - bool m_calledAsConstructor; - - int calleeMetaIndex; - - QScriptContext *q_ptr; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif diff --git a/src/script/qscriptcontextinfo_p.h b/src/script/qscriptcontextinfo_p.h deleted file mode 100644 index 5b63161..0000000 --- a/src/script/qscriptcontextinfo_p.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTCONTEXTINFO_P_H -#define QSCRIPTCONTEXTINFO_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptcontextinfo.h" - -#ifndef QT_NO_SCRIPT - -#include <QtCore/qatomic.h> -#include <QtCore/qstring.h> - -QT_BEGIN_NAMESPACE - -class QScriptContext; - -class QScriptContextInfo; -class QScriptContextInfoPrivate -{ - Q_DECLARE_PUBLIC(QScriptContextInfo) -public: - QScriptContextInfoPrivate(); - QScriptContextInfoPrivate(const QScriptContext *context); - ~QScriptContextInfoPrivate(); - - qint64 scriptId; - int lineNumber; - int columnNumber; - QString fileName; - - QString functionName; - QScriptContextInfo::FunctionType functionType; - - int functionStartLineNumber; - int functionEndLineNumber; - int functionMetaIndex; - - QStringList parameterNames; - - QBasicAtomicInt ref; - - QScriptContextInfo *q_ptr; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptecmaarray.cpp b/src/script/qscriptecmaarray.cpp deleted file mode 100644 index 3933a0d..0000000 --- a/src/script/qscriptecmaarray.cpp +++ /dev/null @@ -1,777 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmaarray_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptclassdata_p.h" - -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class ArrayClassData: public QScriptClassData -{ - QScriptClassInfo *m_classInfo; - -public: - ArrayClassData(QScriptClassInfo *classInfo); - virtual ~ArrayClassData(); - - inline QScriptClassInfo *classInfo() const - { return m_classInfo; } - - virtual void mark(const QScriptValueImpl &object, int generation); - virtual bool resolve(const QScriptValueImpl &object, - QScriptNameIdImpl *nameId, - QScript::Member *member, - QScriptValueImpl *base, - QScript::AccessMode mode); - virtual bool get(const QScriptValueImpl &obj, const Member &m, - QScriptValueImpl *out_value); - virtual bool put(QScriptValueImpl *object, const Member &member, - const QScriptValueImpl &value); - virtual bool removeMember(const QScriptValueImpl &object, - const QScript::Member &member); - virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object); -}; - -class ArrayClassDataIterator: public QScriptClassDataIterator -{ -public: - ArrayClassDataIterator(Array::Instance *instance); - virtual ~ArrayClassDataIterator(); - - virtual bool hasNext() const; - virtual void next(QScript::Member *member); - - virtual bool hasPrevious() const; - virtual void previous(QScript::Member *member); - - virtual void toFront(); - virtual void toBack(); - -private: - Array::Instance *m_instance; - QList<uint> m_keys; - quint32 m_pos; -}; - -ArrayClassData::ArrayClassData(QScriptClassInfo *classInfo): - m_classInfo(classInfo) -{ -} - -ArrayClassData::~ArrayClassData() -{ -} - -void ArrayClassData::mark(const QScriptValueImpl &object, int generation) -{ - Array::Instance *instance = Array::Instance::get(object, classInfo()); - if (! instance) - return; - - instance->value.mark(generation); -} - -bool ArrayClassData::resolve(const QScriptValueImpl &object, - QScriptNameIdImpl *nameId, - QScript::Member *member, - QScriptValueImpl *base, - QScript::AccessMode access) -{ - QScriptEnginePrivate *eng_p = object.engine(); - - Array::Instance *instance = Array::Instance::get(object, classInfo()); - if (!instance) - return false; - - if (nameId == eng_p->idTable()->id_length) { - member->native(nameId, /*id=*/ 0, - QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration); - *base = object; - return true; - } - - QString propertyName = eng_p->toString(nameId); - bool isNumber; - quint32 pos = propertyName.toUInt(&isNumber); - - if (!isNumber || (pos == 0xFFFFFFFF) - || (QScriptValueImpl(pos).toString() != propertyName)) { // ### improve me - return false; - } - - if ((access == QScript::Read) && ((pos >= instance->value.count()) || !instance->value.at(pos).isValid())) - return false; - - member->native(0, pos, /*flags=*/0); - *base = object; - return true; -} - -bool ArrayClassData::get(const QScriptValueImpl &object, - const QScript::Member &member, - QScriptValueImpl *result) -{ - Q_ASSERT(member.isValid()); - - if (! member.isNativeProperty()) - return false; - - QScriptEnginePrivate *eng = object.engine(); - - Array::Instance *instance = Array::Instance::get(object, classInfo()); - if (! instance) - return false; - - if (member.nameId() == eng->idTable()->id_length) - *result = QScriptValueImpl(instance->value.count()); - - else { - quint32 pos = quint32 (member.id()); - - if (pos < instance->value.count()) - *result = instance->value.at(pos); - else - *result = eng->undefinedValue(); - } - - return true; -} - -bool ArrayClassData::put(QScriptValueImpl *object, - const QScript::Member &member, - const QScriptValueImpl &value) -{ - Q_ASSERT(object != 0); - Q_ASSERT(member.isValid()); - - if (! member.isNativeProperty()) - return false; - - Array::Instance *instance = Array::Instance::get(*object, classInfo()); - if (! instance) - return false; - - QScriptEnginePrivate *eng_p = object->engine(); - - if (member.nameId() == eng_p->idTable()->id_length) { - qsreal length = value.toNumber(); - quint32 len = eng_p->toUint32(length); - instance->value.resize(len); - } - - else if (member.nameId() == 0) { - quint32 pos = quint32 (member.id()); - instance->value.assign(pos, value); - } - - return true; -} - -bool ArrayClassData::removeMember(const QScriptValueImpl &object, - const QScript::Member &member) -{ - if (!member.isNativeProperty() || !member.isDeletable() || (member.nameId() != 0)) - return false; - - Array::Instance *instance = Array::Instance::get(object, classInfo()); - if (! instance) - return false; - - quint32 pos = quint32 (member.id()); - if (instance->value.at(pos).isValid()) - instance->value.assign(pos, QScriptValueImpl()); - return true; -} - -QScriptClassDataIterator *ArrayClassData::newIterator(const QScriptValueImpl &object) -{ - Array::Instance *instance = Array::Instance::get(object, classInfo()); - return new ArrayClassDataIterator(instance); -} - -ArrayClassDataIterator::ArrayClassDataIterator(Array::Instance *instance) -{ - m_instance = instance; - toFront(); -} - -ArrayClassDataIterator::~ArrayClassDataIterator() -{ -} - -bool ArrayClassDataIterator::hasNext() const -{ - quint32 limit = m_keys.isEmpty() ? m_instance->value.size() : quint32(m_keys.size()); - for (quint32 i = m_pos; i < limit; ++i) { - quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i); - if (m_instance->value.at(realI).isValid()) - return true; - } - return false; -} - -void ArrayClassDataIterator::next(QScript::Member *member) -{ - quint32 limit = m_keys.isEmpty() ? m_instance->value.size() : quint32(m_keys.size()); - for (quint32 i = m_pos; i < limit; ++i) { - quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i); - if (m_instance->value.at(realI).isValid()) { - member->native(/*nameId=*/0, realI, /*flags=*/0); - m_pos = i + 1; - return; - } - } - member->invalidate(); -} - -bool ArrayClassDataIterator::hasPrevious() const -{ - for (quint32 i = m_pos - 1; i != 0xFFFFFFFF; --i) { - quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i); - if (m_instance->value.at(realI).isValid()) - return true; - } - return false; -} - -void ArrayClassDataIterator::previous(QScript::Member *member) -{ - for (quint32 i = m_pos - 1; i != 0xFFFFFFFF; --i) { - quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i); - if (m_instance->value.at(realI).isValid()) { - member->native(/*nameId=*/ 0, realI, /*flags=*/0); - m_pos = i; - return; - } - } - member->invalidate(); -} - -void ArrayClassDataIterator::toFront() -{ - m_keys = m_instance->value.keys(); - m_pos = 0; -} - -void ArrayClassDataIterator::toBack() -{ - m_keys = m_instance->value.keys(); - m_pos = m_keys.isEmpty() ? m_instance->value.count() : m_keys.size(); -} - - - -Array::Array(QScriptEnginePrivate *eng): - Core(eng, QLatin1String("Array"), QScriptClassInfo::ArrayType) -{ - classInfo()->setData(new ArrayClassData(classInfo())); - - newArray(&publicPrototype, QScript::Array(eng)); - - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("toString"), method_toString, 0); - addPrototypeFunction(QLatin1String("toLocaleString"), method_toLocaleString, 0); - addPrototypeFunction(QLatin1String("concat"), method_concat, 1); - addPrototypeFunction(QLatin1String("join"), method_join, 1); - addPrototypeFunction(QLatin1String("pop"), method_pop, 0); - addPrototypeFunction(QLatin1String("push"), method_push, 1); - addPrototypeFunction(QLatin1String("reverse"), method_reverse, 0); - addPrototypeFunction(QLatin1String("shift"), method_shift, 0); - addPrototypeFunction(QLatin1String("slice"), method_slice, 2); - addPrototypeFunction(QLatin1String("sort"), method_sort, 1); - addPrototypeFunction(QLatin1String("splice"), method_splice, 2); - addPrototypeFunction(QLatin1String("unshift"), method_unshift, 1); -} - -Array::~Array() -{ -} - -void Array::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - QScript::Array value(engine()); - - if (context->argumentCount() == 1 && context->argument(0).isNumber()) { - qsreal size = context->argument(0).toNumber(); - quint32 isize = QScriptEnginePrivate::toUint32(size); - - if (size != qsreal(isize)) { - context->throwError(QScriptContext::RangeError, QLatin1String("invalid array length")); - return; - } - - value.resize(isize); - } else { - for (int i = 0; i < context->argumentCount(); ++i) { - value.assign(i, context->argument(i)); - } - } - - if (context->isCalledAsConstructor()) { - QScriptValueImpl &object = context->m_thisObject; - object.setClassInfo(classInfo()); - object.setPrototype(publicPrototype); - initArray(&object, value); - } else { - newArray(&context->m_result, value); - } - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -void Array::newArray(QScriptValueImpl *result, const QScript::Array &value) -{ - engine()->newObject(result, publicPrototype, classInfo()); - initArray(result, value); -} - -void Array::initArray(QScriptValueImpl *result, const QScript::Array &value) -{ - Instance *instance = new Instance(engine()); - instance->value = value; - result->setObjectData(instance); -} - -QScriptValueImpl Array::method_toString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - return method_join(context, eng, classInfo); // ### fixme -} - -QScriptValueImpl Array::method_toLocaleString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - return method_toString(context, eng, classInfo); -} - -QScriptValueImpl Array::method_concat(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - QScript::Array result(eng); - - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) - result = instance->value; - - else { - QString v = context->thisObject().toString(); - result.assign(0, QScriptValueImpl(eng, v)); - } - - for (int i = 0; i < context->argumentCount(); ++i) { - quint32 k = result.size(); - QScriptValueImpl arg = context->argument(i); - - if (Instance *elt = Instance::get(arg, classInfo)) - result.concat(elt->value); - - else - result.assign(k, QScriptValueImpl(eng, arg.toString())); - } - - return eng->newArray(result); -} - -QScriptValueImpl Array::method_join(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QScriptValueImpl arg = context->argument(0); - - QString r4; - if (arg.isUndefined()) - r4 = QLatin1String(","); - else - r4 = arg.toString(); - - QScriptValueImpl self = context->thisObject(); - - QScriptNameIdImpl *id_length = eng->idTable()->id_length; - QScriptValueImpl length = self.property(id_length); - qsreal r1 = length.isValid() ? length.toNumber() : 0; - quint32 r2 = QScriptEnginePrivate::toUint32(r1); - - if (! r2) - return QScriptValueImpl(eng, QString()); - - if (eng->visitedArrayElements.contains(self.objectValue())) { - // avoid infinite recursion - return QScriptValueImpl(eng, QString()); - } - eng->visitedArrayElements.insert(self.objectValue()); - - QString R; - - QScriptValueImpl r6 = self.property(QLatin1String("0")); - if (r6.isValid() && !(r6.isUndefined() || r6.isNull())) - R = r6.toString(); - - for (quint32 k = 1; k < r2; ++k) { - R += r4; - - QScriptNameIdImpl *name = eng->nameId(QScriptValueImpl(k).toString()); - QScriptValueImpl r12 = self.property(name); - - if (r12.isValid() && ! (r12.isUndefined() || r12.isNull())) - R += r12.toString(); - } - - eng->visitedArrayElements.remove(self.objectValue()); - return QScriptValueImpl(eng, R); -} - -QScriptValueImpl Array::method_pop(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (Instance *instance = Instance::get(self, classInfo)) { - QScriptValueImpl elt = instance->value.pop(); - if (! elt.isValid()) - elt = eng->undefinedValue(); - - return elt; - } - - QScriptNameIdImpl *id_length = eng->idTable()->id_length; - - QScriptValueImpl r1 = self.property(id_length); - quint32 r2 = r1.toUInt32(); - if (! r2) { - self.setProperty(id_length, QScriptValueImpl(0)); - return eng->undefinedValue(); - } - QScriptNameIdImpl *r6 = eng->nameId(QScriptValueImpl(r2 - 1).toString()); - QScriptValueImpl r7 = self.property(r6); - self.deleteProperty(r6); - self.setProperty(id_length, QScriptValueImpl(r2 - 1)); - if (!r7.isValid()) - return eng->undefinedValue(); - return r7; -} - -QScriptValueImpl Array::method_push(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (Instance *instance = Instance::get(self, classInfo)) { - uint pos = instance->value.size(); - for (int i = 0; i < context->argumentCount(); ++i) { - QScriptValueImpl val = context->argument(i); - if (pos == 0xFFFFFFFF) { - self.setProperty(pos++, val); - self.setProperty(eng->idTable()->id_length, 0); - } else { - instance->value.assign(pos++, val); - } - } - return QScriptValueImpl(pos); - } - - QScriptNameIdImpl *id_length = eng->idTable()->id_length; - QScriptValueImpl r1 = self.property(id_length); - quint32 n = r1.toUInt32(); - for (int index = 0; index < context->argumentCount(); ++index, ++n) { - QScriptValueImpl r3 = context->argument(index); - QScriptNameIdImpl *name = eng->nameId(QScriptValueImpl(n).toString()); - self.setProperty(name, r3); - } - QScriptValueImpl r(n); - self.setProperty(id_length, r); - return r; -} - -QScriptValueImpl Array::method_reverse(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (Instance *instance = Instance::get(self, classInfo)) { - int lo = 0, hi = instance->value.count () - 1; - - for (; lo < hi; ++lo, --hi) { - QScriptValueImpl tmp = instance->value.at(lo); - instance->value.assign(lo, instance->value.at(hi)); - instance->value.assign(hi, tmp); - } - - } else { - QScriptNameIdImpl *id_length = eng->idTable()->id_length; - - QScriptValueImpl lengthValue = self.property(id_length); - quint32 length = 0; - if (lengthValue.isValid()) - length = QScriptEnginePrivate::toUint32(lengthValue.toNumber()); - const quint32 m = length / 2; - for (quint32 i = 0; i < m; ++i) { - quint32 j = length - i - 1; - - QScriptNameIdImpl *iid = eng->nameId(QScriptValueImpl(i).toString()); - QScriptNameIdImpl *jid = eng->nameId(QScriptValueImpl(j).toString()); - - QScript::Member imember; - QScriptValueImpl ibase; - QScriptValueImpl ival; - bool iok = self.resolve(iid, &imember, &ibase, QScriptValue::ResolvePrototype, QScript::ReadWrite); - if (iok) - ibase.get(iid, &ival); - else - ival = eng->undefinedValue(); - - QScript::Member jmember; - QScriptValueImpl jbase; - QScriptValueImpl jval; - bool jok = self.resolve(jid, &jmember, &jbase, QScriptValue::ResolvePrototype, QScript::ReadWrite); - if (jok) - jbase.get(jid, &jval); - else - jval = eng->undefinedValue(); - - if (!jok) { - if (iok) { - if (eng->strictlyEquals(ibase, self)) - ibase.removeMember(imember); - self.setProperty(jid, ival); - } - } else if (!iok) { - self.setProperty(iid, jval); - if (eng->strictlyEquals(jbase, self)) - jbase.removeMember(jmember); - } else { - if (eng->strictlyEquals(self, ibase)) - self.put(imember, jval); - else - self.setProperty(iid, jval); - if (eng->strictlyEquals(self, jbase)) - self.put(jmember, ival); - else - self.setProperty(jid, ival); - } - } - } - - return context->thisObject(); -} - -QScriptValueImpl Array::method_shift(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QScriptNameIdImpl *id_length = eng->idTable()->id_length; - - QScriptValueImpl self = context->thisObject(); - quint32 length = self.property(id_length).toUInt32(); - if (length == 0) { - self.setProperty(id_length, QScriptValueImpl(0)); - return eng->undefinedValue(); - } - - QScript::Member member; - QScriptValueImpl base; - - QScriptValueImpl result = self.property(QLatin1String("0")); - if (! result.isValid()) - result = eng->undefinedValue(); - - for (quint32 index = 1; index < length; ++index) { - QScriptNameIdImpl *k = eng->nameId(QScriptValueImpl(index).toString()); - QScriptNameIdImpl *k1 = eng->nameId(QScriptValueImpl(index - 1).toString()); - - QScriptValueImpl v = self.property(k); - QScriptValueImpl v1 = self.property(k1); - - if (v.isValid()) - self.setProperty(k1, v); - - else if (v1.isValid() && self.resolve(k1, &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite)) - self.removeMember(member); - } - - QScriptValueImpl len = QScriptValueImpl(length - 1); - - if (self.resolve(eng->nameId(len.toString()), &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite)) - self.removeMember(member); - - self.setProperty(id_length, len); - return (result); -} - -QScriptValueImpl Array::method_slice(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QScript::Array result(eng); - - QScriptValueImpl start = context->argument(0); - QScriptValueImpl end = context->argument(1); - - QScriptValueImpl self = context->thisObject(); - QScriptNameIdImpl *id_length = eng->idTable()->id_length; - qsreal r2 = self.property(id_length).toNumber(); - quint32 r3 = QScriptEnginePrivate::toUint32(r2); - qint32 r4 = qint32 (start.toInteger()); - quint32 r5 = r4 < 0 ? qMax(quint32(r3 + r4), quint32(0)) : qMin(quint32(r4), r3); - quint32 k = r5; - qint32 r7 = end.isUndefined() ? r3 : qint32 (end.toInteger()); - quint32 r8 = r7 < 0 ? qMax(quint32(r3 + r7), quint32(0)) : qMin(quint32(r7), r3); - quint32 n = 0; - for (; k < r8; ++k) { - QString r11 = QScriptValueImpl(k).toString(); - QScriptValueImpl v = self.property(r11); - if (v.isValid()) - result.assign(n++, v); - } - return eng->newArray(result); -} - -QScriptValueImpl Array::method_sort(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - QScriptValueImpl comparefn = context->argument(0); - if (Instance *instance = Instance::get(self, classInfo)) { - instance->value.sort(comparefn); - return context->thisObject(); - } - return context->throwNotImplemented(QLatin1String("Array.prototype.sort")); -} - -QScriptValueImpl Array::method_splice(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - if (context->argumentCount() < 2) - return eng->undefinedValue(); - - QScriptValueImpl self = context->thisObject(); - - qsreal start = context->argument(0).toInteger(); - qsreal deleteCount = context->argument(1).toInteger(); - - QScriptValueImpl arrayCtor = eng->globalObject().property(QLatin1String("Array")); - QScriptValueImpl a = arrayCtor.construct(); - - if (Instance *instance = Instance::get(self, classInfo)) { - QVector<QScriptValueImpl> items; - for (int i = 2; i < context->argumentCount(); ++i) - items << context->argument(i); - Instance *otherInstance = Instance::get(a, classInfo); - Q_ASSERT(otherInstance); - instance->value.splice(start, deleteCount, items, otherInstance->value); - return a; - } - - return context->throwNotImplemented(QLatin1String("Array.prototype.splice")); -} - -QScriptValueImpl Array::method_unshift(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QScriptValueImpl self = context->thisObject(); - - QScriptNameIdImpl *id_length = eng->idTable()->id_length; - QScriptValueImpl r1 = self.property(id_length); - quint32 r2 = r1.isValid() ? QScriptEnginePrivate::toUint32(r1.toNumber()) : 0; - quint32 r3 = quint32 (context->argumentCount()); - quint32 k = r2; - for (; k != 0; --k) { - QScriptNameIdImpl *r6 = eng->nameId(QScriptValueImpl(k - 1).toString()); - QScriptNameIdImpl *r7 = eng->nameId(QScriptValueImpl(k + r3 - 1).toString()); - QScriptValueImpl r8 = self.property(r6); - if (r8.isValid()) - self.setProperty(r7, r8); - - else { - QScript::Member member; - QScriptValueImpl base; - - if (self.resolve(r7, &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite)) - self.removeMember(member); - } - } - - for (k = 0; k < r3; ++k) { - QScriptValueImpl r16 = context->argument(k); - QScriptNameIdImpl *r17 = eng->nameId(QScriptValueImpl(k).toString()); - self.setProperty(r17, r16); - } - QScriptValueImpl r(r2 + r3); - self.setProperty(id_length, r); - return (r); -} - -Array::Instance *Array::Instance::get(const QScriptValueImpl &object, QScriptClassInfo *klass) -{ - if (! klass || klass == object.classInfo()) - return static_cast<Instance*> (object.objectData()); - - return 0; -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmaarray_p.h b/src/script/qscriptecmaarray_p.h deleted file mode 100644 index 33e81d2..0000000 --- a/src/script/qscriptecmaarray_p.h +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMAARRAY_P_H -#define QSCRIPTECMAARRAY_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptarray_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptecmacore_p.h" - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class Array: public Core -{ -public: - Array(QScriptEnginePrivate *engine); - virtual ~Array(); - - virtual void execute(QScriptContextPrivate *context); - - class Instance: public QScriptObjectData { - public: - Instance(QScriptEnginePrivate *engine) - : value(QScript::Array(engine)) {} - virtual ~Instance() {} - - static Instance *get(const QScriptValueImpl &object, - QScriptClassInfo *klass); - - public: // attributes - QScript::Array value; - }; - - inline Instance *get(const QScriptValueImpl &object) const - { return Instance::get(object, classInfo()); } - - void newArray(QScriptValueImpl *result, - const QScript::Array &value); - -protected: - static QScriptValueImpl method_toString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLocaleString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_concat(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_join(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_pop(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_push(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_reverse(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_shift(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_slice(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_sort(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_splice(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_unshift(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - -private: - void initArray(QScriptValueImpl *result, const QScript::Array &value); -}; - -} } // namespace QScript::Ecma - -#endif // QT_NO_SCRIPT - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptecmaboolean.cpp b/src/script/qscriptecmaboolean.cpp deleted file mode 100644 index 7d37237..0000000 --- a/src/script/qscriptecmaboolean.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmaboolean_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -Boolean::Boolean(QScriptEnginePrivate *eng): - Core(eng, QLatin1String("Boolean"), QScriptClassInfo::BooleanType) -{ - newBoolean(&publicPrototype, false); - - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("toString"), method_toString, 0); - addPrototypeFunction(QLatin1String("valueOf"), method_valueOf, 0); -} - -Boolean::~Boolean() -{ -} - -void Boolean::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - bool value; - if (context->argumentCount() > 0) - value = context->argument(0).toBoolean(); - else - value = false; - - QScriptValueImpl boolean(value); - if (!context->isCalledAsConstructor()) { - context->setReturnValue(boolean); - } else { - QScriptValueImpl &obj = context->m_thisObject; - obj.setClassInfo(classInfo()); - obj.setInternalValue(boolean); - obj.setPrototype(publicPrototype); - context->setReturnValue(obj); - } -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -void Boolean::newBoolean(QScriptValueImpl *result, bool value) -{ - engine()->newObject(result, publicPrototype, classInfo()); - result->setInternalValue(QScriptValueImpl(value)); -} - -QScriptValueImpl Boolean::method_toString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("Boolean.prototype.toString")); - } - const QScript::IdTable *t = eng->idTable(); - bool v = self.internalValue().toBoolean(); - QScriptValueImpl result; - eng->newNameId(&result, v ? t->id_true : t->id_false); - return result; -} - -QScriptValueImpl Boolean::method_valueOf(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("Boolean.prototype.valueOf")); - } - return self.internalValue(); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmaboolean_p.h b/src/script/qscriptecmaboolean_p.h deleted file mode 100644 index 9124035..0000000 --- a/src/script/qscriptecmaboolean_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMABOOLEAN_P_H -#define QSCRIPTECMABOOLEAN_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptecmacore_p.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_SCRIPT - -namespace QScript { namespace Ecma { - -class Boolean: public Core -{ -public: - Boolean(QScriptEnginePrivate *engine); - virtual ~Boolean(); - - virtual void execute(QScriptContextPrivate *context); - - void newBoolean(QScriptValueImpl *result, bool value = false); - -protected: - static QScriptValueImpl method_toString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_valueOf(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); -}; - -} } // namespace QScript::Ecma - -#endif // QT_NO_SCRIPT - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptecmacore.cpp b/src/script/qscriptecmacore.cpp deleted file mode 100644 index d1bf645..0000000 --- a/src/script/qscriptecmacore.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmacore_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -Core::Core(QScriptEnginePrivate *engine, const QString &className, - QScriptClassInfo::Type type) - : m_engine(engine) -{ - m_classInfo = engine->registerClass(className, type); - this->length = 1; -} - -Core::Core(QScriptEnginePrivate *engine, QScriptClassInfo *classInfo) - : m_engine(engine), m_classInfo(classInfo) -{ - this->length = 1; -} - -Core::~Core() -{ -} - -void Core::addPrototypeFunction(const QString &name, QScriptInternalFunctionSignature fun, - int length, const QScriptValue::PropertyFlags flags) -{ - addFunction(publicPrototype, name, fun, length, flags); -} - -void Core::addConstructorFunction(const QString &name, QScriptInternalFunctionSignature fun, - int length, const QScriptValue::PropertyFlags flags) -{ - addFunction(ctor, name, fun, length, flags); -} - -void Core::addFunction(QScriptValueImpl &object, const QString &name, - QScriptInternalFunctionSignature fun, int length, - const QScriptValue::PropertyFlags flags) -{ - QScriptValueImpl val = engine()->createFunction(fun, length, m_classInfo, name); - object.setProperty(name, val, flags); -} - -QString Core::functionName() const -{ - return m_classInfo->name(); -} - -void Core::mark(QScriptEnginePrivate *eng, int generation) -{ - QScriptFunction::mark(eng, generation); - eng->markObject(ctor, generation); - eng->markObject(publicPrototype, generation); -} - -QScriptValueImpl Core::throwThisObjectTypeError(QScriptContextPrivate *context, - const QString &functionName) -{ - return context->throwError(QScriptContext::TypeError, - QString::fromLatin1("%0 called on incompatible object") - .arg(functionName)); -} - -} // namespace Ecma - -} // namespace QScript - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmacore_p.h b/src/script/qscriptecmacore_p.h deleted file mode 100644 index 0b3a3ab..0000000 --- a/src/script/qscriptecmacore_p.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMACORE_P_H -#define QSCRIPTECMACORE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptfunction_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptvalueimplfwd_p.h" -#include "qscriptclassinfo_p.h" - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class Core: public QScriptFunction -{ -public: - Core(QScriptEnginePrivate *engine, const QString &className, - QScriptClassInfo::Type type); - Core(QScriptEnginePrivate *engine, QScriptClassInfo *classInfo); - virtual ~Core(); - - inline QScriptEnginePrivate *engine() const - { return m_engine; } - - inline QScriptClassInfo *classInfo() const - { return m_classInfo; } - - void addPrototypeFunction( - const QString &name, QScriptInternalFunctionSignature fun, int length, - const QScriptValue::PropertyFlags flags = QScriptValue::SkipInEnumeration); - void addConstructorFunction( - const QString &name, QScriptInternalFunctionSignature fun, int length, - const QScriptValue::PropertyFlags flags = QScriptValue::SkipInEnumeration); - - QString functionName() const; - - virtual void mark(QScriptEnginePrivate *eng, int generation); - -public: // attributes - QScriptValueImpl ctor; - QScriptValueImpl publicPrototype; - -protected: - static QScriptValueImpl throwThisObjectTypeError( - QScriptContextPrivate *context, const QString &functionName); - -private: - void addFunction(QScriptValueImpl &object, const QString &name, - QScriptInternalFunctionSignature fun, int length, - const QScriptValue::PropertyFlags flags); - - QScriptEnginePrivate *m_engine; - QScriptClassInfo *m_classInfo; -}; - -} } // namespace QScript::Ecma - -#endif // QT_NO_SCRIPT - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptecmadate.cpp b/src/script/qscriptecmadate.cpp deleted file mode 100644 index 3b2d72c..0000000 --- a/src/script/qscriptecmadate.cpp +++ /dev/null @@ -1,1285 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmadate_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QDateTime> -#include <QtCore/QRegExp> -#include <QtCore/QtDebug> -#include <QtCore/QLocale> -#include <QtCore/qnumeric.h> - -#include <math.h> - -#ifndef Q_WS_WIN -# include <time.h> -# ifndef Q_OS_VXWORKS -# include <sys/time.h> -# else -# include "qplatformdefs.h" -# endif -#else -# include <windows.h> -#endif - -QT_BEGIN_NAMESPACE - -namespace QScript { - -static const qsreal HoursPerDay = 24.0; -static const qsreal MinutesPerHour = 60.0; -static const qsreal SecondsPerMinute = 60.0; -static const qsreal msPerSecond = 1000.0; -static const qsreal msPerMinute = 60000.0; -static const qsreal msPerHour = 3600000.0; -static const qsreal msPerDay = 86400000.0; - -static qsreal LocalTZA = 0.0; // initialized at startup - -static inline qsreal TimeWithinDay(qsreal t) -{ - qsreal r = ::fmod(t, msPerDay); - return (r >= 0) ? r : r + msPerDay; -} - -static inline int HourFromTime(qsreal t) -{ - int r = int(::fmod(::floor(t / msPerHour), HoursPerDay)); - return (r >= 0) ? r : r + int(HoursPerDay); -} - -static inline int MinFromTime(qsreal t) -{ - int r = int(::fmod(::floor(t / msPerMinute), MinutesPerHour)); - return (r >= 0) ? r : r + int(MinutesPerHour); -} - -static inline int SecFromTime(qsreal t) -{ - int r = int(::fmod(::floor(t / msPerSecond), SecondsPerMinute)); - return (r >= 0) ? r : r + int(SecondsPerMinute); -} - -static inline int msFromTime(qsreal t) -{ - int r = int(::fmod(t, msPerSecond)); - return (r >= 0) ? r : r + int(msPerSecond); -} - -static inline qsreal Day(qsreal t) -{ - return ::floor(t / msPerDay); -} - -static inline qsreal DaysInYear(qsreal y) -{ - if (::fmod(y, 4)) - return 365; - - else if (::fmod(y, 100)) - return 366; - - else if (::fmod(y, 400)) - return 365; - - return 366; -} - -static inline qsreal DayFromYear(qsreal y) -{ - return 365 * (y - 1970) - + ::floor((y - 1969) / 4) - - ::floor((y - 1901) / 100) - + ::floor((y - 1601) / 400); -} - -static inline qsreal TimeFromYear(qsreal y) -{ - return msPerDay * DayFromYear(y); -} - -static inline qsreal YearFromTime(qsreal t) -{ - int y = 1970; - y += (int) ::floor(t / (msPerDay * 365.2425)); - - qsreal t2 = TimeFromYear(y); - return (t2 > t) ? y - 1 : ((t2 + msPerDay * DaysInYear(y)) <= t) ? y + 1 : y; -} - -static inline bool InLeapYear(qsreal t) -{ - qsreal x = DaysInYear(YearFromTime(t)); - if (x == 365) - return 0; - - Q_ASSERT (x == 366); - return 1; -} - -static inline qsreal DayWithinYear(qsreal t) -{ - return Day(t) - DayFromYear(YearFromTime(t)); -} - -static inline qsreal MonthFromTime(qsreal t) -{ - qsreal d = DayWithinYear(t); - qsreal l = InLeapYear(t); - - if (d < 31.0) - return 0; - - else if (d < 59.0 + l) - return 1; - - else if (d < 90.0 + l) - return 2; - - else if (d < 120.0 + l) - return 3; - - else if (d < 151.0 + l) - return 4; - - else if (d < 181.0 + l) - return 5; - - else if (d < 212.0 + l) - return 6; - - else if (d < 243.0 + l) - return 7; - - else if (d < 273.0 + l) - return 8; - - else if (d < 304.0 + l) - return 9; - - else if (d < 334.0 + l) - return 10; - - else if (d < 365.0 + l) - return 11; - - return qSNaN(); // ### assert? -} - -static inline qsreal DateFromTime(qsreal t) -{ - int m = (int) QScriptEnginePrivate::toInteger(MonthFromTime(t)); - qsreal d = DayWithinYear(t); - qsreal l = InLeapYear(t); - - switch (m) { - case 0: return d + 1.0; - case 1: return d - 30.0; - case 2: return d - 58.0 - l; - case 3: return d - 89.0 - l; - case 4: return d - 119.0 - l; - case 5: return d - 150.0 - l; - case 6: return d - 180.0 - l; - case 7: return d - 211.0 - l; - case 8: return d - 242.0 - l; - case 9: return d - 272.0 - l; - case 10: return d - 303.0 - l; - case 11: return d - 333.0 - l; - } - - return qSNaN(); // ### assert -} - -static inline qsreal WeekDay(qsreal t) -{ - qsreal r = ::fmod (Day(t) + 4.0, 7.0); - return (r >= 0) ? r : r + 7.0; -} - - -static inline qsreal MakeTime(qsreal hour, qsreal min, qsreal sec, qsreal ms) -{ - return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms; -} - -static inline qsreal DayFromMonth(qsreal month, qsreal leap) -{ - switch ((int) month) { - case 0: return 0; - case 1: return 31.0; - case 2: return 59.0 + leap; - case 3: return 90.0 + leap; - case 4: return 120.0 + leap; - case 5: return 151.0 + leap; - case 6: return 181.0 + leap; - case 7: return 212.0 + leap; - case 8: return 243.0 + leap; - case 9: return 273.0 + leap; - case 10: return 304.0 + leap; - case 11: return 334.0 + leap; - } - - return qSNaN(); // ### assert? -} - -static qsreal MakeDay(qsreal year, qsreal month, qsreal day) -{ - year += ::floor(month / 12.0); - - month = ::fmod(month, 12.0); - if (month < 0) - month += 12.0; - - qsreal t = TimeFromYear(year); - qsreal leap = InLeapYear(t); - - day += ::floor(t / msPerDay); - day += DayFromMonth(month, leap); - - return day - 1; -} - -static inline qsreal MakeDate(qsreal day, qsreal time) -{ - return day * msPerDay + time; -} - -static inline qsreal DaylightSavingTA(double t) -{ -#ifndef Q_WS_WIN - long int tt = (long int)(t / msPerSecond); - struct tm *tmtm = localtime((const time_t*)&tt); - if (! tmtm) - return 0; - return (tmtm->tm_isdst > 0) ? msPerHour : 0; -#else - Q_UNUSED(t); - /// ### implement me - return 0; -#endif -} - -static inline qsreal LocalTime(qsreal t) -{ - return t + LocalTZA + DaylightSavingTA(t); -} - -static inline qsreal UTC(qsreal t) -{ - return t - LocalTZA - DaylightSavingTA(t - LocalTZA); -} - -static inline qsreal currentTime() -{ -#ifndef Q_WS_WIN - struct timeval tv; - - gettimeofday(&tv, 0); - return ::floor(tv.tv_sec * msPerSecond + (tv.tv_usec / 1000.0)); -#else - SYSTEMTIME st; - GetSystemTime(&st); - FILETIME ft; - SystemTimeToFileTime(&st, &ft); - LARGE_INTEGER li; - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - return double(li.QuadPart - Q_INT64_C(116444736000000000)) / 10000.0; -#endif -} - -static inline qsreal TimeClip(qsreal t) -{ - if (! qIsFinite(t) || fabs(t) > 8.64e15) - return qSNaN(); - return QScriptEnginePrivate::toInteger(t); -} - -static inline qsreal FromDateTime(const QDateTime &dt) -{ - if (!dt.isValid()) - return qSNaN(); - QDate date = dt.date(); - QTime taim = dt.time(); - int year = date.year(); - int month = date.month() - 1; - int day = date.day(); - int hours = taim.hour(); - int mins = taim.minute(); - int secs = taim.second(); - int ms = taim.msec(); - double t = MakeDate(MakeDay(year, month, day), - MakeTime(hours, mins, secs, ms)); - if (dt.timeSpec() == Qt::LocalTime) - t = UTC(t); - return TimeClip(t); -} - -static inline qsreal ParseString(const QString &s) -{ - QDateTime dt = QDateTime::fromString(s, Qt::TextDate); - if (!dt.isValid()) - dt = QDateTime::fromString(s, Qt::ISODate); - if (!dt.isValid()) { - QStringList formats; - formats << QLatin1String("M/d/yyyy") - << QLatin1String("M/d/yyyy hh:mm") - << QLatin1String("M/d/yyyy hh:mm A") - - << QLatin1String("M/d/yyyy, hh:mm") - << QLatin1String("M/d/yyyy, hh:mm A") - - << QLatin1String("MMM d yyyy") - << QLatin1String("MMM d yyyy hh:mm") - << QLatin1String("MMM d yyyy hh:mm:ss") - << QLatin1String("MMM d yyyy, hh:mm") - << QLatin1String("MMM d yyyy, hh:mm:ss") - - << QLatin1String("MMMM d yyyy") - << QLatin1String("MMMM d yyyy hh:mm") - << QLatin1String("MMMM d yyyy hh:mm:ss") - << QLatin1String("MMMM d yyyy, hh:mm") - << QLatin1String("MMMM d yyyy, hh:mm:ss") - - << QLatin1String("MMM d, yyyy") - << QLatin1String("MMM d, yyyy hh:mm") - << QLatin1String("MMM d, yyyy hh:mm:ss") - - << QLatin1String("MMMM d, yyyy") - << QLatin1String("MMMM d, yyyy hh:mm") - << QLatin1String("MMMM d, yyyy hh:mm:ss") - - << QLatin1String("d MMM yyyy") - << QLatin1String("d MMM yyyy hh:mm") - << QLatin1String("d MMM yyyy hh:mm:ss") - << QLatin1String("d MMM yyyy, hh:mm") - << QLatin1String("d MMM yyyy, hh:mm:ss") - - << QLatin1String("d MMMM yyyy") - << QLatin1String("d MMMM yyyy hh:mm") - << QLatin1String("d MMMM yyyy hh:mm:ss") - << QLatin1String("d MMMM yyyy, hh:mm") - << QLatin1String("d MMMM yyyy, hh:mm:ss") - - << QLatin1String("d MMM, yyyy") - << QLatin1String("d MMM, yyyy hh:mm") - << QLatin1String("d MMM, yyyy hh:mm:ss") - - << QLatin1String("d MMMM, yyyy") - << QLatin1String("d MMMM, yyyy hh:mm") - << QLatin1String("d MMMM, yyyy hh:mm:ss"); - - for (int i = 0; i < formats.size(); ++i) { - dt = QDateTime::fromString(s, formats.at(i)); - if (dt.isValid()) - break; - } - } - return FromDateTime(dt); -} - -/*! - \internal - - Converts the ECMA Date value \tt (in UTC form) to QDateTime - according to \a spec. -*/ -static inline QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec) -{ - if (qIsNaN(t)) - return QDateTime(); - if (spec == Qt::LocalTime) - t = LocalTime(t); - int year = int(YearFromTime(t)); - int month = int(MonthFromTime(t) + 1); - int day = int(DateFromTime(t)); - int hours = HourFromTime(t); - int mins = MinFromTime(t); - int secs = SecFromTime(t); - int ms = msFromTime(t); - return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec); -} - -static inline QString ToString(qsreal t) -{ - if (qIsNaN(t)) - return QLatin1String("Invalid Date"); - QString str = ToDateTime(t, Qt::LocalTime).toString() + QLatin1String(" GMT"); - qsreal tzoffset = LocalTZA + DaylightSavingTA(t); - if (tzoffset) { - int hours = static_cast<int>(::fabs(tzoffset) / 1000 / 60 / 60); - int mins = int(::fabs(tzoffset) / 1000 / 60) % 60; - str.append(QLatin1Char((tzoffset > 0) ? '+' : '-')); - if (hours < 10) - str.append(QLatin1Char('0')); - str.append(QString::number(hours)); - if (mins < 10) - str.append(QLatin1Char('0')); - str.append(QString::number(mins)); - } - return str; -} - -static inline QString ToUTCString(qsreal t) -{ - if (qIsNaN(t)) - return QLatin1String("Invalid Date"); - return ToDateTime(t, Qt::UTC).toString() + QLatin1String(" GMT"); -} - -static inline QString ToDateString(qsreal t) -{ - return ToDateTime(t, Qt::LocalTime).date().toString(); -} - -static inline QString ToTimeString(qsreal t) -{ - return ToDateTime(t, Qt::LocalTime).time().toString(); -} - -static inline QString ToLocaleString(qsreal t) -{ - return ToDateTime(t, Qt::LocalTime).toString(Qt::LocaleDate); -} - -static inline QString ToLocaleDateString(qsreal t) -{ - return ToDateTime(t, Qt::LocalTime).date().toString(Qt::LocaleDate); -} - -static inline QString ToLocaleTimeString(qsreal t) -{ - return ToDateTime(t, Qt::LocalTime).time().toString(Qt::LocaleDate); -} - -static qsreal getLocalTZA() -{ -#ifndef Q_WS_WIN - struct tm* t; - time_t curr; - time(&curr); - t = localtime(&curr); - time_t locl = mktime(t); - t = gmtime(&curr); - time_t globl = mktime(t); - return double(locl - globl) * 1000.0; -#else - TIME_ZONE_INFORMATION tzInfo; - GetTimeZoneInformation(&tzInfo); - return -tzInfo.Bias * 60.0 * 1000.0; -#endif -} - -namespace Ecma { - -Date::Date(QScriptEnginePrivate *eng): - Core(eng, QLatin1String("Date"), QScriptClassInfo::DateType) -{ - LocalTZA = getLocalTZA(); - - newDate(&publicPrototype, qSNaN()); - - eng->newConstructor(&ctor, this, publicPrototype); - addConstructorFunction(QLatin1String("parse"), method_parse, 1); - addConstructorFunction(QLatin1String("UTC"), method_UTC, 7); - - addPrototypeFunction(QLatin1String("toString"), method_toString, 0); - addPrototypeFunction(QLatin1String("toDateString"), method_toDateString, 0); - addPrototypeFunction(QLatin1String("toTimeString"), method_toTimeString, 0); - addPrototypeFunction(QLatin1String("toLocaleString"), method_toLocaleString, 0); - addPrototypeFunction(QLatin1String("toLocaleDateString"), method_toLocaleDateString, 0); - addPrototypeFunction(QLatin1String("toLocaleTimeString"), method_toLocaleTimeString, 0); - addPrototypeFunction(QLatin1String("valueOf"), method_valueOf, 0); - addPrototypeFunction(QLatin1String("getTime"), method_getTime, 0); - addPrototypeFunction(QLatin1String("getYear"), method_getYear, 0); - addPrototypeFunction(QLatin1String("getFullYear"), method_getFullYear, 0); - addPrototypeFunction(QLatin1String("getUTCFullYear"), method_getUTCFullYear, 0); - addPrototypeFunction(QLatin1String("getMonth"), method_getMonth, 0); - addPrototypeFunction(QLatin1String("getUTCMonth"), method_getUTCMonth, 0); - addPrototypeFunction(QLatin1String("getDate"), method_getDate, 0); - addPrototypeFunction(QLatin1String("getUTCDate"), method_getUTCDate, 0); - addPrototypeFunction(QLatin1String("getDay"), method_getDay, 0); - addPrototypeFunction(QLatin1String("getUTCDay"), method_getUTCDay, 0); - addPrototypeFunction(QLatin1String("getHours"), method_getHours, 0); - addPrototypeFunction(QLatin1String("getUTCHours"), method_getUTCHours, 0); - addPrototypeFunction(QLatin1String("getMinutes"), method_getMinutes, 0); - addPrototypeFunction(QLatin1String("getUTCMinutes"), method_getUTCMinutes, 0); - addPrototypeFunction(QLatin1String("getSeconds"), method_getSeconds, 0); - addPrototypeFunction(QLatin1String("getUTCSeconds"), method_getUTCSeconds, 0); - addPrototypeFunction(QLatin1String("getMilliseconds"), method_getMilliseconds, 0); - addPrototypeFunction(QLatin1String("getUTCMilliseconds"), method_getUTCMilliseconds, 0); - addPrototypeFunction(QLatin1String("getTimezoneOffset"), method_getTimezoneOffset, 0); - addPrototypeFunction(QLatin1String("setTime"), method_setTime, 1); - addPrototypeFunction(QLatin1String("setMilliseconds"), method_setMilliseconds, 1); - addPrototypeFunction(QLatin1String("setUTCMilliseconds"), method_setUTCMilliseconds, 1); - addPrototypeFunction(QLatin1String("setSeconds"), method_setSeconds, 2); - addPrototypeFunction(QLatin1String("setUTCSeconds"), method_setUTCSeconds, 2); - addPrototypeFunction(QLatin1String("setMinutes"), method_setMinutes, 3); - addPrototypeFunction(QLatin1String("setUTCMinutes"), method_setUTCMinutes, 3); - addPrototypeFunction(QLatin1String("setHours"), method_setHours, 4); - addPrototypeFunction(QLatin1String("setUTCHours"), method_setUTCHours, 4); - addPrototypeFunction(QLatin1String("setDate"), method_setDate, 1); - addPrototypeFunction(QLatin1String("setUTCDate"), method_setUTCDate, 1); - addPrototypeFunction(QLatin1String("setMonth"), method_setMonth, 2); - addPrototypeFunction(QLatin1String("setUTCMonth"), method_setUTCMonth, 2); - addPrototypeFunction(QLatin1String("setYear"), method_setYear, 1); - addPrototypeFunction(QLatin1String("setFullYear"), method_setFullYear, 3); - addPrototypeFunction(QLatin1String("setUTCFullYear"), method_setUTCFullYear, 3); - addPrototypeFunction(QLatin1String("toUTCString"), method_toUTCString, 0); - addPrototypeFunction(QLatin1String("toGMTString"), method_toUTCString, 0); -} - -Date::~Date() -{ -} - -void Date::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - if (!context->isCalledAsConstructor()) { - double t = currentTime(); - context->setReturnValue(QScriptValueImpl(engine(), ToString(t))); - } else { - // called as constructor - qsreal t; - - if (context->argumentCount() == 0) - t = currentTime(); - - else if (context->argumentCount() == 1) { - QScriptValueImpl arg = context->argument(0); - if (arg.isDate()) - arg = arg.internalValue(); - else - arg = engine()->toPrimitive(arg); - if (arg.isString()) - t = ParseString(arg.toString()); - else - t = TimeClip(arg.toNumber()); - } - - else { // context->argumentCount() > 1 - qsreal year = context->argument(0).toNumber(); - qsreal month = context->argument(1).toNumber(); - qsreal day = context->argumentCount() >= 3 ? context->argument(2).toNumber() : 1; - qsreal hours = context->argumentCount() >= 4 ? context->argument(3).toNumber() : 0; - qsreal mins = context->argumentCount() >= 5 ? context->argument(4).toNumber() : 0; - qsreal secs = context->argumentCount() >= 6 ? context->argument(5).toNumber() : 0; - qsreal ms = context->argumentCount() >= 7 ? context->argument(6).toNumber() : 0; - if (year >= 0 && year <= 99) - year += 1900; - t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms)); - t = TimeClip(UTC(t)); - } - - QScriptValueImpl &obj = context->m_thisObject; - obj.setClassInfo(classInfo()); - obj.setInternalValue(QScriptValueImpl(t)); - obj.setPrototype(publicPrototype); - context->setReturnValue(obj); - } -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -void Date::newDate(QScriptValueImpl *result, qsreal t) -{ - engine()->newObject(result, publicPrototype, classInfo()); - result->setInternalValue(QScriptValueImpl(t)); -} - -void Date::newDate(QScriptValueImpl *result, const QDateTime &dt) -{ - newDate(result, FromDateTime(dt)); -} - -void Date::newDate(QScriptValueImpl *result, const QDate &d) -{ - newDate(result, QDateTime(d)); -} - -QDateTime Date::toDateTime(const QScriptValueImpl &date) const -{ - Q_ASSERT(date.classInfo() == classInfo()); - qsreal t = date.internalValue().toNumber(); - return ToDateTime(t, Qt::LocalTime); -} - -QScriptValueImpl Date::method_parse(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *) -{ - return QScriptValueImpl(ParseString(context->argument(0).toString())); -} - -QScriptValueImpl Date::method_UTC(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - const int numArgs = context->argumentCount(); - if (numArgs >= 2) { - qsreal year = context->argument(0).toNumber(); - qsreal month = context->argument(1).toNumber(); - qsreal day = numArgs >= 3 ? context->argument(2).toNumber() : 1; - qsreal hours = numArgs >= 4 ? context->argument(3).toNumber() : 0; - qsreal mins = numArgs >= 5 ? context->argument(4).toNumber() : 0; - qsreal secs = numArgs >= 6 ? context->argument(5).toNumber() : 0; - qsreal ms = numArgs >= 7 ? context->argument(6).toNumber() : 0; - if (year >= 0 && year <= 99) - year += 1900; - qsreal t = MakeDate(MakeDay(year, month, day), - MakeTime(hours, mins, secs, ms)); - return QScriptValueImpl(TimeClip(t)); - } - return (eng->undefinedValue()); -} - -QScriptValueImpl Date::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - return QScriptValueImpl(eng, ToString(t)); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.toString")); -} - -QScriptValueImpl Date::method_toDateString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - return QScriptValueImpl(eng, ToDateString(t)); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.toDateString")); -} - -QScriptValueImpl Date::method_toTimeString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - return QScriptValueImpl(eng, ToTimeString(t)); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.toTimeString")); -} - -QScriptValueImpl Date::method_toLocaleString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - return QScriptValueImpl(eng, ToLocaleString(t)); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.toLocaleString")); -} - -QScriptValueImpl Date::method_toLocaleDateString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - return QScriptValueImpl(eng, ToLocaleDateString(t)); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.toLocaleDateString")); -} - -QScriptValueImpl Date::method_toLocaleTimeString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - return QScriptValueImpl(eng, ToLocaleTimeString(t)); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.toLocaleTimeString")); -} - -QScriptValueImpl Date::method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) - return QScriptValueImpl(self.internalValue().toNumber()); - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.valueOf")); -} - -QScriptValueImpl Date::method_getTime(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) - return QScriptValueImpl(self.internalValue().toNumber()); - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getTime")); -} - -QScriptValueImpl Date::method_getYear(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = YearFromTime(LocalTime(t)) - 1900; - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getYear")); -} - -QScriptValueImpl Date::method_getFullYear(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = YearFromTime(LocalTime(t)); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getFullYear")); -} - -QScriptValueImpl Date::method_getUTCFullYear(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = YearFromTime(t); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getUTCFullYear")); -} - -QScriptValueImpl Date::method_getMonth(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = MonthFromTime(LocalTime(t)); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getMonth")); -} - -QScriptValueImpl Date::method_getUTCMonth(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = MonthFromTime(t); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getUTCMonth")); -} - -QScriptValueImpl Date::method_getDate(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = DateFromTime(LocalTime(t)); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getDate")); -} - -QScriptValueImpl Date::method_getUTCDate(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = DateFromTime(t); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getUTCDate")); -} - -QScriptValueImpl Date::method_getDay(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = WeekDay(LocalTime(t)); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getDay")); -} - -QScriptValueImpl Date::method_getUTCDay(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = WeekDay(t); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getUTCDay")); -} - -QScriptValueImpl Date::method_getHours(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = HourFromTime(LocalTime(t)); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getHours")); -} - -QScriptValueImpl Date::method_getUTCHours(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = HourFromTime(t); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getUTCHours")); -} - -QScriptValueImpl Date::method_getMinutes(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = MinFromTime(LocalTime(t)); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getMinutes")); -} - -QScriptValueImpl Date::method_getUTCMinutes(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = MinFromTime(t); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getUTCMinutes")); -} - -QScriptValueImpl Date::method_getSeconds(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = SecFromTime(LocalTime(t)); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getSeconds")); -} - -QScriptValueImpl Date::method_getUTCSeconds(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = SecFromTime(t); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getUTCSeconds")); -} - -QScriptValueImpl Date::method_getMilliseconds(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = msFromTime(LocalTime(t)); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getMilliseconds")); -} - -QScriptValueImpl Date::method_getUTCMilliseconds(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = msFromTime(t); - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getUTCMilliseconds")); -} - -QScriptValueImpl Date::method_getTimezoneOffset(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (! qIsNaN(t)) - t = (t - LocalTime(t)) / msPerMinute; - return QScriptValueImpl(t); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.getTimezoneOffset")); -} - -QScriptValueImpl Date::method_setTime(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = TimeClip(context->argument(0).toNumber()); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setTime")); -} - -QScriptValueImpl Date::method_setMilliseconds(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = LocalTime(self.internalValue().toNumber()); - qsreal ms = context->argument(0).toNumber(); - t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setMilliseconds")); -} - -QScriptValueImpl Date::method_setUTCMilliseconds(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - qsreal ms = context->argument(0).toNumber(); - t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setUTCMilliseconds")); -} - -QScriptValueImpl Date::method_setSeconds(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = LocalTime(self.internalValue().toNumber()); - qsreal sec = context->argument(0).toNumber(); - qsreal ms = (context->argumentCount() < 2) ? msFromTime(t) : context->argument(1).toNumber(); - t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setSeconds")); -} - -QScriptValueImpl Date::method_setUTCSeconds(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - qsreal sec = context->argument(0).toNumber(); - qsreal ms = (context->argumentCount() < 2) ? msFromTime(t) : context->argument(1).toNumber(); - t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setUTCSeconds")); -} - -QScriptValueImpl Date::method_setMinutes(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = LocalTime(self.internalValue().toNumber()); - qsreal min = context->argument(0).toNumber(); - qsreal sec = (context->argumentCount() < 2) ? SecFromTime(t) : context->argument(1).toNumber(); - qsreal ms = (context->argumentCount() < 3) ? msFromTime(t) : context->argument(2).toNumber(); - t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setMinutes")); -} - -QScriptValueImpl Date::method_setUTCMinutes(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - qsreal min = context->argument(0).toNumber(); - qsreal sec = (context->argumentCount() < 2) ? SecFromTime(t) : context->argument(1).toNumber(); - qsreal ms = (context->argumentCount() < 3) ? msFromTime(t) : context->argument(2).toNumber(); - t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setUTCMinutes")); -} - -QScriptValueImpl Date::method_setHours(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = LocalTime(self.internalValue().toNumber()); - qsreal hour = context->argument(0).toNumber(); - qsreal min = (context->argumentCount() < 2) ? MinFromTime(t) : context->argument(1).toNumber(); - qsreal sec = (context->argumentCount() < 3) ? SecFromTime(t) : context->argument(2).toNumber(); - qsreal ms = (context->argumentCount() < 4) ? msFromTime(t) : context->argument(3).toNumber(); - t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setHours")); -} - -QScriptValueImpl Date::method_setUTCHours(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - qsreal hour = context->argument(0).toNumber(); - qsreal min = (context->argumentCount() < 2) ? MinFromTime(t) : context->argument(1).toNumber(); - qsreal sec = (context->argumentCount() < 3) ? SecFromTime(t) : context->argument(2).toNumber(); - qsreal ms = (context->argumentCount() < 4) ? msFromTime(t) : context->argument(3).toNumber(); - t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setUTCHours")); -} - -QScriptValueImpl Date::method_setDate(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = LocalTime(self.internalValue().toNumber()); - qsreal date = context->argument(0).toNumber(); - t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setDate")); -} - -QScriptValueImpl Date::method_setUTCDate(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - qsreal date = context->argument(0).toNumber(); - t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setUTCDate")); -} - -QScriptValueImpl Date::method_setMonth(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = LocalTime(self.internalValue().toNumber()); - qsreal month = context->argument(0).toNumber(); - qsreal date = (context->argumentCount() < 2) ? DateFromTime(t) : context->argument(1).toNumber(); - t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setMonth")); -} - -QScriptValueImpl Date::method_setUTCMonth(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - qsreal month = context->argument(0).toNumber(); - qsreal date = (context->argumentCount() < 2) ? DateFromTime(t) : context->argument(1).toNumber(); - t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setUTCMonth")); -} - -QScriptValueImpl Date::method_setFullYear(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = LocalTime(self.internalValue().toNumber()); - qsreal year = context->argument(0).toNumber(); - qsreal month = (context->argumentCount() < 2) ? MonthFromTime(t) : context->argument(1).toNumber(); - qsreal date = (context->argumentCount() < 3) ? DateFromTime(t) : context->argument(2).toNumber(); - t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setFullYear")); -} - -QScriptValueImpl Date::method_setUTCFullYear(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - qsreal year = context->argument(0).toNumber(); - qsreal month = (context->argumentCount() < 2) ? MonthFromTime(t) : context->argument(1).toNumber(); - qsreal date = (context->argumentCount() < 3) ? DateFromTime(t) : context->argument(2).toNumber(); - t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))); - QScriptValueImpl r(t); - self.setInternalValue(r); - return r; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setUTCFullYear")); -} - -QScriptValueImpl Date::method_setYear(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - Q_UNUSED(eng); - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - if (qIsNaN(t)) - t = 0; - else - t = LocalTime(t); - qsreal year = context->argument(0).toNumber(); - qsreal r; - if (qIsNaN(year)) { - r = qSNaN(); - } else { - if ((eng->toInteger(year) >= 0) && (eng->toInteger(year) <= 99)) - year += 1900; - r = MakeDay(year, MonthFromTime(t), DateFromTime(t)); - r = UTC(MakeDate(r, TimeWithinDay(t))); - r = TimeClip(r); - } - QScriptValueImpl v = QScriptValueImpl(r); - self.setInternalValue(v); - return v; - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.setYear")); -} - -QScriptValueImpl Date::method_toUTCString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() == classInfo) { - qsreal t = self.internalValue().toNumber(); - return QScriptValueImpl(eng, ToUTCString(t)); - } - return throwThisObjectTypeError( - context, QLatin1String("Date.prototype.toUTCString")); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmadate_p.h b/src/script/qscriptecmadate_p.h deleted file mode 100644 index f06201f..0000000 --- a/src/script/qscriptecmadate_p.h +++ /dev/null @@ -1,234 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMADATE_P_H -#define QSCRIPTECMADATE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptecmacore_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -class QDate; -class QDateTime; - -namespace QScript { namespace Ecma { - -class Date: public Core -{ -public: - Date(QScriptEnginePrivate *engine); - virtual ~Date(); - - virtual void execute(QScriptContextPrivate *context); - - void newDate(QScriptValueImpl *result, double t); - void newDate(QScriptValueImpl *result, const QDateTime &dt); - void newDate(QScriptValueImpl *result, const QDate &d); - - QDateTime toDateTime(const QScriptValueImpl &date) const; - -protected: - static QScriptValueImpl method_MakeTime(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_MakeDate(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_TimeClip(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_parse(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_UTC(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toDateString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toTimeString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLocaleString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLocaleDateString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLocaleTimeString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_valueOf(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getTime(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getYear(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getFullYear(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getUTCFullYear(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getMonth(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getUTCMonth(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getDate(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getUTCDate(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getDay(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getUTCDay(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getHours(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getUTCHours(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getMinutes(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getUTCMinutes(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getSeconds(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getUTCSeconds(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getMilliseconds(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getUTCMilliseconds(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_getTimezoneOffset(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setTime(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setMilliseconds(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setUTCMilliseconds(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setSeconds(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setUTCSeconds(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setMinutes(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setUTCMinutes(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setHours(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setUTCHours(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setDate(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setUTCDate(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setMonth(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setUTCMonth(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setYear(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setFullYear(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_setUTCFullYear(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toUTCString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); -}; - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptecmaerror.cpp b/src/script/qscriptecmaerror.cpp deleted file mode 100644 index 84aea19..0000000 --- a/src/script/qscriptecmaerror.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmaerror_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -static QString getMessage(QScriptContextPrivate *context) -{ - if (context->argumentCount() > 0) - return context->argument(0).toString(); - return QString(); -} - -static void setDebugInformation(QScriptValueImpl *error, QScriptContextPrivate *context) -{ - Q_ASSERT(context->previous); - context->previous->setDebugInformation(error); -} - -static QScriptValueImpl method_EvalError(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->isCalledAsConstructor()) - result = context->thisObject(); - eng->errorConstructor->newEvalError(&result, getMessage(context)); - setDebugInformation(&result, context); - return result; -} - -static QScriptValueImpl method_RangeError(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->isCalledAsConstructor()) - result = context->thisObject(); - eng->errorConstructor->newRangeError(&result, getMessage(context)); - setDebugInformation(&result, context); - return result; -} - -static QScriptValueImpl method_ReferenceError(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->isCalledAsConstructor()) - result = context->thisObject(); - eng->errorConstructor->newReferenceError(&result, getMessage(context)); - setDebugInformation(&result, context); - return result; -} - -static QScriptValueImpl method_SyntaxError(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->isCalledAsConstructor()) - result = context->thisObject(); - eng->errorConstructor->newSyntaxError(&result, getMessage(context)); - setDebugInformation(&result, context); - return result; -} - -static QScriptValueImpl method_TypeError(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->isCalledAsConstructor()) - result = context->thisObject(); - eng->errorConstructor->newTypeError(&result, getMessage(context)); - setDebugInformation(&result, context); - return result; -} - -static QScriptValueImpl method_UriError(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->isCalledAsConstructor()) - result = context->thisObject(); - eng->errorConstructor->newURIError(&result, getMessage(context)); - setDebugInformation(&result, context); - return result; -} - -Error::Error(QScriptEnginePrivate *eng): - Core(eng, QLatin1String("Error"), QScriptClassInfo::ErrorType) -{ - eng->newFunction(&ctor, this); - newErrorPrototype(&publicPrototype, QScriptValueImpl(), ctor, QLatin1String("Error")); - addPrototypeFunction(QLatin1String("backtrace"), method_backtrace, 0); - addPrototypeFunction(QLatin1String("toString"), method_toString, 0); - - // native errors - - evalErrorCtor = eng->createFunction(method_EvalError, 3, - classInfo(), QLatin1String("EvalError")); - rangeErrorCtor = eng->createFunction(method_RangeError, 3, - classInfo(), QLatin1String("RangeError")); - referenceErrorCtor = eng->createFunction(method_ReferenceError, 3, - classInfo(), QLatin1String("ReferenceError")); - syntaxErrorCtor = eng->createFunction(method_SyntaxError, 3, - classInfo(), QLatin1String("SyntaxError")); - typeErrorCtor = eng->createFunction(method_TypeError, 3, - classInfo(), QLatin1String("TypeError")); - uriErrorCtor = eng->createFunction(method_UriError, 3, - classInfo(), QLatin1String("URIError")); - - newErrorPrototype(&evalErrorPrototype, publicPrototype, - evalErrorCtor, QLatin1String("EvalError")); - newErrorPrototype(&rangeErrorPrototype, publicPrototype, - rangeErrorCtor, QLatin1String("RangeError")); - newErrorPrototype(&referenceErrorPrototype, publicPrototype, - referenceErrorCtor, QLatin1String("ReferenceError")); - newErrorPrototype(&syntaxErrorPrototype, publicPrototype, - syntaxErrorCtor, QLatin1String("SyntaxError")); - newErrorPrototype(&typeErrorPrototype, publicPrototype, - typeErrorCtor, QLatin1String("TypeError")); - newErrorPrototype(&uriErrorPrototype, publicPrototype, - uriErrorCtor, QLatin1String("URIError")); -} - -Error::~Error() -{ -} - -void Error::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - QString message = QString(); - - if (context->argumentCount() > 0) - message = context->argument(0).toString(); - - QScriptValueImpl result; - newError(&result, publicPrototype, message); - - setDebugInformation(&result, context); - - context->setReturnValue(result); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -void Error::mark(QScriptEnginePrivate *eng, int generation) -{ - Core::mark(eng, generation); - - eng->markObject(evalErrorCtor, generation); - eng->markObject(rangeErrorCtor, generation); - eng->markObject(referenceErrorCtor, generation); - eng->markObject(syntaxErrorCtor, generation); - eng->markObject(typeErrorCtor, generation); - eng->markObject(uriErrorCtor, generation); - - eng->markObject(evalErrorPrototype, generation); - eng->markObject(rangeErrorPrototype, generation); - eng->markObject(referenceErrorPrototype, generation); - eng->markObject(syntaxErrorPrototype, generation); - eng->markObject(typeErrorPrototype, generation); - eng->markObject(uriErrorPrototype, generation); -} - -void Error::newError(QScriptValueImpl *result, const QString &message) -{ - newError(result, publicPrototype, message); -} - -void Error::newEvalError(QScriptValueImpl *result, const QString &message) -{ - newError(result, evalErrorPrototype, message); -} - -void Error::newRangeError(QScriptValueImpl *result, const QString &message) -{ - newError(result, rangeErrorPrototype, message); -} - -void Error::newReferenceError(QScriptValueImpl *result, const QString &message) -{ - newError(result, referenceErrorPrototype, message); -} - -void Error::newSyntaxError(QScriptValueImpl *result, const QString &message) -{ - newError(result, syntaxErrorPrototype, message); -} - -void Error::newTypeError(QScriptValueImpl *result, const QString &message) -{ - newError(result, typeErrorPrototype, message); -} - -void Error::newURIError(QScriptValueImpl *result, const QString &message) -{ - newError(result, uriErrorPrototype, message); -} - -void Error::newError(QScriptValueImpl *result, const QScriptValueImpl &proto, - const QString &message) -{ - QScriptEnginePrivate *eng_p = engine(); - - if (!result->isValid()) - eng_p->newObject(result, proto, classInfo()); - else - result->setClassInfo(classInfo()); - result->setProperty(QLatin1String("message"), QScriptValueImpl(eng_p, message)); -} - -void Error::newErrorPrototype(QScriptValueImpl *result, const QScriptValueImpl &proto, - QScriptValueImpl &ztor, const QString &name) -{ - newError(result, proto); - result->setProperty(QLatin1String("name"), QScriptValueImpl(engine(), name)); - result->setProperty(QLatin1String("constructor"), ztor, - QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration); - ztor.setProperty(QLatin1String("prototype"), *result, - QScriptValue::Undeletable - | QScriptValue::ReadOnly - | QScriptValue::SkipInEnumeration); -} - -bool Error::isEvalError(const QScriptValueImpl &value) const -{ - return value.instanceOf(evalErrorPrototype); -} - -bool Error::isRangeError(const QScriptValueImpl &value) const -{ - return value.instanceOf(rangeErrorPrototype); -} - -bool Error::isReferenceError(const QScriptValueImpl &value) const -{ - return value.instanceOf(referenceErrorPrototype); -} - -bool Error::isSyntaxError(const QScriptValueImpl &value) const -{ - return value.instanceOf(syntaxErrorPrototype); -} - -bool Error::isTypeError(const QScriptValueImpl &value) const -{ - return value.instanceOf(typeErrorPrototype); -} - -bool Error::isURIError(const QScriptValueImpl &value) const -{ - return value.instanceOf(uriErrorPrototype); -} - -QStringList Error::backtrace(const QScriptValueImpl &error) -{ - QStringList result; - QScriptValueImpl stack = error.property(QLatin1String("stack")); - int frameCount = stack.property(QLatin1String("length")).toInt32(); - for (int i = 0; i < frameCount; ++i) { - QScriptValueImpl o = stack.property(i); - QScriptValueImpl frame = o.property(QLatin1String("frame")); - QString s; - QString functionName = o.property(QLatin1String("functionName")).toString(); - if (functionName.isEmpty()) { - if (i == frameCount-1) - s += QLatin1String("<global>"); - else - s += QLatin1String("<anonymous>"); - } else { - s += functionName; - } - s += QLatin1Char('('); - QScriptValueImpl arguments = frame.property(QLatin1String("arguments")); - if (arguments.isObject()) { - int argCount = arguments.property(QLatin1String("length")).toInt32(); - for (int j = 0; j < argCount; ++j) { - if (j > 0) - s += QLatin1Char(','); - s += arguments.property(j).toString(); - } - } - s += QLatin1String(")@") + o.property(QLatin1String("fileName")).toString() - + QLatin1Char(':') + o.property(QLatin1String("lineNumber")).toString(); - result.append(s); - } - return result; -} - -QScriptValueImpl Error::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl name = context->thisObject().property(QLatin1String("name"), - QScriptValue::ResolvePrototype); - QScriptValueImpl message = context->thisObject().property(QLatin1String("message"), - QScriptValue::ResolvePrototype); - QString result = QLatin1String(""); - if (name.isValid()) - result = name.toString(); - if (message.isValid()) { - QString str = message.toString(); - if (!str.isEmpty()) { - if (!result.isEmpty()) - result += QLatin1String(": "); - result += str; - } - } - return (QScriptValueImpl(eng, result)); -} - -QScriptValueImpl Error::method_backtrace(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl self = context->thisObject(); - return eng->arrayFromStringList(backtrace(self)); -} - -} } // namespace QSA::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmaerror_p.h b/src/script/qscriptecmaerror_p.h deleted file mode 100644 index d58f532..0000000 --- a/src/script/qscriptecmaerror_p.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMAERROR_P_H -#define QSCRIPTECMAERROR_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptecmacore_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class Error: public Core -{ -public: - Error(QScriptEnginePrivate *engine); - virtual ~Error(); - - virtual void execute(QScriptContextPrivate *context); - - virtual void mark(QScriptEnginePrivate *eng, int generation); - - void newError(QScriptValueImpl *result, const QString &message = QString()); - void newEvalError(QScriptValueImpl *result, const QString &message = QString()); - void newRangeError(QScriptValueImpl *result, const QString &message = QString()); - void newReferenceError(QScriptValueImpl *result, const QString &message = QString()); - void newSyntaxError(QScriptValueImpl *result, const QString &message = QString()); - void newTypeError(QScriptValueImpl *result, const QString &message = QString()); - void newURIError(QScriptValueImpl *result, const QString &message = QString()); - - bool isEvalError(const QScriptValueImpl &value) const; - bool isRangeError(const QScriptValueImpl &value) const; - bool isReferenceError(const QScriptValueImpl &value) const; - bool isSyntaxError(const QScriptValueImpl &value) const; - bool isTypeError(const QScriptValueImpl &value) const; - bool isURIError(const QScriptValueImpl &value) const; - - static QStringList backtrace(const QScriptValueImpl &error); - - QScriptValueImpl evalErrorCtor; - QScriptValueImpl rangeErrorCtor; - QScriptValueImpl referenceErrorCtor; - QScriptValueImpl syntaxErrorCtor; - QScriptValueImpl typeErrorCtor; - QScriptValueImpl uriErrorCtor; - - QScriptValueImpl evalErrorPrototype; - QScriptValueImpl rangeErrorPrototype; - QScriptValueImpl referenceErrorPrototype; - QScriptValueImpl syntaxErrorPrototype; - QScriptValueImpl typeErrorPrototype; - QScriptValueImpl uriErrorPrototype; - -protected: - static QScriptValueImpl method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - static QScriptValueImpl method_backtrace(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - -private: - void newError(QScriptValueImpl *result, const QScriptValueImpl &proto, - const QString &message = QString()); - void newErrorPrototype(QScriptValueImpl *result, const QScriptValueImpl &proto, - QScriptValueImpl &ztor, const QString &name); -}; - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif // QSCRIPTECMAERROR_P_H diff --git a/src/script/qscriptecmafunction.cpp b/src/script/qscriptecmafunction.cpp deleted file mode 100644 index 1604a72..0000000 --- a/src/script/qscriptecmafunction.cpp +++ /dev/null @@ -1,459 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmafunction_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QtDebug> - -#ifndef QT_NO_QOBJECT -# include "qscriptextqobject_p.h" -# include <QtCore/QMetaMethod> -#endif - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class FunctionClassData: public QScriptClassData -{ - QScriptClassInfo *m_classInfo; - -public: - FunctionClassData(QScriptClassInfo *classInfo); - virtual ~FunctionClassData(); - - inline QScriptClassInfo *classInfo() const - { return m_classInfo; } - - virtual bool resolve(const QScriptValueImpl &object, - QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode access); - virtual bool get(const QScriptValueImpl &obj, const Member &m, - QScriptValueImpl *out_value); - virtual bool put(QScriptValueImpl *object, const QScript::Member &member, - const QScriptValueImpl &value); - virtual void mark(const QScriptValueImpl &object, int generation); -}; - -FunctionClassData::FunctionClassData(QScriptClassInfo *classInfo) - : m_classInfo(classInfo) -{ -} - -FunctionClassData::~FunctionClassData() -{ -} - -bool FunctionClassData::resolve(const QScriptValueImpl &object, - QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode /*access*/) -{ - if (object.classInfo() != classInfo()) - return false; - - QScriptEnginePrivate *eng = object.engine(); - - if ((nameId == eng->idTable()->id_length) - || (nameId == eng->idTable()->id_arguments)) { - member->native(nameId, /*id=*/ 0, - QScriptValue::Undeletable - | QScriptValue::ReadOnly - | QScriptValue::SkipInEnumeration); - *base = object; - return true; - } - - return false; -} - -bool FunctionClassData::get(const QScriptValueImpl &object, const Member &member, - QScriptValueImpl *result) -{ - if (object.classInfo() != classInfo()) - return false; - - QScriptEnginePrivate *eng = object.engine(); - if (! member.isNativeProperty()) - return false; - - if (member.nameId() == eng->idTable()->id_length) { - *result = QScriptValueImpl(object.toFunction()->length); - return true; - } else if (member.nameId() == eng->idTable()->id_arguments) { - *result = eng->nullValue(); - return true; - } - - return false; -} - -bool FunctionClassData::put(QScriptValueImpl *, const QScript::Member &, - const QScriptValueImpl &) -{ - return false; -} - -void FunctionClassData::mark(const QScriptValueImpl &object, int generation) -{ - if (object.classInfo() != classInfo()) - return; - QScriptFunction *fun = object.toFunction(); - QScriptEnginePrivate *eng = object.engine(); - fun->mark(eng, generation); -} - -Function::Function(QScriptEnginePrivate *eng, QScriptClassInfo *classInfo): - Core(eng, classInfo) -{ - publicPrototype = eng->createFunction(method_void, 0, classInfo); // public prototype -} - -Function::~Function() -{ -} - -void Function::initialize() -{ - QScriptEnginePrivate *eng = engine(); - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("toString"), method_toString, 1); - addPrototypeFunction(QLatin1String("apply"), method_apply, 2); - addPrototypeFunction(QLatin1String("call"), method_call, 1); - addPrototypeFunction(QLatin1String("connect"), method_connect, 1); - addPrototypeFunction(QLatin1String("disconnect"), method_disconnect, 1); - - classInfo()->setData(new FunctionClassData(classInfo())); -} - -void Function::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - int lineNumber = context->currentLine; - QString contents = buildFunction(context); - engine()->evaluate(context, contents, lineNumber); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -QString Function::buildFunction(QScriptContextPrivate *context) -{ - int argc = context->argumentCount(); - - QString code; - code += QLatin1String("function("); - - // the formals - for (int i = 0; i < argc - 1; ++i) { - if (i != 0) - code += QLatin1Char(','); - - code += context->argument(i).toString(); - } - - code += QLatin1String("){"); - - // the function body - if (argc != 0) - code += context->argument(argc - 1).toString(); - - code += QLatin1String("\n}"); - - return code; -} - -void Function::newFunction(QScriptValueImpl *result, QScriptFunction *foo) -{ - engine()->newFunction(result, foo); -} - -QScriptValueImpl Function::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl self = context->thisObject(); - if (QScriptFunction *foo = self.toFunction()) { - QString code = foo->toString(context); - return QScriptValueImpl(eng, code); - } - - return throwThisObjectTypeError( - context, QLatin1String("Function.prototype.toString")); -} - -QScriptValueImpl Function::method_call(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - if (! context->thisObject().isFunction()) { - return throwThisObjectTypeError( - context, QLatin1String("Function.prototype.call")); - } - - QScriptValueImpl thisObject = eng->toObject(context->argument(0)); - if (! (thisObject.isValid () && thisObject.isObject())) - thisObject = eng->globalObject(); - - QScriptValueImplList args; - for (int i = 1; i < context->argumentCount(); ++i) - args << context->argument(i); - - return context->thisObject().call(thisObject, args); -} - -QScriptValueImpl Function::method_apply(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - if (! context->thisObject().isFunction()) { - return throwThisObjectTypeError( - context, QLatin1String("Function.prototype.apply")); - } - - QScriptValueImpl thisObject = eng->toObject(context->argument(0)); - if (! (thisObject.isValid () && thisObject.isObject())) - thisObject = eng->globalObject(); - - QScriptValueImplList args; - QScriptValueImpl undefined = eng->undefinedValue(); - - QScriptValueImpl arg = context->argument(1); - - if (Ecma::Array::Instance *arr = eng->arrayConstructor->get(arg)) { - QScript::Array actuals = arr->value; - - for (quint32 i = 0; i < actuals.count(); ++i) { - QScriptValueImpl a = actuals.at(i); - if (! a.isValid()) - args << undefined; - else - args << a; - } - } else if (arg.classInfo() == eng->m_class_arguments) { - QScript::ArgumentsObjectData *arguments; - arguments = static_cast<QScript::ArgumentsObjectData*> (arg.objectData()); - QScriptObject *activation = arguments->activation.objectValue(); - for (uint i = 0; i < arguments->length; ++i) - args << activation->m_values[i]; - } else if (!(arg.isUndefined() || arg.isNull())) { - return context->throwError(QScriptContext::TypeError, - QLatin1String("Function.prototype.apply: second argument is not an array")); - } - - return context->thisObject().call(thisObject, args); -} - -QScriptValueImpl Function::method_void(QScriptContextPrivate *, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - return eng->undefinedValue(); -} - -QScriptValueImpl Function::method_disconnect(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ -#ifndef QT_NO_QOBJECT - if (context->argumentCount() == 0) { - return context->throwError( - QLatin1String("Function.prototype.disconnect: no arguments given")); - } - - QScriptValueImpl self = context->thisObject(); - QScriptFunction *fun = self.toFunction(); - if ((fun == 0) || (fun->type() != QScriptFunction::Qt)) { - return context->throwError( - QScriptContext::TypeError, - QLatin1String("Function.prototype.disconnect: this object is not a signal")); - } - - QtFunction *qtSignal = static_cast<QtFunction*>(fun); - - const QMetaObject *meta = qtSignal->metaObject(); - if (!meta) { - return context->throwError( - QScriptContext::TypeError, - QString::fromLatin1("Function.prototype.disconnect: cannot disconnect from deleted QObject")); - } - - QMetaMethod sig = meta->method(qtSignal->initialIndex()); - if (sig.methodType() != QMetaMethod::Signal) { - return context->throwError(QScriptContext::TypeError, - QString::fromLatin1("Function.prototype.disconnect: %0::%1 is not a signal") - .arg(QLatin1String(qtSignal->metaObject()->className())) - .arg(QLatin1String(sig.signature()))); - } - - QScriptValueImpl receiver; - QScriptValueImpl slot; - QScriptValueImpl arg0 = context->argument(0); - if (context->argumentCount() < 2) { - receiver = QScriptValueImpl(); - slot = arg0; - } else { - receiver = arg0; - QScriptValueImpl arg1 = context->argument(1); - if (arg1.isFunction()) - slot = arg1; - else - slot = receiver.property(arg1.toString(), QScriptValue::ResolvePrototype); - } - - if (!slot.isFunction()) { - return context->throwError( - QScriptContext::TypeError, - QLatin1String("Function.prototype.disconnect: target is not a function")); - } - - bool ok = eng->scriptDisconnect(self, receiver, slot); - if (!ok) { - return context->throwError( - QString::fromLatin1("Function.prototype.disconnect: failed to disconnect from %0::%1") - .arg(QLatin1String(qtSignal->metaObject()->className())) - .arg(QLatin1String(sig.signature()))); - } - return eng->undefinedValue(); -#else - Q_UNUSED(eng); - return context->throwError(QScriptContext::TypeError, - QLatin1String("Function.prototype.disconnect")); -#endif // QT_NO_QOBJECT -} - -QScriptValueImpl Function::method_connect(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - Q_UNUSED(classInfo); - -#ifndef QT_NO_QOBJECT - if (context->argumentCount() == 0) { - return context->throwError( - QLatin1String("Function.prototype.connect: no arguments given")); - } - - QScriptValueImpl self = context->thisObject(); - QScriptFunction *fun = self.toFunction(); - if ((fun == 0) || (fun->type() != QScriptFunction::Qt)) { - return context->throwError( - QScriptContext::TypeError, - QLatin1String("Function.prototype.connect: this object is not a signal")); - } - - QtFunction *qtSignal = static_cast<QtFunction*>(fun); - - const QMetaObject *meta = qtSignal->metaObject(); - if (!meta) { - return context->throwError( - QScriptContext::TypeError, - QString::fromLatin1("Function.prototype.connect: cannot connect to deleted QObject")); - } - - QMetaMethod sig = meta->method(qtSignal->initialIndex()); - if (sig.methodType() != QMetaMethod::Signal) { - return context->throwError(QScriptContext::TypeError, - QString::fromLatin1("Function.prototype.connect: %0::%1 is not a signal") - .arg(QLatin1String(qtSignal->metaObject()->className())) - .arg(QLatin1String(sig.signature()))); - } - - { - QList<int> overloads = qtSignal->overloadedIndexes(); - if (!overloads.isEmpty()) { - overloads.append(qtSignal->initialIndex()); - QByteArray signature = sig.signature(); - QString message = QString::fromLatin1("Function.prototype.connect: ambiguous connect to %0::%1(); candidates are\n") - .arg(QLatin1String(qtSignal->metaObject()->className())) - .arg(QLatin1String(signature.left(signature.indexOf('(')))); - for (int i = 0; i < overloads.size(); ++i) { - QMetaMethod mtd = meta->method(overloads.at(i)); - message.append(QString::fromLatin1(" %0\n").arg(QString::fromLatin1(mtd.signature()))); - } - message.append(QString::fromLatin1("Use e.g. object['%0'].connect() to connect to a particular overload") - .arg(QLatin1String(signature))); - return context->throwError(message); - } - } - - QScriptValueImpl receiver; - QScriptValueImpl slot; - QScriptValueImpl arg0 = context->argument(0); - if (context->argumentCount() < 2) { - receiver = QScriptValueImpl(); - slot = arg0; - } else { - receiver = arg0; - QScriptValueImpl arg1 = context->argument(1); - if (arg1.isFunction()) - slot = arg1; - else - slot = receiver.property(arg1.toString(), QScriptValue::ResolvePrototype); - } - - if (!slot.isFunction()) { - return context->throwError( - QScriptContext::TypeError, - QLatin1String("Function.prototype.connect: target is not a function")); - } - - bool ok = eng->scriptConnect(self, receiver, slot, Qt::AutoConnection); - if (!ok) { - return context->throwError( - QString::fromLatin1("Function.prototype.connect: failed to connect to %0::%1") - .arg(QLatin1String(qtSignal->metaObject()->className())) - .arg(QLatin1String(sig.signature()))); - } - return eng->undefinedValue(); -#else - Q_UNUSED(eng); - Q_UNUSED(classInfo); - return context->throwError(QScriptContext::TypeError, - QLatin1String("Function.prototype.connect")); -#endif // QT_NO_QOBJECT -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmafunction_p.h b/src/script/qscriptecmafunction_p.h deleted file mode 100644 index 2a016cc..0000000 --- a/src/script/qscriptecmafunction_p.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMAFUNCTION_P_H -#define QSCRIPTECMAFUNCTION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptecmacore_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class Function: public Core -{ -public: - Function(QScriptEnginePrivate *engine, QScriptClassInfo *classInfo); - virtual ~Function(); - - void initialize(); - - virtual void execute(QScriptContextPrivate *context); - - void newFunction(QScriptValueImpl *result, QScriptFunction *foo); - -protected: - QString buildFunction(QScriptContextPrivate *context); - - static QScriptValueImpl method_toString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_apply(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_call(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_void(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_disconnect(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_connect(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); -}; - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptecmaglobal.cpp b/src/script/qscriptecmaglobal.cpp deleted file mode 100644 index 10d3343..0000000 --- a/src/script/qscriptecmaglobal.cpp +++ /dev/null @@ -1,571 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// for strtoll -#include <qplatformdefs.h> - -#ifndef QT_NO_SCRIPT - -#include "qscriptecmaglobal_p.h" -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QVarLengthArray> -#include <QtCore/qnumeric.h> - -QT_BEGIN_NAMESPACE - -extern double qstrtod(const char *s00, char const **se, bool *ok); - -namespace QScript { - -extern qsreal integerFromString(const QString &str, int radix); - -static inline char toHex(char c) -{ - static const char hexnumbers[] = "0123456789ABCDEF"; - return hexnumbers[c & 0xf]; -} - -static int fromHex(char c) -{ - if ((c >= '0') && (c <= '9')) - return c - '0'; - if ((c >= 'A') && (c <= 'F')) - return c - 'A' + 10; - if ((c >= 'a') && (c <= 'f')) - return c - 'a' + 10; - return -1; -} - -static QByteArray escape(const QString &input) -{ - QVarLengthArray<char> output; - output.reserve(input.size() * 3); - const int length = input.length(); - for (int i = 0; i < length; ++i) { - ushort uc = input.at(i).unicode(); - if (uc < 0x100) { - if ( (uc > 0x60 && uc < 0x7B) - || (uc > 0x3F && uc < 0x5B) - || (uc > 0x2C && uc < 0x3A) - || (uc == 0x2A) - || (uc == 0x2B) - || (uc == 0x5F)) { - output.append(char(uc)); - } else { - output.append('%'); - output.append(toHex(uc >> 4)); - output.append(toHex(uc)); - } - } else { - output.append('%'); - output.append('u'); - output.append(toHex(uc >> 12)); - output.append(toHex(uc >> 8)); - output.append(toHex(uc >> 4)); - output.append(toHex(uc)); - } - } - return QByteArray(output.constData(), output.size()); -} - -static QString unescape(const QByteArray &input) -{ - QString result; - int i = 0; - const int length = input.length(); - while (i < length) { - char c = input.at(i++); - if ((c == '%') && (i + 1 < length)) { - char a = input.at(i); - if ((a == 'u') && (i + 4 < length)) { - int d3 = fromHex(input.at(i+1)); - int d2 = fromHex(input.at(i+2)); - int d1 = fromHex(input.at(i+3)); - int d0 = fromHex(input.at(i+4)); - if ((d3 != -1) && (d2 != -1) && (d1 != -1) && (d0 != -1)) { - ushort uc = ushort((d3 << 12) | (d2 << 8) | (d1 << 4) | d0); - result.append(QChar(uc)); - i += 5; - } else { - result.append(QLatin1Char(c)); - } - } else { - int d1 = fromHex(a); - int d0 = fromHex(input.at(i+1)); - if ((d1 != -1) && (d0 != -1)) { - c = (d1 << 4) | d0; - i += 2; - } - result.append(QLatin1Char(c)); - } - } else { - result.append(QLatin1Char(c)); - } - } - return result; -} - -static const char uriReserved[] = ";/?:@&=+$,"; -static const char uriUnescaped[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()"; - -static QString encode(const QString &input, const QString &unescapedSet, bool *ok) -{ - QString output; - const int length = input.length(); - int i = 0; - while (i < length) { - const QChar c = input.at(i); - if (!unescapedSet.contains(c)) { - ushort uc = c.unicode(); - if ((uc >= 0xDC00) && (uc <= 0xDFFF)) { - // URIError - break; - } - if (!((uc < 0xD800) || (uc > 0xDBFF))) { - ++i; - if (i == length) { - // URIError - break; - } - const ushort uc2 = input.at(i).unicode(); - if ((uc < 0xDC00) || (uc > 0xDFFF)) { - // URIError - break; - } - uc = ((uc - 0xD800) * 0x400) + (uc2 - 0xDC00) + 0x10000; - } - QString tmp(1, QChar(uc)); - QByteArray octets = tmp.toUtf8(); - for (int j = 0; j < octets.length(); ++j) { - output.append(QLatin1Char('%')); - output.append(QLatin1Char(toHex(octets.at(j) >> 4))); - output.append(QLatin1Char(toHex(octets.at(j)))); - } - } else { - output.append(c); - } - ++i; - } - *ok = (i == length); - return output; -} - -static QString decode(const QString &input, const QString &reservedSet, bool *ok) -{ - QString output; - const int length = input.length(); - int i = 0; - const QChar percent = QLatin1Char('%'); - while (i < length) { - const QChar c = input.at(i); - if (c == percent) { - int start = i; - if (i + 2 >= length) { - // URIError - break; - } - int d1 = fromHex(input.at(i+1).toLatin1()); - int d0 = fromHex(input.at(i+2).toLatin1()); - if ((d1 == -1) || (d0 == -1)) { - // URIError - break; - } - int b = (d1 << 4) | d0; - i += 2; - if (b & 0x80) { - int n = -1; - while ((b << ++n) & 0x80) ; - if ((n == 1) || (n > 4)) { - // URIError - break; - } - QByteArray octets; - octets.append(b); - if (i + (3 * (n - 1)) >= length) { - // URIError - break; - } - for (int j = 1; j < n; ++j) { - ++i; - if (input.at(i) != percent) { - // URIError - break; - } - d1 = fromHex(input.at(i+1).toLatin1()); - d0 = fromHex(input.at(i+2).toLatin1()); - if ((d1 == -1) || (d0 == -1)) { - // URIError - break; - } - b = (d1 << 4) | d0; - if ((b & 0xC0) != 0x80) { - // URIError - break; - } - i += 2; - octets.append(b); - } - QString tmp = QString::fromUtf8(octets); - Q_ASSERT(tmp.length() == 1); - uint v = tmp.at(0).unicode(); // ### need 32-bit value - if (v < 0x10000) { - QChar z = QChar(ushort(v)); - if (!reservedSet.contains(z)) { - output.append(z); - } else { - output.append(input.mid(start, i - start + 1)); - } - } else { - if (v > 0x10FFFF) { - // URIError - break; - } - ushort l = ushort(((v - 0x10000) & 0x3FF) + 0xDC00); - ushort h = ushort((((v - 0x10000) >> 10) & 0x3FF) + 0xD800); - output.append(QChar(l)); - output.append(QChar(h)); - } - } else { - output.append(ushort(b)); - } - } else { - output.append(c); - } - ++i; - } - *ok = (i == length); - return output; -} - -class PrintFunction : public QScriptFunction -{ -public: - PrintFunction() {} - - virtual ~PrintFunction() {} - - virtual void execute(QScriptContextPrivate *context) - { - QScriptEnginePrivate *eng = context->engine(); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng->notifyFunctionEntry(context); -#endif - QString result; - for (int i = 0; i < context->argumentCount(); ++i) { - if (i != 0) - result.append(QLatin1Char(' ')); - - QString s = context->argument(i).toString(); - if (context->state() == QScriptContext::ExceptionState) - break; - result.append(s); - } - - if (context->state() != QScriptContext::ExceptionState) { - qDebug(qPrintable(result)); - context->setReturnValue(eng->undefinedValue()); - } -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng->notifyFunctionExit(context); -#endif - } - - QString functionName() const - { - return QLatin1String("print"); - } -}; - -} // anonumous - -namespace QScript { namespace Ecma { - -Global::Global(QScriptEnginePrivate *engine, QScriptClassInfo *classInfo) - : m_engine(engine), m_classInfo(classInfo) -{ -} - -Global::~Global() -{ -} - -void Global::construct(QScriptValueImpl *object, QScriptEnginePrivate *eng) -{ - QScriptClassInfo *classInfo = eng->registerClass(QLatin1String("global"), - QScriptClassInfo::ActivationType); - - // create with prototype null, since Object.prototype doesn't exist at this point - eng->newObject(object, eng->nullValue(), classInfo); - - Global *instance = new Global(eng, classInfo); - object->setObjectData(instance); -} - -void Global::initialize(QScriptValueImpl *object, QScriptEnginePrivate *eng) -{ - // set the real prototype - object->setPrototype(eng->objectConstructor->publicPrototype); - - const QScriptValue::PropertyFlags flags = QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration; - - object->setProperty(QLatin1String("NaN"), QScriptValueImpl(qSNaN()), flags); - object->setProperty(QLatin1String("Infinity"), QScriptValueImpl(qInf()), flags); - object->setProperty(QLatin1String("undefined"), eng->undefinedValue(), flags); - - object->setProperty(QLatin1String("print"), - eng->createFunction(new PrintFunction()), flags); - addFunction(*object, QLatin1String("parseInt"), method_parseInt, 2, flags); - addFunction(*object, QLatin1String("parseFloat"), method_parseFloat, 1, flags); - addFunction(*object, QLatin1String("isNaN"), method_isNaN, 1, flags); - addFunction(*object, QLatin1String("isFinite"), method_isFinite, 1, flags); - addFunction(*object, QLatin1String("decodeURI"), method_decodeURI, 1, flags); - addFunction(*object, QLatin1String("decodeURIComponent"), method_decodeURIComponent, 1, flags); - addFunction(*object, QLatin1String("encodeURI"), method_encodeURI, 1, flags); - addFunction(*object, QLatin1String("encodeURIComponent"), method_encodeURIComponent, 1, flags); - addFunction(*object, QLatin1String("escape"), method_escape, 1, flags); - addFunction(*object, QLatin1String("unescape"), method_unescape, 1, flags); - addFunction(*object, QLatin1String("version"), method_version, 0, flags); - addFunction(*object, QLatin1String("gc"), method_gc, 0, flags); -} - -QScriptValueImpl Global::method_parseInt(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - if (context->argumentCount() == 0) - return qSNaN(); - - qsreal radix = 0; - if (context->argumentCount() > 1) { - radix = context->argument(1).toInteger(); - if (qIsNaN(radix) || (radix && (radix < 2 || radix > 36))) { - return qSNaN(); - } - } - - return QScript::integerFromString(context->argument(0).toString(), static_cast<int>(radix)); -} - -QScriptValueImpl Global::method_parseFloat(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - if (context->argumentCount() == 0) - return QScriptValueImpl(qSNaN()); - QString str = context->argument(0).toString().trimmed(); - QByteArray latin1 = str.toLatin1(); - const char *data = latin1.constData(); - const char *eptr = 0; - qsreal result = qstrtod(data, &eptr, 0); - if (eptr == data) { - if (str == QLatin1String("Infinity")) - result = +qInf(); - else if (str == QLatin1String("+Infinity")) - result = +qInf(); - else if (str == QLatin1String("-Infinity")) - result = -qInf(); - else - result = qSNaN(); - } - return result; -} - -QScriptValueImpl Global::method_isNaN(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = qSNaN(); - if (context->argumentCount() > 0) - v = context->argument(0).toNumber(); - return (QScriptValueImpl(qIsNaN(v))); -} - -QScriptValueImpl Global::method_isFinite(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = qInf(); - if (context->argumentCount() > 0) - v = context->argument(0).toNumber(); - return (QScriptValueImpl(qIsFinite(v))); -} - -QScriptValueImpl Global::method_decodeURI(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QScriptValueImpl result; - - if (context->argumentCount() > 0) { - QString str = context->argument(0).toString(); - bool ok; - QString out = decode(str, QString::fromUtf8(uriReserved) + QString::fromUtf8("#"), &ok); - if (ok) - return QScriptValueImpl(eng, out); - else - return context->throwError(QScriptContext::URIError, - QLatin1String("malformed URI sequence")); - } - - return eng->undefinedValue(); -} - -QScriptValueImpl Global::method_decodeURIComponent(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->argumentCount() > 0) { - QString str = context->argument(0).toString(); - bool ok; - QString out = decode(str, QString::fromUtf8(""), &ok); - if (ok) - result = QScriptValueImpl(eng, out); - else - result = context->throwError(QScriptContext::URIError, - QLatin1String("malformed URI sequence")); - } else { - result = eng->undefinedValue(); - } - return result; -} - -QScriptValueImpl Global::method_encodeURI(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->argumentCount() > 0) { - QString str = context->argument(0).toString(); - bool ok; - QString out = encode(str, - QLatin1String(uriReserved) - + QLatin1String(uriUnescaped) - + QString::fromUtf8("#"), - &ok); - if (ok) - result = QScriptValueImpl(eng, out); - else - result = context->throwError(QScriptContext::URIError, - QLatin1String("malformed URI sequence")); - } else { - result = eng->undefinedValue(); - } - return result; -} - -QScriptValueImpl Global::method_encodeURIComponent(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QScriptValueImpl result; - if (context->argumentCount() > 0) { - QString str = context->argument(0).toString(); - bool ok; - QString out = encode(str, QLatin1String(uriUnescaped), &ok); - if (ok) - result = QScriptValueImpl(eng, out); - else - result = context->throwError(QScriptContext::URIError, - QLatin1String("malformed URI sequence")); - } else { - result = eng->undefinedValue(); - } - return result; -} - -QScriptValueImpl Global::method_escape(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - if (context->argumentCount() > 0) { - QString str = context->argument(0).toString(); - return QScriptValueImpl(eng, QLatin1String(escape(str))); - } - return QScriptValueImpl(eng, QLatin1String("undefined")); -} - -QScriptValueImpl Global::method_unescape(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - if (context->argumentCount() > 0) { - QByteArray data = context->argument(0).toString().toLatin1(); - return QScriptValueImpl(eng, unescape(data)); - } - return QScriptValueImpl(eng, QLatin1String("undefined")); -} - -QScriptValueImpl Global::method_version(QScriptContextPrivate *, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - return (QScriptValueImpl(1)); -} - -QScriptValueImpl Global::method_gc(QScriptContextPrivate *, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - eng->gc(); - return QScriptValueImpl(eng->objectAllocator.freeBlocks()); -} - -void Global::addFunction(QScriptValueImpl &object, const QString &name, - QScriptInternalFunctionSignature fun, int length, - const QScriptValue::PropertyFlags flags) -{ - QScriptEnginePrivate *eng_p = object.engine(); - QScriptValueImpl val = eng_p->createFunction(fun, length, object.classInfo(), name); - object.setProperty(name, val, flags); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmaglobal_p.h b/src/script/qscriptecmaglobal_p.h deleted file mode 100644 index 8d3316d..0000000 --- a/src/script/qscriptecmaglobal_p.h +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMAGLOBAL_P_H -#define QSCRIPTECMAGLOBAL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptobjectdata_p.h" -#include "qscriptfunction_p.h" -#include "qscriptvalue.h" - -QT_BEGIN_NAMESPACE - -class QScriptEnginePrivate; -class QScriptContextPrivate; -class QScriptClassInfo; -class QScriptValueImpl; - -#ifndef QT_NO_SCRIPT - -namespace QScript { namespace Ecma { - -class Global: public QScriptObjectData -{ -protected: - Global(QScriptEnginePrivate *engine, QScriptClassInfo *classInfo); - -public: - virtual ~Global(); - - inline QScriptEnginePrivate *engine() const; - - static void construct(QScriptValueImpl *object, QScriptEnginePrivate *eng); - static void initialize(QScriptValueImpl *object, QScriptEnginePrivate *eng); - -protected: - static QScriptValueImpl method_parseInt(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_parseFloat(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_isNaN(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_isFinite(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_decodeURI(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_decodeURIComponent(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_encodeURI(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_encodeURIComponent(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_escape(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_unescape(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_version(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_gc(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - -private: - static void addFunction(QScriptValueImpl &object, const QString &name, - QScriptInternalFunctionSignature fun, int length, - const QScriptValue::PropertyFlags flags); - - QScriptEnginePrivate *m_engine; - QScriptClassInfo *m_classInfo; -}; - -inline QScriptEnginePrivate *Global::engine() const -{ return m_engine; } - - -} } // namespace QScript::Ecma - -#endif // QT_NO_SCRIPT - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptecmamath.cpp b/src/script/qscriptecmamath.cpp deleted file mode 100644 index 2e137de..0000000 --- a/src/script/qscriptecmamath.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmamath_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QtDebug> -#include <QtCore/qnumeric.h> -#include <QtCore/QSysInfo> -#include <math.h> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -static const qsreal qt_PI = 2.0 * ::asin(1.0); - -Math::Math(QScriptEnginePrivate *engine, QScriptClassInfo *classInfo): - m_engine(engine), - m_classInfo(classInfo) -{ -} - -Math::~Math() -{ -} - -void Math::construct(QScriptValueImpl *object, QScriptEnginePrivate *eng) -{ - QScriptClassInfo *classInfo = eng->registerClass(QLatin1String("Math")); - - Math *instance = new Math(eng, classInfo); - eng->newObject(object, classInfo); - object->setObjectData(instance); - - QScriptValue::PropertyFlags flags = QScriptValue::Undeletable - | QScriptValue::ReadOnly - | QScriptValue::SkipInEnumeration; - - object->setProperty(QLatin1String("E"), - QScriptValueImpl(::exp(1.0)), flags); - object->setProperty(QLatin1String("LN2"), - QScriptValueImpl(::log(2.0)), flags); - object->setProperty(QLatin1String("LN10"), - QScriptValueImpl(::log(10.0)), flags); - object->setProperty(QLatin1String("LOG2E"), - QScriptValueImpl(1.0/::log(2.0)), flags); - object->setProperty(QLatin1String("LOG10E"), - QScriptValueImpl(1.0/::log(10.0)), flags); - object->setProperty(QLatin1String("PI"), - QScriptValueImpl(qt_PI), flags); - object->setProperty(QLatin1String("SQRT1_2"), - QScriptValueImpl(::sqrt(0.5)), flags); - object->setProperty(QLatin1String("SQRT2"), - QScriptValueImpl(::sqrt(2.0)), flags); - - flags = QScriptValue::SkipInEnumeration; - addFunction(*object, QLatin1String("abs"), method_abs, 1, flags); - addFunction(*object, QLatin1String("acos"), method_acos, 1, flags); - addFunction(*object, QLatin1String("asin"), method_asin, 0, flags); - addFunction(*object, QLatin1String("atan"), method_atan, 1, flags); - addFunction(*object, QLatin1String("atan2"), method_atan2, 2, flags); - addFunction(*object, QLatin1String("ceil"), method_ceil, 1, flags); - addFunction(*object, QLatin1String("cos"), method_cos, 1, flags); - addFunction(*object, QLatin1String("exp"), method_exp, 1, flags); - addFunction(*object, QLatin1String("floor"), method_floor, 1, flags); - addFunction(*object, QLatin1String("log"), method_log, 1, flags); - addFunction(*object, QLatin1String("max"), method_max, 2, flags); - addFunction(*object, QLatin1String("min"), method_min, 2, flags); - addFunction(*object, QLatin1String("pow"), method_pow, 2, flags); - addFunction(*object, QLatin1String("random"), method_random, 0, flags); - addFunction(*object, QLatin1String("round"), method_round, 1, flags); - addFunction(*object, QLatin1String("sin"), method_sin, 1, flags); - addFunction(*object, QLatin1String("sqrt"), method_sqrt, 1, flags); - addFunction(*object, QLatin1String("tan"), method_tan, 1, flags); -} - -/* copies the sign from y to x and returns the result */ -static qsreal copySign(qsreal x, qsreal y) -{ - uchar *xch = (uchar *)&x; - uchar *ych = (uchar *)&y; - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) - xch[0] = (xch[0] & 0x7f) | (ych[0] & 0x80); - else - xch[7] = (xch[7] & 0x7f) | (ych[7] & 0x80); - return x; -} - -QScriptValueImpl Math::method_abs(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - if (v == 0) // 0 | -0 - return (QScriptValueImpl(0)); - else - return (QScriptValueImpl(v < 0 ? -v : v)); -} - -QScriptValueImpl Math::method_acos(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - if (v > 1) - return QScriptValueImpl(qSNaN()); - return (QScriptValueImpl(::acos(v))); -} - -QScriptValueImpl Math::method_asin(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - if (v > 1) - return QScriptValueImpl(qSNaN()); - return (QScriptValueImpl(::asin(v))); -} - -QScriptValueImpl Math::method_atan(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - if (v == 0.0) - return QScriptValueImpl(v); - return (QScriptValueImpl(::atan(v))); -} - -QScriptValueImpl Math::method_atan2(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v1 = context->argument(0).toNumber(); - qsreal v2 = context->argument(1).toNumber(); -#ifdef Q_OS_WINCE - if (v1 == 0.0) { - const bool v1MinusZero = _copysign(1.0, v1) < 0.0; - const bool v2MinusZero = (v2 == 0 && _copysign(1.0, v2) < 0.0); - if ((v1MinusZero && v2MinusZero) || (v1MinusZero && v2 == -1.0)) - return QScriptValueImpl(-qt_PI); - if (v2MinusZero) - return QScriptValueImpl(qt_PI); - if (v1MinusZero && v2 == 1.0) - return QScriptValueImpl(-0.0); -#if defined(_X86_) - if (v2 == 0.0 && (v1MinusZero || (!v1MinusZero && !v2MinusZero))) - return QScriptValueImpl(0.0); -#endif - } -#endif -#if defined(Q_OS_WINCE) && defined(_X86_) - if (v1 == -1.0 && !_finite(v2) && _copysign(1.0, v2) > 0.0) - return QScriptValueImpl(-0.0); -#endif - if ((v1 < 0) && qIsFinite(v1) && qIsInf(v2) && (copySign(1.0, v2) == 1.0)) - return QScriptValueImpl(copySign(0, -1.0)); - if ((v1 == 0.0) && (v2 == 0.0)) { - if ((copySign(1.0, v1) == 1.0) && (copySign(1.0, v2) == -1.0)) - return QScriptValueImpl(qt_PI); - else if ((copySign(1.0, v1) == -1.0) && (copySign(1.0, v2) == -1.0)) - return QScriptValueImpl(-qt_PI); - } - return (QScriptValueImpl(::atan2(v1, v2))); -} - -QScriptValueImpl Math::method_ceil(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - if (v < 0.0 && v > -1.0) - return QScriptValueImpl(copySign(0, -1.0)); - return (QScriptValueImpl(::ceil(v))); -} - -QScriptValueImpl Math::method_cos(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - return (QScriptValueImpl(::cos(v))); -} - -QScriptValueImpl Math::method_exp(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - if (qIsInf(v)) { - if (copySign(1.0, v) == -1.0) - return QScriptValueImpl(0); - else - return QScriptValueImpl(qInf()); - } - return (QScriptValueImpl(::exp(v))); -} - -QScriptValueImpl Math::method_floor(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - return (QScriptValueImpl(::floor(v))); -} - -QScriptValueImpl Math::method_log(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - if (v < 0) - return QScriptValueImpl(qSNaN()); - return (QScriptValueImpl(::log(v))); -} - -QScriptValueImpl Math::method_max(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal mx = -qInf(); - for (int i = 0; i < context->argumentCount(); ++i) { - qsreal x = context->argument(i).toNumber(); - if (x > mx || qIsNaN(x)) - mx = x; - } - return (QScriptValueImpl(mx)); -} - -QScriptValueImpl Math::method_min(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal mx = qInf(); - for (int i = 0; i < context->argumentCount(); ++i) { - qsreal x = context->argument(i).toNumber(); - if ((x == 0 && mx == x && copySign(1.0, x) == -1.0) - || (x < mx) || qIsNaN(x)) { - mx = x; - } - } - return (QScriptValueImpl(mx)); -} - -QScriptValueImpl Math::method_pow(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal x = context->argument(0).toNumber(); - qsreal y = context->argument(1).toNumber(); - if (qIsNaN(y)) - return QScriptValueImpl(qSNaN()); - if (y == 0) - return QScriptValueImpl(1); - if (((x == 1) || (x == -1)) && qIsInf(y)) - return QScriptValueImpl(qSNaN()); - if (((x == 0) && copySign(1.0, x) == 1.0) && (y < 0)) - return QScriptValueImpl(qInf()); - if ((x == 0) && copySign(1.0, x) == -1.0) { - if (y < 0) { - if (::fmod(-y, 2.0) == 1.0) - return QScriptValueImpl(-qInf()); - else - return QScriptValueImpl(qInf()); - } else if (y > 0) { - if (::fmod(y, 2.0) == 1.0) - return QScriptValueImpl(copySign(0, -1.0)); - else - return QScriptValueImpl(0); - } - } -#ifdef Q_OS_AIX - if (qIsInf(x) && copySign(1.0, x) == -1.0) { - if (y > 0) { - if (::fmod(y, 2.0) == 1.0) - return QScriptValueImpl(-qInf()); - else - return QScriptValueImpl(qInf()); - } else if (y < 0) { - if (::fmod(-y, 2.0) == 1.0) - return QScriptValueImpl(copySign(0, -1.0)); - else - return QScriptValueImpl(0); - } - } -#endif - return (QScriptValueImpl(::pow(x, y))); -} - -QScriptValueImpl Math::method_random(QScriptContextPrivate *, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - return (QScriptValueImpl(qrand() / (qsreal) RAND_MAX)); -} - -QScriptValueImpl Math::method_round(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - v = copySign(::floor(v + 0.5), v); - return (QScriptValueImpl(v)); -} - -QScriptValueImpl Math::method_sin(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - return (QScriptValueImpl(::sin(v))); -} - -QScriptValueImpl Math::method_sqrt(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - return (QScriptValueImpl(::sqrt(v))); -} - -QScriptValueImpl Math::method_tan(QScriptContextPrivate *context, - QScriptEnginePrivate *, - QScriptClassInfo *) -{ - qsreal v = context->argument(0).toNumber(); - if (v == 0.0) - return QScriptValueImpl(v); - return (QScriptValueImpl(::tan(v))); -} - -void Math::addFunction(QScriptValueImpl &object, const QString &name, - QScriptInternalFunctionSignature fun, int length, - const QScriptValue::PropertyFlags flags) -{ - QScriptEnginePrivate *eng_p = object.engine(); - QScriptValueImpl val = eng_p->createFunction(fun, length, object.classInfo(), name); - object.setProperty(name, val, flags); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmamath_p.h b/src/script/qscriptecmamath_p.h deleted file mode 100644 index 029fb91..0000000 --- a/src/script/qscriptecmamath_p.h +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMAMATH_P_H -#define QSCRIPTECMAMATH_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptobjectdata_p.h" -#include "qscriptfunction_p.h" -#include "qscriptvalue.h" - -QT_BEGIN_NAMESPACE - -class QScriptEnginePrivate; -class QScriptContextPrivate; -class QScriptClassInfo; -class QScriptValueImpl; - -#ifndef QT_NO_SCRIPT - -namespace QScript { namespace Ecma { - -class Math: public QScriptObjectData -{ -protected: - Math(QScriptEnginePrivate *engine, QScriptClassInfo *classInfo); - -public: - virtual ~Math(); - - static void construct(QScriptValueImpl *object, QScriptEnginePrivate *eng); - - inline QScriptEnginePrivate *engine() const; - -protected: - static QScriptValueImpl method_abs(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_acos(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_asin(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_atan(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_atan2(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_ceil(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_cos(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_exp(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_floor(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_log(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_max(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_min(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_pow(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_random(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_round(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_sin(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_sqrt(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_tan(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - -private: - static void addFunction(QScriptValueImpl &object, const QString &name, - QScriptInternalFunctionSignature fun, int length, - const QScriptValue::PropertyFlags flags); - - QScriptEnginePrivate *m_engine; - QScriptClassInfo *m_classInfo; -}; - -inline QScriptEnginePrivate *Math::engine() const -{ return m_engine; } - - -} } // namespace QScript::Ecma - -#endif // QT_NO_SCRIPT - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptecmanumber.cpp b/src/script/qscriptecmanumber.cpp deleted file mode 100644 index 59e84d4..0000000 --- a/src/script/qscriptecmanumber.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmanumber_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QtDebug> -#include <QtCore/qnumeric.h> -#include <math.h> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -Number::Number(QScriptEnginePrivate *eng): - Core(eng, QLatin1String("Number"), QScriptClassInfo::NumberType) -{ - newNumber(&publicPrototype, 0); - - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("toString"), method_toString, 0); - addPrototypeFunction(QLatin1String("toLocaleString"), method_toLocaleString, 0); - addPrototypeFunction(QLatin1String("valueOf"), method_valueOf, 0); - addPrototypeFunction(QLatin1String("toFixed"), method_toFixed, 1); - addPrototypeFunction(QLatin1String("toExponential"), method_toExponential, 1); - addPrototypeFunction(QLatin1String("toPrecision"), method_toPrecision, 1); - - QScriptValue::PropertyFlags flags = QScriptValue::Undeletable - | QScriptValue::ReadOnly - | QScriptValue::SkipInEnumeration; - ctor.setProperty(QLatin1String("NaN"), - QScriptValueImpl(qSNaN()), flags); - ctor.setProperty(QLatin1String("NEGATIVE_INFINITY"), - QScriptValueImpl(-qInf()), flags); - ctor.setProperty(QLatin1String("POSITIVE_INFINITY"), - QScriptValueImpl(qInf()), flags); - ctor.setProperty(QLatin1String("MAX_VALUE"), - QScriptValueImpl(1.7976931348623158e+308), flags); -#ifdef __INTEL_COMPILER -# pragma warning( push ) -# pragma warning(disable: 239) -#endif - ctor.setProperty(QLatin1String("MIN_VALUE"), - QScriptValueImpl(5e-324), flags); -#ifdef __INTEL_COMPILER -# pragma warning( pop ) -#endif -} - -Number::~Number() -{ -} - -void Number::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - qsreal value; - if (context->argumentCount() > 0) - value = context->argument(0).toNumber(); - else - value = 0; - - QScriptValueImpl num(value); - if (!context->isCalledAsConstructor()) { - context->setReturnValue(num); - } else { - QScriptValueImpl &obj = context->m_thisObject; - obj.setClassInfo(classInfo()); - obj.setInternalValue(num); - obj.setPrototype(publicPrototype); - context->setReturnValue(obj); - } -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -void Number::newNumber(QScriptValueImpl *result, qsreal value) -{ - engine()->newObject(result, publicPrototype, classInfo()); - result->setInternalValue(QScriptValueImpl(value)); -} - -QScriptValueImpl Number::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("Number.prototype.toString")); - } - QScriptValueImpl arg = context->argument(0); - if (!arg.isUndefined()) { - int radix = arg.toInt32(); - if (radix < 2 || radix > 36) - return context->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix") - .arg(radix)); - if (radix != 10) { - QString str; - qsreal num = self.internalValue().toNumber(); - if (qIsNaN(num)) - return QScriptValueImpl(eng, QLatin1String("NaN")); - else if (qIsInf(num)) - return QScriptValueImpl(eng, QLatin1String(num < 0 ? "-Infinity" : "Infinity")); - bool negative = false; - if (num < 0) { - negative = true; - num = -num; - } - qsreal frac = num - ::floor(num); - num = QScriptEnginePrivate::toInteger(num); - do { - char c = (char)::fmod(num, radix); - c = (c < 10) ? (c + '0') : (c - 10 + 'a'); - str.prepend(QLatin1Char(c)); - num = ::floor(num / radix); - } while (num != 0); - if (frac != 0) { - str.append(QLatin1Char('.')); - do { - frac = frac * radix; - char c = (char)::floor(frac); - c = (c < 10) ? (c + '0') : (c - 10 + 'a'); - str.append(QLatin1Char(c)); - frac = frac - ::floor(frac); - } while (frac != 0); - } - if (negative) - str.prepend(QLatin1Char('-')); - return QScriptValueImpl(eng, str); - } - } - QString str = self.internalValue().toString(); - return (QScriptValueImpl(eng, str)); -} - -QScriptValueImpl Number::method_toLocaleString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("Number.prototype.toLocaleString")); - } - QString str = self.internalValue().toString(); - return (QScriptValueImpl(eng, str)); -} - -QScriptValueImpl Number::method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("Number.prototype.valueOf")); - } - return (self.internalValue()); -} - -QScriptValueImpl Number::method_toFixed(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("Number.prototype.toFixed")); - } - qsreal fdigits = 0; - - if (context->argumentCount() > 0) - fdigits = context->argument(0).toInteger(); - - if (qIsNaN(fdigits)) - fdigits = 0; - - qsreal v = self.internalValue().toNumber(); - QString str; - if (qIsNaN(v)) - str = QString::fromLatin1("NaN"); - else if (qIsInf(v)) - str = QString::fromLatin1(v < 0 ? "-Infinity" : "Infinity"); - else - str = QString::number(v, 'f', int (fdigits)); - return (QScriptValueImpl(eng, str)); -} - -QScriptValueImpl Number::method_toExponential(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("Number.prototype.toExponential")); - } - qsreal fdigits = 0; - - if (context->argumentCount() > 0) - fdigits = context->argument(0).toInteger(); - - qsreal v = self.internalValue().toNumber(); - QString z = QString::number(v, 'e', int (fdigits)); - return (QScriptValueImpl(eng, z)); -} - -QScriptValueImpl Number::method_toPrecision(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("Number.prototype.toPrecision")); - } - qsreal fdigits = 0; - - if (context->argumentCount() > 0) - fdigits = context->argument(0).toInteger(); - - qsreal v = self.internalValue().toNumber(); - return (QScriptValueImpl(eng, QString::number(v, 'g', int (fdigits)))); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmanumber_p.h b/src/script/qscriptecmanumber_p.h deleted file mode 100644 index 5ba6039..0000000 --- a/src/script/qscriptecmanumber_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMANUMBER_P_H -#define QSCRIPTECMANUMBER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptecmacore_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class Number: public Core -{ -public: - Number(QScriptEnginePrivate *engine); - virtual ~Number(); - - virtual void execute(QScriptContextPrivate *context); - - void newNumber(QScriptValueImpl *result, double value = 0); - -protected: - static QScriptValueImpl method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLocaleString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - static QScriptValueImpl method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - static QScriptValueImpl method_toFixed(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - static QScriptValueImpl method_toExponential(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - static QScriptValueImpl method_toPrecision(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); -}; - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptecmaobject.cpp b/src/script/qscriptecmaobject.cpp deleted file mode 100644 index fb6da16..0000000 --- a/src/script/qscriptecmaobject.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmaobject_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -Object::Object(QScriptEnginePrivate *eng, QScriptClassInfo *classInfo): - Core(eng, classInfo) -{ - newObject(&publicPrototype, eng->nullValue()); -} - -Object::~Object() -{ -} - -void Object::initialize() -{ - QScriptEnginePrivate *eng = engine(); - - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("toString"), method_toString, 1); - addPrototypeFunction(QLatin1String("toLocaleString"), method_toLocaleString, 1); - addPrototypeFunction(QLatin1String("valueOf"), method_valueOf, 0); - addPrototypeFunction(QLatin1String("hasOwnProperty"), method_hasOwnProperty, 1); - addPrototypeFunction(QLatin1String("isPrototypeOf"), method_isPrototypeOf, 1); - addPrototypeFunction(QLatin1String("propertyIsEnumerable"), method_propertyIsEnumerable, 1); - addPrototypeFunction(QLatin1String("__defineGetter__"), method_defineGetter, 2); - addPrototypeFunction(QLatin1String("__defineSetter__"), method_defineSetter, 2); -} - -void Object::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - QScriptValueImpl value; - - if (context->argumentCount() > 0) - value = engine()->toObject(context->argument(0)); - else - value.invalidate(); - - if (! value.isValid()) - newObject(&value); - - context->setReturnValue(value); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -void Object::newObject(QScriptValueImpl *result, const QScriptValueImpl &proto) -{ - engine()->newObject(result, proto, classInfo()); -} - -QScriptValueImpl Object::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl glo = eng->globalObject(); - QString s = QLatin1String("[object "); - QScriptValueImpl self = context->thisObject(); - s += self.classInfo()->name(); - s += QLatin1Char(']'); - return (QScriptValueImpl(eng, s)); -} - -QScriptValueImpl Object::method_toLocaleString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - return method_toString(context, eng, classInfo); -} - -QScriptValueImpl Object::method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *) -{ - return (context->thisObject()); -} - -QScriptValueImpl Object::method_hasOwnProperty(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - bool result = false; - - if (context->thisObject().isObject() && (context->argumentCount() > 0)) { - QScriptValueImpl arg = context->argument(0); - - QScriptNameIdImpl *id = 0; - if (arg.isString()) - id = arg.stringValue(); - - if (! id || ! id->unique) { - QString str = arg.toString(); - id = eng->nameId(str); - } - - QScript::Member member; - QScriptValueImpl base; - QScriptValueImpl self = context->thisObject(); - if (self.resolve(id, &member, &base, QScriptValue::ResolveLocal, QScript::Read)) - result = true; - } - - return (QScriptValueImpl(result)); -} - -QScriptValueImpl Object::method_isPrototypeOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *) -{ - bool result = false; - - if (context->thisObject().isObject() && (context->argumentCount() > 0)) { - QScriptValueImpl arg = context->argument(0); - - if (arg.isObject()) { - QScriptValueImpl proto = arg.prototype(); - - if (proto.isObject()) { - QScriptValueImpl self = context->thisObject(); - result = self.objectValue() == proto.objectValue(); - } - } - } - - return (QScriptValueImpl(result)); -} - -QScriptValueImpl Object::method_propertyIsEnumerable(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - bool result = false; - - if (context->thisObject().isObject() && (context->argumentCount() > 0)) { - QScriptValueImpl arg = context->argument(0); - - QScriptNameIdImpl *id = 0; - if (arg.isString()) - id = arg.stringValue(); - - if (! id || ! id->unique) { - QString str = arg.toString(); - id = eng->nameId(str); - } - - QScript::Member member; - QScriptValueImpl base; - QScriptValueImpl self = context->thisObject(); - if (self.resolve(id, &member, &base, QScriptValue::ResolveLocal, QScript::Read)) { - result = ! member.dontEnum(); - if (result) { - QScriptValueImpl tmp; - base.get(member, &tmp); - result = tmp.isValid(); - } - } - } - - return (QScriptValueImpl(result)); -} - -QScriptValueImpl Object::method_defineGetter(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QString propertyName = context->argument(0).toString(); - if (context->thisObject().propertyFlags(propertyName) & QScriptValue::ReadOnly) - return context->throwError(QLatin1String("cannot redefine read-only property")); - QScriptValueImpl getter = context->argument(1); - if (!getter.isFunction()) - return context->throwError(QLatin1String("getter must be a function")); - context->thisObject().setProperty(propertyName, getter, QScriptValue::PropertyGetter); - return eng->undefinedValue(); -} - -QScriptValueImpl Object::method_defineSetter(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QString propertyName = context->argument(0).toString(); - if (context->thisObject().propertyFlags(propertyName) & QScriptValue::ReadOnly) - return context->throwError(QLatin1String("cannot redefine read-only property")); - QScriptValueImpl setter = context->argument(1); - if (!setter.isFunction()) - return context->throwError(QLatin1String("setter must be a function")); - context->thisObject().setProperty(propertyName, setter, QScriptValue::PropertySetter); - return eng->undefinedValue(); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmaobject_p.h b/src/script/qscriptecmaobject_p.h deleted file mode 100644 index 56d2cea..0000000 --- a/src/script/qscriptecmaobject_p.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMAOBJECT_P_H -#define QSCRIPTECMAOBJECT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptecmacore_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class Object: public Core -{ -public: - Object(QScriptEnginePrivate *engine, QScriptClassInfo *classInfo); - virtual ~Object(); - - void initialize(); - - virtual void execute(QScriptContextPrivate *context); - - void newObject(QScriptValueImpl *result, const QScriptValueImpl &proto = QScriptValueImpl()); - -protected: - static QScriptValueImpl method_toString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLocaleString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_valueOf(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_hasOwnProperty(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_isPrototypeOf(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_propertyIsEnumerable(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_defineGetter(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_defineSetter(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); -}; - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptecmaregexp.cpp b/src/script/qscriptecmaregexp.cpp deleted file mode 100644 index 8a40e8b..0000000 --- a/src/script/qscriptecmaregexp.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmaregexp_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QStringList> -#include <QtCore/QRegExp> -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -RegExp::RegExp(QScriptEnginePrivate *eng): - Core(eng, QLatin1String("RegExp"), QScriptClassInfo::RegExpType) -{ - newRegExp(&publicPrototype, QString(), /*flags=*/0); - - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("exec"), method_exec, 1); - addPrototypeFunction(QLatin1String("test"), method_test, 1); - addPrototypeFunction(QLatin1String("toString"), method_toString, 1); -} - -RegExp::~RegExp() -{ -} - -RegExp::Instance *RegExp::Instance::get(const QScriptValueImpl &object, QScriptClassInfo *klass) -{ - if (! klass || klass == object.classInfo()) - return static_cast<Instance*> (object.objectData()); - - return 0; -} - -void RegExp::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - QString P; - int F; - QScriptValueImpl pattern = context->argument(0); - QScriptValueImpl flags = context->argument(1); - if (!context->isCalledAsConstructor()) { - if ((pattern.classInfo() == classInfo()) && flags.isUndefined()) { - context->m_result = pattern; - goto Lout; - } - } - if (pattern.classInfo() == classInfo()) { - if (!flags.isUndefined()) { - context->throwTypeError(QString::fromLatin1("cannot specify flags when creating a copy of a RegExp")); - goto Lout; - } - Instance *data = Instance::get(pattern, classInfo()); -#ifndef QT_NO_REGEXP - P = data->value.pattern(); -#else - P = data->pattern; -#endif - F = data->flags; - } else { - if (!pattern.isUndefined()) - P = pattern.toString(); - F = 0; - if (!flags.isUndefined()) { - QString flagsStr = flags.toString(); - for (int i = 0; i < flagsStr.length(); ++i) { - int bitflag = flagFromChar(flagsStr.at(i)); - if (bitflag == 0) { - context->throwError( - QScriptContext::SyntaxError, - QString::fromUtf8("invalid regular expression flag '%0'") - .arg(flagsStr.at(i))); - goto Lout; - } - F |= bitflag; - } - } - } - if (context->isCalledAsConstructor()) { - QScriptValueImpl &object = context->m_thisObject; - object.setClassInfo(classInfo()); - object.setPrototype(publicPrototype); -#ifndef QT_NO_REGEXP - initRegExp(&object, toRegExp(P, F), F); -#else - initRegExp(&object, P, F); -#endif - } else { - newRegExp(&context->m_result, P, F); - } - Lout: ; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -void RegExp::newRegExp(QScriptValueImpl *result, const QString &pattern, int flags) -{ -#ifndef QT_NO_REGEXP - QRegExp rx = toRegExp(pattern, flags); - newRegExp_helper(result, rx, flags); -#else - engine()->newObject(result, publicPrototype, classInfo()); - initRegExp(result, pattern, flags); -#endif // QT_NO_REGEXP -} - -#ifndef QT_NO_REGEXP -void RegExp::newRegExp(QScriptValueImpl *result, const QRegExp &rx, int flags) -{ - Q_ASSERT(!(flags & IgnoreCase) || (rx.caseSensitivity() == Qt::CaseInsensitive)); - newRegExp_helper(result, rx, flags); -} - -void RegExp::newRegExp_helper(QScriptValueImpl *result, const QRegExp &rx, - int flags) -{ - engine()->newObject(result, publicPrototype, classInfo()); - initRegExp(result, rx, flags); -} - -QRegExp RegExp::toRegExp(const QScriptValueImpl &value) const -{ - Instance *rx_data = Instance::get(value, classInfo()); - Q_ASSERT(rx_data != 0); - return rx_data->value; -} - -QRegExp RegExp::toRegExp(const QString &pattern, int flags) -{ - bool ignoreCase = (flags & IgnoreCase) != 0; - return QRegExp(pattern, - (ignoreCase ? Qt::CaseInsensitive: Qt::CaseSensitive), - QRegExp::RegExp2); -} - -#endif // QT_NO_REGEXP - -void RegExp::initRegExp(QScriptValueImpl *result, -#ifndef QT_NO_REGEXP - const QRegExp &rx, -#else - const QString &pattern, -#endif - int flags) -{ - Instance *instance = new Instance(); -#ifndef QT_NO_REGEXP - instance->value = rx; -#else - instance->pattern = pattern; -#endif - instance->flags = flags; - result->setObjectData(instance); - - bool global = (flags & Global) != 0; - bool ignoreCase = (flags & IgnoreCase) != 0; - bool multiline = (flags & Multiline) != 0; - - QScriptValue::PropertyFlags propertyFlags = QScriptValue::SkipInEnumeration - | QScriptValue::Undeletable - | QScriptValue::ReadOnly; - - result->setProperty(QLatin1String("global"), QScriptValueImpl(global), - propertyFlags); - result->setProperty(QLatin1String("ignoreCase"), QScriptValueImpl(ignoreCase), - propertyFlags); - result->setProperty(QLatin1String("multiline"), QScriptValueImpl(multiline), - propertyFlags); -#ifndef QT_NO_REGEXP - const QString &pattern = rx.pattern(); -#endif - result->setProperty(QLatin1String("source"), QScriptValueImpl(engine(), pattern), - propertyFlags); - result->setProperty(QLatin1String("lastIndex"), QScriptValueImpl(0), - propertyFlags & ~QScriptValue::ReadOnly); -} - -int RegExp::flagFromChar(const QChar &ch) -{ - static QHash<QChar, int> flagsHash; - if (flagsHash.isEmpty()) { - flagsHash[QLatin1Char('g')] = Global; - flagsHash[QLatin1Char('i')] = IgnoreCase; - flagsHash[QLatin1Char('m')] = Multiline; - } - QHash<QChar, int>::const_iterator it; - it = flagsHash.constFind(ch); - if (it == flagsHash.constEnd()) - return 0; - return it.value(); -} - -QString RegExp::flagsToString(int flags) -{ - QString result; - if (flags & Global) - result += QLatin1Char('g'); - if (flags & IgnoreCase) - result += QLatin1Char('i'); - if (flags & Multiline) - result += QLatin1Char('m'); - return result; -} - -QScriptValueImpl RegExp::method_exec(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("RegExp.prototype.exec")); - } - Instance *rx_data = Instance::get(self, classInfo); - Q_ASSERT(rx_data != 0); - - QString S = context->argument(0).toString(); - int length = S.length(); - QScriptValueImpl lastIndex = self.property(QLatin1String("lastIndex")); - - int i = lastIndex.isValid() ? int (lastIndex.toInteger()) : 0; - bool global = self.property(QLatin1String("global")).toBoolean(); - - if (! global) - i = 0; - - if (i < 0 || i >= length) - return (eng->nullValue()); - -#ifndef QT_NO_REGEXP - int index = rx_data->value.indexIn(S, i); - if (index == -1) -#endif // QT_NO_REGEXP - return eng->nullValue(); - -#ifndef QT_NO_REGEXP - int e = index + rx_data->value.matchedLength(); - - if (global) - self.setProperty(QLatin1String("lastIndex"), QScriptValueImpl(e)); - - QScript::Array elts(eng); - QStringList capturedTexts = rx_data->value.capturedTexts(); - for (int i = 0; i < capturedTexts.count(); ++i) - elts.assign(i, QScriptValueImpl(eng, capturedTexts.at(i))); - - QScriptValueImpl r = eng->newArray(elts); - - r.setProperty(QLatin1String("index"), QScriptValueImpl(index)); - r.setProperty(QLatin1String("input"), QScriptValueImpl(eng, S)); - - return r; -#endif // QT_NO_REGEXP -} - -QScriptValueImpl RegExp::method_test(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - QScriptValueImpl r = method_exec(context, eng, classInfo); - return QScriptValueImpl(!r.isNull()); -} - -QScriptValueImpl RegExp::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) { - QString result; - result += QLatin1Char('/'); -#ifndef QT_NO_REGEXP - const QString &pattern = instance->value.pattern(); -#else - const QString &pattern = instance->pattern; -#endif - if (pattern.isEmpty()) - result += QLatin1String("(?:)"); - else - result += pattern; // ### quote - result += QLatin1Char('/'); - result += flagsToString(instance->flags); - return (QScriptValueImpl(eng, result)); - } - - return throwThisObjectTypeError( - context, QLatin1String("RegExp.prototype.toString")); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmaregexp_p.h b/src/script/qscriptecmaregexp_p.h deleted file mode 100644 index 1a33718..0000000 --- a/src/script/qscriptecmaregexp_p.h +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMAREGEXP_P_H -#define QSCRIPTECMAREGEXP_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QRegExp> - -#ifndef QT_NO_SCRIPT - -#include "qscriptecmacore_p.h" - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class RegExp: public Core -{ -public: - enum RegExpFlag { - Global = 0x01, - IgnoreCase = 0x02, - Multiline = 0x04 - }; - - RegExp(QScriptEnginePrivate *engine); - virtual ~RegExp(); - - virtual void execute(QScriptContextPrivate *context); - - class Instance: public QScriptObjectData { - public: - Instance() : flags(0) {} - virtual ~Instance() {} - - static Instance *get(const QScriptValueImpl &object, - QScriptClassInfo *klass); - - public: // attributes -#ifndef QT_NO_REGEXP - QRegExp value; -#else - QString pattern; -#endif - int flags; - }; - - inline Instance *get(const QScriptValueImpl &object) const - { return Instance::get(object, classInfo()); } - - void newRegExp(QScriptValueImpl *result, const QString &pattern, - int flags); -#ifndef QT_NO_REGEXP - void newRegExp(QScriptValueImpl *result, const QRegExp &rx, - int flags = 0); - QRegExp toRegExp(const QScriptValueImpl &value) const; - static QRegExp toRegExp(const QString &pattern, int flags); -#endif - - static int flagFromChar(const QChar &ch); - static QString flagsToString(int flags); - -protected: - static QScriptValueImpl method_exec(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_test(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toString(QScriptContextPrivate *context, - QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - -private: -#ifndef QT_NO_REGEXP - void newRegExp_helper(QScriptValueImpl *result, const QRegExp &rx, - int flags); -#endif - void initRegExp(QScriptValueImpl *result, -#ifndef QT_NO_REGEXP - const QRegExp &rx, -#else - const QString &pattern, -#endif - int flags); -}; - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif // QSCRIPTECMAREGEXP_P_H diff --git a/src/script/qscriptecmastring.cpp b/src/script/qscriptecmastring.cpp deleted file mode 100644 index d703657..0000000 --- a/src/script/qscriptecmastring.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptecmastring_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptclassdata_p.h" - -#include <QtCore/QStringList> -#include <QtCore/QtDebug> -#include <QtCore/qnumeric.h> - -#include <limits.h> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class StringClassData: public QScriptClassData -{ - QScriptClassInfo *m_classInfo; - -public: - StringClassData(QScriptClassInfo *classInfo); - virtual ~StringClassData(); - - inline QScriptClassInfo *classInfo() const - { return m_classInfo; } - - virtual bool resolve(const QScriptValueImpl &object, - QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode access); - virtual bool get(const QScriptValueImpl &object, const Member &member, - QScriptValueImpl *out_value); - virtual bool put(QScriptValueImpl *object, const Member &member, - const QScriptValueImpl &value); - virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object); -}; - -class StringClassDataIterator: public QScriptClassDataIterator -{ -public: - StringClassDataIterator(int length); - virtual ~StringClassDataIterator(); - - virtual bool hasNext() const; - virtual void next(QScript::Member *member); - - virtual bool hasPrevious() const; - virtual void previous(QScript::Member *member); - - virtual void toFront(); - virtual void toBack(); - -private: - int m_length; - int m_pos; -}; - -StringClassData::StringClassData(QScriptClassInfo *classInfo): - m_classInfo(classInfo) -{ -} - -StringClassData::~StringClassData() -{ -} - -bool StringClassData::resolve(const QScriptValueImpl &object, - QScriptNameIdImpl *nameId, - QScript::Member *member, - QScriptValueImpl *base, - QScript::AccessMode /*access*/) -{ - if (object.classInfo() != classInfo()) - return false; - - QScriptEnginePrivate *eng = object.engine(); - - if (nameId == eng->idTable()->id_length) { - member->native(nameId, /*id=*/ 0, - QScriptValue::Undeletable - | QScriptValue::ReadOnly - | QScriptValue::SkipInEnumeration); - *base = object; - return true; - } - - bool ok = false; - int index = nameId->s.toInt(&ok); - if (!ok || (index < 0)) - return false; - - QScriptNameIdImpl *ref = object.internalValue().stringValue(); - if (index >= ref->s.length()) - return false; - - member->native(nameId, index, QScriptValue::Undeletable | QScriptValue::ReadOnly); - return true; -} - -bool StringClassData::get(const QScriptValueImpl &object, - const QScript::Member &member, - QScriptValueImpl *result) -{ - Q_ASSERT(member.isValid()); - - if (object.classInfo() != classInfo()) - return false; - - QScriptEnginePrivate *eng = object.engine(); - if (! member.isNativeProperty()) - return false; - - QScriptNameIdImpl *ref = object.internalValue().stringValue(); - int len = ref->s.length(); - - if (member.nameId() == eng->idTable()->id_length) - *result = QScriptValueImpl(len); - - else if (member.id() >= 0 && member.id() < len) - eng->newString(result, ref->s.at(member.id())); - - else - *result = eng->undefinedValue(); - - return true; -} - -bool StringClassData::put(QScriptValueImpl *, const Member &, - const QScriptValueImpl &) -{ - // writes to string elements are ignored - return true; -} - -QScriptClassDataIterator *StringClassData::newIterator(const QScriptValueImpl &object) -{ - QScriptNameIdImpl *id = object.internalValue().stringValue(); - return new StringClassDataIterator(id->s.length()); -} - -StringClassDataIterator::StringClassDataIterator(int length) -{ - m_length = length; - m_pos = 0; -} - -StringClassDataIterator::~StringClassDataIterator() -{ -} - -bool StringClassDataIterator::hasNext() const -{ - return m_pos < m_length; -} - -void StringClassDataIterator::next(QScript::Member *member) -{ - member->native(/*nameId=*/ 0, m_pos, QScriptValue::Undeletable | QScriptValue::ReadOnly); - ++m_pos; -} - -bool StringClassDataIterator::hasPrevious() const -{ - return (m_pos - 1) >= 0; -} - -void StringClassDataIterator::previous(QScript::Member *member) -{ - --m_pos; - member->native(/*nameId=*/ 0, m_pos, QScriptValue::Undeletable | QScriptValue::ReadOnly); -} - -void StringClassDataIterator::toFront() -{ - m_pos = 0; -} - -void StringClassDataIterator::toBack() -{ - m_pos = m_length; -} - - - -String::String(QScriptEnginePrivate *eng): - Core(eng, QLatin1String("String"), QScriptClassInfo::StringType) -{ - classInfo()->setData(new StringClassData(classInfo())); - - newString(&publicPrototype, QString()); - - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("toString"), method_toString, 0); - addPrototypeFunction(QLatin1String("valueOf"), method_valueOf, 0); - addPrototypeFunction(QLatin1String("charAt"), method_charAt, 1); - addPrototypeFunction(QLatin1String("charCodeAt"), method_charCodeAt, 1); - addPrototypeFunction(QLatin1String("concat"), method_concat, 1); - addPrototypeFunction(QLatin1String("indexOf"), method_indexOf, 1); - addPrototypeFunction(QLatin1String("lastIndexOf"), method_lastIndexOf, 1); - addPrototypeFunction(QLatin1String("localeCompare"), method_localeCompare, 1); - addPrototypeFunction(QLatin1String("match"), method_match, 1); - addPrototypeFunction(QLatin1String("replace"), method_replace, 2); - addPrototypeFunction(QLatin1String("search"), method_search, 1); - addPrototypeFunction(QLatin1String("slice"), method_slice, 2); - addPrototypeFunction(QLatin1String("split"), method_split, 2); - addPrototypeFunction(QLatin1String("substr"), method_substr, 2); - addPrototypeFunction(QLatin1String("substring"), method_substring, 2); - addPrototypeFunction(QLatin1String("toLowerCase"), method_toLowerCase, 0); - addPrototypeFunction(QLatin1String("toLocaleLowerCase"), method_toLocaleLowerCase, 0); - addPrototypeFunction(QLatin1String("toUpperCase"), method_toUpperCase, 0); - addPrototypeFunction(QLatin1String("toLocaleUpperCase"), method_toLocaleUpperCase, 0); - - addConstructorFunction(QLatin1String("fromCharCode"), method_fromCharCode, 1); -} - -String::~String() -{ -} - -void String::execute(QScriptContextPrivate *context) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionEntry(context); -#endif - QString value; - - if (context->argumentCount() > 0) - value = context->argument(0).toString(); - - QScriptValueImpl str(engine(), value); - if (!context->isCalledAsConstructor()) { - context->setReturnValue(str); - } else { - QScriptValueImpl &obj = context->m_thisObject; - obj.setClassInfo(classInfo()); - obj.setInternalValue(str); - obj.setPrototype(publicPrototype); - context->setReturnValue(obj); - } -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine()->notifyFunctionExit(context); -#endif -} - -void String::newString(QScriptValueImpl *result, const QString &value) -{ - engine()->newObject(result, publicPrototype, classInfo()); - result->setInternalValue(QScriptValueImpl(engine(), value)); -} - -QScriptValueImpl String::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return context->throwError(QScriptContext::TypeError, QLatin1String("String.prototype.toString")); - } - return (self.internalValue()); -} - -QScriptValueImpl String::method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - QScriptValueImpl self = context->thisObject(); - if (self.classInfo() != classInfo) { - return throwThisObjectTypeError( - context, QLatin1String("String.prototype.valueOf")); - } - return (self.internalValue()); -} - -QScriptValueImpl String::method_charAt(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString str = context->thisObject().toString(); - - int pos = 0; - if (context->argumentCount() > 0) - pos = int (context->argument(0).toInteger()); - - QString result; - if (pos >= 0 && pos < str.length()) - result += str.at(pos); - - return (QScriptValueImpl(eng, result)); -} - -QScriptValueImpl String::method_charCodeAt(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *) -{ - QString str = context->thisObject().toString(); - - int pos = 0; - if (context->argumentCount() > 0) - pos = int (context->argument(0).toInteger()); - - qsreal result = qSNaN(); - - if (pos >= 0 && pos < str.length()) - result = str.at(pos).unicode(); - - return (QScriptValueImpl(result)); -} - -QScriptValueImpl String::method_concat(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - - for (int i = 0; i < context->argumentCount(); ++i) - value += context->argument(i).toString(); - - return (QScriptValueImpl(eng, value)); -} - -QScriptValueImpl String::method_indexOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - - QString searchString = context->argument(0).toString(); - - int pos = 0; - if (context->argumentCount() > 1) - pos = int (context->argument(1).toInteger()); - - int index = -1; - if (! value.isEmpty()) - index = value.indexOf(searchString, qMin(qMax(pos, 0), value.length())); - - return (QScriptValueImpl(index)); -} - -QScriptValueImpl String::method_lastIndexOf(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - - QString searchString = context->argument(0).toString(); - - qsreal position = context->argument(1).toNumber(); - if (qIsNaN(position)) - position = +qInf(); - else - position = QScriptEnginePrivate::toInteger(position); - - int pos = QScriptEnginePrivate::toInt32(qMin(qMax(position, 0.0), qsreal(value.length()))); - if (!searchString.isEmpty() && pos == value.length()) - --pos; - int index = value.lastIndexOf(searchString, pos); - return (QScriptValueImpl(index)); -} - -QScriptValueImpl String::method_localeCompare(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - QString that = context->argument(0).toString(); - return QScriptValueImpl(QString::localeAwareCompare(value, that)); -} - -QScriptValueImpl String::method_match(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl pattern = context->argument(0); - - if (! eng->regexpConstructor->get(pattern)) - eng->regexpConstructor->newRegExp(&pattern, context->argument(0).toString(), /*flags=*/0); - - QScriptValueImpl rx_exec = pattern.property(QLatin1String("exec"), QScriptValue::ResolvePrototype); - if (! (rx_exec.isValid() && rx_exec.isFunction())) { - return context->throwError(QScriptContext::TypeError, - QLatin1String("String.prototype.match")); - } - - QScriptValueImplList args; - args << context->thisObject(); - - QScriptValueImpl global = pattern.property(QLatin1String("global")); - if (! (global.isValid() && global.toBoolean())) - return (rx_exec.call(pattern, args)); - - QScript::Array result(eng); - - QScriptNameIdImpl *lastIndexId = eng->nameId(QLatin1String("lastIndex")); - QScriptNameIdImpl *zeroId = eng->nameId(QLatin1String("0")); - - pattern.setProperty(lastIndexId, QScriptValueImpl(0)); - int n = 0; - while (true) { - qsreal lastIndex = pattern.property(lastIndexId).toNumber(); - QScriptValueImpl r = rx_exec.call(pattern, args); - if (r.isNull()) - break; - qsreal newLastIndex = pattern.property(lastIndexId).toNumber(); - if (newLastIndex == lastIndex) - pattern.setProperty(lastIndexId, QScriptValueImpl(lastIndex + 1)); - result.assign(n++, r.property(zeroId)); - } - - return (eng->newArray(result)); -} - -QScriptValueImpl String::method_replace(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString input = context->thisObject().toString(); - QScriptValueImpl searchValue = context->argument(0); - QScriptValueImpl replaceValue = context->argument(1); - - QString output; - if (searchValue.classInfo() == eng->regexpConstructor->classInfo()) { - // searchValue is a RegExp - QScriptValueImpl rx_exec = searchValue.property(QLatin1String("exec"), QScriptValue::ResolvePrototype); - if (!rx_exec.isFunction()) { - return context->throwError(QScriptContext::TypeError, - QLatin1String("String.prototype.replace")); - } - QVector<QScriptValueImpl> occurrences; - QScriptValueImpl global = searchValue.property(QLatin1String("global")); - QScriptValueImplList args; - args << QScriptValueImpl(eng, input); - if (!global.toBoolean()) { - QScriptValueImpl r = rx_exec.call(searchValue, args); - if (!r.isNull()) - occurrences.append(r); - } else { - QScriptNameIdImpl *lastIndexId = eng->nameId(QLatin1String("lastIndex")); - searchValue.setProperty(lastIndexId, QScriptValueImpl(0)); - while (true) { - qsreal lastIndex = searchValue.property(lastIndexId).toNumber(); - QScriptValueImpl r = rx_exec.call(searchValue, args); - if (r.isNull()) - break; - qsreal newLastIndex = searchValue.property(lastIndexId).toNumber(); - if (newLastIndex == lastIndex) - searchValue.setProperty(lastIndexId, QScriptValueImpl(lastIndex + 1)); - occurrences.append(r); - } - } - int pos = 0; - if (replaceValue.isFunction()) { - QScriptNameIdImpl *indexId = eng->nameId(QLatin1String("index")); - QScriptNameIdImpl *lengthId = eng->nameId(QLatin1String("length")); - for (int i = 0; i < occurrences.count(); ++i) { - QScriptValueImpl needle = occurrences.at(i); - int index = int (needle.property(indexId).toInteger()); - uint length = eng->toUint32(needle.property(lengthId).toNumber()); - output += input.mid(pos, index - pos); - args.clear(); - for (uint j = 0; j < length; ++j) - args << needle.property(j); - args << QScriptValueImpl(index); - args << QScriptValueImpl(eng, input); - QScriptValueImpl ret = replaceValue.call(eng->nullValue(), args); - output += ret.toString(); - pos = index + args[0].toString().length(); - } - } else { - // use string representation of replaceValue - const QString replaceString = replaceValue.toString(); - const QLatin1Char dollar = QLatin1Char('$'); - QScriptNameIdImpl *indexId = eng->nameId(QLatin1String("index")); - QScriptNameIdImpl *zeroId = eng->nameId(QLatin1String("0")); - for (int i = 0; i < occurrences.count(); ++i) { - QScriptValueImpl needle = occurrences.at(i); - int index = int (needle.property(indexId).toInteger()); - output += input.mid(pos, index - pos); - int j = 0; - while (j < replaceString.length()) { - const QChar c = replaceString.at(j++); - if ((c == dollar) && (j < replaceString.length())) { - const QChar nc = replaceString.at(j); - if (nc == dollar) { - ++j; - } else if (nc == QLatin1Char('`')) { - ++j; - output += input.left(index); - continue; - } else if (nc == QLatin1Char('\'')) { - ++j; - output += input.mid(index + needle.property(zeroId).toString().length()); - continue; - } else if (nc.isDigit()) { - ++j; - int cap = nc.toLatin1() - '0'; - if ((j < replaceString.length()) && replaceString.at(j).isDigit()) { - cap = cap * 10; - cap = replaceString.at(j++).toLatin1() - '0'; - } - output += needle.property(QScriptValueImpl(cap).toString()).toString(); - continue; - } - } - output += c; - } - pos = index + needle.property(zeroId).toString().length(); - } - } - output += input.mid(pos); - } else { - // use string representation of searchValue - const QString searchString = searchValue.toString(); - int pos = 0; - if (replaceValue.isFunction()) { - int index = input.indexOf(searchString, pos); - if (index != -1) { - output += input.mid(pos, index - pos); - QScriptValueImplList args; - args << QScriptValueImpl(eng, searchString); - args << QScriptValueImpl(index); - args << QScriptValueImpl(eng, input); - QScriptValueImpl ret = replaceValue.call(eng->nullValue(), args); - output += ret.toString(); - pos = index + searchString.length(); - } - } else { - // use string representation of replaceValue - const QString replaceString = replaceValue.toString(); - const QLatin1Char dollar = QLatin1Char('$'); - int index = input.indexOf(searchString, pos); - if (index != -1) { - output += input.mid(pos, index - pos); - int j = 0; - while (j < replaceString.length()) { - const QChar c = replaceString.at(j++); - if ((c == dollar) && (j < replaceString.length())) { - const QChar nc = replaceString.at(j); - if (nc == dollar) { - ++j; - } else if (nc == QLatin1Char('`')) { - output += input.left(index); - ++j; - continue; - } else if (nc == QLatin1Char('\'')) { - output += input.mid(index + searchString.length()); - ++j; - continue; - } - } - output += c; - } - pos = index + searchString.length(); - } - } - output += input.mid(pos); - } - return QScriptValueImpl(eng, output); -} - -QScriptValueImpl String::method_search(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl pattern = context->argument(0); - - Ecma::RegExp::Instance *rx_data = 0; - if (0 == (rx_data = eng->regexpConstructor->get(pattern))) { - eng->regexpConstructor->newRegExp(&pattern, context->argument(0).toString(), /*flags=*/0); - rx_data = eng->regexpConstructor->get(pattern); - } - - QString value = context->thisObject().toString(); -#ifndef QT_NO_REGEXP - return (QScriptValueImpl(value.indexOf(rx_data->value))); -#else - return eng->nullValue(); -#endif -} - -QScriptValueImpl String::method_slice(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString text = context->thisObject().toString(); - int length = text.length(); - - int start = int (context->argument(0).toInteger()); - int end = context->argument(1).isUndefined() - ? length : int (context->argument(1).toInteger()); - - if (start < 0) - start = qMax(length + start, 0); - else - start = qMin(start, length); - - if (end < 0) - end = qMax(length + end, 0); - else - end = qMin(end, length); - - int count = qMax(0, end - start); - return (QScriptValueImpl(eng, text.mid(start, count))); -} - -QScriptValueImpl String::method_split(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QScriptValueImpl l = context->argument(1); - quint32 lim = l.isUndefined() ? UINT_MAX : QScriptEnginePrivate::toUint32(l.toNumber()); - - if (lim == 0) - return eng->newArray(); - - QString S = context->thisObject().toString(); - QScriptValueImpl separator = context->argument(0); - - QScript::Array A(eng); - // the argumentCount() check is for compatibility with spidermonkey; - // it is not according to ECMA-262 - if (separator.isUndefined() && (context->argumentCount() == 0)) { - A.assign(0, QScriptValueImpl(eng, S)); - } else { - QStringList matches; -#ifndef QT_NO_REGEXP - if (Ecma::RegExp::Instance *rx = eng->regexpConstructor->get(separator)) { - matches = S.split(rx->value, rx->value.pattern().isEmpty() - ? QString::SkipEmptyParts : QString::KeepEmptyParts); - } else -#endif // QT_NO_REGEXP - { - QString sep = separator.toString(); - matches = S.split(sep, sep.isEmpty() - ? QString::SkipEmptyParts : QString::KeepEmptyParts); - } - uint count = qMin(lim, uint(matches.count())); - for (uint i = 0; i < count; ++i) - A.assign(i, QScriptValueImpl(eng, matches.at(i))); - } - - return eng->newArray(A); -} - -QScriptValueImpl String::method_substr(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - - qsreal start = 0; - if (context->argumentCount() > 0) - start = context->argument(0).toInteger(); - - qsreal length = +qInf(); - if (context->argumentCount() > 1) - length = context->argument(1).toInteger(); - - qsreal count = value.length(); - if (start < 0) - start = qMax(count + start, 0.0); - - length = qMin(qMax(length, 0.0), count - start); - - qint32 x = QScriptEnginePrivate::toInt32(start); - qint32 y = QScriptEnginePrivate::toInt32(length); - return QScriptValueImpl(eng, value.mid(x, y)); -} - -QScriptValueImpl String::method_substring(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - int length = value.length(); - - qsreal start = 0; - qsreal end = length; - - if (context->argumentCount() > 0) - start = context->argument(0).toInteger(); - - if (context->argumentCount() > 1) - end = context->argument(1).toInteger(); - - if (qIsNaN(start) || start < 0) - start = 0; - - if (qIsNaN(end) || end < 0) - end = 0; - - if (start > length) - start = length; - - if (end > length) - end = length; - - if (start > end) { - qsreal was = start; - start = end; - end = was; - } - - qint32 x = QScriptEnginePrivate::toInt32(start); - qint32 y = QScriptEnginePrivate::toInt32(end - start); - - return (QScriptValueImpl(eng, value.mid(x, y))); -} - -QScriptValueImpl String::method_toLowerCase(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - return (QScriptValueImpl(eng, value.toLower())); -} - -QScriptValueImpl String::method_toLocaleLowerCase(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - return method_toLowerCase(context, eng, classInfo); // ### check me -} - -QScriptValueImpl String::method_toUpperCase(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - return (QScriptValueImpl(eng, value.toUpper())); -} - -QScriptValueImpl String::method_toLocaleUpperCase(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - return method_toUpperCase(context, eng, classInfo); // ### check me -} - -QScriptValueImpl String::method_fromCharCode(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString str; - for (int i = 0; i < context->argumentCount(); ++i) { - QChar c(context->argument(i).toUInt16()); - str += c; - } - return (QScriptValueImpl(eng, str)); -} - -// Qt extensions - -QScriptValueImpl String::method_ext_arg(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - QString value = context->thisObject().toString(); - QScriptValueImpl arg = context->argument(0); - QString result; - if (arg.isString()) - result = value.arg(arg.toString()); - else if (arg.isNumber()) - result = value.arg(arg.toNumber()); - return QScriptValueImpl(eng, result); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptecmastring_p.h b/src/script/qscriptecmastring_p.h deleted file mode 100644 index 6d4c84a..0000000 --- a/src/script/qscriptecmastring_p.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTECMASTRING_P_H -#define QSCRIPTECMASTRING_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptecmacore_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ecma { - -class String: public Core -{ -public: - String(QScriptEnginePrivate *engine); - virtual ~String(); - - virtual void execute(QScriptContextPrivate *context); - - void newString(QScriptValueImpl *result, const QString &value = QString()); - -protected: - static QScriptValueImpl method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_charAt(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_charCodeAt(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_concat(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_indexOf(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_lastIndexOf(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_localeCompare(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_match(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_replace(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_search(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_slice(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_split(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_substr(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_substring(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLowerCase(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLocaleLowerCase(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toUpperCase(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_toLocaleUpperCase(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_fromCharCode(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - -public: - // Qt extensions - static QScriptValueImpl method_ext_arg(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); -}; - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptengine.cpp b/src/script/qscriptengine.cpp deleted file mode 100644 index 59ce460..0000000 --- a/src/script/qscriptengine.cpp +++ /dev/null @@ -1,1881 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptengine.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptsyntaxcheckresult_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \since 4.3 - \class QScriptEngine - \reentrant - - \brief The QScriptEngine class provides an environment for evaluating Qt Script code. - - \ingroup script - - - See the \l{QtScript} documentation for information about the Qt Script language, - and how to get started with scripting your C++ application. - - \section1 Evaluating Scripts - - Use evaluate() to evaluate script code; this is the C++ equivalent - of the built-in script function \c{eval()}. - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 0 - - evaluate() returns a QScriptValue that holds the result of the - evaluation. The QScriptValue class provides functions for converting - the result to various C++ types (e.g. QScriptValue::toString() - and QScriptValue::toNumber()). - - The following code snippet shows how a script function can be - defined and then invoked from C++ using QScriptValue::call(): - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 1 - - As can be seen from the above snippets, a script is provided to the - engine in the form of a string. One common way of loading scripts is - by reading the contents of a file and passing it to evaluate(): - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 2 - - Here we pass the name of the file as the second argument to - evaluate(). This does not affect evaluation in any way; the second - argument is a general-purpose string that is used to identify the - script for debugging purposes (for example, our filename will now - show up in any uncaughtExceptionBacktrace() involving the script). - - \section1 Engine Configuration - - The globalObject() function returns the \bold {Global Object} - associated with the script engine. Properties of the Global Object - are accessible from any script code (i.e. they are global - variables). Typically, before evaluating "user" scripts, you will - want to configure a script engine by adding one or more properties - to the Global Object: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 3 - - Adding custom properties to the scripting environment is one of the - standard means of providing a scripting API that is specific to your - application. Usually these custom properties are objects created by - the newQObject() or newObject() functions, or constructor functions - created by newFunction(). - - \section1 Script Exceptions - - evaluate() can throw a script exception (e.g. due to a syntax - error); in that case, the return value is the value that was thrown - (typically an \c{Error} object). You can check whether the - evaluation caused an exception by calling hasUncaughtException(). In - that case, you can call toString() on the error object to obtain an - error message. The current uncaught exception is also available - through uncaughtException(). You can obtain a human-readable - backtrace of the exception with uncaughtExceptionBacktrace(). - Calling clearExceptions() will cause any uncaught exceptions to be - cleared. - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4 - - The checkSyntax() function can be used to determine whether code can be - usefully passed to evaluate(). - - \section1 Script Object Creation - - Use newObject() to create a standard Qt Script object; this is the - C++ equivalent of the script statement \c{new Object()}. You can use - the object-specific functionality in QScriptValue to manipulate the - script object (e.g. QScriptValue::setProperty()). Similarly, use - newArray() to create a Qt Script array object. Use newDate() to - create a \c{Date} object, and newRegExp() to create a \c{RegExp} - object. - - \section1 QObject Integration - - Use newQObject() to wrap a QObject (or subclass) - pointer. newQObject() returns a proxy script object; properties, - children, and signals and slots of the QObject are available as - properties of the proxy object. No binding code is needed because it - is done dynamically using the Qt meta object system. - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 5 - - Use qScriptConnect() to connect a C++ signal to a script function; - this is the Qt Script equivalent of QObject::connect(). When a - script function is invoked in response to a C++ signal, it can cause - a script exception; you can connect to the signalHandlerException() - signal to catch such an exception. - - Use newQMetaObject() to wrap a QMetaObject; this gives you a "script - representation" of a QObject-based class. newQMetaObject() returns a - proxy script object; enum values of the class are available as - properties of the proxy object. You can also specify a function that - will be used to construct objects of the class (e.g. when the - constructor is invoked from a script). For classes that have a - "standard" Qt constructor, Qt Script can provide a default script - constructor for you; see scriptValueFromQMetaObject(). - - See the \l{QtScript} documentation for more information on - the QObject integration. - - \section1 Support for Custom C++ Types - - Use newVariant() to wrap a QVariant. This can be used to store - values of custom (non-QObject) C++ types that have been registered - with the Qt meta-type system. To make such types scriptable, you - typically associate a prototype (delegate) object with the C++ type - by calling setDefaultPrototype(); the prototype object defines the - scripting API for the C++ type. Unlike the QObject integration, - there is no automatic binding possible here; i.e. you have to create - the scripting API yourself, for example by using the QScriptable - class. - - Use fromScriptValue() to cast from a QScriptValue to another type, - and toScriptValue() to create a QScriptValue from another value. - You can specify how the conversion of C++ types is to be performed - with qScriptRegisterMetaType() and qScriptRegisterSequenceMetaType(). - By default, Qt Script will use QVariant to store values of custom - types. - - \section1 Importing Extensions - - Use importExtension() to import plugin-based extensions into the - engine. Call availableExtensions() to obtain a list naming all the - available extensions, and importedExtensions() to obtain a list - naming only those extensions that have been imported. - - Call pushContext() to open up a new variable scope, and popContext() - to close the current scope. This is useful if you are implementing - an extension that evaluates script code containing temporary - variable definitions (e.g. \c{var foo = 123;}) that are safe to - discard when evaluation has completed. - - \section1 Native Functions - - Use newFunction() to wrap native (C++) functions, including - constructors for your own custom types, so that these can be invoked - from script code. Such functions must have the signature - QScriptEngine::FunctionSignature. You may then pass the function as - argument to newFunction(). Here is an example of a function that - returns the sum of its first two arguments: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 6 - - To expose this function to script code, you can set it as a property - of the Global Object: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 7 - - Once this is done, script code can call your function in the exact - same manner as a "normal" script function: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 8 - - \section1 Long-running Scripts - - If you need to evaluate possibly long-running scripts from the main - (GUI) thread, you should first call setProcessEventsInterval() to - make sure that the GUI stays responsive. You can abort a currently - running script by calling abortEvaluation(). You can determine - whether an engine is currently running a script by calling - isEvaluating(). - - \section1 Core Debugging/Tracing Facilities - - Since Qt 4.4, you can be notified of events pertaining to script - execution (e.g. script function calls and statement execution) - through the QScriptEngineAgent interface; see the setAgent() - function. This can be used to implement debugging and profiling of a - QScriptEngine. - - \sa QScriptValue, QScriptContext, QScriptEngineAgent - -*/ - -/*! - \enum QScriptEngine::ValueOwnership - - This enum specifies the ownership when wrapping a C++ value, e.g. by using newQObject(). - - \value QtOwnership The standard Qt ownership rules apply, i.e. the associated object will never be explicitly deleted by the script engine. This is the default. (QObject ownership is explained in \l{Object Trees and Object Ownership}.) - \value ScriptOwnership The value is owned by the script environment. The associated data will be deleted when appropriate (i.e. after the garbage collector has discovered that there are no more live references to the value). - \value AutoOwnership If the associated object has a parent, the Qt ownership rules apply (QtOwnership); otherwise, the object is owned by the script environment (ScriptOwnership). -*/ - -/*! - \enum QScriptEngine::QObjectWrapOption - - These flags specify options when wrapping a QObject pointer with newQObject(). - - \value ExcludeChildObjects The script object will not expose child objects as properties. - \value ExcludeSuperClassMethods The script object will not expose signals and slots inherited from the superclass. - \value ExcludeSuperClassProperties The script object will not expose properties inherited from the superclass. - \value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties - \value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot. - \value AutoCreateDynamicProperties Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object. - \value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object. - \value SkipMethodsInEnumeration Don't include methods (signals and slots) when enumerating the object's properties. -*/ - -#ifdef QT_NO_QOBJECT - -QScriptEngine::QScriptEngine() - : d_ptr(new QScriptEnginePrivate) -{ - d_ptr->q_ptr = this; - d_ptr->init(); -} - -/*! \internal -*/ -QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd) - : d_ptr(&dd) -{ - d_ptr->q_ptr = this; - d_ptr->init(); -} -#else - -/*! - Constructs a QScriptEngine object. - - The globalObject() is initialized to have properties as described in - \l{ECMA-262}, Section 15.1. -*/ -QScriptEngine::QScriptEngine() - : QObject(*new QScriptEnginePrivate, 0) -{ - Q_D(QScriptEngine); - d->init(); -} - -/*! - Constructs a QScriptEngine object with the given \a parent. - - The globalObject() is initialized to have properties as described in - \l{ECMA-262}, Section 15.1. -*/ - -QScriptEngine::QScriptEngine(QObject *parent) - : QObject(*new QScriptEnginePrivate, parent) -{ - Q_D(QScriptEngine); - d->init(); -} - -/*! \internal -*/ -QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent) - : QObject(dd, parent) -{ - Q_D(QScriptEngine); - d->init(); -} -#endif - -/*! - Destroys this QScriptEngine. -*/ -QScriptEngine::~QScriptEngine() -{ - Q_D(QScriptEngine); - d->m_frameRepository.release(currentContext()); - d->objectAllocator.destruct(); -#ifdef QT_NO_QOBJECT - delete d_ptr; - d_ptr = 0; -#endif -} - -/*! - Returns this engine's Global Object. - - By default, the Global Object contains the built-in objects that are - part of \l{ECMA-262}, such as Math, Date and String. Additionally, - you can set properties of the Global Object to make your own - extensions available to all script code. Non-local variables in - script code will be created as properties of the Global Object, as - well as local variables in global code. -*/ -QScriptValue QScriptEngine::globalObject() const -{ - Q_D(const QScriptEngine); - return const_cast<QScriptEnginePrivate*>(d)->toPublic(d->m_globalObject); -} - -/*! - \since 4.5 - - Sets this engine's Global Object to be the given \a object. - If \a object is not a valid script object, this function does - nothing. - - When setting a custom global object, you may want to use - QScriptValueIterator to copy the properties of the standard Global - Object; alternatively, you can set the internal prototype of your - custom object to be the original Global Object. -*/ -void QScriptEngine::setGlobalObject(const QScriptValue &object) -{ - Q_D(QScriptEngine); - if (!object.isObject()) - return; - QScriptValueImpl objectImpl = d->toImpl(object); - - // update properties of the global context - QScriptValueImpl old = d->m_globalObject; - QScriptContextPrivate *ctx = d->currentContext(); - while (ctx->parentContext() != 0) - ctx = ctx->parentContext(); - if (QScriptEnginePrivate::strictlyEquals(ctx->m_thisObject, old)) - ctx->m_thisObject = objectImpl; - if (QScriptEnginePrivate::strictlyEquals(ctx->m_activation, old)) - ctx->m_activation = objectImpl; - if (QScriptEnginePrivate::strictlyEquals(ctx->m_scopeChain, old)) - ctx->m_scopeChain = objectImpl; - - d->m_globalObject = objectImpl; -} - -/*! - Returns a QScriptValue of the primitive type Null. - - \sa undefinedValue() -*/ -QScriptValue QScriptEngine::nullValue() -{ - Q_D(QScriptEngine); - return d->toPublic(d->nullValue()); -} - -/*! - Returns a QScriptValue of the primitive type Undefined. - - \sa nullValue() -*/ -QScriptValue QScriptEngine::undefinedValue() -{ - Q_D(QScriptEngine); - return d->toPublic(d->undefinedValue()); -} - -/*! - Creates a constructor function from \a fun, with the given \a length. - The \c{prototype} property of the resulting function is set to be the - given \a prototype. The \c{constructor} property of \a prototype is - set to be the resulting function. - - When a function is called as a constructor (e.g. \c{new Foo()}), the - `this' object associated with the function call is the new object - that the function is expected to initialize; the prototype of this - default constructed object will be the function's public - \c{prototype} property. If you always want the function to behave as - a constructor (e.g. \c{Foo()} should also create a new object), or - if you need to create your own object rather than using the default - `this' object, you should make sure that the prototype of your - object is set correctly; either by setting it manually, or, when - wrapping a custom type, by having registered the defaultPrototype() - of that type. Example: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9 - - To wrap a custom type and provide a constructor for it, you'd typically - do something like this: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10 -*/ -QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, - const QScriptValue &prototype, - int length) -{ - Q_D(QScriptEngine); - QScriptValueImpl v = d->createFunction(new QScript::CFunction(fun, length)); - QScriptValueImpl proto = d->toImpl(prototype); - v.setProperty(d->idTable()->id_prototype, proto, - QScriptValue::Undeletable); - proto.setProperty(d->idTable()->id_constructor, v, - QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration); - return d->toPublic(v); -} - -#ifndef QT_NO_REGEXP -/*! - Creates a QtScript object of class RegExp with the given - \a regexp. - - \sa QScriptValue::toRegExp() -*/ -QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp) -{ - Q_D(QScriptEngine); - QScriptValueImpl v; - d->regexpConstructor->newRegExp(&v, regexp); - return d->toPublic(v); -} - -#endif // QT_NO_REGEXP - -/*! - Creates a QtScript object holding the given variant \a value. - - If a default prototype has been registered with the meta type id of - \a value, then the prototype of the created object will be that - prototype; otherwise, the prototype will be the Object prototype - object. - - \sa setDefaultPrototype(), QScriptValue::toVariant() -*/ -QScriptValue QScriptEngine::newVariant(const QVariant &value) -{ - Q_D(QScriptEngine); - QScriptValueImpl result; - d->newVariant(&result, value); - return d->toPublic(result); -} - -/*! - \since 4.4 - \overload - - Initializes the given Qt Script \a object to hold the given variant - \a value, and returns the \a object. - - This function enables you to "promote" a plain Qt Script object - (created by the newObject() function) to a variant, or to replace - the variant contained inside an object previously created by the - newVariant() function. - - The prototype() of the \a object will remain unchanged. - - If \a object is not an object, this function behaves like the normal - newVariant(), i.e. it creates a new script object and returns it. - - This function is useful when you want to provide a script - constructor for a C++ type. If your constructor is invoked in a - \c{new} expression (QScriptContext::isCalledAsConstructor() returns - true), you can pass QScriptContext::thisObject() (the default - constructed script object) to this function to initialize the new - object. -*/ -QScriptValue QScriptEngine::newVariant(const QScriptValue &object, - const QVariant &value) -{ - Q_D(QScriptEngine); - QScriptValuePrivate *p = QScriptValuePrivate::get(object); - if (!p || !p->value.isObject()) - return newVariant(value); - if (p->value.isVariant()) - p->value.setVariantValue(value); - else - d->newVariant(&p->value, value, /*setDefaultPrototype=*/false); - return object; -} - -#ifndef QT_NO_QOBJECT -/*! - Creates a QtScript object that wraps the given QObject \a - object, using the given \a ownership. The given \a options control - various aspects of the interaction with the resulting script object. - - Signals and slots, properties and children of \a object are - available as properties of the created QScriptValue. For more - information, see the \l{QtScript} documentation. - - If \a object is a null pointer, this function returns nullValue(). - - If a default prototype has been registered for the \a object's class - (or its superclass, recursively), the prototype of the new script - object will be set to be that default prototype. - - If the given \a object is deleted outside of QtScript's control, any - attempt to access the deleted QObject's members through the QtScript - wrapper object (either by script code or C++) will result in a - script exception. - - \sa QScriptValue::toQObject() -*/ -QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership, - const QObjectWrapOptions &options) -{ - Q_D(QScriptEngine); - QScriptValueImpl result; - d->newQObject(&result, object, ownership, options); - return d->toPublic(result); -} - -/*! - \since 4.4 - \overload - - Initializes the given \a scriptObject to hold the given \a qtObject, - and returns the \a scriptObject. - - This function enables you to "promote" a plain Qt Script object - (created by the newObject() function) to a QObject proxy, or to - replace the QObject contained inside an object previously created by - the newQObject() function. - - The prototype() of the \a scriptObject will remain unchanged. - - If \a scriptObject is not an object, this function behaves like the - normal newQObject(), i.e. it creates a new script object and returns - it. - - This function is useful when you want to provide a script - constructor for a QObject-based class. If your constructor is - invoked in a \c{new} expression - (QScriptContext::isCalledAsConstructor() returns true), you can pass - QScriptContext::thisObject() (the default constructed script object) - to this function to initialize the new object. -*/ -QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject, - QObject *qtObject, - ValueOwnership ownership, - const QObjectWrapOptions &options) -{ - Q_D(QScriptEngine); - QScriptValuePrivate *p = QScriptValuePrivate::get(scriptObject); - if (!p || !p->value.isObject()) - return newQObject(qtObject, ownership, options); - if (p->value.isQObject()) { - QScript::ExtQObject::Instance *data; - data = d->qobjectConstructor->get(p->value); - Q_ASSERT(data != 0); - data->value = qtObject; - data->ownership = ownership; - data->options = options; - } else { - d->newQObject(&p->value, qtObject, ownership, options, - /*setDefaultPrototype=*/false); - } - return scriptObject; -} - -#endif // QT_NO_QOBJECT - -/*! - Creates a QtScript object of class Object. - - The prototype of the created object will be the Object - prototype object. - - \sa newArray(), QScriptValue::setProperty() -*/ -QScriptValue QScriptEngine::newObject() -{ - Q_D(QScriptEngine); - QScriptValueImpl v; - d->newObject(&v, d->objectConstructor->publicPrototype); - return d->toPublic(v); -} - -/*! - \since 4.4 - \overload - - Creates a QtScript Object of the given class, \a scriptClass. - - The prototype of the created object will be the Object - prototype object. - - \a data, if specified, is set as the internal data of the - new object (using QScriptValue::setData()). - - \sa QScriptValue::scriptClass() -*/ -QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass, - const QScriptValue &data) -{ - Q_D(QScriptEngine); - return d->toPublic(d->newObject(scriptClass, d->toImpl(data))); -} - -/*! - \internal -*/ -QScriptValue QScriptEngine::newActivationObject() -{ - Q_D(QScriptEngine); - QScriptValueImpl v; - d->newActivation(&v); - return d->toPublic(v); -} - -/*! - Creates a QScriptValue that wraps a native (C++) function. \a fun - must be a C++ function with signature QScriptEngine::FunctionSignature. \a - length is the number of arguments that \a fun expects; this becomes - the \c{length} property of the created QScriptValue. - - Note that \a length only gives an indication of the number of - arguments that the function expects; an actual invocation of a - function can include any number of arguments. You can check the - \l{QScriptContext::argumentCount()}{argumentCount()} of the - QScriptContext associated with the invocation to determine the - actual number of arguments passed. - - A \c{prototype} property is automatically created for the resulting - function object, to provide for the possibility that the function - will be used as a constructor. - - By combining newFunction() and the property flags - QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you - can create script object properties that behave like normal - properties in script code, but are in fact accessed through - functions (analogous to how properties work in \l{Qt's Property - System}). Example: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11 - - When the property \c{foo} of the script object is subsequently - accessed in script code, \c{getSetFoo()} will be invoked to handle - the access. In this particular case, we chose to store the "real" - value of \c{foo} as a property of the accessor function itself; you - are of course free to do whatever you like in this function. - - In the above example, a single native function was used to handle - both reads and writes to the property; the argument count is used to - determine if we are handling a read or write. You can also use two - separate functions; just specify the relevant flag - (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when - setting the property, e.g.: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12 - - \sa QScriptValue::call() -*/ -QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length) -{ - Q_D(QScriptEngine); - QScriptValueImpl v = d->createFunction(new QScript::CFunction(fun, length)); - QScriptValueImpl prototype = d->newObject(); - v.setProperty(d->idTable()->id_prototype, prototype, QScriptValue::Undeletable); - prototype.setProperty(d->idTable()->id_constructor, v, - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); - return d->toPublic(v); -} - -/*! - \internal - \since 4.4 -*/ -QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg) -{ - Q_D(QScriptEngine); - QScriptValueImpl v = d->createFunction(new QScript::C3Function(fun, arg, /*length=*/0)); - QScriptValueImpl prototype = d->newObject(); - v.setProperty(d->idTable()->id_prototype, prototype, QScriptValue::Undeletable); - prototype.setProperty(d->idTable()->id_constructor, v, - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); - return d->toPublic(v); -} - -/*! - Creates a QtScript object of class Array with the given \a length. - - \sa newObject() -*/ -QScriptValue QScriptEngine::newArray(uint length) -{ - Q_D(QScriptEngine); - QScriptValueImpl v; - QScript::Array a(d); - a.resize(length); - d->newArray(&v, a); - return d->toPublic(v); -} - -/*! - Creates a QtScript object of class RegExp with the given - \a pattern and \a flags. - - The legal flags are 'g' (global), 'i' (ignore case), and 'm' - (multiline). -*/ -QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags) -{ - Q_D(QScriptEngine); - int bitflags = 0; - for (int i = 0; i < flags.size(); ++i) - bitflags |= QScript::Ecma::RegExp::flagFromChar(flags.at(i)); - QScriptValueImpl v; - d->regexpConstructor->newRegExp(&v, pattern, bitflags); - return d->toPublic(v); -} - -/*! - Creates a QtScript object of class Date with the given - \a value (the number of milliseconds since 01 January 1970, - UTC). -*/ -QScriptValue QScriptEngine::newDate(qsreal value) -{ - Q_D(QScriptEngine); - QScriptValueImpl v; - d->dateConstructor->newDate(&v, value); - return d->toPublic(v); -} - -/*! - Creates a QtScript object of class Date from the given \a value. - - \sa QScriptValue::toDateTime() -*/ -QScriptValue QScriptEngine::newDate(const QDateTime &value) -{ - Q_D(QScriptEngine); - QScriptValueImpl v; - d->dateConstructor->newDate(&v, value); - return d->toPublic(v); -} - -#ifndef QT_NO_QOBJECT -/*! - Creates a QtScript object that represents a QObject class, using the - the given \a metaObject and constructor \a ctor. - - Enums of \a metaObject (declared with Q_ENUMS) are available as - properties of the created QScriptValue. When the class is called as - a function, \a ctor will be called to create a new instance of the - class. - - Example: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 27 - - \sa newQObject(), scriptValueFromQMetaObject() -*/ -QScriptValue QScriptEngine::newQMetaObject( - const QMetaObject *metaObject, const QScriptValue &ctor) -{ - Q_D(QScriptEngine); - QScriptValueImpl v; - d->qmetaObjectConstructor->newQMetaObject(&v, metaObject, d->toImpl(ctor)); - return d->toPublic(v); -} - -/*! - \fn QScriptValue QScriptEngine::scriptValueFromQMetaObject() - - Creates a QScriptValue that represents the Qt class \c{T}. - - This function is used in combination with one of the - Q_SCRIPT_DECLARE_QMETAOBJECT() macro. Example: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13 - - \warning This function is not available with MSVC 6. Use - qScriptValueFromQMetaObject() instead if you need to support that version - of the compiler. - - \sa QScriptEngine::newQMetaObject() -*/ - -/*! - \fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine) - \since 4.3 - \relates QScriptEngine - - Uses \a engine to create a QScriptValue that represents the Qt class - \c{T}. - - This function is equivalent to - QScriptEngine::scriptValueFromQMetaObject(). It is provided as a - work-around for MSVC 6, which doesn't support member template - functions. - - \sa QScriptEngine::newQMetaObject() -*/ -#endif // QT_NO_QOBJECT - -/*! - \obsolete - - Returns true if \a program can be evaluated; i.e. the code is - sufficient to determine whether it appears to be a syntactically - correct program, or contains a syntax error. - - This function returns false if \a program is incomplete; i.e. the - input is syntactically correct up to the point where the input is - terminated. - - Note that this function only does a static check of \a program; - e.g. it does not check whether references to variables are - valid, and so on. - - A typical usage of canEvaluate() is to implement an interactive - interpreter for QtScript. The user is repeatedly queried for - individual lines of code; the lines are concatened internally, and - only when canEvaluate() returns true for the resulting program is it - passed to evaluate(). - - The following are some examples to illustrate the behavior of - canEvaluate(). (Note that all example inputs are assumed to have an - explicit newline as their last character, since otherwise the - QtScript parser would automatically insert a semi-colon character at - the end of the input, and this could cause canEvaluate() to produce - different results.) - - Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 14 - canEvaluate() will return true, since the program appears to be complete. - - Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 15 - canEvaluate() will return false, since the if-statement is not complete, - but is syntactically correct so far. - - Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 16 - canEvaluate() will return true, but evaluate() will throw a - SyntaxError given the same input. - - Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 17 - canEvaluate() will return true, even though the code is clearly not - syntactically valid QtScript code. evaluate() will throw a - SyntaxError when this code is evaluated. - - Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 18 - canEvaluate() will return true, but evaluate() will throw a - ReferenceError if \c{foo} is not defined in the script - environment. - - \sa evaluate(), checkSyntax() -*/ -bool QScriptEngine::canEvaluate(const QString &program) const -{ - return QScriptEnginePrivate::canEvaluate(program); -} - -/*! - \since 4.5 - - Checks the syntax of the given \a program. Returns a - QScriptSyntaxCheckResult object that contains the result of the check. -*/ -QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program) -{ - return QScriptEnginePrivate::checkSyntax(program); -} - -/*! - Evaluates \a program, using \a lineNumber as the base line number, - and returns the result of the evaluation. - - The script code will be evaluated in the current context. - - The evaluation of \a program can cause an exception in the - engine; in this case the return value will be the exception - that was thrown (typically an \c{Error} object). You can call - hasUncaughtException() to determine if an exception occurred in - the last call to evaluate(). - - \a lineNumber is used to specify a starting line number for \a - program; line number information reported by the engine that pertain - to this evaluation (e.g. uncaughtExceptionLineNumber()) will be - based on this argument. For example, if \a program consists of two - lines of code, and the statement on the second line causes a script - exception, uncaughtExceptionLineNumber() would return the given \a - lineNumber plus one. When no starting line number is specified, line - numbers will be 1-based. - - \a fileName is used for error reporting. For example in error objects - the file name is accessible through the "fileName" property if it's - provided with this function. - - \sa checkSyntax(), hasUncaughtException(), isEvaluating(), abortEvaluation() -*/ -QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber) -{ - Q_D(QScriptEngine); - QScriptContextPrivate *ctx_p = d->currentContext(); - d->evaluate(ctx_p, program, lineNumber, fileName); - return d->toPublic(ctx_p->m_result); -} - -/*! - Returns the current context. - - The current context is typically accessed to retrieve the arguments - and `this' object in native functions; for convenience, it is - available as the first argument in QScriptEngine::FunctionSignature. -*/ -QScriptContext *QScriptEngine::currentContext() const -{ - Q_D(const QScriptEngine); - return QScriptContextPrivate::get(d->currentContext()); -} - -/*! - Enters a new execution context and returns the associated - QScriptContext object. - - Once you are done with the context, you should call popContext() to - restore the old context. - - By default, the `this' object of the new context is the Global Object. - The context's \l{QScriptContext::callee()}{callee}() will be invalid. - - This function is useful when you want to evaluate script code - as if it were the body of a function. You can use the context's - \l{QScriptContext::activationObject()}{activationObject}() to initialize - local variables that will be available to scripts. Example: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 19 - - In the above example, the new variable "tmp" defined in the script - will be local to the context; in other words, the script doesn't - have any effect on the global environment. - - \sa popContext() -*/ -QScriptContext *QScriptEngine::pushContext() -{ - Q_D(QScriptEngine); - QScriptContextPrivate *ctx_p = d->pushContext(); - ctx_p->setThisObject(d->globalObject()); - QScriptValueImpl activation; - d->newActivation(&activation); - activation.setScope(d->globalObject()); - ctx_p->setActivationObject(activation); - return QScriptContextPrivate::get(ctx_p); -} - -/*! - Pops the current execution context and restores the previous one. - This function must be used in conjunction with pushContext(). - - \sa pushContext() -*/ -void QScriptEngine::popContext() -{ - Q_D(QScriptEngine); - if (d->currentContext() && d->currentContext()->parentContext()) - d->popContext(); -} - -/*! - Returns true if the last script evaluation resulted in an uncaught - exception; otherwise returns false. - - The exception state is cleared when evaluate() is called. - - \sa uncaughtException(), uncaughtExceptionLineNumber(), - uncaughtExceptionBacktrace() -*/ -bool QScriptEngine::hasUncaughtException() const -{ - Q_D(const QScriptEngine); - return d->hasUncaughtException(); -} - -/*! - Returns the current uncaught exception, or an invalid QScriptValue - if there is no uncaught exception. - - The exception value is typically an \c{Error} object; in that case, - you can call toString() on the return value to obtain an error - message. - - \sa hasUncaughtException(), uncaughtExceptionLineNumber(), - uncaughtExceptionBacktrace() -*/ -QScriptValue QScriptEngine::uncaughtException() const -{ - Q_D(const QScriptEngine); - return const_cast<QScriptEnginePrivate*>(d)->toPublic(d->uncaughtException()); -} - -/*! - Returns the line number where the last uncaught exception occurred. - - Line numbers are 1-based, unless a different base was specified as - the second argument to evaluate(). - - \sa hasUncaughtException(), uncaughtExceptionBacktrace() -*/ -int QScriptEngine::uncaughtExceptionLineNumber() const -{ - return QScriptContextPrivate::get(currentContext())->errorLineNumber; -} - -/*! - Returns a human-readable backtrace of the last uncaught exception. - - Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}. - - \sa uncaughtException() -*/ -QStringList QScriptEngine::uncaughtExceptionBacktrace() const -{ - Q_D(const QScriptEngine); - return d->uncaughtExceptionBacktrace(); -} - -/*! - \since 4.4 - - Clears any uncaught exceptions in this engine. - - \sa hasUncaughtException() -*/ -void QScriptEngine::clearExceptions() -{ - Q_D(QScriptEngine); - d->clearExceptions(); -} - -/*! - Returns the default prototype associated with the given \a metaTypeId, - or an invalid QScriptValue if no default prototype has been set. - - \sa setDefaultPrototype() -*/ -QScriptValue QScriptEngine::defaultPrototype(int metaTypeId) const -{ - Q_D(const QScriptEngine); - return const_cast<QScriptEnginePrivate*>(d)->toPublic(d->defaultPrototype(metaTypeId)); -} - -/*! - Sets the default prototype of the C++ type identified by the given - \a metaTypeId to \a prototype. - - The default prototype provides a script interface for values of - type \a metaTypeId when a value of that type is accessed from script - code. Whenever the script engine (implicitly or explicitly) creates - a QScriptValue from a value of type \a metaTypeId, the default - prototype will be set as the QScriptValue's prototype. - - The \a prototype object itself may be constructed using one of two - principal techniques; the simplest is to subclass QScriptable, which - enables you to define the scripting API of the type through QObject - properties and slots. Another possibility is to create a script - object by calling newObject(), and populate the object with the - desired properties (e.g. native functions wrapped with - newFunction()). - - \sa defaultPrototype(), qScriptRegisterMetaType(), QScriptable, {Default Prototypes Example} -*/ -void QScriptEngine::setDefaultPrototype(int metaTypeId, const QScriptValue &prototype) -{ - Q_D(QScriptEngine); - d->setDefaultPrototype(metaTypeId, d->toImpl(prototype)); -} - -/*! - \typedef QScriptEngine::FunctionSignature - \relates QScriptEngine - - The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}. - - A function with such a signature can be passed to - QScriptEngine::newFunction() to wrap the function. -*/ - -/*! - \typedef QScriptEngine::FunctionWithArgSignature - \relates QScriptEngine - - The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}. - - A function with such a signature can be passed to - QScriptEngine::newFunction() to wrap the function. -*/ - -/*! - \typedef QScriptEngine::MarshalFunction - \internal -*/ - -/*! - \typedef QScriptEngine::DemarshalFunction - \internal -*/ - -/*! - \internal -*/ -QScriptValue QScriptEngine::create(int type, const void *ptr) -{ - Q_D(QScriptEngine); - return d->toPublic(d->create(type, ptr)); -} - -/*! - \internal -*/ -bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr) -{ - Q_D(QScriptEngine); - return QScriptEnginePrivate::convert(d->toImpl(value), type, ptr, d); -} - -/*! - \internal -*/ -bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr) -{ - QScriptValueImpl impl = QScriptValuePrivate::valueOf(value); - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(value.engine()); - return QScriptEnginePrivate::convert(impl, type, ptr, eng_p); -} - -/*! - \internal -*/ -void QScriptEngine::registerCustomType(int type, MarshalFunction mf, - DemarshalFunction df, - const QScriptValue &prototype) -{ - Q_D(QScriptEngine); - QScriptCustomTypeInfo info = d->m_customTypes.value(type); - info.marshal = mf; - info.demarshal = df; - info.prototype = d->toImpl(prototype); - d->m_customTypes.insert(type, info); -} - -/*! - \since 4.5 - - Installs translator functions on the given \a object, or on the Global - Object if no object is specified. - - The relation between Qt Script translator functions and C++ translator - functions is described in the following table: - - \table - \header \o Script Function \o Corresponding C++ Function - \row \o qsTr() \o QObject::tr() - \row \o QT_TR_NOOP() \o QT_TR_NOOP() - \row \o qsTranslate() \o QCoreApplication::translate() - \row \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP() - \endtable - - \sa {Internationalization with Qt} -*/ -void QScriptEngine::installTranslatorFunctions(const QScriptValue &object) -{ - Q_D(QScriptEngine); - QScriptValue target = object.isObject() ? object : globalObject(); - QScriptValueImpl impl = QScriptValuePrivate::valueOf(target); - d->installTranslatorFunctions(impl); -} - -/*! - Imports the given \a extension into this QScriptEngine. Returns - undefinedValue() if the extension was successfully imported. You - can call hasUncaughtException() to check if an error occurred; in - that case, the return value is the value that was thrown by the - exception (usually an \c{Error} object). - - QScriptEngine ensures that a particular extension is only imported - once; subsequent calls to importExtension() with the same extension - name will do nothing and return undefinedValue(). - - \sa availableExtensions(), QScriptExtensionPlugin, {Creating QtScript Extensions} -*/ -QScriptValue QScriptEngine::importExtension(const QString &extension) -{ - Q_D(QScriptEngine); - return d->toPublic(d->importExtension(extension)); -} - -/*! - \since 4.4 - - Returns a list naming the available extensions that can be - imported using the importExtension() function. This list includes - extensions that have been imported. - - \sa importExtension(), importedExtensions() -*/ -QStringList QScriptEngine::availableExtensions() const -{ - Q_D(const QScriptEngine); - return d->availableExtensions(); -} - -/*! - \since 4.4 - - Returns a list naming the extensions that have been imported - using the importExtension() function. - - \sa availableExtensions() -*/ -QStringList QScriptEngine::importedExtensions() const -{ - Q_D(const QScriptEngine); - return d->importedExtensions(); -} - -/*! \fn QScriptValue QScriptEngine::toScriptValue(const T &value) - - Creates a QScriptValue with the given \a value. - - Note that the template type \c{T} must be known to QMetaType. - - See \l{Conversion Between QtScript and C++ Types} for a - description of the built-in type conversion provided by - QtScript. By default, the types that are not specially handled by - QtScript are represented as QVariants (e.g. the \a value is passed - to newVariant()); you can change this behavior by installing your - own type conversion functions with qScriptRegisterMetaType(). - - \warning This function is not available with MSVC 6. Use - qScriptValueFromValue() instead if you need to support that - version of the compiler. - - \sa fromScriptValue(), qScriptRegisterMetaType() -*/ - -/*! \fn T QScriptEngine::fromScriptValue(const QScriptValue &value) - - Returns the given \a value converted to the template type \c{T}. - - Note that \c{T} must be known to QMetaType. - - See \l{Conversion Between QtScript and C++ Types} for a - description of the built-in type conversion provided by - QtScript. - - \warning This function is not available with MSVC 6. Use - qScriptValueToValue() or qscriptvalue_cast() instead if you need - to support that version of the compiler. - - \sa toScriptValue(), qScriptRegisterMetaType() -*/ - -/*! - \fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value) - \since 4.3 - \relates QScriptEngine - - Creates a QScriptValue using the given \a engine with the given \a - value of template type \c{T}. - - This function is equivalent to QScriptEngine::toScriptValue(). - It is provided as a work-around for MSVC 6, which doesn't support - member template functions. - - \sa qScriptValueToValue() -*/ - -/*! - \fn T qScriptValueToValue<T>(const QScriptValue &value) - \since 4.3 - \relates QScriptEngine - - Returns the given \a value converted to the template type \c{T}. - - This function is equivalent to QScriptEngine::fromScriptValue(). - It is provided as a work-around for MSVC 6, which doesn't - support member template functions. - - \sa qScriptValueFromValue() -*/ - -/*! - \fn QScriptValue qScriptValueFromSequence(QScriptEngine *engine, const Container &container) - \since 4.3 - \relates QScriptEngine - - Creates an array in the form of a QScriptValue using the given \a engine - with the given \a container of template type \c{Container}. - - The \c Container type must provide a \c const_iterator class to enable the - contents of the container to be copied into the array. - - Additionally, the type of each element in the sequence should be suitable - for conversion to a QScriptValue. - See \l{Making Applications Scriptable#Conversion Between QtScript and C++ Types} - {Conversion Between QtScript and C++ Types} for more information about the - restrictions on types that can be used with QScriptValue. - - \sa qScriptValueFromValue() -*/ - -/*! - \fn void qScriptValueToSequence(const QScriptValue &value, Container &container) - \since 4.3 - \relates QScriptEngine - - Copies the elements in the sequence specified by \a value to the given - \a container of template type \c{Container}. - - The \a value used is typically an array, but any container can be copied - as long as it provides a \c length property describing how many elements - it contains. - - Additionally, the type of each element in the sequence must be suitable - for conversion to a C++ type from a QScriptValue. - See \l{Making Applications Scriptable#Conversion Between QtScript and C++ Types} - {Conversion Between QtScript and C++ Types} for more information about the - restrictions on types that can be used with QScriptValue. - - \sa qscriptvalue_cast() -*/ - -/*! - \fn T qscriptvalue_cast<T>(const QScriptValue &value) - \since 4.3 - \relates QScriptValue - - Returns the given \a value converted to the template type \c{T}. - - \sa qScriptRegisterMetaType(), QScriptEngine::toScriptValue() -*/ - -/*! \fn int qScriptRegisterMetaType( - QScriptEngine *engine, - QScriptValue (*toScriptValue)(QScriptEngine *, const T &t), - void (*fromScriptValue)(const QScriptValue &, T &t), - const QScriptValue &prototype = QScriptValue()) - \relates QScriptEngine - - Registers the type \c{T} in the given \a engine. \a toScriptValue must - be a function that will convert from a value of type \c{T} to a - QScriptValue, and \a fromScriptValue a function that does the - opposite. \a prototype, if valid, is the prototype that's set on - QScriptValues returned by \a toScriptValue. - - Returns the internal ID used by QMetaType. - - You only need to call this function if you want to provide custom - conversion of values of type \c{T}, i.e. if the default - QVariant-based representation and conversion is not - appropriate. (Note that custom QObject-derived types also fall in - this category; e.g. for a QObject-derived class called MyObject, - you probably want to define conversion functions for MyObject* - that utilize QScriptEngine::newQObject() and - QScriptValue::toQObject().) - - If you only want to define a common script interface for values of - type \c{T}, and don't care how those values are represented - (i.e. storing them in QVariants is fine), use - \l{QScriptEngine::setDefaultPrototype()}{setDefaultPrototype}() - instead; this will minimize conversion costs. - - You need to declare the custom type first with - Q_DECLARE_METATYPE(). - - After a type has been registered, you can convert from a - QScriptValue to that type using - \l{QScriptEngine::fromScriptValue()}{fromScriptValue}(), and - create a QScriptValue from a value of that type using - \l{QScriptEngine::toScriptValue()}{toScriptValue}(). The engine - will take care of calling the proper conversion function when - calling C++ slots, and when getting or setting a C++ property; - i.e. the custom type may be used seamlessly on both the C++ side - and the script side. - - The following is an example of how to use this function. We will - specify custom conversion of our type \c{MyStruct}. Here's the C++ - type: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 20 - - We must declare it so that the type will be known to QMetaType: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 21 - - Next, the \c{MyStruct} conversion functions. We represent the - \c{MyStruct} value as a script object and just copy the properties: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 22 - - Now we can register \c{MyStruct} with the engine: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 23 - - Working with \c{MyStruct} values is now easy: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 24 - - If you want to be able to construct values of your custom type - from script code, you have to register a constructor function for - the type. For example: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 25 - - \sa qScriptRegisterSequenceMetaType(), qRegisterMetaType() -*/ - -/*! - \macro Q_SCRIPT_DECLARE_QMETAOBJECT(QMetaObject, ArgType) - \since 4.3 - \relates QScriptEngine - - Declares the given \a QMetaObject. Used in combination with - QScriptEngine::scriptValueFromQMetaObject() to make enums and - instantiation of \a QMetaObject available to script code. The - constructor generated by this macro takes a single argument of - type \a ArgType; typically the argument is the parent type of the - new instance, in which case \a ArgType is \c{QWidget*} or - \c{QObject*}. Objects created by the constructor will have - QScriptEngine::AutoOwnership ownership. -*/ - -/*! \fn int qScriptRegisterSequenceMetaType( - QScriptEngine *engine, - const QScriptValue &prototype = QScriptValue()) - \relates QScriptEngine - - Registers the sequence type \c{T} in the given \a engine. This - function provides conversion functions that convert between \c{T} - and Qt Script \c{Array} objects. \c{T} must provide a - const_iterator class and begin(), end() and push_back() - functions. If \a prototype is valid, it will be set as the - prototype of \c{Array} objects due to conversion from \c{T}; - otherwise, the standard \c{Array} prototype will be used. - - Returns the internal ID used by QMetaType. - - You need to declare the container type first with - Q_DECLARE_METATYPE(). If the element type isn't a standard Qt/C++ - type, it must be declared using Q_DECLARE_METATYPE() as well. - Example: - - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 26 - - \sa qScriptRegisterMetaType() -*/ - -/*! - Runs the garbage collector. - - The garbage collector will attempt to reclaim memory by locating and - disposing of objects that are no longer reachable in the script - environment. - - Normally you don't need to call this function; the garbage collector - will automatically be invoked when the QScriptEngine decides that - it's wise to do so (i.e. when a certain number of new objects have - been created). However, you can call this function to explicitly - request that garbage collection should be performed as soon as - possible. -*/ -void QScriptEngine::collectGarbage() -{ - Q_D(QScriptEngine); - d->gc(); -} - -/*! - - Sets the interval between calls to QCoreApplication::processEvents - to \a interval milliseconds. - - While the interpreter is running, all event processing is by default - blocked. This means for instance that the gui will not be updated - and timers will not be fired. To allow event processing during - interpreter execution one can specify the processing interval to be - a positive value, indicating the number of milliseconds between each - time QCoreApplication::processEvents() is called. - - The default value is -1, which disables event processing during - interpreter execution. - - You can use QCoreApplication::postEvent() to post an event that - performs custom processing at the next interval. For example, you - could keep track of the total running time of the script and call - abortEvaluation() when you detect that the script has been running - for a long time without completing. - - \sa processEventsInterval() -*/ -void QScriptEngine::setProcessEventsInterval(int interval) -{ - Q_D(QScriptEngine); - d->m_processEventsInterval = interval; -} - -/*! - - Returns the interval in milliseconds between calls to - QCoreApplication::processEvents() while the interpreter is running. - - \sa setProcessEventsInterval() -*/ -int QScriptEngine::processEventsInterval() const -{ - Q_D(const QScriptEngine); - return d->m_processEventsInterval; -} - -/*! - \since 4.4 - - Returns true if this engine is currently evaluating a script, - otherwise returns false. - - \sa evaluate(), abortEvaluation() -*/ -bool QScriptEngine::isEvaluating() const -{ - Q_D(const QScriptEngine); - return d->m_evaluating; -} - -/*! - \since 4.4 - - Aborts any script evaluation currently taking place in this engine. - The given \a result is passed back as the result of the evaluation - (i.e. it is returned from the call to evaluate() being aborted). - - If the engine isn't evaluating a script (i.e. isEvaluating() returns - false), this function does nothing. - - Call this function if you need to abort a running script for some - reason, e.g. when you have detected that the script has been - running for several seconds without completing. - - \sa evaluate(), isEvaluating(), setProcessEventsInterval() -*/ -void QScriptEngine::abortEvaluation(const QScriptValue &result) -{ - Q_D(QScriptEngine); - d->abortEvaluation(d->toImpl(result)); -} - -#ifndef QT_NO_QOBJECT - -/*! - \since 4.4 - \relates QScriptEngine - - Creates a connection from the \a signal in the \a sender to the - given \a function. If \a receiver is an object, it will act as the - `this' object when the signal handler function is invoked. Returns - true if the connection succeeds; otherwise returns false. - - \sa qScriptDisconnect(), QScriptEngine::signalHandlerException() -*/ -bool qScriptConnect(QObject *sender, const char *signal, - const QScriptValue &receiver, const QScriptValue &function) -{ - if (!sender || !signal) - return false; - if (!function.isFunction()) - return false; - if (receiver.isObject() && (receiver.engine() != function.engine())) - return false; - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(function.engine()); - return eng_p->scriptConnect(sender, signal, - eng_p->toImpl(receiver), - eng_p->toImpl(function), - Qt::AutoConnection); -} - -/*! - \since 4.4 - \relates QScriptEngine - - Disconnects the \a signal in the \a sender from the given (\a - receiver, \a function) pair. Returns true if the connection is - successfully broken; otherwise returns false. - - \sa qScriptConnect() -*/ -bool qScriptDisconnect(QObject *sender, const char *signal, - const QScriptValue &receiver, const QScriptValue &function) -{ - if (!sender || !signal) - return false; - if (!function.isFunction()) - return false; - if (receiver.isObject() && (receiver.engine() != function.engine())) - return false; - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(function.engine()); - return eng_p->scriptDisconnect(sender, signal, - eng_p->toImpl(receiver), - eng_p->toImpl(function)); -} - -/*! - \since 4.4 - \fn void QScriptEngine::signalHandlerException(const QScriptValue &exception) - - This signal is emitted when a script function connected to a signal causes - an \a exception. - - \sa qScriptConnect() -*/ - -QT_BEGIN_INCLUDE_NAMESPACE -#include "moc_qscriptengine.cpp" -QT_END_INCLUDE_NAMESPACE - -#endif // QT_NO_QOBJECT - -/*! - \since 4.4 - - Installs the given \a agent on this engine. The agent will be - notified of various events pertaining to script execution. This is - useful when you want to find out exactly what the engine is doing, - e.g. when evaluate() is called. The agent interface is the basis of - tools like debuggers and profilers. - - The engine maintains ownership of the \a agent. - - Calling this function will replace the existing agent, if any. - - \sa agent() -*/ -void QScriptEngine::setAgent(QScriptEngineAgent *agent) -{ - Q_D(QScriptEngine); - d->setAgent(agent); -} - -/*! - \since 4.4 - - Returns the agent currently installed on this engine, or 0 if no - agent is installed. - - \sa setAgent() -*/ -QScriptEngineAgent *QScriptEngine::agent() const -{ - Q_D(const QScriptEngine); - return d->agent(); -} - -/*! - \since 4.4 - - Returns a handle that represents the given string, \a str. - - QScriptString can be used to quickly look up properties, and - compare property names, of script objects. - - \sa QScriptValue::property() -*/ -QScriptString QScriptEngine::toStringHandle(const QString &str) -{ - Q_D(QScriptEngine); - return d->internedString(str); -} - -/*! - \since 4.5 - - Converts the given \a value to an object, if such a conversion is - possible; otherwise returns an invalid QScriptValue. The conversion - is performed according to the following table: - - \table - \header \o Input Type \o Result - \row \o Undefined \o An invalid QScriptValue. - \row \o Null \o An invalid QScriptValue. - \row \o Boolean \o A new Boolean object whose internal value is set to the value of the boolean. - \row \o Number \o A new Number object whose internal value is set to the value of the number. - \row \o String \o A new String object whose internal value is set to the value of the string. - \row \o Object \o The result is the object itself (no conversion). - \endtable - - \sa newObject() -*/ -QScriptValue QScriptEngine::toObject(const QScriptValue &value) -{ - Q_D(QScriptEngine); - return d->toPublic(d->toObject(d->toImpl(value))); -} - -/*! - \internal - - Returns the object with the given \a id, or an invalid - QScriptValue if there is no object with that id. - - \sa QScriptValue::objectId() -*/ -QScriptValue QScriptEngine::objectById(qint64 id) const -{ - Q_D(const QScriptEngine); - return const_cast<QScriptEnginePrivate*>(d)->toPublic(d->objectById(id)); -} - -/*! - \since 4.5 - \class QScriptSyntaxCheckResult - - \brief The QScriptSyntaxCheckResult class provides the result of a script syntax check. - - \ingroup script - - - QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to - provide information about the syntactical (in)correctness of a script. -*/ - -/*! - \enum QScriptSyntaxCheckResult::State - - This enum specifies the state of a syntax check. - - \value Error The program contains a syntax error. - \value Intermediate The program is incomplete. - \value Valid The program is a syntactically correct Qt Script program. -*/ - -/*! - Constructs a new QScriptSyntaxCheckResult from the \a other result. -*/ -QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult &other) - : d_ptr(other.d_ptr) -{ - if (d_ptr) - d_ptr->ref.ref(); -} - -/*! - \internal -*/ -QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate *d) - : d_ptr(d) -{ - if (d_ptr) - d_ptr->ref.ref(); -} - -/*! - \internal -*/ -QScriptSyntaxCheckResult::QScriptSyntaxCheckResult() - : d_ptr(0) -{ -} - -/*! - Destroys this QScriptSyntaxCheckResult. -*/ -QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult() -{ - if (d_ptr && !d_ptr->ref.deref()) { - delete d_ptr; - d_ptr = 0; - } -} - -/*! - Returns the state of this QScriptSyntaxCheckResult. -*/ -QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const -{ - Q_D(const QScriptSyntaxCheckResult); - return d->state; -} - -/*! - Returns the error line number of this QScriptSyntaxCheckResult, or -1 if - there is no error. - - \sa state(), errorMessage() -*/ -int QScriptSyntaxCheckResult::errorLineNumber() const -{ - Q_D(const QScriptSyntaxCheckResult); - return d->errorLineNumber; -} - -/*! - Returns the error column number of this QScriptSyntaxCheckResult, or -1 if - there is no error. - - \sa state(), errorLineNumber() -*/ -int QScriptSyntaxCheckResult::errorColumnNumber() const -{ - Q_D(const QScriptSyntaxCheckResult); - return d->errorColumnNumber; -} - -/*! - Returns the error message of this QScriptSyntaxCheckResult, or an empty - string if there is no error. - - \sa state(), errorLineNumber() -*/ -QString QScriptSyntaxCheckResult::errorMessage() const -{ - Q_D(const QScriptSyntaxCheckResult); - return d->errorMessage; -} - -/*! - Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a - reference to this QScriptSyntaxCheckResult. -*/ -QScriptSyntaxCheckResult &QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult &other) -{ - if (d_ptr == other.d_ptr) - return *this; - if (d_ptr && !d_ptr->ref.deref()) { - delete d_ptr; - d_ptr = 0; - } - d_ptr = other.d_ptr; - if (d_ptr) - d_ptr->ref.ref(); - return *this; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptengine_p.cpp b/src/script/qscriptengine_p.cpp deleted file mode 100644 index 8f64512..0000000 --- a/src/script/qscriptengine_p.cpp +++ /dev/null @@ -1,2732 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptengine_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptlexer_p.h" -#include "qscriptnodepool_p.h" -#include "qscriptparser_p.h" -#include "qscriptcompiler_p.h" -#include "qscriptvalueiteratorimpl_p.h" -#include "qscriptecmaglobal_p.h" -#include "qscriptecmamath_p.h" -#include "qscriptecmaarray_p.h" -#include "qscriptextenumeration_p.h" -#include "qscriptsyntaxchecker_p.h" -#include "qscriptsyntaxcheckresult_p.h" -#include "qscriptclass.h" -#include "qscriptclass_p.h" -#include "qscriptengineagent.h" - -#include <QtCore/QDate> -#include <QtCore/QDateTime> -#include <QtCore/QRegExp> -#include <QtCore/QStringList> -#include <QtCore/QVariant> - -#ifndef QT_NO_QOBJECT -#include "qscriptextensioninterface.h" -#include <QtCore/QDir> -#include <QtCore/QFile> -#include <QtCore/QFileInfo> -#include <QtCore/QTextStream> -#include <QtCore/QCoreApplication> -#include <QtCore/QPluginLoader> -#endif - -Q_DECLARE_METATYPE(QScriptValue) -#ifndef QT_NO_QOBJECT -Q_DECLARE_METATYPE(QObjectList) -#endif -Q_DECLARE_METATYPE(QList<int>) - -QT_BEGIN_NAMESPACE - -extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str); -extern double qstrtod(const char *s00, char const **se, bool *ok); - -namespace QScript { - -QString numberToString(qsreal value) -{ - if (qIsNaN(value)) - return QLatin1String("NaN"); - - else if (qIsInf(value)) - return QLatin1String(value < 0 ? "-Infinity" : "Infinity"); - - else if (value == 0) - return QLatin1String("0"); - - QByteArray buf; - buf.reserve(80); - - int decpt; - int sign; - char *result = 0; - (void) qdtoa(value, 0, 0, &decpt, &sign, 0, &result); - - if (! result) - return QString(); - - else if (decpt <= 0 && decpt > -6) { - - buf.fill('0', -decpt + 2 + sign); - - if (sign) // fix the sign. - buf[0] = '-'; - - buf[sign + 1] = '.'; - buf += result; - } - - else { - if (sign) - buf += '-'; - - buf += result; - int length = buf.length() - sign; - - if (decpt <= 21 && decpt > 0) { - if (length <= decpt) - buf += QByteArray().fill('0', decpt - length); - else - buf.insert(decpt + sign, '.'); - } - - else if (result[0] >= '0' && result[0] <= '9') { - if (length > 1) - buf.insert(1 + sign, '.'); - - buf += 'e'; - buf += (decpt >= 0) ? '+' : '-'; - - int e = decpt - 1; - - if (e < 0) - e = -e; - - if (e >= 100) - buf += '0' + e / 100; - - if (e >= 10) - buf += '0' + (e % 100) / 10; - - buf += '0' + e % 10; - } - } - - free(result); - - return QString::fromLatin1(buf); -} - -static int toDigit(char c) -{ - if ((c >= '0') && (c <= '9')) - return c - '0'; - else if ((c >= 'a') && (c <= 'z')) - return 10 + c - 'a'; - else if ((c >= 'A') && (c <= 'Z')) - return 10 + c - 'A'; - return -1; -} - -qsreal integerFromString(const char *buf, int size, int radix) -{ - if (size == 0) - return qSNaN(); - - qsreal sign = 1.0; - int i = 0; - if (buf[0] == '+') { - ++i; - } else if (buf[0] == '-') { - sign = -1.0; - ++i; - } - - if (((size-i) >= 2) && (buf[i] == '0')) { - if (((buf[i+1] == 'x') || (buf[i+1] == 'X')) - && (radix < 34)) { - if ((radix != 0) && (radix != 16)) - return 0; - radix = 16; - i += 2; - } else { - if (radix == 0) { - radix = 8; - ++i; - } - } - } else if (radix == 0) { - radix = 10; - } - - int j = i; - for ( ; i < size; ++i) { - int d = toDigit(buf[i]); - if ((d == -1) || (d >= radix)) - break; - } - qsreal result; - if (j == i) { - if (!qstrcmp(buf, "Infinity")) - result = qInf(); - else - result = qSNaN(); - } else { - result = 0; - qsreal multiplier = 1; - for (--i ; i >= j; --i, multiplier *= radix) - result += toDigit(buf[i]) * multiplier; - } - result *= sign; - return result; -} - -qsreal integerFromString(const QString &str, int radix) -{ - QByteArray ba = str.trimmed().toUtf8(); - return integerFromString(ba.constData(), ba.size(), radix); -} - -qsreal numberFromString(const QString &repr) -{ - QString str = repr.trimmed(); - if ((str.length() > 2) && (str.at(0) == QLatin1Char('0')) && (str.at(1).toUpper() == QLatin1Char('X'))) - return integerFromString(str.mid(2), 16); - QByteArray latin1 = str.toLatin1(); - const char *data = latin1.constData(); - const char *eptr = 0; - qsreal result = qstrtod(data, &eptr, 0); - if (eptr == data) { - if (str == QLatin1String("Infinity")) - result = +qInf(); - else if (str == QLatin1String("+Infinity")) - result = +qInf(); - else if (str == QLatin1String("-Infinity")) - result = -qInf(); - else if (str.isEmpty()) - result = 0; - else - result = qSNaN(); - } else if (eptr != (data + latin1.length())) { - result = qSNaN(); - } - return result; -} - -NodePool::NodePool(const QString &fileName, QScriptEnginePrivate *engine) - : m_fileName(fileName), m_engine(engine) -{ -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - m_id = engine->nextScriptId(); -#endif -} - -NodePool::~NodePool() -{ - qDeleteAll(m_codeCache); - m_codeCache.clear(); - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - m_engine->notifyScriptUnload(id()); -#endif -} - -Code *NodePool::createCompiledCode(AST::Node *node, CompilationUnit &compilation) -{ - QHash<AST::Node*, Code*>::const_iterator it = m_codeCache.constFind(node); - if (it != m_codeCache.constEnd()) - return it.value(); - - Code *code = new Code(); - code->init(compilation, this); - - m_codeCache.insert(node, code); - return code; -} - -class EvalFunction : public QScriptFunction -{ -public: - EvalFunction(QScriptEnginePrivate *) - { length = 1; } - - virtual ~EvalFunction() {} - - void evaluate(QScriptContextPrivate *context, const QString &contents, - int lineNo, const QString &fileName, bool calledFromScript) - { - QScriptEnginePrivate *eng_p = context->engine(); - - QExplicitlySharedDataPointer<NodePool> pool; - pool = new NodePool(fileName, eng_p); - eng_p->setNodePool(pool.data()); - - QString errorMessage; - int errorLineNumber; - AST::Node *program = eng_p->createAbstractSyntaxTree( - contents, lineNo, &errorMessage, &errorLineNumber); - - eng_p->setNodePool(0); - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyScriptLoad(pool->id(), contents, fileName, lineNo); -#endif - - Code *code = 0; - if (program) { - Compiler compiler(eng_p); - compiler.setTopLevelCompiler(true); - CompilationUnit compilation = compiler.compile(program); - if (!compilation.isValid()) { - errorMessage = compilation.errorMessage(); - errorLineNumber = compilation.errorLineNumber(); - } else { - code = pool->createCompiledCode(program, compilation); - } - } - - if (!code) { - context->errorLineNumber = errorLineNumber; - context->currentLine = errorLineNumber; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - Code *oldCode = context->m_code; - Code dummy; - dummy.astPool = pool.data(); - context->m_code = &dummy; // so agents get the script ID - bool wasEvaluating = eng_p->m_evaluating; - eng_p->m_evaluating = true; - eng_p->notifyFunctionEntry(context); -#endif - context->throwError(QScriptContext::SyntaxError, errorMessage); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionExit(context); - eng_p->m_evaluating = wasEvaluating; - context->m_code = oldCode; -#endif - return; - } - - if (calledFromScript) { - if (QScriptContextPrivate *pc = context->parentContext()) { - context->setActivationObject(pc->activationObject()); - context->setThisObject(pc->thisObject()); - context->m_scopeChain = pc->m_scopeChain; - } - } - - const QScriptInstruction *iPtr = context->instructionPointer(); - context->execute(code); - context->setInstructionPointer(iPtr); - } - - virtual void execute(QScriptContextPrivate *context) - { - QScriptEnginePrivate *eng = context->engine(); - int lineNo = context->currentLine; - if (lineNo == -1) { - QScriptContextPrivate *pc = context->parentContext(); - if (pc) - lineNo = pc->currentLine; - else - lineNo = 1; - } - QString fileName; // don't set this for now, we don't want to change the official eval() for now. - - if (context->argumentCount() == 0) { - context->setReturnValue(eng->undefinedValue()); - } else { - QScriptValueImpl arg = context->argument(0); - if (arg.isString()) { - QString contents = arg.toString(); - evaluate(context, contents, lineNo, fileName, /*calledFromScript=*/true); - } else { - context->setReturnValue(arg); - } - } - } - - QString functionName() const - { - return QLatin1String("eval"); - } -}; - -class ArgumentsClassData: public QScriptClassData -{ - -public: - - static inline QScript::ArgumentsObjectData *get(const QScriptValueImpl &object) - { return static_cast<QScript::ArgumentsObjectData*>(object.objectData()); } - - virtual bool resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode access); - virtual bool get(const QScriptValueImpl &object, const QScript::Member &member, - QScriptValueImpl *out_value); - virtual bool put(QScriptValueImpl *object, const QScript::Member &member, - const QScriptValueImpl &value); - virtual void mark(const QScriptValueImpl &object, int generation); - virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object); -}; - -class ArgumentsClassDataIterator: public QScriptClassDataIterator -{ -public: - ArgumentsClassDataIterator(ArgumentsObjectData *data); - virtual ~ArgumentsClassDataIterator(); - - virtual bool hasNext() const; - virtual void next(QScript::Member *member); - - virtual bool hasPrevious() const; - virtual void previous(QScript::Member *member); - - virtual void toFront(); - virtual void toBack(); - -private: - ArgumentsObjectData *m_data; - uint m_pos; -}; - -bool ArgumentsClassData::resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode /*access*/) -{ - QString propertyName = object.engine()->toString(nameId); - bool isNumber; - quint32 index = propertyName.toUInt(&isNumber); - if (isNumber) { - QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object); - if (index < data->length) { - member->native(/*nameId=*/0, index, QScriptValue::SkipInEnumeration); - *base = object; - return true; - } - } - - return false; -} - -bool ArgumentsClassData::get(const QScriptValueImpl &object, const QScript::Member &member, - QScriptValueImpl *out_value) -{ - QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object); - if (member.nameId() == 0) { - QScriptObject *activation_data = data->activation.objectValue(); - *out_value = activation_data->m_values[member.id()]; - return true; - } - return false; -} - -bool ArgumentsClassData::put(QScriptValueImpl *object, const QScript::Member &member, - const QScriptValueImpl &value) -{ - Q_ASSERT(member.nameId() == 0); - QScript::ArgumentsObjectData *data = ArgumentsClassData::get(*object); - QScriptObject *activation_data = data->activation.objectValue(); - activation_data->m_values[member.id()] = value; - return true; -} - -void ArgumentsClassData::mark(const QScriptValueImpl &object, int generation) -{ - QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object); - data->activation.mark(generation); -} - -QScriptClassDataIterator *ArgumentsClassData::newIterator(const QScriptValueImpl &object) -{ - QScript::ArgumentsObjectData *data = ArgumentsClassData::get(object); - return new ArgumentsClassDataIterator(data); -} - -ArgumentsClassDataIterator::ArgumentsClassDataIterator(ArgumentsObjectData *data) - : m_data(data), m_pos(0) -{ -} - -ArgumentsClassDataIterator::~ArgumentsClassDataIterator() -{ -} - -bool ArgumentsClassDataIterator::hasNext() const -{ - return m_pos < m_data->length; -} - -void ArgumentsClassDataIterator::next(QScript::Member *member) -{ - if (m_pos == m_data->length) { - member->invalidate(); - } else { - member->native(/*nameId=*/0, m_pos, QScriptValue::SkipInEnumeration); - ++m_pos; - } -} - -bool ArgumentsClassDataIterator::hasPrevious() const -{ - return (m_pos != 0); -} - -void ArgumentsClassDataIterator::previous(QScript::Member *member) -{ - if (m_pos == 0) { - member->invalidate(); - } else { - --m_pos; - member->native(/*nameId=*/0, m_pos, QScriptValue::SkipInEnumeration); - } -} - -void ArgumentsClassDataIterator::toFront() -{ - m_pos = 0; -} - -void ArgumentsClassDataIterator::toBack() -{ - m_pos = m_data->length; -} - -} // namespace QScript - -const qsreal QScriptEnginePrivate::D16 = 65536.0; -const qsreal QScriptEnginePrivate::D32 = 4294967296.0; - -QScriptEnginePrivate::~QScriptEnginePrivate() -{ - while (!m_agents.isEmpty()) - delete m_agents.takeFirst(); - - // invalidate values that we have references to - { - QHash<QScriptObject*, QScriptValuePrivate*>::const_iterator it; - for (it = m_objectHandles.constBegin(); it != m_objectHandles.constEnd(); ++it) - (*it)->invalidate(); - } - { - QHash<QScriptNameIdImpl*, QScriptValuePrivate*>::const_iterator it; - for (it = m_stringHandles.constBegin(); it != m_stringHandles.constEnd(); ++it) - (*it)->invalidate(); - } - { - QVector<QScriptValuePrivate*>::const_iterator it; - for (it = m_otherHandles.constBegin(); it != m_otherHandles.constEnd(); ++it) - (*it)->invalidate(); - } - - // invalidate interned strings that are known to the outside world - { - QHash<QScriptNameIdImpl*, QScriptStringPrivate*>::const_iterator it; - for (it = m_internedStrings.constBegin(); it != m_internedStrings.constEnd(); ++it) - it.value()->nameId = 0; - } - - delete[] m_string_hash_base; - qDeleteAll(m_stringRepository); - qDeleteAll(m_tempStringRepository); - - if (tempStackBegin) - delete[] tempStackBegin; - -#ifndef QT_NO_QOBJECT - deletePendingQObjects(); - qDeleteAll(m_qobjectData); -# ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - qDeleteAll(m_cachedMetaObjects); -# endif -#endif - - qDeleteAll(m_allocated_classes); -} - -QScript::AST::Node *QScriptEnginePrivate::changeAbstractSyntaxTree(QScript::AST::Node *prg) -{ - QScript::AST::Node *was = m_abstractSyntaxTree; - m_abstractSyntaxTree = prg; - return was; -} - -QScript::AST::Node *QScriptEnginePrivate::createAbstractSyntaxTree( - const QString &source, int lineNumber, QString *errorMessage, int *errorLineNumber) -{ - QScript::Lexer lex(this); - setLexer(&lex); - lex.setCode(source, lineNumber); - - QScriptParser parser; - - if (! parser.parse(this)) { - if (errorMessage) - *errorMessage = parser.errorMessage(); - if (errorLineNumber) - *errorLineNumber = parser.errorLineNumber(); - return 0; - } - - return abstractSyntaxTree(); -} - -void QScriptEnginePrivate::markObject(const QScriptValueImpl &object, int generation) -{ - QScriptObject *instance = object.objectValue(); - QScript::GCBlock *block = QScript::GCBlock::get(instance); - - enum { MAX_GC_DEPTH = 32 }; - - if (block->generation + 1 != generation) - return; - - if (m_gc_depth >= MAX_GC_DEPTH) { - // do the marking later - m_markStack.append(object); - return; - } - - ++block->generation; - ++m_gc_depth; - - if (QScriptClassData *data = object.classInfo()->data()) - data->mark(object, generation); - - if (instance->m_prototype.isObject()) - markObject(instance->m_prototype, generation); - - if (instance->m_scope.isObject()) - markObject(instance->m_scope, generation); - - const QScriptValueImpl &internalValue = instance->m_internalValue; - - if (internalValue.isValid()) { - if (internalValue.isObject()) - markObject(internalValue, generation); - - else if (internalValue.isString()) - markString(internalValue.m_string_value, generation); - } - - int garbage = 0; - - for (int i = 0; i < instance->memberCount(); ++i) { - QScript::Member m; - instance->member(i, &m); - - if (! m.isValid()) { - ++garbage; - continue; - } - - Q_ASSERT(m.isObjectProperty()); - - QScriptValueImpl child; - instance->get(m, &child); - - if (m.nameId()) - markString(m.nameId(), generation); - - if (! child.isValid()) - continue; - - else if (child.isObject()) - markObject(child, generation); - - else if (child.isString()) - markString(child.m_string_value, generation); - } - - --m_gc_depth; - - if (garbage < 128) // ### - return; - - int j = 0; - for (int i = 0; i < instance->memberCount(); ++i) { - QScript::Member m; - instance->member(i, &m); - - if (! m.isValid()) - continue; - - if (i != j) { - instance->m_members[j].object(m.nameId(), j, m.flags()); - instance->m_values[j] = instance->m_values[i]; - } - ++j; - } - //qDebug() << "==> old:" << instance->m_members.size() << "new:" << j; - instance->m_members.resize(j); - instance->m_values.resize(j); -} - -void QScriptEnginePrivate::markFrame(QScriptContextPrivate *context, int generation) -{ - QScriptValueImpl activation = context->activationObject(); - QScriptValueImpl thisObject = context->thisObject(); - QScriptValueImpl scopeChain = context->m_scopeChain; - QScriptValueImpl callee = context->m_callee; - QScriptValueImpl arguments = context->m_arguments; - - if (activation.isObject()) - markObject(activation, generation); - - if (scopeChain.isObject()) - markObject(scopeChain, generation); - - if (thisObject.isObject()) - markObject(thisObject, generation); - - if (callee.isObject()) - markObject(callee, generation); - - if (arguments.isObject()) - markObject(arguments, generation); - - if (context->returnValue().isValid()) { - if (context->returnValue().isObject()) - markObject(context->returnValue(), generation); - - else if (context->returnValue().isString()) - markString(context->returnValue().m_string_value, generation); - } - - if (context->baseStackPointer() != context->currentStackPointer()) { - // mark the temp stack - - for (const QScriptValueImpl *it = context->baseStackPointer(); it != (context->currentStackPointer() + 1); ++it) { - if (! it) { - qWarning() << "no temp stack!!!"; - break; - } - - else if (! it->isValid()) // ### assert? - continue; - - else if (it->isObject()) - markObject(*it, generation); - - else if (it->isString()) - markString(it->m_string_value, generation); - } - } -} - -bool QScriptEnginePrivate::isCollecting() const -{ - return (m_gc_depth != -1) || objectAllocator.sweeping(); -} - -void QScriptEnginePrivate::maybeGC_helper(bool do_string_gc) -{ - // qDebug() << "==>" << objectAllocator.newAllocatedBlocks() << "free:" << objectAllocator.freeBlocks(); - Q_ASSERT(m_gc_depth == -1); - ++m_gc_depth; - - int generation = m_objectGeneration + 1; - - markObject(m_globalObject, generation); - - objectConstructor->mark(this, generation); - numberConstructor->mark(this, generation); - booleanConstructor->mark(this, generation); - stringConstructor->mark(this, generation); - dateConstructor->mark(this, generation); - functionConstructor->mark(this, generation); - arrayConstructor->mark(this, generation); - regexpConstructor->mark(this, generation); - errorConstructor->mark(this, generation); - enumerationConstructor->mark(this, generation); - variantConstructor->mark(this, generation); -#ifndef QT_NO_QOBJECT - qobjectConstructor->mark(this, generation); - qmetaObjectConstructor->mark(this, generation); -#endif - - { - QScriptContextPrivate *current = currentContext(); - while (current != 0) { - markFrame (current, generation); - current = current->parentContext(); - } - } - - { - QHash<QScriptObject*, QScriptValuePrivate*>::const_iterator it; - for (it = m_objectHandles.constBegin(); it != m_objectHandles.constEnd(); ++it) - markObject((*it)->value, generation); - } - - { - QHash<QScriptNameIdImpl*, QScriptValuePrivate*>::const_iterator it; - for (it = m_stringHandles.constBegin(); it != m_stringHandles.constEnd(); ++it) - markString((*it)->value.stringValue(), generation); - } - - { - QHash<int, QScriptCustomTypeInfo>::const_iterator it; - for (it = m_customTypes.constBegin(); it != m_customTypes.constEnd(); ++it) - (*it).prototype.mark(generation); - } - -#ifndef QT_NO_QOBJECT -# ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - { - QHash<const QMetaObject*, QScriptMetaObject*>::const_iterator it; - for (it = m_cachedMetaObjects.constBegin(); it != m_cachedMetaObjects.constEnd(); ++it) { - { - QList<QScriptNameIdImpl*> memberNames = (*it)->registeredMemberNames(); - QList<QScriptNameIdImpl*>::const_iterator it2; - for (it2 = memberNames.constBegin(); it2 != memberNames.constEnd(); ++it2) - markString(*it2, generation); - } - { - QList<QScriptValueImpl> propertyAccessors = (*it)->registeredPropertyAccessors(); - QList<QScriptValueImpl>::const_iterator it2; - for (it2 = propertyAccessors.constBegin(); it2 != propertyAccessors.constEnd(); ++it2) - markObject(*it2, generation); - } - } - } -# endif - processMarkStack(generation); // make sure everything is marked before marking qobject data - { - QHash<QObject*, QScriptQObjectData*>::const_iterator it; - for (it = m_qobjectData.constBegin(); it != m_qobjectData.constEnd(); ++it) { - QScriptQObjectData *qdata = it.value(); - qdata->mark(generation); - } - } -#endif - processMarkStack(generation); - - Q_ASSERT(m_gc_depth == 0); - --m_gc_depth; - - objectAllocator.sweep(generation); - - m_objectGeneration = generation; - - //qDebug() << "free blocks:" << objectAllocator.freeBlocks(); - -#ifndef QT_NO_QOBJECT - deletePendingQObjects(); -#endif - - if (! do_string_gc) - return; - - { - QHash<QScriptNameIdImpl*, QScriptStringPrivate*>::const_iterator it; - for (it = m_internedStrings.constBegin(); it != m_internedStrings.constEnd(); ++it) { - it.value()->nameId->used = true; - } - } - -#if 0 - qDebug() << "do_string_gc:" << do_string_gc - << ((m_stringRepository.size() - m_oldStringRepositorySize) > 256) - << ((m_tempStringRepository.size() - m_oldTempStringRepositorySize) > 2048); -#endif - - QVector<QScriptNameIdImpl*> compressed; - compressed.reserve(m_stringRepository.size()); - - for (int i = 0; i < m_stringRepository.size(); ++i) { - QScriptNameIdImpl *entry = m_stringRepository.at(i); - - if (entry->used || entry->persistent) { - compressed.append(entry); - entry->used = false; - } - - else { - //qDebug() << "deleted unique:" << entry->s; - delete entry; - } - } - - // qDebug() << "before:" << m_stringRepository.size() << "after:" << compressed.size() << globalObject.objectValue()->m_members.size(); - m_stringRepository = compressed; - rehashStringRepository(/*resize=*/ false); - m_oldStringRepositorySize = m_stringRepository.size(); - m_newAllocatedStringRepositoryChars = 0; - - compressed.clear(); - for (int i = 0; i < m_tempStringRepository.size(); ++i) { - QScriptNameIdImpl *entry = m_tempStringRepository.at(i); - - if (entry->used || entry->persistent) { - compressed.append(entry); - entry->used = false; - } - - else { - //qDebug() << "deleted:" << entry->s; - delete entry; - } - } - - //qDebug() << "before:" << m_tempStringRepository.size() << "after:" << compressed.size(); - - m_tempStringRepository = compressed; - m_oldTempStringRepositorySize = m_tempStringRepository.size(); - m_newAllocatedTempStringRepositoryChars = 0; -} - -void QScriptEnginePrivate::processMarkStack(int generation) -{ - // mark the objects we couldn't process due to recursion depth - while (!m_markStack.isEmpty()) - markObject(m_markStack.takeLast(), generation); -} - -void QScriptEnginePrivate::evaluate(QScriptContextPrivate *context, const QString &contents, int lineNumber, const QString &fileName) -{ - // ### try to remove cast - QScript::EvalFunction *evalFunction = static_cast<QScript::EvalFunction*>(m_evalFunction); - evalFunction->evaluate(context, contents, lineNumber, fileName, /*calledFromScript=*/ false); -} - -qsreal QScriptEnginePrivate::convertToNativeDouble_helper(const QScriptValueImpl &value) -{ - switch (value.type()) { - case QScript::InvalidType: - Q_ASSERT(value.isValid()); - break; - - case QScript::UndefinedType: - case QScript::PointerType: - break; - - case QScript::NullType: - return 0; - - case QScript::BooleanType: - return value.m_bool_value; - - case QScript::IntegerType: - case QScript::ReferenceType: - return value.m_int_value; - - case QScript::NumberType: - return value.m_number_value; - - case QScript::StringType: - return QScript::numberFromString(toString(value.m_string_value)); - - case QScript::ObjectType: { - QScriptValueImpl p = value.engine()->toPrimitive(value, QScriptValueImpl::NumberTypeHint); - if (! p.isValid() || p.isObject()) - break; - - return convertToNativeDouble(p); - } - - case QScript::LazyStringType: - return QScript::numberFromString(*value.m_lazy_string_value); - - } // switch - - return qSNaN(); -} - -bool QScriptEnginePrivate::convertToNativeBoolean_helper(const QScriptValueImpl &value) -{ - switch (value.type()) { - case QScript::InvalidType: - Q_ASSERT(value.isValid()); - return false; - - case QScript::UndefinedType: - case QScript::PointerType: - case QScript::NullType: - case QScript::ReferenceType: - return false; - - case QScript::BooleanType: - return value.m_bool_value; - - case QScript::IntegerType: - return value.m_int_value != 0; - - case QScript::NumberType: - return value.m_number_value != 0 && !qIsNaN(value.m_number_value); - - case QScript::StringType: - return toString(value.m_string_value).length() != 0; - - case QScript::ObjectType: - return true; - - case QScript::LazyStringType: - return value.m_lazy_string_value->length() != 0; - - } // switch - - return false; -} - -QString QScriptEnginePrivate::convertToNativeString_helper(const QScriptValueImpl &value) -{ - static QStringList predefined; - if (predefined.isEmpty()) { - predefined.append(QString::fromLatin1("undefined")); - predefined.append(QString::fromLatin1("null")); - predefined.append(QString::fromLatin1("true")); - predefined.append(QString::fromLatin1("false")); - predefined.append(QString::fromLatin1("pointer")); - } - - switch (value.type()) { - case QScript::InvalidType: - Q_ASSERT(value.isValid()); - return QString(); - - case QScript::UndefinedType: - return predefined.at(0); - - case QScript::NullType: - return predefined.at(1); - - case QScript::BooleanType: - return value.m_bool_value ? predefined.at(2) : predefined.at(3); - - case QScript::IntegerType: - return QString::number(value.m_int_value); - - case QScript::NumberType: - return QScript::numberToString(value.m_number_value); - - case QScript::PointerType: - return predefined.at(4); - - case QScript::StringType: - return toString(value.m_string_value); - - case QScript::ReferenceType: - return QString(); - - case QScript::ObjectType: { - QScriptValueImpl p = value.engine()->toPrimitive(value, QScriptValueImpl::StringTypeHint); - - if (!p.isValid() || strictlyEquals(p, value)) - return p.classInfo()->name(); - - return convertToNativeString(p); - } - - case QScript::LazyStringType: - return *value.m_lazy_string_value; - - } // switch - - return QString(); -} - -QScriptValueImpl QScriptEnginePrivate::toObject_helper(const QScriptValueImpl &value) -{ - QScriptValueImpl result; - switch (value.type()) { - case QScript::BooleanType: - booleanConstructor->newBoolean(&result, value.m_bool_value); - break; - - case QScript::NumberType: - numberConstructor->newNumber(&result, value.m_number_value); - break; - - case QScript::StringType: - stringConstructor->newString(&result, value.m_string_value->s); - break; - - case QScript::LazyStringType: - stringConstructor->newString(&result, *value.m_lazy_string_value); - break; - - case QScript::InvalidType: - case QScript::UndefinedType: - case QScript::NullType: - case QScript::IntegerType: - case QScript::ReferenceType: - case QScript::PointerType: - case QScript::ObjectType: - break; - } // switch - - return result; -} - -// [[defaultValue]] -QScriptValueImpl QScriptEnginePrivate::toPrimitive_helper(const QScriptValueImpl &object, - QScriptValueImpl::TypeHint hint) -{ - QScriptNameIdImpl *functionIds[2]; - - if ((hint == QScriptValueImpl::NumberTypeHint) - || (hint == QScriptValueImpl::NoTypeHint - && object.classInfo() != dateConstructor->classInfo())) { - functionIds[0] = idTable()->id_valueOf; - functionIds[1] = idTable()->id_toString; - } else { - functionIds[0] = idTable()->id_toString; - functionIds[1] = idTable()->id_valueOf; - } - - for (int i = 0; i < 2; ++i) { - QScriptValueImpl base; - QScript::Member member; - - if (! object.resolve(functionIds[i], &member, &base, QScriptValue::ResolvePrototype, QScript::Read)) - return object; - - QScriptValueImpl f_valueOf; - base.get(member, &f_valueOf); - - if (QScriptFunction *foo = convertToNativeFunction(f_valueOf)) { - QScriptContextPrivate *me = pushContext(); - QScriptValueImpl activation; - newActivation(&activation); - if (f_valueOf.scope().isValid()) - activation.setScope(f_valueOf.scope()); - else - activation.setScope(m_globalObject); - me->setActivationObject(activation); - me->setThisObject(object); - me->m_callee = f_valueOf; - foo->execute(me); - QScriptValueImpl result = me->returnValue(); - bool exception = (me->state() == QScriptContext::ExceptionState); - popContext(); - if (exception || (result.isValid() && !result.isObject())) - return result; - } - } - - return object; -} - -void QScriptEnginePrivate::rehashStringRepository(bool resize) -{ - if (resize) { - delete[] m_string_hash_base; - m_string_hash_size <<= 1; // ### use primes - - m_string_hash_base = new QScriptNameIdImpl* [m_string_hash_size]; - } - - memset(m_string_hash_base, 0, sizeof(QScriptNameIdImpl*) * m_string_hash_size); - - for (int index = 0; index < m_stringRepository.size(); ++index) { - QScriptNameIdImpl *entry = m_stringRepository.at(index); - uint h = _q_scriptHash(entry->s) % m_string_hash_size; - entry->h = h; - entry->next = m_string_hash_base[h]; - m_string_hash_base[h] = entry; - } -} - -QScriptNameIdImpl *QScriptEnginePrivate::insertStringEntry(const QString &s) -{ - QScriptNameIdImpl *entry = new QScriptNameIdImpl(s); - entry->unique = true; - m_stringRepository.append(entry); - m_newAllocatedStringRepositoryChars += s.length(); - - uint h = _q_scriptHash(s) % m_string_hash_size; - entry->h = h; - entry->next = m_string_hash_base[h]; - m_string_hash_base[h] = entry; - - if (m_stringRepository.count() == m_string_hash_size) - rehashStringRepository(); - - return entry; -} - -QScriptValueImpl QScriptEnginePrivate::call(const QScriptValueImpl &callee, - const QScriptValueImpl &thisObject, - const QScriptValueImplList &args, - bool asConstructor) -{ - QScriptFunction *function = callee.toFunction(); - Q_ASSERT(function); - - if (++m_callDepth == m_maxCallDepth) { - QScriptContextPrivate *ctx_p = currentContext(); - return ctx_p->throwError(QLatin1String("call stack overflow")); - } - - QScriptContextPrivate *nested = pushContext(); - // set up the temp stack - if (! nested->tempStack) - nested->stackPtr = nested->tempStack = tempStackBegin; - - newActivation(&nested->m_activation); - if (callee.m_object_value->m_scope.isValid()) - nested->m_activation.m_object_value->m_scope = callee.m_object_value->m_scope; - else - nested->m_activation.m_object_value->m_scope = m_globalObject; - - QScriptObject *activation_data = nested->m_activation.m_object_value; - - int formalCount = function->formals.count(); - int argc = args.count(); - int mx = qMax(formalCount, argc); - activation_data->m_members.resize(mx); - activation_data->m_values.resize(mx); - for (int i = 0; i < mx; ++i) { - QScriptNameIdImpl *nameId = 0; - if (i < formalCount) - nameId = function->formals.at(i); - - activation_data->m_members[i].object(nameId, i, QScriptValue::SkipInEnumeration); - QScriptValueImpl arg = (i < argc) ? args.at(i) : m_undefinedValue; - if (arg.isValid() && arg.engine() && (arg.engine() != this)) { - qWarning("QScriptValue::call() failed: " - "cannot call function with argument created in " - "a different engine"); - popContext(); - return QScriptValueImpl(); - } - activation_data->m_values[i] = arg.isValid() ? arg : m_undefinedValue; - } - - nested->argc = argc; - QVector<QScriptValueImpl> argsv = args.toVector(); - nested->args = const_cast<QScriptValueImpl*> (argsv.constData()); - - if (thisObject.isObject()) - nested->m_thisObject = thisObject; - else - nested->m_thisObject = m_globalObject; - nested->m_callee = callee; - nested->m_calledAsConstructor = asConstructor; - - nested->m_result = m_undefinedValue; - function->execute(nested); - --m_callDepth; - QScriptValueImpl result = nested->m_result; - nested->args = 0; - popContext(); - - return result; -} - -QScriptValueImpl QScriptEnginePrivate::call(const QScriptValueImpl &callee, - const QScriptValueImpl &thisObject, - const QScriptValueImpl &args, - bool asConstructor) -{ - QScriptValueImplList argsList; - if (QScript::Ecma::Array::Instance *arr = arrayConstructor->get(args)) { - QScript::Array actuals = arr->value; - for (quint32 i = 0; i < actuals.count(); ++i) { - QScriptValueImpl a = actuals.at(i); - if (! a.isValid()) - argsList << undefinedValue(); - else - argsList << a; - } - } else if (args.classInfo() == m_class_arguments) { - QScript::ArgumentsObjectData *arguments; - arguments = static_cast<QScript::ArgumentsObjectData*> (args.objectData()); - QScriptObject *activation = arguments->activation.objectValue(); - for (uint i = 0; i < arguments->length; ++i) - argsList << activation->m_values[i]; - } else if (!(args.isUndefined() || args.isNull())) { - return currentContext()->throwError( - QScriptContext::TypeError, - QLatin1String("QScriptValue::call(): arguments must be an array")); - } - return call(callee, thisObject, argsList, asConstructor); -} - -QScriptValueImpl QScriptEnginePrivate::arrayFromStringList(const QStringList &lst) -{ - QScriptValueImpl arr = newArray(lst.size()); - for (int i = 0; i < lst.size(); ++i) - arr.setProperty(i, QScriptValueImpl(this, lst.at(i))); - return arr; -} - -QStringList QScriptEnginePrivate::stringListFromArray(const QScriptValueImpl &arr) -{ - QStringList lst; - uint len = arr.property(QLatin1String("length")).toUInt32(); - for (uint i = 0; i < len; ++i) - lst.append(arr.property(i).toString()); - return lst; -} - -QScriptValueImpl QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst) -{ - QScriptValueImpl arr = newArray(lst.size()); - for (int i = 0; i < lst.size(); ++i) - arr.setProperty(i, valueFromVariant(lst.at(i))); - return arr; -} - -QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValueImpl &arr) -{ - QVariantList lst; - uint len = arr.property(QLatin1String("length")).toUInt32(); - for (uint i = 0; i < len; ++i) - lst.append(arr.property(i).toVariant()); - return lst; -} - -QScriptValueImpl QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap) -{ - QScriptValueImpl obj = newObject(); - QVariantMap::const_iterator it; - for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) - obj.setProperty(it.key(), valueFromVariant(it.value())); - return obj; -} - -QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValueImpl &obj) -{ - QVariantMap vmap; - QScriptValueIteratorImpl it(obj); - while (it.hasNext()) { - it.next(); - vmap.insert(it.name(), it.value().toVariant()); - } - return vmap; -} - -QScriptValueImpl QScriptEnginePrivate::create(int type, const void *ptr) -{ - Q_Q(QScriptEngine); - Q_ASSERT(ptr); - QScriptValueImpl result; - QScriptCustomTypeInfo info = m_customTypes.value(type); - if (info.marshal) { - result = toImpl(info.marshal(q, ptr)); - } else { - // check if it's one of the types we know - switch (QMetaType::Type(type)) { - case QMetaType::Void: - result = m_undefinedValue; - break; - case QMetaType::Bool: - result = QScriptValueImpl(*reinterpret_cast<const bool*>(ptr)); - break; - case QMetaType::Int: - result = QScriptValueImpl(*reinterpret_cast<const int*>(ptr)); - break; - case QMetaType::UInt: - result = QScriptValueImpl(*reinterpret_cast<const uint*>(ptr)); - break; - case QMetaType::LongLong: - result = QScriptValueImpl(qsreal(*reinterpret_cast<const qlonglong*>(ptr))); - break; - case QMetaType::ULongLong: -#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 -#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") - result = QScriptValueImpl(qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); -#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - result = QScriptValueImpl(qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); -#else - result = QScriptValueImpl(qsreal(*reinterpret_cast<const qulonglong*>(ptr))); -#endif - break; - case QMetaType::Double: - result = QScriptValueImpl(*reinterpret_cast<const double*>(ptr)); - break; - case QMetaType::QString: - result = QScriptValueImpl(this, *reinterpret_cast<const QString*>(ptr)); - break; - case QMetaType::Float: - result = QScriptValueImpl(*reinterpret_cast<const float*>(ptr)); - break; - case QMetaType::Short: - result = QScriptValueImpl(*reinterpret_cast<const short*>(ptr)); - break; - case QMetaType::UShort: - result = QScriptValueImpl(*reinterpret_cast<const unsigned short*>(ptr)); - break; - case QMetaType::Char: - result = QScriptValueImpl(*reinterpret_cast<const char*>(ptr)); - break; - case QMetaType::UChar: - result = QScriptValueImpl(*reinterpret_cast<const unsigned char*>(ptr)); - break; - case QMetaType::QChar: - result = QScriptValueImpl((*reinterpret_cast<const QChar*>(ptr)).unicode()); - break; - case QMetaType::QStringList: - result = arrayFromStringList(*reinterpret_cast<const QStringList *>(ptr)); - break; - case QMetaType::QVariantList: - result = arrayFromVariantList(*reinterpret_cast<const QVariantList *>(ptr)); - break; - case QMetaType::QVariantMap: - result = objectFromVariantMap(*reinterpret_cast<const QVariantMap *>(ptr)); - break; - case QMetaType::QDateTime: { - QDateTime dateTime = *reinterpret_cast<const QDateTime *>(ptr); - dateConstructor->newDate(&result, dateTime); - } break; - case QMetaType::QDate: { - QDate date = *reinterpret_cast<const QDate *>(ptr); - dateConstructor->newDate(&result, date); - } break; -#ifndef QT_NO_REGEXP - case QMetaType::QRegExp: { - QRegExp rx = *reinterpret_cast<const QRegExp *>(ptr); - regexpConstructor->newRegExp(&result, rx); - } break; -#endif -#ifndef QT_NO_QOBJECT - case QMetaType::QObjectStar: - case QMetaType::QWidgetStar: - newQObject(&result, *reinterpret_cast<QObject* const *>(ptr)); - break; -#endif - default: - if (type == qMetaTypeId<QScriptValue>()) { - result = toImpl(*reinterpret_cast<const QScriptValue*>(ptr)); - if (!result.isValid()) - result = m_undefinedValue; - } - -#ifndef QT_NO_QOBJECT - // lazy registration of some common list types - else if (type == qMetaTypeId<QObjectList>()) { - qScriptRegisterSequenceMetaType<QObjectList>(q); - return create(type, ptr); - } -#endif - else if (type == qMetaTypeId<QList<int> >()) { - qScriptRegisterSequenceMetaType<QList<int> >(q); - return create(type, ptr); - } - - else { - QByteArray typeName = QMetaType::typeName(type); - if (typeName == "QVariant") - result = valueFromVariant(*reinterpret_cast<const QVariant*>(ptr)); - else if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr)) - result = nullValue(); - else - newVariant(&result, QVariant(type, ptr)); - } - } - } - if (result.isObject() && info.prototype.isValid() - && strictlyEquals(result.prototype(), objectConstructor->publicPrototype)) { - result.setPrototype(info.prototype); - } - return result; -} - -bool QScriptEnginePrivate::convert(const QScriptValueImpl &value, - int type, void *ptr, - QScriptEnginePrivate *eng) -{ - if (!eng) - eng = value.engine(); - if (eng) { - QScriptCustomTypeInfo info = eng->m_customTypes.value(type); - if (info.demarshal) { - info.demarshal(eng->toPublic(value), ptr); - return true; - } - } - - // check if it's one of the types we know - switch (QMetaType::Type(type)) { - case QMetaType::Bool: - *reinterpret_cast<bool*>(ptr) = value.toBoolean(); - return true; - case QMetaType::Int: - *reinterpret_cast<int*>(ptr) = value.toInt32(); - return true; - case QMetaType::UInt: - *reinterpret_cast<uint*>(ptr) = value.toUInt32(); - return true; - case QMetaType::LongLong: - *reinterpret_cast<qlonglong*>(ptr) = qlonglong(value.toInteger()); - return true; - case QMetaType::ULongLong: - *reinterpret_cast<qulonglong*>(ptr) = qulonglong(value.toInteger()); - return true; - case QMetaType::Double: - *reinterpret_cast<double*>(ptr) = value.toNumber(); - return true; - case QMetaType::QString: - if (value.isUndefined() || value.isNull()) - *reinterpret_cast<QString*>(ptr) = QString(); - else - *reinterpret_cast<QString*>(ptr) = value.toString(); - return true; - case QMetaType::Float: - *reinterpret_cast<float*>(ptr) = value.toNumber(); - return true; - case QMetaType::Short: - *reinterpret_cast<short*>(ptr) = short(value.toInt32()); - return true; - case QMetaType::UShort: - *reinterpret_cast<unsigned short*>(ptr) = value.toUInt16(); - return true; - case QMetaType::Char: - *reinterpret_cast<char*>(ptr) = char(value.toInt32()); - return true; - case QMetaType::UChar: - *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(value.toInt32()); - return true; - case QMetaType::QChar: - if (value.isString()) { - QString str = value.toString(); - *reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0); - } else { - *reinterpret_cast<QChar*>(ptr) = QChar(value.toUInt16()); - } - return true; - case QMetaType::QDateTime: - if (value.isDate()) { - *reinterpret_cast<QDateTime *>(ptr) = value.toDateTime(); - return true; - } break; - case QMetaType::QDate: - if (value.isDate()) { - *reinterpret_cast<QDate *>(ptr) = value.toDateTime().date(); - return true; - } break; -#ifndef QT_NO_REGEXP - case QMetaType::QRegExp: - if (value.isRegExp()) { - *reinterpret_cast<QRegExp *>(ptr) = value.toRegExp(); - return true; - } break; -#endif -#ifndef QT_NO_QOBJECT - case QMetaType::QObjectStar: - if (value.isQObject() || value.isNull()) { - *reinterpret_cast<QObject* *>(ptr) = value.toQObject(); - return true; - } break; - case QMetaType::QWidgetStar: - if (value.isQObject() || value.isNull()) { - QObject *qo = value.toQObject(); - if (!qo || qo->isWidgetType()) { - *reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo); - return true; - } - } break; -#endif - case QMetaType::QStringList: - if (value.isArray()) { - *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(value); - return true; - } break; - case QMetaType::QVariantList: - if (value.isArray()) { - *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(value); - return true; - } break; - case QMetaType::QVariantMap: - if (value.isObject()) { - *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(value); - return true; - } break; - default: - ; - } - - QByteArray name = QMetaType::typeName(type); -#ifndef QT_NO_QOBJECT - if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(ptr))) - return true; -#endif - if (value.isVariant() && name.endsWith('*')) { - int valueType = QMetaType::type(name.left(name.size()-1)); - QVariant &var = value.variantValue(); - if (valueType == var.userType()) { - *reinterpret_cast<void* *>(ptr) = var.data(); - return true; - } else { - // look in the prototype chain - QScriptValueImpl proto = value.prototype(); - while (proto.isObject()) { - bool canCast = false; - if (proto.isVariant()) { - canCast = (type == proto.variantValue().userType()) - || (valueType && (valueType == proto.variantValue().userType())); - } -#ifndef QT_NO_QOBJECT - else if (proto.isQObject()) { - QByteArray className = name.left(name.size()-1); - if (QObject *qobject = proto.toQObject()) - canCast = qobject->qt_metacast(className) != 0; - } -#endif - if (canCast) { - QByteArray varTypeName = QMetaType::typeName(var.userType()); - if (varTypeName.endsWith('*')) - *reinterpret_cast<void* *>(ptr) = *reinterpret_cast<void* *>(var.data()); - else - *reinterpret_cast<void* *>(ptr) = var.data(); - return true; - } - proto = proto.prototype(); - } - } - } else if (value.isNull() && name.endsWith('*')) { - *reinterpret_cast<void* *>(ptr) = 0; - return true; - } else if (type == qMetaTypeId<QScriptValue>()) { - if (!eng) - return false; - *reinterpret_cast<QScriptValue*>(ptr) = eng->toPublic(value); - return true; - } else if (name == "QVariant") { - *reinterpret_cast<QVariant*>(ptr) = value.toVariant(); - return true; - } - - // lazy registration of some common list types -#ifndef QT_NO_QOBJECT - else if (type == qMetaTypeId<QObjectList>()) { - if (!eng) - return false; - qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func()); - return convert(value, type, ptr, eng); - } -#endif - else if (type == qMetaTypeId<QList<int> >()) { - if (!eng) - return false; - qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func()); - return convert(value, type, ptr, eng); - } - -#if 0 - if (!name.isEmpty()) { - qWarning("QScriptEngine::convert: unable to convert value to type `%s'", - name.constData()); - } -#endif - return false; -} - -QScriptEngine::DemarshalFunction QScriptEnginePrivate::demarshalFunction(int type) const -{ - return m_customTypes.value(type).demarshal; -} - -QScriptValuePrivate *QScriptEnginePrivate::registerValue(const QScriptValueImpl &value) -{ - if (value.isString()) { - QScriptNameIdImpl *id = value.stringValue(); - QScriptValuePrivate *p = m_stringHandles.value(id); - if (p) - return p; - p = m_handleRepository.get(); - p->engine = q_func(); - p->value = value; - m_stringHandles.insert(id, p); - return p; - } else if (value.isObject()) { - QScriptObject *instance = value.objectValue(); - QScriptValuePrivate *p = m_objectHandles.value(instance); - if (p) - return p; - p = m_handleRepository.get(); - p->engine = q_func(); - p->value = value; - m_objectHandles.insert(instance, p); - return p; - } - QScriptValuePrivate *p = m_handleRepository.get(); - p->engine = q_func(); - p->value = value; - m_otherHandles.append(p); - return p; -} - -QScriptEnginePrivate::QScriptEnginePrivate() -{ - m_undefinedValue = QScriptValueImpl(QScriptValue::UndefinedValue); - m_nullValue = QScriptValueImpl(QScriptValue::NullValue); - - m_evaluating = false; - m_abort = false; - m_callDepth = 0; -#if defined(Q_OS_WIN) - m_maxCallDepth = 88; -#elif defined(Q_OS_MAC) - m_maxCallDepth = 640; -#elif defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) - m_maxCallDepth = 360; -#else - m_maxCallDepth = 512; -#endif - m_oldStringRepositorySize = 0; - m_oldTempStringRepositorySize = 0; - m_newAllocatedStringRepositoryChars = 0; - m_newAllocatedTempStringRepositoryChars = 0; - m_context = 0; - m_abstractSyntaxTree = 0; - m_lexer = 0; - m_scriptCounter = 0; - m_agent = 0; - m_objectGeneration = 0; - m_class_prev_id = QScriptClassInfo::CustomType; - m_next_object_id = 0; - m_gc_depth = -1; - - objectConstructor = 0; - numberConstructor = 0; - booleanConstructor = 0; - stringConstructor = 0; - dateConstructor = 0; - functionConstructor = 0; - arrayConstructor = 0; - regexpConstructor = 0; - errorConstructor = 0; - enumerationConstructor = 0; - variantConstructor = 0; - qobjectConstructor = 0; - qmetaObjectConstructor = 0; - - m_processEventsInterval = -1; - m_nextProcessEvents = 0; - m_processEventIncr = 0; - - m_stringRepository.reserve(DefaultHashSize); - m_string_hash_size = DefaultHashSize; - m_string_hash_base = new QScriptNameIdImpl* [m_string_hash_size]; - memset(m_string_hash_base, 0, sizeof(QScriptNameIdImpl*) * m_string_hash_size); - - tempStackBegin = 0; -} - -void QScriptEnginePrivate::init() -{ - qMetaTypeId<QScriptValue>(); - qMetaTypeId<QList<int> >(); -#ifndef QT_NO_QOBJECT - qMetaTypeId<QObjectList>(); -#endif - - m_class_prev_id = QScriptClassInfo::CustomType; - m_class_object = registerClass(QLatin1String("Object"), QScriptClassInfo::ObjectType); - m_class_function = registerClass(QLatin1String("Function"), QScriptClassInfo::FunctionType); - m_class_activation = registerClass(QLatin1String("activation"), QScriptClassInfo::ActivationType); - - m_class_arguments = registerClass(QLatin1String("arguments"), QScript::ObjectType); - m_class_arguments->setData(new QScript::ArgumentsClassData()); - - m_class_with = registerClass(QLatin1String("__qscript_internal_with"), QScript::ObjectType); - - // public name ids - m_id_table.id_constructor = nameId(QLatin1String("constructor"), true); - m_id_table.id_false = nameId(QLatin1String("false"), true); - m_id_table.id_null = nameId(QLatin1String("null"), true); - m_id_table.id_object = nameId(QLatin1String("object"), true); - m_id_table.id_pointer = nameId(QLatin1String("pointer"), true); - m_id_table.id_prototype = nameId(QLatin1String("prototype"), true); - m_id_table.id_arguments = nameId(QLatin1String("arguments"), true); - m_id_table.id_this = nameId(QLatin1String("this"), true); - m_id_table.id_toString = nameId(QLatin1String("toString"), true); - m_id_table.id_true = nameId(QLatin1String("true"), true); - m_id_table.id_undefined = nameId(QLatin1String("undefined"), true); - m_id_table.id_valueOf = nameId(QLatin1String("valueOf"), true); - m_id_table.id_length = nameId(QLatin1String("length"), true); - m_id_table.id_callee = nameId(QLatin1String("callee"), true); - m_id_table.id___proto__ = nameId(QLatin1String("__proto__"), true); - m_id_table.id___qt_sender__ = nameId(QLatin1String("__qt_sender__"), true); - - const int TEMP_STACK_SIZE = 10 * 1024; - tempStackBegin = new QScriptValueImpl[TEMP_STACK_SIZE]; - tempStackEnd = tempStackBegin + TEMP_STACK_SIZE; - tempStackBegin[0] = m_undefinedValue; - - objectAllocator.blockGC(true); - - QScript::Ecma::Global::construct(&m_globalObject, this); - - // create the prototypes first... - objectConstructor = new QScript::Ecma::Object(this, m_class_object); - functionConstructor = new QScript::Ecma::Function(this, m_class_function); - // ... then we can initialize - functionConstructor->initialize(); - objectConstructor->initialize(); - - numberConstructor = new QScript::Ecma::Number(this); - booleanConstructor = new QScript::Ecma::Boolean(this); - stringConstructor = new QScript::Ecma::String(this); - dateConstructor = new QScript::Ecma::Date(this); - arrayConstructor = new QScript::Ecma::Array(this); - regexpConstructor = new QScript::Ecma::RegExp(this); - errorConstructor = new QScript::Ecma::Error(this); - - QScript::Ecma::Global::initialize(&m_globalObject, this); - - const QScriptValue::PropertyFlags flags = QScriptValue::SkipInEnumeration; - - m_globalObject.setProperty(QLatin1String("Object"), - objectConstructor->ctor, flags); - m_globalObject.setProperty(QLatin1String("Function"), - functionConstructor->ctor, flags); - m_globalObject.setProperty(QLatin1String("Number"), - numberConstructor->ctor, flags); - m_globalObject.setProperty(QLatin1String("Boolean"), - booleanConstructor->ctor, flags); - m_globalObject.setProperty(QLatin1String("String"), - stringConstructor->ctor, flags); - m_globalObject.setProperty(QLatin1String("Date"), - dateConstructor->ctor, flags); - m_globalObject.setProperty(QLatin1String("Array"), - arrayConstructor->ctor, flags); - m_globalObject.setProperty(QLatin1String("RegExp"), - regexpConstructor->ctor, flags); - m_globalObject.setProperty(QLatin1String("Error"), - errorConstructor->ctor, flags); - - m_globalObject.setProperty(QLatin1String("EvalError"), - errorConstructor->evalErrorCtor, flags); - m_globalObject.setProperty(QLatin1String("RangeError"), - errorConstructor->rangeErrorCtor, flags); - m_globalObject.setProperty(QLatin1String("ReferenceError"), - errorConstructor->referenceErrorCtor, flags); - m_globalObject.setProperty(QLatin1String("SyntaxError"), - errorConstructor->syntaxErrorCtor, flags); - m_globalObject.setProperty(QLatin1String("TypeError"), - errorConstructor->typeErrorCtor, flags); - m_globalObject.setProperty(QLatin1String("URIError"), - errorConstructor->uriErrorCtor, flags); - - QScriptValueImpl tmp; // ### fixme - m_evalFunction = new QScript::EvalFunction(this); - functionConstructor->newFunction(&tmp, m_evalFunction); - m_globalObject.setProperty(QLatin1String("eval"), tmp, flags); - - QScriptValueImpl mathObject; - QScript::Ecma::Math::construct(&mathObject, this); - m_globalObject.setProperty(QLatin1String("Math"), mathObject, flags); - - enumerationConstructor = new QScript::Ext::Enumeration(this); - - variantConstructor = new QScript::Ext::Variant(this); - -#ifndef QT_NO_QOBJECT - qobjectConstructor = new QScript::ExtQObject(this); - qmetaObjectConstructor = new QScript::ExtQMetaObject(this); -#endif - - objectAllocator.blockGC(false); - - QScriptContextPrivate *context_p = pushContext(); - context_p->setActivationObject(m_globalObject); - context_p->setThisObject(m_globalObject); -} - -#if !defined(QT_NO_QOBJECT) && !defined(QT_NO_LIBRARY) -static QScriptValueImpl __setupPackage__(QScriptContextPrivate *ctx, - QScriptEnginePrivate *eng, - QScriptClassInfo *) -{ - QString path = ctx->argument(0).toString(); - QStringList components = path.split(QLatin1Char('.')); - QScriptValueImpl o = eng->globalObject(); - for (int i = 0; i < components.count(); ++i) { - QString name = components.at(i); - QScriptValueImpl oo = o.property(name); - if (!oo.isValid()) { - oo = eng->newObject(); - o.setProperty(name, oo); - } - o = oo; - } - return o; -} -#endif - -QScriptValueImpl QScriptEnginePrivate::importExtension(const QString &extension) -{ -#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS) - Q_UNUSED(extension); -#else - Q_Q(QScriptEngine); - if (m_importedExtensions.contains(extension)) - return undefinedValue(); // already imported - - QScriptContextPrivate *context = currentContext(); - QCoreApplication *app = QCoreApplication::instance(); - if (!app) - return context->throwError(QLatin1String("No application object")); - - QObjectList staticPlugins = QPluginLoader::staticInstances(); - QStringList libraryPaths = app->libraryPaths(); - QString dot = QLatin1String("."); - QStringList pathComponents = extension.split(dot); - QString initDotJs = QLatin1String("__init__.js"); - - QString ext; - for (int i = 0; i < pathComponents.count(); ++i) { - if (!ext.isEmpty()) - ext.append(dot); - ext.append(pathComponents.at(i)); - if (m_importedExtensions.contains(ext)) - continue; // already imported - - if (m_extensionsBeingImported.contains(ext)) { - return context->throwError(QString::fromLatin1("recursive import of %0") - .arg(extension)); - } - m_extensionsBeingImported.insert(ext); - - QScriptExtensionInterface *iface = 0; - QString initjsContents; - QString initjsFileName; - - // look for the extension in static plugins - for (int j = 0; j < staticPlugins.size(); ++j) { - iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(j)); - if (!iface) - continue; - if (iface->keys().contains(ext)) - break; // use this one - else - iface = 0; // keep looking - } - - { - // look for __init__.js resource - QString path = QString::fromLatin1(":/qtscriptextension"); - for (int j = 0; j <= i; ++j) { - path.append(QLatin1Char('/')); - path.append(pathComponents.at(j)); - } - path.append(QLatin1Char('/')); - path.append(initDotJs); - QFile file(path); - if (file.open(QIODevice::ReadOnly)) { - QTextStream ts(&file); - initjsContents = ts.readAll(); - initjsFileName = path; - file.close(); - } - } - - if (!iface && initjsContents.isEmpty()) { - // look for the extension in library paths - for (int j = 0; j < libraryPaths.count(); ++j) { - QString libPath = libraryPaths.at(j) + QDir::separator() + QLatin1String("script"); - QDir dir(libPath); - if (!dir.exists(dot)) - continue; - - // look for C++ plugin - QFileInfoList files = dir.entryInfoList(QDir::Files); - for (int k = 0; k < files.count(); ++k) { - QFileInfo entry = files.at(k); - QString filePath = entry.canonicalFilePath(); - QPluginLoader loader(filePath); - iface = qobject_cast<QScriptExtensionInterface*>(loader.instance()); - if (iface) { - if (iface->keys().contains(ext)) - break; // use this one - else - iface = 0; // keep looking - } - } - - // look for __init__.js in the corresponding dir - QDir dirdir(libPath); - bool dirExists = dirdir.exists(); - for (int k = 0; dirExists && (k <= i); ++k) - dirExists = dirdir.cd(pathComponents.at(k)); - if (dirExists && dirdir.exists(initDotJs)) { - QFile file(dirdir.canonicalPath() - + QDir::separator() + initDotJs); - if (file.open(QIODevice::ReadOnly)) { - QTextStream ts(&file); - initjsContents = ts.readAll(); - initjsFileName = file.fileName(); - file.close(); - } - } - - if (iface || !initjsContents.isEmpty()) - break; - } - } - - if (!iface && initjsContents.isEmpty()) { - m_extensionsBeingImported.remove(ext); - return context->throwError( - QString::fromLatin1("Unable to import %0: no such extension") - .arg(extension)); - } - - // initialize the extension in a new context - QScriptContextPrivate *ctx_p = pushContext(); - ctx_p->setThisObject(globalObject()); - newActivation(&ctx_p->m_activation); - QScriptObject *activation_data = ctx_p->m_activation.m_object_value; - activation_data->m_scope = globalObject(); - - activation_data->m_members.resize(4); - activation_data->m_values.resize(4); - activation_data->m_members[0].object( - nameId(QLatin1String("__extension__")), 0, - QScriptValue::ReadOnly | QScriptValue::Undeletable); - activation_data->m_values[0] = QScriptValueImpl(this, ext); - activation_data->m_members[1].object( - nameId(QLatin1String("__setupPackage__")), 1, 0); - activation_data->m_values[1] = createFunction(__setupPackage__, 0, 0); - activation_data->m_members[2].object( - nameId(QLatin1String("__all__")), 2, 0); - activation_data->m_values[2] = undefinedValue(); - activation_data->m_members[3].object( - nameId(QLatin1String("__postInit__")), 3, 0); - activation_data->m_values[3] = undefinedValue(); - - // the script is evaluated first - if (!initjsContents.isEmpty()) { - evaluate(ctx_p, initjsContents, /*lineNumber=*/1, initjsFileName); - if (hasUncaughtException()) { - QScriptValueImpl r = ctx_p->returnValue(); - popContext(); - m_extensionsBeingImported.remove(ext); - return r; - } - } - - // next, the C++ plugin is called - if (iface) { - iface->initialize(ext, q); - if (hasUncaughtException()) { - QScriptValueImpl r = ctx_p->returnValue(); - popContext(); - m_extensionsBeingImported.remove(ext); - return r; - } - } - - // if the __postInit__ function has been set, we call it - QScriptValueImpl postInit = ctx_p->m_activation.property(QLatin1String("__postInit__")); - if (postInit.isFunction()) { - postInit.call(globalObject()); - if (hasUncaughtException()) { - QScriptValueImpl r = ctx_p->returnValue(); - popContext(); - m_extensionsBeingImported.remove(ext); - return r; - } - } - - popContext(); - - m_importedExtensions.insert(ext); - m_extensionsBeingImported.remove(ext); - } // for (i) -#endif // QT_NO_QOBJECT - return undefinedValue(); -} - -QStringList QScriptEnginePrivate::availableExtensions() const -{ -#if defined(QT_NO_QOBJECT) || defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS) - return QStringList(); -#else - QCoreApplication *app = QCoreApplication::instance(); - if (!app) - return QStringList(); - - QSet<QString> result; - - QObjectList staticPlugins = QPluginLoader::staticInstances(); - for (int i = 0; i < staticPlugins.size(); ++i) { - QScriptExtensionInterface *iface; - iface = qobject_cast<QScriptExtensionInterface*>(staticPlugins.at(i)); - if (iface) { - QStringList keys = iface->keys(); - for (int j = 0; j < keys.count(); ++j) - result << keys.at(j); - } - } - - QStringList libraryPaths = app->libraryPaths(); - for (int i = 0; i < libraryPaths.count(); ++i) { - QString libPath = libraryPaths.at(i) + QDir::separator() + QLatin1String("script"); - QDir dir(libPath); - if (!dir.exists()) - continue; - - // look for C++ plugins - QFileInfoList files = dir.entryInfoList(QDir::Files); - for (int j = 0; j < files.count(); ++j) { - QFileInfo entry = files.at(j); - QString filePath = entry.canonicalFilePath(); - QPluginLoader loader(filePath); - QScriptExtensionInterface *iface; - iface = qobject_cast<QScriptExtensionInterface*>(loader.instance()); - if (iface) { - QStringList keys = iface->keys(); - for (int k = 0; k < keys.count(); ++k) - result << keys.at(k); - } - } - - // look for scripts - QString initDotJs = QLatin1String("__init__.js"); - QList<QFileInfo> stack; - stack << dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); - while (!stack.isEmpty()) { - QFileInfo entry = stack.takeLast(); - QDir dd(entry.canonicalFilePath()); - if (dd.exists(initDotJs)) { - QString rpath = dir.relativeFilePath(dd.canonicalPath()); - QStringList components = rpath.split(QLatin1Char('/')); - result << components.join(QLatin1String(".")); - stack << dd.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); - } - } - } - - QStringList lst = result.toList(); - qSort(lst); - return lst; -#endif -} - -QStringList QScriptEnginePrivate::importedExtensions() const -{ - QStringList lst = m_importedExtensions.toList(); - qSort(lst); - return lst; -} - -void QScriptEnginePrivate::gc() -{ - if (!objectAllocator.blocked()) { - // do the GC now - maybeGC_helper(/*do_string_gc=*/true); - } else { - // GC will be performed the next time maybeGC() - // is called and the allocator is not blocked - objectAllocator.requestGC(); - } -} - -QStringList QScriptEnginePrivate::uncaughtExceptionBacktrace() const -{ - QScriptValueImpl value = uncaughtException(); - if (!value.isError()) - return m_exceptionBacktrace; - return QScript::Ecma::Error::backtrace(value); -} - -void QScriptEnginePrivate::clearExceptions() -{ - m_exceptionBacktrace = QStringList(); - QScriptContextPrivate *ctx_p = currentContext(); - while (ctx_p) { - ctx_p->m_state = QScriptContext::NormalState; - ctx_p = ctx_p->parentContext(); - } -} - -#ifndef QT_NO_QOBJECT -void QScriptEnginePrivate::emitSignalHandlerException() -{ - Q_Q(QScriptEngine); - emit q->signalHandlerException(toPublic(uncaughtException())); -} -#endif - -void QScriptEnginePrivate::processEvents() -{ -#ifndef QT_NO_QOBJECT - Q_ASSERT(m_processEventTracker.isValid()); - int elapsed = m_processEventTracker.elapsed(); - if (m_nextProcessEvents < elapsed) { - do { - m_nextProcessEvents = m_nextProcessEvents + m_processEventsInterval; - } while (m_nextProcessEvents < elapsed); - QCoreApplication::processEvents(); - } -#endif -} - -void QScriptEnginePrivate::setupProcessEvents() -{ - if (m_processEventsInterval > 0) { - m_nextProcessEvents = m_processEventsInterval; - m_processEventIncr = 0; - m_processEventTracker.restart(); - } -} - -void QScriptEnginePrivate::abortEvaluation(const QScriptValueImpl &result) -{ - m_abort = true; - currentContext()->setReturnValue(result); -} - -#ifndef QT_NO_QOBJECT - -void QScriptEnginePrivate::newQObject(QScriptValueImpl *out, QObject *object, - QScriptEngine::ValueOwnership ownership, - const QScriptEngine::QObjectWrapOptions &options, - bool setDefaultPrototype) -{ - if (!object) { - *out = m_nullValue; - return; - } - Q_ASSERT(qobjectConstructor != 0); - QScriptQObjectData *data = qobjectData(object); - bool preferExisting = (options & QScriptEngine::PreferExistingWrapperObject) != 0; - QScriptEngine::QObjectWrapOptions opt = options & ~QScriptEngine::PreferExistingWrapperObject; - QScriptValueImpl existingWrapper; - bool hasExisting = data->findWrapper(ownership, opt, &existingWrapper); - if (preferExisting) { - if (hasExisting) { - *out = existingWrapper; - } else { - qobjectConstructor->newQObject(out, object, ownership, opt); - data->registerWrapper(*out, ownership, opt); - } - } else { - qobjectConstructor->newQObject(out, object, ownership, opt); - if (!hasExisting) - data->registerWrapper(*out, ownership, opt); - } - - if (setDefaultPrototype) { - const QMetaObject *meta = object->metaObject(); - while (meta) { - QByteArray typeString = meta->className(); - typeString.append('*'); - int typeId = QMetaType::type(typeString); - if (typeId != 0) { - QScriptValueImpl proto = defaultPrototype(typeId); - if (proto.isValid()) { - out->setPrototype(proto); - break; - } - } - meta = meta->superClass(); - } - } -} - -QScriptQObjectData *QScriptEnginePrivate::qobjectData(QObject *object) -{ - QHash<QObject*, QScriptQObjectData*>::const_iterator it; - it = m_qobjectData.constFind(object); - if (it != m_qobjectData.constEnd()) - return it.value(); - - QScriptQObjectData *data = new QScriptQObjectData(); - m_qobjectData.insert(object, data); - QObject::connect(object, SIGNAL(destroyed(QObject*)), - q_func(), SLOT(_q_objectDestroyed(QObject *))); - return data; -} - -void QScriptEnginePrivate::_q_objectDestroyed(QObject *object) -{ - QHash<QObject*, QScriptQObjectData*>::iterator it; - it = m_qobjectData.find(object); - Q_ASSERT(it != m_qobjectData.end()); - QScriptQObjectData *data = it.value(); - m_qobjectData.erase(it); - delete data; -} - -void QScriptEnginePrivate::disposeQObject(QObject *object) -{ - if (isCollecting()) { - // wait until we're done with GC before deleting it - int index = m_qobjectsToBeDeleted.indexOf(object); - if (index == -1) - m_qobjectsToBeDeleted.append(object); - } else { - delete object; - } -} - -void QScriptEnginePrivate::deletePendingQObjects() -{ - while (!m_qobjectsToBeDeleted.isEmpty()) - delete m_qobjectsToBeDeleted.takeFirst(); -} - -bool QScriptEnginePrivate::scriptConnect(QObject *sender, const char *signal, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function, - Qt::ConnectionType type) -{ - Q_ASSERT(sender); - Q_ASSERT(signal); - const QMetaObject *meta = sender->metaObject(); - int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1)); - if (index == -1) - return false; - return scriptConnect(sender, index, receiver, function, /*wrapper=*/QScriptValueImpl(), type); -} - -bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, const char *signal, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function) -{ - Q_ASSERT(sender); - Q_ASSERT(signal); - const QMetaObject *meta = sender->metaObject(); - int index = meta->indexOfSignal(QMetaObject::normalizedSignature(signal+1)); - if (index == -1) - return false; - return scriptDisconnect(sender, index, receiver, function); -} - -bool QScriptEnginePrivate::scriptConnect(QObject *sender, int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function, - const QScriptValueImpl &senderWrapper, - Qt::ConnectionType type) -{ - QScriptQObjectData *data = qobjectData(sender); - return data->addSignalHandler(sender, signalIndex, receiver, function, senderWrapper, type); -} - -bool QScriptEnginePrivate::scriptDisconnect(QObject *sender, int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function) -{ - QScriptQObjectData *data = qobjectData(sender); - if (!data) - return false; - return data->removeSignalHandler(sender, signalIndex, receiver, function); -} - -bool QScriptEnginePrivate::scriptConnect(const QScriptValueImpl &signal, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function, - Qt::ConnectionType type) -{ - QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(signal.toFunction()); - int index = fun->mostGeneralMethod(); - return scriptConnect(fun->qobject(), index, receiver, function, fun->object(), type); -} - -bool QScriptEnginePrivate::scriptDisconnect(const QScriptValueImpl &signal, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function) -{ - QScript::QtFunction *fun = static_cast<QScript::QtFunction*>(signal.toFunction()); - int index = fun->mostGeneralMethod(); - return scriptDisconnect(fun->qobject(), index, receiver, function); -} - -bool QScriptEnginePrivate::convertToNativeQObject(const QScriptValueImpl &value, - const QByteArray &targetType, - void **result) -{ - if (!targetType.endsWith('*')) - return false; - if (QObject *qobject = value.toQObject()) { - int start = targetType.startsWith("const ") ? 6 : 0; - QByteArray className = targetType.mid(start, targetType.size()-start-1); - if (void *instance = qobject->qt_metacast(className)) { - *result = instance; - return true; - } - } - return false; -} - -#endif // QT_NO_QOBJECT - -void QScriptEnginePrivate::setAgent(QScriptEngineAgent *agent) -{ - Q_Q(QScriptEngine); - if (agent && (agent->engine() != q)) { - qWarning("QScriptEngine::setAgent(): " - "cannot set agent belonging to different engine"); - return; - } - if (agent) { - int index = m_agents.indexOf(agent); - if (index == -1) - m_agents.append(agent); - } - m_agent = agent; -} - -QScriptEngineAgent *QScriptEnginePrivate::agent() const -{ - return m_agent; -} - -void QScriptEnginePrivate::agentDeleted(QScriptEngineAgent *agent) -{ - m_agents.removeOne(agent); - if (m_agent == agent) - m_agent = 0; -} - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY -qint64 QScriptEnginePrivate::nextScriptId() -{ - // ### reuse IDs by using a pool - return m_scriptCounter++; -} - -void QScriptEnginePrivate::notifyScriptLoad_helper(qint64 id, const QString &program, - const QString &fileName, int lineNumber) -{ - m_agent->scriptLoad(id, program, fileName, lineNumber); -} - -void QScriptEnginePrivate::notifyScriptUnload_helper(qint64 id) -{ - m_agent->scriptUnload(id); -} - -void QScriptEnginePrivate::notifyPositionChange_helper(QScriptContextPrivate *ctx) -{ - m_agent->positionChange(ctx->scriptId(), ctx->currentLine, ctx->currentColumn); -} - -void QScriptEnginePrivate::notifyContextPush_helper() -{ - m_agent->contextPush(); -} - -void QScriptEnginePrivate::notifyContextPop_helper() -{ - m_agent->contextPop(); -} - -void QScriptEnginePrivate::notifyFunctionEntry_helper(QScriptContextPrivate *ctx) -{ - m_agent->functionEntry(ctx->scriptId()); -} - -void QScriptEnginePrivate::notifyFunctionExit_helper(QScriptContextPrivate *ctx) -{ - m_agent->functionExit(ctx->scriptId(), toPublic(ctx->returnValue())); -} - -void QScriptEnginePrivate::notifyException_helper(QScriptContextPrivate *ctx) -{ - bool hasHandler = (ctx->exceptionHandlerContext() != 0); - m_agent->exceptionThrow(ctx->scriptId(), toPublic(ctx->returnValue()), hasHandler); -} - -void QScriptEnginePrivate::notifyExceptionCatch_helper(QScriptContextPrivate *ctx) -{ - m_agent->exceptionCatch(ctx->scriptId(), toPublic(ctx->returnValue())); -} - -void QScriptEnginePrivate::notifyDebugger(QScriptContextPrivate *ctx) -{ - if (m_agent && m_agent->supportsExtension(QScriptEngineAgent::DebuggerInvocationRequest)) { - QVariantList args; - args.append(ctx->scriptId()); - args.append(ctx->currentLine); - args.append(ctx->currentColumn); - QVariant ret = m_agent->extension(QScriptEngineAgent::DebuggerInvocationRequest, args); - QScriptValueImpl val = valueFromVariant(ret); - if (val.isValid()) - ctx->m_result = val; - } -} - -#endif // Q_SCRIPT_NO_EVENT_NOTIFY - -QScriptString QScriptEnginePrivate::internedString(const QString &str) -{ - return internedString(nameId(str, /*persistent=*/false)); -} - -QScriptString QScriptEnginePrivate::internedString(QScriptNameIdImpl *nid) -{ - if (!nid) - return QScriptString(); - QScriptStringPrivate *d = m_internedStrings.value(nid); - if (!d) { - d = m_internedStringRepository.get(); - d->nameId = nid; - d->engine = this; - m_internedStrings.insert(d->nameId, d); - } - QScriptString result; - QScriptStringPrivate::init(result, d); - return result; -} - -void QScriptEnginePrivate::uninternString(QScriptStringPrivate *d) -{ - Q_ASSERT(d->nameId); - QHash<QScriptNameIdImpl*, QScriptStringPrivate*>::iterator it; - it = m_internedStrings.find(d->nameId); - Q_ASSERT(it != m_internedStrings.end()); - m_internedStrings.erase(it); - m_internedStringRepository.release(d); -} - -QScriptValueImpl QScriptEnginePrivate::toImpl_helper(const QScriptValue &value) -{ - QScriptValuePrivate *p = QScriptValuePrivate::get(value); - Q_ASSERT(p != 0); - Q_ASSERT(p->value.type() == QScript::LazyStringType); - QString str = *p->value.m_lazy_string_value; - if (!p->ref.deref()) - delete p; - QScriptValueImpl v; - newString(&v, str); - p = registerValue(v); - QScriptValuePrivate::init(const_cast<QScriptValue&>(value), p); - return v; -} - -QScriptValueImpl QScriptEnginePrivate::newObject(QScriptClass *scriptClass, - const QScriptValueImpl &data) -{ - if (!scriptClass) - return QScriptValueImpl(); - QScriptValueImpl v; - QScriptValueImpl proto = toImpl(scriptClass->prototype()); - if (!proto.isObject()) - proto = objectConstructor->publicPrototype; - newObject(&v, proto); - QScriptClassPrivate *cls_p = QScriptClassPrivate::get(scriptClass); - QScriptClassInfo *info = cls_p->classInfo(); - v.setClassInfo(info); - if (info->type() & QScriptClassInfo::FunctionBased) { - QScriptFunction *fun = cls_p->newFunction(); - v.setObjectData(fun); - } - v.setInternalValue(data); - return v; -} - -int QScriptEnginePrivate::registerCustomClassType() -{ - return ++m_class_prev_id; -} - -QScriptValueImpl QScriptEnginePrivate::objectById(qint64 id) const -{ - QScript::GCAlloc<QScriptObject>::const_iterator it; - for (it = objectAllocator.constBegin(); it != objectAllocator.constEnd(); ++it) { - const QScriptObject *obj = it.data(); - if (obj->m_id == id) { - QScriptValueImpl ret; - ret.m_type = QScript::ObjectType; - ret.m_object_value = const_cast<QScriptObject*>(obj); - return ret; - } - } - return QScriptValueImpl(); -} - -namespace QScript { - -static QScriptValueImpl qsTranslate(QScriptContextPrivate *ctx, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - if (ctx->argumentCount() < 2) - return ctx->throwError(QString::fromLatin1("qsTranslate() requires at least two arguments")); - if (!ctx->argument(0).isString()) - return ctx->throwError(QString::fromLatin1("qsTranslate(): first argument (context) must be a string")); - if (!ctx->argument(1).isString()) - return ctx->throwError(QString::fromLatin1("qsTranslate(): second argument (text) must be a string")); - if ((ctx->argumentCount() > 2) && !ctx->argument(2).isString()) - return ctx->throwError(QString::fromLatin1("qsTranslate(): third argument (comment) must be a string")); - if ((ctx->argumentCount() > 3) && !ctx->argument(3).isString()) - return ctx->throwError(QString::fromLatin1("qsTranslate(): fourth argument (encoding) must be a string")); - if ((ctx->argumentCount() > 4) && !ctx->argument(4).isNumber()) - return ctx->throwError(QString::fromLatin1("qsTranslate(): fifth argument (n) must be a number")); -#ifndef QT_NO_QOBJECT - QString context = ctx->argument(0).toString(); -#endif - QString text = ctx->argument(1).toString(); -#ifndef QT_NO_QOBJECT - QString comment; - if (ctx->argumentCount() > 2) - comment = ctx->argument(2).toString(); - QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr; - if (ctx->argumentCount() > 3) { - QString encStr = ctx->argument(3).toString(); - if (encStr == QLatin1String("CodecForTr")) - encoding = QCoreApplication::CodecForTr; - else if (encStr == QLatin1String("UnicodeUTF8")) - encoding = QCoreApplication::UnicodeUTF8; - else - return ctx->throwError(QString::fromLatin1("qsTranslate(): invalid encoding '%s'").arg(encStr)); - } - int n = -1; - if (ctx->argumentCount() > 4) - n = ctx->argument(4).toInt32(); -#endif - QString result; -#ifndef QT_NO_QOBJECT - result = QCoreApplication::translate(context.toLatin1().constData(), - text.toLatin1().constData(), - comment.toLatin1().constData(), - encoding, n); -#else - result = text; -#endif - return QScriptValueImpl(eng, result); -} - -static QScriptValueImpl qTranslateNoOp(QScriptContextPrivate *ctx, QScriptEnginePrivate *, QScriptClassInfo *) -{ - return ctx->argument(1); -} - -static QScriptValueImpl qsTr(QScriptContextPrivate *ctx, QScriptEnginePrivate *eng, QScriptClassInfo *) -{ - if (ctx->argumentCount() < 1) - return ctx->throwError(QString::fromLatin1("qsTr() requires at least one argument")); - if (!ctx->argument(0).isString()) - return ctx->throwError(QString::fromLatin1("qsTr(): first argument (text) must be a string")); - if ((ctx->argumentCount() > 1) && !ctx->argument(1).isString()) - return ctx->throwError(QString::fromLatin1("qsTr(): second argument (comment) must be a string")); - if ((ctx->argumentCount() > 2) && !ctx->argument(2).isNumber()) - return ctx->throwError(QString::fromLatin1("qsTranslate(): third argument (n) must be a number")); -#ifndef QT_NO_QOBJECT - QString context; - if (ctx->parentContext()) - context = QFileInfo(ctx->parentContext()->fileName()).baseName(); -#endif - QString text = ctx->argument(0).toString(); -#ifndef QT_NO_QOBJECT - QString comment; - if (ctx->argumentCount() > 1) - comment = ctx->argument(1).toString(); - int n = -1; - if (ctx->argumentCount() > 2) - n = ctx->argument(2).toInt32(); -#endif - QString result; -#ifndef QT_NO_QOBJECT - result = QCoreApplication::translate(context.toLatin1().constData(), - text.toLatin1().constData(), - comment.toLatin1().constData(), - QCoreApplication::CodecForTr, n); -#else - result = text; -#endif - return QScriptValueImpl(eng, result); -} - -static QScriptValueImpl qTrNoOp(QScriptContextPrivate *ctx, QScriptEnginePrivate *, QScriptClassInfo *) -{ - return ctx->argument(0); -} - -} // namespace QScript - -void QScriptEnginePrivate::installTranslatorFunctions(QScriptValueImpl &object) -{ - Q_ASSERT(object.isObject()); - const QScriptValue::PropertyFlags flags = QScriptValue::SkipInEnumeration; - object.setProperty(QLatin1String("qsTranslate"), - createFunction(QScript::qsTranslate, /*length=*/5, /*classInfo=*/0), - flags); - object.setProperty(QLatin1String("QT_TRANSLATE_NOOP"), - createFunction(QScript::qTranslateNoOp, /*length=*/2, /*classInfo=*/0), - flags); - object.setProperty(QLatin1String("qsTr"), - createFunction(QScript::qsTr, /*length=*/3, /*classInfo=*/0), - flags); - object.setProperty(QLatin1String("QT_TR_NOOP"), - createFunction(QScript::qTrNoOp, /*length=*/1, /*classInfo=*/0), - flags); - - stringConstructor->addPrototypeFunction(QLatin1String("arg"), QScript::Ecma::String::method_ext_arg, 1); -} - -bool QScriptEnginePrivate::canEvaluate(const QString &program) -{ - QScript::SyntaxChecker checker; - QScript::SyntaxChecker::Result result = checker.checkSyntax(program); - return (result.state != QScript::SyntaxChecker::Intermediate); -} - -QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &program) -{ - QScript::SyntaxChecker checker; - QScript::SyntaxChecker::Result result = checker.checkSyntax(program); - QScriptSyntaxCheckResultPrivate *p = new QScriptSyntaxCheckResultPrivate(); - switch (result.state) { - case QScript::SyntaxChecker::Error: - p->state = QScriptSyntaxCheckResult::Error; - break; - case QScript::SyntaxChecker::Intermediate: - p->state = QScriptSyntaxCheckResult::Intermediate; - break; - case QScript::SyntaxChecker::Valid: - p->state = QScriptSyntaxCheckResult::Valid; - break; - } - p->errorLineNumber = result.errorLineNumber; - p->errorColumnNumber = result.errorColumnNumber; - p->errorMessage = result.errorMessage; - return QScriptSyntaxCheckResult(p); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptengine_p.h b/src/script/qscriptengine_p.h deleted file mode 100644 index f3fb57f..0000000 --- a/src/script/qscriptengine_p.h +++ /dev/null @@ -1,828 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTENGINE_P_H -#define QSCRIPTENGINE_P_H - -#include "qscriptenginefwd_p.h" - -#ifndef QT_NO_SCRIPT - -#include <QtCore/QDateTime> -#include <QtCore/QMutex> -#include <QtCore/QLinkedList> -#include <QtCore/QString> -#include <QtCore/QVector> -#include <QtCore/QHash> -#include <QtCore/qnumeric.h> - -#include "qscriptengine.h" -#include "qscriptnameid_p.h" -#include "qscriptobjectfwd_p.h" -#include "qscriptrepository_p.h" -#include "qscriptgc_p.h" -#include "qscriptecmaarray_p.h" -#include "qscriptecmadate_p.h" -#include "qscriptecmaobject_p.h" -#include "qscriptecmaboolean_p.h" -#include "qscriptecmanumber_p.h" -#include "qscriptecmastring_p.h" -#include "qscriptecmafunction_p.h" -#include "qscriptextvariant_p.h" -#include "qscriptextqobject_p.h" -#include "qscriptvalue_p.h" -#include "qscriptcontextfwd_p.h" - -#include <math.h> - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -namespace QScript { - -class ArgumentsObjectData: public QScriptObjectData -{ -public: - ArgumentsObjectData() : length(0) {} - virtual ~ArgumentsObjectData() {} - -public: // attributes - QScriptValueImpl activation; - uint length; -}; - -} // namespace QScript - -inline QScriptEnginePrivate *QScriptEnginePrivate::get(QScriptEngine *q) -{ - if (q) - return q->d_func(); - return 0; -} - -inline const QScriptEnginePrivate *QScriptEnginePrivate::get(const QScriptEngine *q) -{ - if (q) - return q->d_func(); - return 0; -} - -inline QScriptEngine *QScriptEnginePrivate::get(QScriptEnginePrivate *d) -{ - return d->q_func(); -} - -inline QString QScriptEnginePrivate::toString(QScriptNameIdImpl *id) -{ - if (! id) - return QString(); - - return id->s; -} - -inline QString QScriptEnginePrivate::memberName(const QScript::Member &member) const -{ - return toString(member.nameId()); -} - -inline void QScriptEnginePrivate::newReference(QScriptValueImpl *o, int mode) -{ - Q_ASSERT(o); - o->m_type = QScript::ReferenceType; - o->m_int_value = (mode); -} - -inline void QScriptEnginePrivate::newActivation(QScriptValueImpl *o) -{ - Q_ASSERT(o); - newObject(o, nullValue(), m_class_activation); -} - -inline void QScriptEnginePrivate::newPointer(QScriptValueImpl *o, void *ptr) -{ - Q_ASSERT(o); - o->m_type = QScript::PointerType; - o->m_ptr_value = ptr; -} - -inline void QScriptEnginePrivate::newInteger(QScriptValueImpl *o, int i) -{ - Q_ASSERT(o); - o->m_type = QScript::IntegerType; - o->m_int_value = (i); -} - -inline void QScriptEnginePrivate::newNameId(QScriptValueImpl *o, const QString &s) -{ - Q_ASSERT(o); - o->m_type = QScript::StringType; - o->m_string_value = (nameId(s, /*persistent=*/false)); -} - -inline void QScriptEnginePrivate::newString(QScriptValueImpl *o, const QString &s) -{ - Q_ASSERT(o); - o->m_type = QScript::StringType; - QScriptNameIdImpl *entry = new QScriptNameIdImpl(s); - m_tempStringRepository.append(entry); - o->m_string_value = (entry); - m_newAllocatedTempStringRepositoryChars += s.length(); -} - -inline void QScriptEnginePrivate::newNameId(QScriptValueImpl *o, QScriptNameIdImpl *id) -{ - Q_ASSERT(o); - o->m_type = QScript::StringType; - o->m_string_value = (id); -} - -inline const QScript::IdTable *QScriptEnginePrivate::idTable() const -{ - return &m_id_table; -} - -inline qsreal QScriptEnginePrivate::convertToNativeDouble(const QScriptValueImpl &value) -{ - Q_ASSERT (value.isValid()); - - if (value.isNumber()) - return value.m_number_value; - - return convertToNativeDouble_helper(value); -} - -inline qint32 QScriptEnginePrivate::convertToNativeInt32(const QScriptValueImpl &value) -{ - Q_ASSERT (value.isValid()); - - return toInt32 (convertToNativeDouble(value)); -} - - -inline bool QScriptEnginePrivate::convertToNativeBoolean(const QScriptValueImpl &value) -{ - Q_ASSERT (value.isValid()); - - if (value.isBoolean()) - return value.m_bool_value; - - return convertToNativeBoolean_helper(value); -} - -inline QString QScriptEnginePrivate::convertToNativeString(const QScriptValueImpl &value) -{ - Q_ASSERT (value.isValid()); - - if (value.isString()) - return value.m_string_value->s; - - return convertToNativeString_helper(value); -} - -inline qsreal QScriptEnginePrivate::toInteger(qsreal n) -{ - if (qIsNaN(n)) - return 0; - - if (n == 0 || qIsInf(n)) - return n; - - int sign = n < 0 ? -1 : 1; - return sign * ::floor(::fabs(n)); -} - -inline qint32 QScriptEnginePrivate::toInt32(qsreal n) -{ - if (qIsNaN(n) || qIsInf(n) || (n == 0)) - return 0; - - double sign = (n < 0) ? -1.0 : 1.0; - qsreal abs_n = fabs(n); - - n = ::fmod(sign * ::floor(abs_n), D32); - const double D31 = D32 / 2.0; - - if (sign == -1 && n < -D31) - n += D32; - - else if (sign != -1 && n >= D31) - n -= D32; - - return qint32 (n); -} - -inline quint32 QScriptEnginePrivate::toUint32(qsreal n) -{ - if (qIsNaN(n) || qIsInf(n) || (n == 0)) - return 0; - - double sign = (n < 0) ? -1.0 : 1.0; - qsreal abs_n = fabs(n); - - n = ::fmod(sign * ::floor(abs_n), D32); - - if (n < 0) - n += D32; - - return quint32 (n); -} - -inline quint16 QScriptEnginePrivate::toUint16(qsreal n) -{ - if (qIsNaN(n) || qIsInf(n) || (n == 0)) - return 0; - - double sign = (n < 0) ? -1.0 : 1.0; - qsreal abs_n = fabs(n); - - n = ::fmod(sign * ::floor(abs_n), D16); - - if (n < 0) - n += D16; - - return quint16 (n); -} - -inline QScript::AST::Node *QScriptEnginePrivate::abstractSyntaxTree() const -{ - return m_abstractSyntaxTree; -} - -inline QScript::MemoryPool *QScriptEnginePrivate::nodePool() -{ - return m_pool; -} - -inline void QScriptEnginePrivate::setNodePool(QScript::MemoryPool *pool) -{ - m_pool = pool; -} - -inline QScript::Lexer *QScriptEnginePrivate::lexer() -{ - return m_lexer; -} - -inline void QScriptEnginePrivate::setLexer(QScript::Lexer *lexer) -{ - m_lexer = lexer; -} - -inline QScriptObject *QScriptEnginePrivate::allocObject() -{ - return objectAllocator(m_objectGeneration); -} - -inline QScriptContextPrivate *QScriptEnginePrivate::currentContext() const -{ - return m_context; -} - -inline QScriptContextPrivate *QScriptEnginePrivate::pushContext() -{ - QScriptContext *context = m_frameRepository.get(); - QScriptContextPrivate *ctx_p = QScriptContextPrivate::get(context); - ctx_p->init(m_context); - m_context = ctx_p; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - notifyContextPush(); -#endif - return m_context; -} - -inline void QScriptEnginePrivate::popContext() -{ - Q_ASSERT(m_context != 0); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - notifyContextPop(); -#endif - QScriptContextPrivate *context = m_context; - m_context = context->parentContext(); - if (m_context) { - QScriptContextPrivate *p1 = m_context; - QScriptContextPrivate *p2 = context; - if ((p1->m_state != QScriptContext::ExceptionState) - || (p2->m_state == QScriptContext::ExceptionState)) { - // propagate the state - p1->m_result = p2->m_result; - p1->m_state = p2->m_state; - // only update errorLineNumber if there actually was an exception - if (p2->m_state == QScriptContext::ExceptionState) { - if (p2->errorLineNumber != -1) - p1->errorLineNumber = p2->errorLineNumber; - else - p1->errorLineNumber = p1->currentLine; - } - } - } - m_frameRepository.release(QScriptContextPrivate::get(context)); -} - -inline void QScriptEnginePrivate::maybeGC() -{ - if (objectAllocator.blocked()) - return; - - bool do_string_gc = ((m_stringRepository.size() - m_oldStringRepositorySize) > 256) - || (m_newAllocatedStringRepositoryChars > 0x800000); - do_string_gc |= ((m_tempStringRepository.size() - m_oldTempStringRepositorySize) > 1024) - || (m_newAllocatedTempStringRepositoryChars > 0x800000); - - if (! do_string_gc && ! objectAllocator.poll()) - return; - - maybeGC_helper(do_string_gc); -} - -inline void QScriptEnginePrivate::adjustBytesAllocated(int bytes) -{ - objectAllocator.adjustBytesAllocated(bytes); -} - -inline bool QScriptEnginePrivate::blockGC(bool block) -{ - return objectAllocator.blockGC(block); -} - -inline void QScriptEnginePrivate::markString(QScriptNameIdImpl *id, int /*generation*/) -{ - id->used = true; -} - -inline QScriptValueImpl QScriptEnginePrivate::createFunction(QScriptFunction *fun) -{ - QScriptValueImpl v; - newFunction(&v, fun); - return v; -} - -inline QScriptValueImpl QScriptEnginePrivate::newArray(const QScript::Array &value) -{ - QScriptValueImpl v; - newArray(&v, value); - return v; -} - -inline QScriptValueImpl QScriptEnginePrivate::newArray(uint length) -{ - QScriptValueImpl v; - QScript::Array a(this); - a.resize(length); - newArray(&v, a); - return v; -} - -inline QScriptClassInfo *QScriptEnginePrivate::registerClass(const QString &pname, int type) -{ - if (type == -1) - type = ++m_class_prev_id; - - QScriptClassInfo *oc = new QScriptClassInfo(this, QScriptClassInfo::Type(type), pname); - m_allocated_classes.append(oc); - - return oc; -} - -inline QScriptClassInfo *QScriptEnginePrivate::registerClass(const QString &name) -{ - return registerClass(name, -1); -} - -inline QScriptValueImpl QScriptEnginePrivate::createFunction(QScriptInternalFunctionSignature fun, - int length, QScriptClassInfo *classInfo, const QString &name) -{ - return createFunction(new QScript::C2Function(fun, length, classInfo, name)); -} - -inline void QScriptEnginePrivate::newFunction(QScriptValueImpl *o, QScriptFunction *function) -{ - QScriptValueImpl proto; - if (functionConstructor) - proto = functionConstructor->publicPrototype; - else { - // creating the Function prototype object - Q_ASSERT(objectConstructor); - proto = objectConstructor->publicPrototype; - } - newObject(o, proto, m_class_function); - o->setObjectData(function); -} - -inline void QScriptEnginePrivate::newConstructor(QScriptValueImpl *ctor, - QScriptFunction *function, - QScriptValueImpl &proto) -{ - newFunction(ctor, function); - ctor->setProperty(m_id_table.id_prototype, proto, - QScriptValue::Undeletable - | QScriptValue::ReadOnly - | QScriptValue::SkipInEnumeration); - proto.setProperty(m_id_table.id_constructor, *ctor, - QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration); -} - -inline void QScriptEnginePrivate::newArguments(QScriptValueImpl *object, - const QScriptValueImpl &activation, - uint length, - const QScriptValueImpl &callee) -{ - QScript::ArgumentsObjectData *data = new QScript::ArgumentsObjectData(); - data->activation = activation; - data->length = length; - newObject(object, m_class_arguments); - object->setObjectData(data); - object->setProperty(m_id_table.id_callee, callee, - QScriptValue::SkipInEnumeration); - object->setProperty(m_id_table.id_length, QScriptValueImpl(length), - QScriptValue::SkipInEnumeration); -} - -inline QScriptFunction *QScriptEnginePrivate::convertToNativeFunction(const QScriptValueImpl &object) -{ - if (object.isFunction()) - return static_cast<QScriptFunction*> (object.objectData()); - return 0; -} - -inline QScriptValue QScriptEnginePrivate::toPublic(const QScriptValueImpl &value) -{ - if (!value.isValid()) - return QScriptValue(); - - QScriptValuePrivate *p = registerValue(value); - QScriptValue v; - QScriptValuePrivate::init(v, p); - return v; -} - -inline QScriptValueImpl QScriptEnginePrivate::toImpl(const QScriptValue &value) -{ - QScriptValuePrivate *p = QScriptValuePrivate::get(value); - if (!p) - return QScriptValueImpl(); - if (p->value.type() == QScript::LazyStringType) - return toImpl_helper(value); - return p->value; -} - -inline QScriptValueImplList QScriptEnginePrivate::toImplList(const QScriptValueList &lst) -{ - QScriptValueImplList result; - QScriptValueList::const_iterator it; - for (it = lst.constBegin(); it != lst.constEnd(); ++it) - result.append(toImpl(*it)); - return result; -} - -inline QScriptValueImpl QScriptEnginePrivate::toObject(const QScriptValueImpl &value) -{ - if (value.isObject() || !value.isValid()) - return value; - return toObject_helper(value); -} - -inline QScriptValueImpl QScriptEnginePrivate::toPrimitive(const QScriptValueImpl &object, - QScriptValueImpl::TypeHint hint) -{ - Q_ASSERT(object.isValid()); - - if (! object.isObject()) - return object; - - return toPrimitive_helper(object, hint); -} - -inline QDateTime QScriptEnginePrivate::toDateTime(const QScriptValueImpl &value) const -{ - return dateConstructor->toDateTime(value); -} - -inline void QScriptEnginePrivate::newArray(QScriptValueImpl *object, const QScript::Array &value) -{ - arrayConstructor->newArray(object, value); -} - -inline void QScriptEnginePrivate::newObject(QScriptValueImpl *o, const QScriptValueImpl &proto, - QScriptClassInfo *oc) -{ - Q_ASSERT(o != 0); - - QScriptObject *od = allocObject(); - od->reset(); - od->m_id = ++m_next_object_id; - if (proto.isValid()) - od->m_prototype = proto; - else { - Q_ASSERT(objectConstructor); - od->m_prototype = objectConstructor->publicPrototype; - } - - o->m_type = QScript::ObjectType; - od->m_class = (oc ? oc : m_class_object); - o->m_object_value = od; -} - -inline void QScriptEnginePrivate::newObject(QScriptValueImpl *o, QScriptClassInfo *oc) -{ - newObject(o, objectConstructor->publicPrototype, oc); -} - -inline QScriptValueImpl QScriptEnginePrivate::newObject() -{ - QScriptValueImpl v; - newObject(&v); - return v; -} - -inline void QScriptEnginePrivate::newVariant(QScriptValueImpl *out, - const QVariant &value, - bool setDefaultPrototype) -{ - Q_ASSERT(variantConstructor != 0); - variantConstructor->newVariant(out, value); - if (setDefaultPrototype) { - QScriptValueImpl proto = defaultPrototype(value.userType()); - if (proto.isValid()) - out->setPrototype(proto); - } -} - -#ifndef QT_NO_QOBJECT -# ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE -inline QScriptMetaObject *QScriptEnginePrivate::cachedMetaObject(const QMetaObject *meta) -{ - QScriptMetaObject *value = m_cachedMetaObjects.value(meta); - if (!value) { - value = new QScriptMetaObject; - m_cachedMetaObjects.insert(meta, value); - } - return value; -} -# endif -#endif // !QT_NO_QOBJECT - -inline QScriptNameIdImpl *QScriptEnginePrivate::nameId(const QString &str, bool persistent) -{ - QScriptNameIdImpl *entry = toStringEntry(str); - if (! entry) - entry = insertStringEntry(str); - - Q_ASSERT(entry->unique); - - if (persistent) - entry->persistent = true; - - return entry; -} - -inline QScriptNameIdImpl *QScriptEnginePrivate::intern(const QChar *u, int s) -{ - QString tmp(u, s); - return nameId(tmp, /*persistent=*/ true); -} - -inline QScriptValueImpl QScriptEnginePrivate::valueFromVariant(const QVariant &v) -{ - QScriptValueImpl result = create(v.userType(), v.data()); - Q_ASSERT(result.isValid()); - return result; -} - -inline QScriptValueImpl QScriptEnginePrivate::undefinedValue() -{ - return m_undefinedValue; -} - -inline QScriptValueImpl QScriptEnginePrivate::nullValue() -{ - return m_nullValue; -} - -inline QScriptValueImpl QScriptEnginePrivate::defaultPrototype(int metaTypeId) const -{ - QScriptCustomTypeInfo info = m_customTypes.value(metaTypeId); - return info.prototype; -} - -inline void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, const QScriptValueImpl &prototype) -{ - QScriptCustomTypeInfo info = m_customTypes.value(metaTypeId); - info.prototype = prototype; - m_customTypes.insert(metaTypeId, info); -} - -inline uint _q_scriptHash(const QString &key) -{ - const QChar *p = key.unicode(); - int n = qMin(key.size(), 128); - uint h = key.size(); - uint g; - - while (n--) { - h = (h << 4) + (*p++).unicode(); - if ((g = (h & 0xf0000000)) != 0) - h ^= g >> 23; - h &= ~g; - } - return h; -} - -inline QScriptNameIdImpl *QScriptEnginePrivate::toStringEntry(const QString &s) -{ - uint h = _q_scriptHash(s) % m_string_hash_size; - - for (QScriptNameIdImpl *entry = m_string_hash_base[h]; entry && entry->h == h; entry = entry->next) { - if (entry->s == s) - return entry; - } - - return 0; -} - -inline bool QScriptEnginePrivate::lessThan(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs) -{ - return QScriptContextPrivate::lt_cmp(lhs, rhs); -} - -inline bool QScriptEnginePrivate::equals(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs) -{ - return QScriptContextPrivate::eq_cmp(lhs, rhs); -} - -inline bool QScriptEnginePrivate::strictlyEquals(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs) -{ - return QScriptContextPrivate::strict_eq_cmp(lhs, rhs); -} - -inline void QScriptEnginePrivate::unregisterValue(QScriptValuePrivate *p) -{ - QScriptValueImpl &v = p->value; - Q_ASSERT(v.isValid()); - if (v.isString()) { - QScriptNameIdImpl *id = v.stringValue(); - m_stringHandles.remove(id); - } else if (v.isObject()) { - QScriptObject *instance = v.objectValue(); - m_objectHandles.remove(instance); - } else { - int i = m_otherHandles.indexOf(p); - Q_ASSERT(i != -1); - m_otherHandles.remove(i); - } - m_handleRepository.release(p); -} - -inline QScriptValueImpl QScriptEnginePrivate::globalObject() const -{ - return m_globalObject; -} - -inline bool QScriptEnginePrivate::hasUncaughtException() const -{ - return (currentContext()->state() == QScriptContext::ExceptionState); -} - -inline QScriptValueImpl QScriptEnginePrivate::uncaughtException() const -{ - if (!hasUncaughtException()) - return QScriptValueImpl(); - return currentContext()->returnValue(); -} - -inline void QScriptEnginePrivate::maybeProcessEvents() -{ - if (m_processEventsInterval > 0 && ++m_processEventIncr > 512) { - m_processEventIncr = 0; - processEvents(); - } -} - -inline bool QScriptEnginePrivate::shouldAbort() const -{ - return m_abort; -} - -inline void QScriptEnginePrivate::resetAbortFlag() -{ - m_abort = false; -} - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - -inline bool QScriptEnginePrivate::shouldNotify() const -{ - return m_agent != 0; -} - -inline void QScriptEnginePrivate::notifyScriptLoad( - qint64 id, const QString &program, - const QString &fileName, int lineNumber) -{ - if (shouldNotify()) - notifyScriptLoad_helper(id, program, fileName, lineNumber); -} - -inline void QScriptEnginePrivate::notifyScriptUnload(qint64 id) -{ - if (shouldNotify()) - notifyScriptUnload_helper(id); -} - -inline void QScriptEnginePrivate::notifyPositionChange(QScriptContextPrivate *ctx) -{ - Q_ASSERT(m_agent != 0); - notifyPositionChange_helper(ctx); -} - -inline void QScriptEnginePrivate::notifyContextPush() -{ - if (shouldNotify()) - notifyContextPush_helper(); -} - -inline void QScriptEnginePrivate::notifyContextPop() -{ - if (shouldNotify()) - notifyContextPop_helper(); -} - -inline void QScriptEnginePrivate::notifyFunctionEntry(QScriptContextPrivate *ctx) -{ - if (shouldNotify()) - notifyFunctionEntry_helper(ctx); -} - -inline void QScriptEnginePrivate::notifyFunctionExit(QScriptContextPrivate *ctx) -{ - if (shouldNotify()) - notifyFunctionExit_helper(ctx); -} - -inline void QScriptEnginePrivate::notifyException(QScriptContextPrivate *ctx) -{ - if (shouldNotify()) - notifyException_helper(ctx); -} - -inline void QScriptEnginePrivate::notifyExceptionCatch(QScriptContextPrivate *ctx) -{ - if (shouldNotify()) - notifyExceptionCatch_helper(ctx); -} - -#endif // Q_SCRIPT_NO_EVENT_NOTIFY - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptengineagent_p.h b/src/script/qscriptengineagent_p.h deleted file mode 100644 index b4f5454..0000000 --- a/src/script/qscriptengineagent_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTENGINEAGENT_P_H -#define QSCRIPTENGINEAGENT_P_H - -#include <QtCore/qobjectdefs.h> - -#ifndef QT_NO_SCRIPT - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -QT_BEGIN_NAMESPACE - -class QScriptEngine; - -class QScriptEngineAgent; -class Q_SCRIPT_EXPORT QScriptEngineAgentPrivate -{ - Q_DECLARE_PUBLIC(QScriptEngineAgent) -public: - QScriptEngineAgentPrivate(); - virtual ~QScriptEngineAgentPrivate(); - - QScriptEngine *engine; - - QScriptEngineAgent *q_ptr; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptenginefwd_p.h b/src/script/qscriptenginefwd_p.h deleted file mode 100644 index fa539a5..0000000 --- a/src/script/qscriptenginefwd_p.h +++ /dev/null @@ -1,563 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTENGINEFWD_P_H -#define QSCRIPTENGINEFWD_P_H - -#ifndef QT_NO_QOBJECT -#include "private/qobject_p.h" -#endif - -#ifndef QT_NO_SCRIPT - -#include <QtCore/qobjectdefs.h> - -#include <QtCore/QHash> -#include <QtCore/QList> -#include <QtCore/QRegExp> -#include <QtCore/QSet> -#include <QtCore/QStringList> -#include <QtCore/QTime> -#include <QtCore/QVector> - -#include "qscriptengine.h" -#include "qscriptrepository_p.h" -#include "qscriptgc_p.h" -#include "qscriptobjectfwd_p.h" -#include "qscriptclassinfo_p.h" -#include "qscriptstring_p.h" - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -class QScriptClass; -class QScriptContext; - -namespace QScript { - -namespace AST { - class Node; -} // namespace AST - -namespace Ecma { - class Object; - class Number; - class Boolean; - class String; - class Math; - class Date; - class Function; - class Array; - class RegExp; - class Error; -} // namespace Ecma - -namespace Ext { - class Enumeration; - class Variant; -} // namespace Ext - -class ExtQObject; -class ExtQMetaObject; - -class Array; -class Lexer; -class Code; -class CompilationUnit; -class IdTable; -class MemoryPool; - -class IdTable -{ -public: - inline IdTable() - : id_constructor(0), id_false(0), id_null(0), - id_object(0), id_pointer(0), id_prototype(0), - id_arguments(0), id_this(0), id_toString(0), - id_true(0), id_undefined(0), id_valueOf(0), - id_length(0), id_callee(0), id___proto__(0), - id___qt_sender__(0) - {} - - QScriptNameIdImpl *id_constructor; - QScriptNameIdImpl *id_false; - QScriptNameIdImpl *id_null; - QScriptNameIdImpl *id_object; - QScriptNameIdImpl *id_pointer; - QScriptNameIdImpl *id_prototype; - QScriptNameIdImpl *id_arguments; - QScriptNameIdImpl *id_this; - QScriptNameIdImpl *id_toString; - QScriptNameIdImpl *id_true; - QScriptNameIdImpl *id_undefined; - QScriptNameIdImpl *id_valueOf; - QScriptNameIdImpl *id_length; - QScriptNameIdImpl *id_callee; - QScriptNameIdImpl *id___proto__; - QScriptNameIdImpl *id___qt_sender__; -}; - -} // namespace QScript - -#ifndef QT_NO_QOBJECT -class QScriptQObjectData; -class QScriptMetaObject; -#endif - -class QScriptCustomTypeInfo -{ -public: - QScriptCustomTypeInfo() : signature(0, '\0'), marshal(0), demarshal(0) - { prototype.invalidate(); } - - QByteArray signature; - QScriptEngine::MarshalFunction marshal; - QScriptEngine::DemarshalFunction demarshal; - QScriptValueImpl prototype; -}; - -class QScriptEnginePrivate -#ifndef QT_NO_QOBJECT - : public QObjectPrivate -#endif -{ - Q_DECLARE_PUBLIC(QScriptEngine) - - enum { - DefaultHashSize = 1021 - }; - -public: - QScriptEnginePrivate(); - virtual ~QScriptEnginePrivate(); - - void init(); - void initStringRepository(); - - static inline QScriptEnginePrivate *get(QScriptEngine *q); - static inline const QScriptEnginePrivate *get(const QScriptEngine *q); - static inline QScriptEngine *get(QScriptEnginePrivate *d); - - QScript::AST::Node *createAbstractSyntaxTree( - const QString &source, int lineNumber, - QString *errorMessage, int *errorLineNumber); - QScript::AST::Node *changeAbstractSyntaxTree(QScript::AST::Node *program); - - inline QScript::AST::Node *abstractSyntaxTree() const; - inline bool hasUncaughtException() const; - inline QScriptValueImpl uncaughtException() const; - QStringList uncaughtExceptionBacktrace() const; - void clearExceptions(); -#ifndef QT_NO_QOBJECT - void emitSignalHandlerException(); -#endif - - static bool canEvaluate(const QString &program); - static QScriptSyntaxCheckResult checkSyntax(const QString &program); - - inline QScriptContextPrivate *currentContext() const; - inline QScriptContextPrivate *pushContext(); - inline void popContext(); - - inline QScript::MemoryPool *nodePool(); - inline QScript::Lexer *lexer(); - inline QScriptObject *allocObject(); - - inline void maybeGC(); - - void maybeGC_helper(bool do_string_gc); - - inline bool blockGC(bool block); - - void gc(); - bool isCollecting() const; - void processMarkStack(int generation); - - inline void adjustBytesAllocated(int bytes); - - void markObject(const QScriptValueImpl &object, int generation); - void markFrame(QScriptContextPrivate *context, int generation); - - inline void markString(QScriptNameIdImpl *id, int generation); - - inline QScriptValueImpl createFunction(QScriptFunction *fun); - inline QScriptValueImpl newArray(const QScript::Array &value); - inline QScriptValueImpl newArray(uint length = 0); - - void evaluate(QScriptContextPrivate *context, const QString &contents, - int lineNumber, const QString &fileName = QString()); - - inline void setLexer(QScript::Lexer *lexer); - - inline void setNodePool(QScript::MemoryPool *pool); - - inline QScriptClassInfo *registerClass(const QString &pname, int type); - - inline QScriptClassInfo *registerClass(const QString &name); - - int registerCustomClassType(); - - inline QScriptValueImpl createFunction(QScriptInternalFunctionSignature fun, - int length, QScriptClassInfo *classInfo, - const QString &name = QString()); - - static inline QString toString(QScriptNameIdImpl *id); - inline QString memberName(const QScript::Member &member) const; - inline void newReference(QScriptValueImpl *object, int mode); - inline void newActivation(QScriptValueImpl *object); - inline void newFunction(QScriptValueImpl *object, QScriptFunction *function); - inline void newConstructor(QScriptValueImpl *ctor, QScriptFunction *function, - QScriptValueImpl &proto); - inline void newInteger(QScriptValueImpl *object, int i); - inline void newPointer(QScriptValueImpl *object, void *ptr); - inline void newNameId(QScriptValueImpl *object, const QString &s); - inline void newNameId(QScriptValueImpl *object, QScriptNameIdImpl *id); - inline void newString(QScriptValueImpl *object, const QString &s); - inline void newArguments(QScriptValueImpl *object, const QScriptValueImpl &activation, - uint length, const QScriptValueImpl &callee); - static inline QString convertToNativeString(const QScriptValueImpl &value); - static QString convertToNativeString_helper(const QScriptValueImpl &value); - static inline qsreal convertToNativeDouble(const QScriptValueImpl &value); - static qsreal convertToNativeDouble_helper(const QScriptValueImpl &value); - static inline bool convertToNativeBoolean(const QScriptValueImpl &value); - static bool convertToNativeBoolean_helper(const QScriptValueImpl &value); - static inline qint32 convertToNativeInt32(const QScriptValueImpl &value); - static inline QScriptFunction *convertToNativeFunction(const QScriptValueImpl &value); - - inline QScriptValue toPublic(const QScriptValueImpl &value); - inline QScriptValueImpl toImpl(const QScriptValue &value); - QScriptValueImpl toImpl_helper(const QScriptValue &value); - inline QScriptValueImplList toImplList(const QScriptValueList &lst); - - inline const QScript::IdTable *idTable() const; - - inline QScriptValueImpl toObject(const QScriptValueImpl &value); - QScriptValueImpl toObject_helper(const QScriptValueImpl &value); - - inline QScriptValueImpl toPrimitive(const QScriptValueImpl &object, - QScriptValueImpl::TypeHint hint = QScriptValueImpl::NoTypeHint); - QScriptValueImpl toPrimitive_helper(const QScriptValueImpl &object, - QScriptValueImpl::TypeHint hint); - - static const qsreal D16; - static const qsreal D32; - - inline static qsreal toInteger(qsreal n); - inline static qint32 toInt32(qsreal m); - inline static quint32 toUint32(qsreal n); - inline static quint16 toUint16(qsreal n); - - inline QDateTime toDateTime(const QScriptValueImpl &value) const; - - inline void newArray(QScriptValueImpl *object, const QScript::Array &value); - - inline void newObject(QScriptValueImpl *o, const QScriptValueImpl &proto, - QScriptClassInfo *oc = 0); - inline void newObject(QScriptValueImpl *o, QScriptClassInfo *oc = 0); - QScriptValueImpl newObject(QScriptClass *scriptClass, const QScriptValueImpl &data); - - inline QScriptValueImpl newObject(); - - inline void newVariant(QScriptValueImpl *out, const QVariant &value, - bool setDefaultPrototype = true); - -#ifndef QT_NO_QOBJECT - void newQObject(QScriptValueImpl *out, QObject *object, - QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership, - const QScriptEngine::QObjectWrapOptions &options = 0, - bool setDefaultPrototype = true); - -# ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - inline QScriptMetaObject *cachedMetaObject(const QMetaObject *meta); -# endif -#endif - - inline QScriptNameIdImpl *nameId(const QString &str, bool persistent = false); - - inline QScriptNameIdImpl *intern(const QChar *u, int s); - - QScriptString internedString(const QString &str); - QScriptString internedString(QScriptNameIdImpl *nid); - void uninternString(QScriptStringPrivate *d); - - inline QScriptValueImpl valueFromVariant(const QVariant &v); - - inline QScriptValueImpl undefinedValue(); - - inline QScriptValueImpl nullValue(); - - inline QScriptValueImpl defaultPrototype(int metaTypeId) const; - - inline void setDefaultPrototype(int metaTypeId, const QScriptValueImpl &prototype); - - QScriptValueImpl call(const QScriptValueImpl &callee, const QScriptValueImpl &thisObject, - const QScriptValueImplList &args, bool asConstructor); - QScriptValueImpl call(const QScriptValueImpl &callee, const QScriptValueImpl &thisObject, - const QScriptValueImpl &args, bool asConstructor); - - void rehashStringRepository(bool resize = true); - inline QScriptNameIdImpl *toStringEntry(const QString &s); - QScriptNameIdImpl *insertStringEntry(const QString &s); - - QScriptValueImpl create(int type, const void *ptr); - static bool convert(const QScriptValueImpl &value, int type, void *ptr, - QScriptEnginePrivate *eng); - QScriptEngine::DemarshalFunction demarshalFunction(int type) const; - - QScriptValueImpl arrayFromStringList(const QStringList &lst); - static QStringList stringListFromArray(const QScriptValueImpl &arr); - - QScriptValueImpl arrayFromVariantList(const QVariantList &lst); - static QVariantList variantListFromArray(const QScriptValueImpl &arr); - - QScriptValueImpl objectFromVariantMap(const QVariantMap &vmap); - static QVariantMap variantMapFromObject(const QScriptValueImpl &obj); - - static inline bool lessThan(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs); - static inline bool equals(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs); - static inline bool strictlyEquals(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs); - - QScriptValuePrivate *registerValue(const QScriptValueImpl &value); - inline void unregisterValue(QScriptValuePrivate *p); - - inline QScriptValueImpl globalObject() const; - - QScriptValueImpl objectById(qint64 id) const; - - QScriptValueImpl importExtension(const QString &extension); - QStringList availableExtensions() const; - QStringList importedExtensions() const; - - inline void maybeProcessEvents(); - void setupProcessEvents(); - void processEvents(); - -#ifndef QT_NO_QOBJECT - QScriptQObjectData *qobjectData(QObject *object); - - bool scriptConnect(QObject *sender, const char *signal, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function, - Qt::ConnectionType type); - bool scriptDisconnect(QObject *sender, const char *signal, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function); - - bool scriptConnect(QObject *sender, int index, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function, - const QScriptValueImpl &senderWrapper, - Qt::ConnectionType type); - bool scriptDisconnect(QObject *sender, int index, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function); - - bool scriptConnect(const QScriptValueImpl &signal, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function, - Qt::ConnectionType type); - bool scriptDisconnect(const QScriptValueImpl &signal, - const QScriptValueImpl &receiver, - const QScriptValueImpl &function); - - void _q_objectDestroyed(QObject *object); - - void disposeQObject(QObject *object); - void deletePendingQObjects(); - - static bool convertToNativeQObject(const QScriptValueImpl &value, - const QByteArray &targetType, - void **result); -#endif - - void abortEvaluation(const QScriptValueImpl &result); - inline bool shouldAbort() const; - inline void resetAbortFlag(); - - void setAgent(QScriptEngineAgent *agent); - QScriptEngineAgent *agent() const; - - void agentDeleted(QScriptEngineAgent *agent); - - void installTranslatorFunctions(QScriptValueImpl &object); - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - qint64 nextScriptId(); - inline bool shouldNotify() const; - inline void notifyScriptLoad(qint64 id, const QString &program, - const QString &fileName, int lineNumber); - void notifyScriptLoad_helper(qint64 id, const QString &program, - const QString &fileName, int lineNumber); - inline void notifyScriptUnload(qint64 id); - void notifyScriptUnload_helper(qint64 id); - inline void notifyPositionChange(QScriptContextPrivate *ctx); - void notifyPositionChange_helper(QScriptContextPrivate *ctx); - inline void notifyContextPush(); - void notifyContextPush_helper(); - inline void notifyContextPop(); - void notifyContextPop_helper(); - inline void notifyFunctionEntry(QScriptContextPrivate *ctx); - void notifyFunctionEntry_helper(QScriptContextPrivate *ctx); - inline void notifyFunctionExit(QScriptContextPrivate *ctx); - void notifyFunctionExit_helper(QScriptContextPrivate *ctx); - inline void notifyException(QScriptContextPrivate *ctx); - void notifyException_helper(QScriptContextPrivate *ctx); - inline void notifyExceptionCatch(QScriptContextPrivate *ctx); - void notifyExceptionCatch_helper(QScriptContextPrivate *ctx); - void notifyDebugger(QScriptContextPrivate *ctx); -#endif // Q_SCRIPT_NO_EVENT_NOTIFY - -public: // attributes - bool m_evaluating; - bool m_abort; - int m_callDepth; - int m_maxCallDepth; - int m_gc_depth; - QList<QScriptValueImpl> m_markStack; - QScriptValueImpl m_globalObject; - int m_oldStringRepositorySize; - int m_oldTempStringRepositorySize; - QVector<QScriptNameIdImpl*> m_stringRepository; - int m_newAllocatedStringRepositoryChars; - QVector<QScriptNameIdImpl*> m_tempStringRepository; - int m_newAllocatedTempStringRepositoryChars; - QScriptNameIdImpl **m_string_hash_base; - int m_string_hash_size; - QScript::GCAlloc<QScriptObject> objectAllocator; - int m_objectGeneration; - QScript::Repository<QScriptContext, QScriptContextPrivate> m_frameRepository; - QScriptContextPrivate *m_context; - QScriptValueImpl *tempStackBegin; - QScriptValueImpl *tempStackEnd; - QScript::AST::Node *m_abstractSyntaxTree; - QScript::Lexer *m_lexer; - QScript::MemoryPool *m_pool; - QStringList m_exceptionBacktrace; - qint64 m_scriptCounter; - - QScriptValueImpl m_undefinedValue; - QScriptValueImpl m_nullValue; - - QScript::Ecma::Object *objectConstructor; - QScript::Ecma::Number *numberConstructor; - QScript::Ecma::Boolean *booleanConstructor; - QScript::Ecma::String *stringConstructor; - QScript::Ecma::Date *dateConstructor; - QScript::Ecma::Function *functionConstructor; - QScript::Ecma::Array *arrayConstructor; - QScript::Ecma::RegExp *regexpConstructor; - QScript::Ecma::Error *errorConstructor; - QScript::Ext::Enumeration *enumerationConstructor; - QScript::Ext::Variant *variantConstructor; - QScript::ExtQObject *qobjectConstructor; - QScript::ExtQMetaObject *qmetaObjectConstructor; - - QHash<int, QScriptCustomTypeInfo> m_customTypes; - - QScriptFunction *m_evalFunction; - - QList<QScriptClassInfo*> m_allocated_classes; - QScriptClassInfo *m_class_object; - QScriptClassInfo *m_class_function; - QScriptClassInfo *m_class_with; - QScriptClassInfo *m_class_arguments; - QScriptClassInfo *m_class_activation; - - int m_class_prev_id; - qint64 m_next_object_id; - - QScript::Repository<QScriptValuePrivate, QScriptValuePrivate> m_handleRepository; - QHash<QScriptObject*, QScriptValuePrivate*> m_objectHandles; - QHash<QScriptNameIdImpl*, QScriptValuePrivate*> m_stringHandles; - QVector<QScriptValuePrivate*> m_otherHandles; - - QScript::Repository<QScriptStringPrivate, - QScriptStringPrivate> m_internedStringRepository; - QHash<QScriptNameIdImpl*, QScriptStringPrivate*> m_internedStrings; - - QSet<QScriptObject*> visitedArrayElements; - -#ifndef QT_NO_REGEXP - QHash<QString, QRegExp> m_regExpLiterals; -#endif - - QScript::IdTable m_id_table; - - QSet<QString> m_importedExtensions; - QSet<QString> m_extensionsBeingImported; - - int m_processEventsInterval; - int m_nextProcessEvents; - int m_processEventIncr; - QTime m_processEventTracker; - - QList<QScriptEngineAgent*> m_agents; - QScriptEngineAgent *m_agent; - -#ifndef QT_NO_QOBJECT - QList<QObject*> m_qobjectsToBeDeleted; - QHash<QObject*, QScriptQObjectData*> m_qobjectData; - -# ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - QHash<const QMetaObject*, QScriptMetaObject*> m_cachedMetaObjects; -# endif -#endif - -#ifdef QT_NO_QOBJECT - QScriptEngine *q_ptr; -#endif -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptextenumeration.cpp b/src/script/qscriptextenumeration.cpp deleted file mode 100644 index 718e27b..0000000 --- a/src/script/qscriptextenumeration.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptextenumeration_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptvalueiteratorimpl_p.h" - -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ext { - -EnumerationClassData::EnumerationClassData(QScriptClassInfo *classInfo): - m_classInfo(classInfo) -{ -} - -EnumerationClassData::~EnumerationClassData() -{ -} - -void EnumerationClassData::mark(const QScriptValueImpl &object, int generation) -{ - Q_ASSERT(object.isValid()); - - QScriptEnginePrivate *eng = object.engine(); - - if (Enumeration::Instance *instance = Enumeration::Instance::get(object, classInfo())) { - eng->markObject(instance->object, generation); - if (instance->it) - eng->markObject(instance->it->object(), generation); - } -} - -Enumeration::Enumeration(QScriptEnginePrivate *eng): - Ecma::Core(eng, QLatin1String("Enumeration"), QScriptClassInfo::EnumerationType) -{ - classInfo()->setData(new EnumerationClassData(classInfo())); - - newEnumeration(&publicPrototype, eng->newArray()); - - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("toFront"), method_toFront, 0); - addPrototypeFunction(QLatin1String("hasNext"), method_hasNext, 0); - addPrototypeFunction(QLatin1String("next"), method_next, 0); -} - -Enumeration::~Enumeration() -{ -} - -Enumeration::Instance *Enumeration::Instance::get(const QScriptValueImpl &object, QScriptClassInfo *klass) -{ - if (! klass || klass == object.classInfo()) - return static_cast<Instance*> (object.objectData()); - - return 0; -} - -void Enumeration::execute(QScriptContextPrivate *context) -{ - if (context->argumentCount() > 0) { - newEnumeration(&context->m_result, context->argument(0)); - } else { - context->throwError(QScriptContext::TypeError, - QLatin1String("Enumeration.execute")); - } -} - -void Enumeration::newEnumeration(QScriptValueImpl *result, const QScriptValueImpl &object) -{ - Instance *instance = new Instance(); - instance->object = object; - if (object.isObject()) { - instance->it = new QScriptValueIteratorImpl(object); - instance->it->setIgnoresDontEnum(false); - instance->it->setEnumeratePrototype(true); - } else { - instance->it = 0; - } - engine()->newObject(result, publicPrototype, classInfo()); - result->setObjectData(instance); -} - -QScriptValueImpl Enumeration::method_toFront(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) { - if (instance->it) - instance->it->toFront(); - return eng->undefinedValue(); - } else { - return context->throwError(QScriptContext::TypeError, - QLatin1String("Enumeration.toFront")); - } -} - -QScriptValueImpl Enumeration::method_hasNext(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - Instance *instance = Instance::get(context->thisObject(), classInfo); - if (!instance) { - return context->throwError(QScriptContext::TypeError, - QLatin1String("Enumeration.hasNext")); - } - - QScriptValueImpl v; - instance->hasNext(context, &v); - return v; -} - -QScriptValueImpl Enumeration::method_next(QScriptContextPrivate *context, QScriptEnginePrivate *, QScriptClassInfo *classInfo) -{ - Instance *instance = Instance::get(context->thisObject(), classInfo); - if (!instance) { - return context->throwError(QScriptContext::TypeError, - QLatin1String("Enumeration.next")); - } - - QScriptValueImpl v; - instance->next(context, &v); - return v; -} - -Enumeration::Instance::~Instance() -{ - if (it) { - delete it; - it = 0; - } -} - -void Enumeration::Instance::toFront() -{ - if (it) - it->toFront(); -} - -void Enumeration::Instance::hasNext(QScriptContextPrivate *, QScriptValueImpl *result) -{ - *result = QScriptValueImpl(it && it->hasNext()); -} - -void Enumeration::Instance::next(QScriptContextPrivate *context, QScriptValueImpl *result) -{ - QScriptEnginePrivate *eng = context->engine(); - Q_ASSERT(it != 0); - it->next(); - QScript::Member *member = it->member(); - if (member->isObjectProperty() || member->nameId()) - eng->newNameId(result, member->nameId()); - - else if (member->isNativeProperty() && !member->nameId()) - *result = QScriptValueImpl(uint(member->id())); - - else - *result = eng->undefinedValue(); -} - -} } // namespace QScript::Ext - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptextenumeration_p.h b/src/script/qscriptextenumeration_p.h deleted file mode 100644 index f97e15b..0000000 --- a/src/script/qscriptextenumeration_p.h +++ /dev/null @@ -1,126 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTEXTENUMERATION_P_H -#define QSCRIPTEXTENUMERATION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptecmacore_p.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_SCRIPT - -class QScriptValueIteratorImpl; - -namespace QScript { namespace Ext { - -class EnumerationClassData: public QScriptClassData -{ - QScriptClassInfo *m_classInfo; - -public: - EnumerationClassData(QScriptClassInfo *classInfo); - virtual ~EnumerationClassData(); - - inline QScriptClassInfo *classInfo() const - { return m_classInfo; } - - virtual void mark(const QScriptValueImpl &object, int generation); -}; - -class Enumeration: public QScript::Ecma::Core -{ -public: - Enumeration(QScriptEnginePrivate *engine); - virtual ~Enumeration(); - - virtual void execute(QScriptContextPrivate *context); - - class Instance: public QScriptObjectData { - public: - Instance() : it(0) {} - virtual ~Instance(); - - static Instance *get(const QScriptValueImpl &object, - QScriptClassInfo *klass); - - void toFront(); - void hasNext(QScriptContextPrivate *context, QScriptValueImpl *result); - void next(QScriptContextPrivate *context, QScriptValueImpl *result); - - public: // attributes - QScriptValueIteratorImpl *it; - QScriptValueImpl object; - }; - - void newEnumeration(QScriptValueImpl *result, const QScriptValueImpl &value); - - inline Instance *get(const QScriptValueImpl &object) const - { - return Instance::get(object, classInfo()); - } - -protected: - static QScriptValueImpl method_toFront(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_hasNext(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_next(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); -}; - -} } // namespace QScript::Ext - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif diff --git a/src/script/qscriptextqobject.cpp b/src/script/qscriptextqobject.cpp deleted file mode 100644 index 8746cc1..0000000 --- a/src/script/qscriptextqobject.cpp +++ /dev/null @@ -1,2244 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qglobal.h> - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptable.h" -#include "qscriptable_p.h" -#include "qscriptextqobject_p.h" - -#include <QtCore/QtDebug> -#include <QtCore/QMetaMethod> -#include <QtCore/QRegExp> -#include <QtCore/QVarLengthArray> -#include <QtCore/QPointer> - -QT_BEGIN_NAMESPACE - -// we use bits 15..12 of property flags -enum { - PROPERTY_ID = 0 << 12, - DYNAPROPERTY_ID = 1 << 12, - METHOD_ID = 2 << 12, - CHILD_ID = 3 << 12, - ID_MASK = 7 << 12, - MAYBE_OVERLOADED = 8 << 12 -}; - -static const bool GeneratePropertyFunctions = true; - -int QScriptMetaType::typeId() const -{ - if (isVariant()) - return QMetaType::type("QVariant"); - return isMetaEnum() ? 2/*int*/ : m_typeId; -} - -QByteArray QScriptMetaType::name() const -{ - if (!m_name.isEmpty()) - return m_name; - else if (m_kind == Variant) - return "QVariant"; - return QMetaType::typeName(typeId()); -} - -namespace QScript { - -class QObjectNotifyCaller : public QObject -{ -public: - void callConnectNotify(const char *signal) - { connectNotify(signal); } - void callDisconnectNotify(const char *signal) - { disconnectNotify(signal); } -}; - -class QtPropertyFunction: public QScriptFunction -{ -public: - QtPropertyFunction(const QMetaObject *meta, int index) - : m_meta(meta), m_index(index) - { } - - ~QtPropertyFunction() { } - - virtual void execute(QScriptContextPrivate *context); - - virtual Type type() const { return QScriptFunction::QtProperty; } - - virtual QString functionName() const; - -private: - const QMetaObject *m_meta; - int m_index; -}; - -class QObjectPrototype : public QObject -{ - Q_OBJECT -public: - QObjectPrototype(QObject *parent = 0) - : QObject(parent) { } - ~QObjectPrototype() { } -}; - -static inline QByteArray methodName(const QMetaMethod &method) -{ - QByteArray signature = method.signature(); - return signature.left(signature.indexOf('(')); -} - -static inline QVariant variantFromValue(QScriptEnginePrivate *eng, - int targetType, const QScriptValueImpl &value) -{ - QVariant v(targetType, (void *)0); - Q_ASSERT(eng); - if (QScriptEnginePrivate::convert(value, targetType, v.data(), eng)) - return v; - if (uint(targetType) == QVariant::LastType) - return value.toVariant(); - if (value.isVariant()) { - v = value.toVariant(); - if (v.canConvert(QVariant::Type(targetType))) { - v.convert(QVariant::Type(targetType)); - return v; - } - QByteArray typeName = v.typeName(); - if (typeName.endsWith('*') - && (QMetaType::type(typeName.left(typeName.size()-1)) == targetType)) { - return QVariant(targetType, *reinterpret_cast<void* *>(v.data())); - } - } - - return QVariant(); -} - -void ExtQObject::Instance::finalize(QScriptEnginePrivate *eng) -{ - switch (ownership) { - case QScriptEngine::QtOwnership: - break; - case QScriptEngine::ScriptOwnership: - if (value) - eng->disposeQObject(value); - break; - case QScriptEngine::AutoOwnership: - if (value && !value->parent()) - eng->disposeQObject(value); - break; - } -} - -ExtQObject::Instance *ExtQObject::Instance::get(const QScriptValueImpl &object, QScriptClassInfo *klass) -{ - if (! klass || klass == object.classInfo()) - return static_cast<Instance*> (object.objectData()); - - return 0; -} - - -static inline QScriptable *scriptableFromQObject(QObject *qobj) -{ - void *ptr = qobj->qt_metacast("QScriptable"); - return reinterpret_cast<QScriptable*>(ptr); -} - -static bool isObjectProperty(const QScriptValueImpl &object, const char *name) -{ - QScriptEnginePrivate *eng = object.engine(); - QScriptNameIdImpl *nameId = eng->nameId(QLatin1String(name)); - QScript::Member member; - QScriptValueImpl base; - return object.resolve(nameId, &member, &base, QScriptValue::ResolveLocal, QScript::Read) - && member.testFlags(QScript::Member::ObjectProperty); -} - -static bool hasMethodAccess(const QMetaMethod &method, int index, const QScriptEngine::QObjectWrapOptions &opt) -{ - return (method.access() != QMetaMethod::Private) - && ((index != 2) || !(opt & QScriptEngine::ExcludeDeleteLater)); -} - -static bool isEnumerableMetaProperty(const QMetaProperty &prop, - const QMetaObject *mo, int index) -{ - return prop.isScriptable() && prop.isValid() - // the following lookup is to ensure that we have the - // "most derived" occurrence of the property with this name - && (mo->indexOfProperty(prop.name()) == index); -} - -static uint flagsForMetaProperty(const QMetaProperty &prop) -{ - return (QScriptValue::Undeletable - | (!prop.isWritable() - ? QScriptValue::ReadOnly - : QScriptValue::PropertyFlag(0)) - | (GeneratePropertyFunctions - ? (QScriptValue::PropertyGetter - | QScriptValue::PropertySetter) - : QScriptValue::PropertyFlag(0)) - | QScriptValue::QObjectMember - | PROPERTY_ID); -} - - -static int indexOfMetaEnum(const QMetaObject *meta, const QByteArray &str) -{ - QByteArray scope; - QByteArray name; - int scopeIdx = str.lastIndexOf("::"); - if (scopeIdx != -1) { - scope = str.left(scopeIdx); - name = str.mid(scopeIdx + 2); - } else { - name = str; - } - for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { - QMetaEnum m = meta->enumerator(i); - if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) - return i; - } - return -1; -} - -static QMetaMethod metaMethod(const QMetaObject *meta, - QMetaMethod::MethodType type, - int index) -{ - if (type != QMetaMethod::Constructor) - return meta->method(index); - else - return meta->constructor(index); -} - -static void callQtMethod(QScriptContextPrivate *context, QMetaMethod::MethodType callType, - QObject *thisQObject, const QMetaObject *meta, int initialIndex, - bool maybeOverloaded) -{ - QScriptValueImpl result; - QScriptEnginePrivate *engine = context->engine(); - - int limit; -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - int lastFoundIndex = initialIndex; - QScriptMetaObject *metaCache = engine->cachedMetaObject(meta); - if (callType != QMetaMethod::Constructor) - limit = metaCache->methodLowerBound(initialIndex); - else - limit = 0; -#else - limit = 0; -#endif - - QByteArray funName; - QScriptMetaMethod chosenMethod; - int chosenIndex = -1; - QVarLengthArray<QVariant, 9> args; - QVector<QScriptMetaArguments> candidates; - QVector<QScriptMetaArguments> unresolved; - QVector<int> tooFewArgs; - QVector<int> conversionFailed; - int index; - for (index = initialIndex; index >= limit; --index) { - QScriptMetaMethod mtd; -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - if (callType != QMetaMethod::Constructor) - mtd = metaCache->findMethod(index); - if (!mtd.isValid()) -#endif - { - QMetaMethod method = metaMethod(meta, callType, index); - - QVector<QScriptMetaType> types; - // 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)); - } - } else { - if (callType == QMetaMethod::Constructor) - types.append(QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*")); - else if (returnTypeName == "QVariant") - types.append(QScriptMetaType::variant()); - else - types.append(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()); - else - types.append(QScriptMetaType::metaType(atype, argTypeName)); - } - } - - mtd = QScriptMetaMethod(methodName(method), types); - -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - if (mtd.fullyResolved() && (callType != QMetaMethod::Constructor)) - metaCache->registerMethod(index, mtd); -#endif - } - - if (index == initialIndex) - funName = mtd.name(); - else { - if (mtd.name() != funName) - continue; -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - lastFoundIndex = index; -#endif - } - - if (context->argumentCount() < mtd.argumentCount()) { - tooFewArgs.append(index); - continue; - } - - if (!mtd.fullyResolved()) { - // remember it so we can give an error message later, if necessary - unresolved.append(QScriptMetaArguments(/*matchDistance=*/INT_MAX, index, - mtd, QVarLengthArray<QVariant, 9>())); - if (mtd.hasUnresolvedReturnType()) - continue; - } - - if (args.count() != mtd.count()) - args.resize(mtd.count()); - - QScriptMetaType retType = mtd.returnType(); - args[0] = QVariant(retType.typeId(), (void *)0); // the result - - // try to convert arguments - bool converted = true; - int matchDistance = 0; - for (int i = 0; converted && i < mtd.argumentCount(); ++i) { - QScriptValueImpl actual = context->argument(i); - 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())); - } else if (argType.isVariant()) { - if (actual.isVariant()) { - v = actual.variantValue(); - } else { - v = actual.toVariant(); - converted = v.isValid() || actual.isUndefined() || actual.isNull(); - } - } else { - tid = argType.typeId(); - v = QVariant(tid, (void *)0); - converted = QScriptEnginePrivate::convert(actual, tid, v.data(), engine); - if (engine->hasUncaughtException()) - return; - } - - if (!converted) { - if (actual.isVariant()) { - if (tid == -1) - tid = argType.typeId(); - QVariant &vv = actual.variantValue(); - if (vv.canConvert(QVariant::Type(tid))) { - v = vv; - converted = v.convert(QVariant::Type(tid)); - if (converted && (vv.userType() != tid)) - matchDistance += 10; - } else { - QByteArray vvTypeName = vv.typeName(); - if (vvTypeName.endsWith('*') - && (vvTypeName.left(vvTypeName.size()-1) == argType.name())) { - v = QVariant(tid, *reinterpret_cast<void* *>(vv.data())); - converted = true; - matchDistance += 10; - } - } - } else if (actual.isNumber() || actual.isString()) { - // see if it's an enum value - QMetaEnum m; - if (argType.isMetaEnum()) { - m = meta->enumerator(argType.enumeratorIndex()); - } else { - int mi = indexOfMetaEnum(meta, argType.name()); - if (mi != -1) - m = meta->enumerator(mi); - } - if (m.isValid()) { - if (actual.isNumber()) { - int ival = actual.toInt32(); - if (m.valueToKey(ival) != 0) { - qVariantSetValue(v, ival); - converted = true; - matchDistance += 10; - } - } else { - QString sval = actual.toString(); - int ival = m.keyToValue(sval.toLatin1()); - if (ival != -1) { - qVariantSetValue(v, ival); - converted = true; - matchDistance += 10; - } - } - } - } - } else { - // determine how well the conversion matched - if (actual.isNumber()) { - switch (tid) { - case QMetaType::Double: - // perfect - break; - case QMetaType::Float: - matchDistance += 1; - break; - case QMetaType::LongLong: - case QMetaType::ULongLong: - matchDistance += 2; - break; - case QMetaType::Long: - case QMetaType::ULong: - matchDistance += 3; - break; - case QMetaType::Int: - case QMetaType::UInt: - matchDistance += 4; - break; - case QMetaType::Short: - case QMetaType::UShort: - matchDistance += 5; - break; - case QMetaType::Char: - case QMetaType::UChar: - matchDistance += 6; - break; - default: - matchDistance += 10; - break; - } - } else if (actual.isString()) { - switch (tid) { - case QMetaType::QString: - // perfect - break; - default: - matchDistance += 10; - break; - } - } else if (actual.isBoolean()) { - switch (tid) { - case QMetaType::Bool: - // perfect - break; - default: - matchDistance += 10; - break; - } - } else if (actual.isDate()) { - switch (tid) { - case QMetaType::QDateTime: - // perfect - break; - case QMetaType::QDate: - matchDistance += 1; - break; - case QMetaType::QTime: - matchDistance += 2; - break; - default: - matchDistance += 10; - break; - } - } else if (actual.isRegExp()) { - switch (tid) { - case QMetaType::QRegExp: - // perfect - break; - default: - matchDistance += 10; - break; - } - } else if (actual.isVariant()) { - if (argType.isVariant() - || (actual.variantValue().userType() == tid)) { - // perfect - } else { - matchDistance += 10; - } - } else if (actual.isArray()) { - switch (tid) { - case QMetaType::QStringList: - case QMetaType::QVariantList: - matchDistance += 5; - break; - default: - matchDistance += 10; - break; - } - } else if (actual.isQObject()) { - switch (tid) { - case QMetaType::QObjectStar: - case QMetaType::QWidgetStar: - // perfect - break; - default: - matchDistance += 10; - break; - } - } else if (actual.isNull()) { - switch (tid) { - case QMetaType::VoidStar: - case QMetaType::QObjectStar: - case QMetaType::QWidgetStar: - // perfect - break; - default: - if (!argType.name().endsWith('*')) - matchDistance += 10; - break; - } - } else { - matchDistance += 10; - } - } - - if (converted) - args[i+1] = v; - } - - if (converted) { - if ((context->argumentCount() == mtd.argumentCount()) - && (matchDistance == 0)) { - // perfect match, use this one - chosenMethod = mtd; - chosenIndex = index; - break; - } else { - bool redundant = false; - if ((callType != QMetaMethod::Constructor) - && (index < meta->methodOffset())) { - // it is possible that a virtual method is redeclared in a subclass, - // in which case we want to ignore the superclass declaration - for (int i = 0; i < candidates.size(); ++i) { - const QScriptMetaArguments &other = candidates.at(i); - if (mtd.types() == other.method.types()) { - redundant = true; - break; - } - } - } - if (!redundant) { - QScriptMetaArguments metaArgs(matchDistance, index, mtd, args); - if (candidates.isEmpty()) { - candidates.append(metaArgs); - } else { - const QScriptMetaArguments &otherArgs = candidates.at(0); - if ((args.count() > otherArgs.args.count()) - || ((args.count() == otherArgs.args.count()) - && (matchDistance <= otherArgs.matchDistance))) { - candidates.prepend(metaArgs); - } else { - candidates.append(metaArgs); - } - } - } - } - } else if (mtd.fullyResolved()) { - conversionFailed.append(index); - } - - if (!maybeOverloaded) - break; - } - -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - if ((index == -1) && (lastFoundIndex != limit) && maybeOverloaded - && (callType != QMetaMethod::Constructor)) { - metaCache->setMethodLowerBound(initialIndex, lastFoundIndex); - } -#endif - - if ((chosenIndex == -1) && candidates.isEmpty()) { - context->calleeMetaIndex = initialIndex; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine->notifyFunctionEntry(context); -#endif - if (!conversionFailed.isEmpty()) { - QString message = QString::fromLatin1("incompatible type of argument(s) in call to %0(); candidates were\n") - .arg(QLatin1String(funName)); - for (int i = 0; i < conversionFailed.size(); ++i) { - if (i > 0) - message += QLatin1String("\n"); - QMetaMethod mtd = metaMethod(meta, callType, conversionFailed.at(i)); - message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); - } - result = context->throwError(QScriptContext::TypeError, message); - } else if (!unresolved.isEmpty()) { - QScriptMetaArguments argsInstance = unresolved.first(); - int unresolvedIndex = argsInstance.method.firstUnresolvedIndex(); - Q_ASSERT(unresolvedIndex != -1); - QScriptMetaType unresolvedType = argsInstance.method.type(unresolvedIndex); - QString unresolvedTypeName = QString::fromLatin1(unresolvedType.name()); - QString message = QString::fromLatin1("cannot call %0(): ") - .arg(QString::fromLatin1(funName)); - if (unresolvedIndex > 0) { - message.append(QString::fromLatin1("argument %0 has unknown type `%1'"). - arg(unresolvedIndex).arg(unresolvedTypeName)); - } else { - message.append(QString::fromLatin1("unknown return type `%0'") - .arg(unresolvedTypeName)); - } - message.append(QString::fromLatin1(" (register the type with qScriptRegisterMetaType())")); - result = context->throwError(QScriptContext::TypeError, message); - } else { - QString message = QString::fromLatin1("too few arguments in call to %0(); candidates are\n") - .arg(QLatin1String(funName)); - for (int i = 0; i < tooFewArgs.size(); ++i) { - if (i > 0) - message += QLatin1String("\n"); - QMetaMethod mtd = metaMethod(meta, callType, tooFewArgs.at(i)); - message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); - } - result = context->throwError(QScriptContext::SyntaxError, message); - } - } else { - if (chosenIndex == -1) { - QScriptMetaArguments metaArgs = candidates.at(0); - if ((candidates.size() > 1) - && (metaArgs.args.count() == candidates.at(1).args.count()) - && (metaArgs.matchDistance == candidates.at(1).matchDistance)) { - // ambiguous call - QString message = QString::fromLatin1("ambiguous call of overloaded function %0(); candidates were\n") - .arg(QLatin1String(funName)); - for (int i = 0; i < candidates.size(); ++i) { - if (i > 0) - message += QLatin1String("\n"); - QMetaMethod mtd = metaMethod(meta, callType, candidates.at(i).index); - message += QString::fromLatin1(" %0").arg(QString::fromLatin1(mtd.signature())); - } - result = context->throwError(QScriptContext::TypeError, message); - } else { - chosenMethod = metaArgs.method; - chosenIndex = metaArgs.index; - args = metaArgs.args; - } - } - - if (chosenIndex != -1) { - // call it - context->calleeMetaIndex = chosenIndex; - - QVarLengthArray<void*, 9> array(args.count()); - void **params = array.data(); - for (int i = 0; i < args.count(); ++i) { - const QVariant &v = args[i]; - switch (chosenMethod.type(i).kind()) { - case QScriptMetaType::Variant: - params[i] = const_cast<QVariant*>(&v); - break; - case QScriptMetaType::MetaType: - case QScriptMetaType::MetaEnum: - case QScriptMetaType::Unresolved: - params[i] = const_cast<void*>(v.constData()); - break; - default: - Q_ASSERT(0); - } - } - - QScriptable *scriptable = 0; - if (thisQObject) - scriptable = scriptableFromQObject(thisQObject); - QScriptEngine *oldEngine = 0; - if (scriptable) { - oldEngine = QScriptablePrivate::get(scriptable)->engine; - QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(engine); - } - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine->notifyFunctionEntry(context); -#endif - - if (callType == QMetaMethod::Constructor) { - Q_ASSERT(meta != 0); - meta->static_metacall(QMetaObject::CreateInstance, chosenIndex, params); - } else { - Q_ASSERT(thisQObject != 0); - QMetaObject::metacall(thisQObject, QMetaObject::InvokeMetaMethod, chosenIndex, params); - } - - if (scriptable) - QScriptablePrivate::get(scriptable)->engine = oldEngine; - - if (context->state() == QScriptContext::ExceptionState) { - result = context->returnValue(); // propagate - } else { - QScriptMetaType retType = chosenMethod.returnType(); - if (retType.isVariant()) { - result = engine->valueFromVariant(*(QVariant *)params[0]); - } else if (retType.typeId() != 0) { - result = engine->create(retType.typeId(), params[0]); - if (!result.isValid()) - engine->newVariant(&result, QVariant(retType.typeId(), params[0])); - } else { - result = engine->undefinedValue(); - } - } - } - } - - context->m_result = result; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - engine->notifyFunctionExit(context); -#endif -} - - -class ExtQObjectDataIterator: public QScriptClassDataIterator -{ -public: - ExtQObjectDataIterator(const QScriptValueImpl &object); - virtual ~ExtQObjectDataIterator(); - - virtual bool hasNext() const; - virtual void next(QScript::Member *member); - - virtual bool hasPrevious() const; - virtual void previous(QScript::Member *member); - - virtual void toFront(); - virtual void toBack(); - -private: - enum State { - MetaProperties, - DynamicProperties, - MetaMethods - }; - - QScriptValueImpl m_object; - int m_index; - State m_state; -}; - -ExtQObjectDataIterator::ExtQObjectDataIterator(const QScriptValueImpl &object) -{ - m_object = object; - toFront(); -} - -ExtQObjectDataIterator::~ExtQObjectDataIterator() -{ -} - -bool ExtQObjectDataIterator::hasNext() const -{ - ExtQObject::Instance *inst = ExtQObject::Instance::get(m_object); - if (!inst->value) - return false; - const QMetaObject *meta = inst->value->metaObject(); - int i = m_index; - - switch (m_state) { - case MetaProperties: { - for ( ; i < meta->propertyCount(); ++i) { - QMetaProperty prop = meta->property(i); - if (isEnumerableMetaProperty(prop, meta, i) - && !isObjectProperty(m_object, prop.name())) { - return true; - } - } - i = 0; - // fall-through - } - - case DynamicProperties: { - QList<QByteArray> dpNames = inst->value->dynamicPropertyNames(); - for ( ; i < dpNames.count(); ++i) { - if (!isObjectProperty(m_object, dpNames.at(i))) { - return true; - } - } - if (inst->options & QScriptEngine::SkipMethodsInEnumeration) - return false; - i = (inst->options & QScriptEngine::ExcludeSuperClassMethods) - ? meta->methodOffset() : 0; - // fall-through - } - - case MetaMethods: { - for ( ; i < meta->methodCount(); ++i) { - QMetaMethod method = meta->method(i); - if (hasMethodAccess(method, i, inst->options) - && !isObjectProperty(m_object, method.signature())) { - return true; - } - } - } - - } // switch - - return false; -} - -void ExtQObjectDataIterator::next(QScript::Member *member) -{ - QScriptEnginePrivate *eng = m_object.engine(); - ExtQObject::Instance *inst = ExtQObject::Instance::get(m_object); - if (!inst->value) - return; - const QMetaObject *meta = inst->value->metaObject(); - int i = m_index; - - switch (m_state) { - case MetaProperties: { - for ( ; i < meta->propertyCount(); ++i) { - QMetaProperty prop = meta->property(i); - if (isEnumerableMetaProperty(prop, meta, i) - && !isObjectProperty(m_object, prop.name())) { - QScriptNameIdImpl *nameId = eng->nameId(QLatin1String(prop.name())); - member->native(nameId, i, flagsForMetaProperty(prop)); - m_index = i + 1; - return; - } - } - m_state = DynamicProperties; - m_index = 0; - i = m_index; - // fall-through - } - - case DynamicProperties: { - QList<QByteArray> dpNames = inst->value->dynamicPropertyNames(); - for ( ; i < dpNames.count(); ++i) { - if (!isObjectProperty(m_object, dpNames.at(i))) { - QByteArray name = dpNames.at(i); - QScriptNameIdImpl *nameId = eng->nameId(QLatin1String(name)); - member->native(nameId, i, - QScriptValue::QObjectMember - | DYNAPROPERTY_ID); - m_index = i + 1; - return; - } - } - m_state = MetaMethods; - m_index = (inst->options & QScriptEngine::ExcludeSuperClassMethods) - ? meta->methodOffset() : 0; - i = m_index; - // fall-through - } - - case MetaMethods: { - for ( ; i < meta->methodCount(); ++i) { - QMetaMethod method = meta->method(i); - if (hasMethodAccess(method, i, inst->options) - && !isObjectProperty(m_object, method.signature())) { - QMetaMethod method = meta->method(i); - QScriptNameIdImpl *nameId = eng->nameId(QLatin1String(method.signature())); - member->native(nameId, i, - QScriptValue::QObjectMember - | METHOD_ID); - m_index = i + 1; - return; - } - } - } - - } // switch - - member->invalidate(); -} - -bool ExtQObjectDataIterator::hasPrevious() const -{ - ExtQObject::Instance *inst = ExtQObject::Instance::get(m_object); - if (!inst->value) - return false; - const QMetaObject *meta = inst->value->metaObject(); - int i = m_index - 1; - - switch (m_state) { - case MetaMethods: { - int limit = (inst->options & QScriptEngine::ExcludeSuperClassMethods) - ? meta->methodOffset() : 0; - for ( ; i >= limit; --i) { - QMetaMethod method = meta->method(i); - if (hasMethodAccess(method, i, inst->options) - && !isObjectProperty(m_object, method.signature())) { - return true; - } - } - i = inst->value->dynamicPropertyNames().count() - 1; - // fall-through - } - - case DynamicProperties: { - QList<QByteArray> dpNames = inst->value->dynamicPropertyNames(); - for ( ; i >= 0; --i) { - if (!isObjectProperty(m_object, dpNames.at(i))) { - return true; - } - } - i = meta->propertyCount() - 1; - // fall-through - } - - case MetaProperties: { - int limit = (inst->options & QScriptEngine::ExcludeSuperClassProperties) - ? meta->propertyOffset() : 0; - for ( ; i >= limit; --i) { - QMetaProperty prop = meta->property(i); - if (isEnumerableMetaProperty(prop, meta, i) - && !isObjectProperty(m_object, prop.name())) { - return true; - } - } - } - - } // switch - - return false; -} - -void ExtQObjectDataIterator::previous(QScript::Member *member) -{ - QScriptEnginePrivate *eng = m_object.engine(); - ExtQObject::Instance *inst = ExtQObject::Instance::get(m_object); - if (!inst->value) - return; - const QMetaObject *meta = inst->value->metaObject(); - int i = m_index - 1; - - switch (m_state) { - case MetaMethods: { - int limit = (inst->options & QScriptEngine::ExcludeSuperClassMethods) - ? meta->methodOffset() : 0; - for ( ; i >= limit; --i) { - QMetaMethod method = meta->method(i); - if (hasMethodAccess(method, i, inst->options) - && !isObjectProperty(m_object, method.signature())) { - QMetaMethod method = meta->method(i); - QScriptNameIdImpl *nameId = eng->nameId(QLatin1String(method.signature())); - member->native(nameId, i, - QScriptValue::QObjectMember - | METHOD_ID); - m_index = i; - return; - } - } - m_state = DynamicProperties; - m_index = inst->value->dynamicPropertyNames().count() - 1; - i = m_index; - // fall-through - } - - case DynamicProperties: { - QList<QByteArray> dpNames = inst->value->dynamicPropertyNames(); - for ( ; i >= 0; --i) { - if (!isObjectProperty(m_object, dpNames.at(i))) { - QByteArray name = dpNames.at(i); - QScriptNameIdImpl *nameId = eng->nameId(QLatin1String(name)); - member->native(nameId, i, - QScriptValue::QObjectMember - | DYNAPROPERTY_ID); - m_index = i; - return; - } - } - m_state = MetaProperties; - m_index = meta->propertyCount() - 1; - i = m_index; - // fall-through - } - - case MetaProperties: { - int limit = (inst->options & QScriptEngine::ExcludeSuperClassProperties) - ? meta->propertyOffset() : 0; - for ( ; i >= limit; --i) { - QMetaProperty prop = meta->property(i); - if (isEnumerableMetaProperty(prop, meta, i) - && !isObjectProperty(m_object, prop.name())) { - QScriptNameIdImpl *nameId = eng->nameId(QLatin1String(prop.name())); - member->native(nameId, i, flagsForMetaProperty(prop)); - m_index = i; - return; - } - } - } - - } // switch - - member->invalidate(); -} - -void ExtQObjectDataIterator::toFront() -{ - ExtQObject::Instance *inst = ExtQObject::Instance::get(m_object); - if (!inst->value) - return; - m_state = MetaProperties; - const QMetaObject *meta = inst->value->metaObject(); - m_index = (inst->options & QScriptEngine::ExcludeSuperClassProperties) - ? meta->propertyOffset() : 0; -} - -void ExtQObjectDataIterator::toBack() -{ - ExtQObject::Instance *inst = ExtQObject::Instance::get(m_object); - if (!inst->value) - return; - if (inst->options & QScriptEngine::SkipMethodsInEnumeration) { - m_state = DynamicProperties; - m_index = inst->value->dynamicPropertyNames().count(); - } else { - m_state = MetaMethods; - const QMetaObject *meta = inst->value->metaObject(); - m_index = meta->methodCount(); - } -} - -class ExtQObjectData: public QScriptClassData -{ -public: - ExtQObjectData(QScriptClassInfo *classInfo) - : m_classInfo(classInfo) - { - } - - virtual bool resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *, - QScript::AccessMode access) - { - ExtQObject::Instance *inst = ExtQObject::Instance::get(object, m_classInfo); - QObject *qobject = inst->value; - if (! qobject) { - // the object was deleted. We return true so we can - // throw an error in get()/put() - member->native(nameId, /*id=*/-1, /*flags=*/0); - return true; - } - - const QScriptEngine::QObjectWrapOptions &opt = inst->options; - const QMetaObject *meta = qobject->metaObject(); - - QScriptEnginePrivate *eng = object.engine(); - -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - QScriptMetaObject *metaCache = eng->cachedMetaObject(meta); - if (metaCache->findMember(nameId, member)) { - bool ignore = false; - switch (member->flags() & ID_MASK) { - case PROPERTY_ID: - ignore = (opt & QScriptEngine::ExcludeSuperClassProperties) - && (member->id() < meta->propertyOffset()); - break; - case METHOD_ID: - ignore = ((opt & QScriptEngine::ExcludeSuperClassMethods) - && (member->id() < meta->methodOffset())) - || ((opt & QScriptEngine::ExcludeDeleteLater) - && (member->id() == 2)); - break; - // we don't cache dynamic properties nor children, - // so no need to handle DYNAPROPERTY_ID and CHILD_ID - default: - break; - } - if (!ignore) - return true; - } -#endif - - QString memberName = eng->toString(nameId); - QByteArray name = memberName.toLatin1(); - - 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)) { - member->native(nameId, index, - QScriptValue::QObjectMember - | METHOD_ID); -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - metaCache->registerMember(nameId, *member); -#endif - if (!(opt & QScriptEngine::ExcludeSuperClassMethods) - || (index >= meta->methodOffset())) { - return true; - } - } - } - } - - index = meta->indexOfProperty(name); - if (index != -1) { - QMetaProperty prop = meta->property(index); - if (prop.isScriptable()) { - member->native(nameId, index, flagsForMetaProperty(prop)); -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - metaCache->registerMember(nameId, *member); -#endif - if (!(opt & QScriptEngine::ExcludeSuperClassProperties) - || (index >= meta->propertyOffset())) { - return true; - } - } - } - - index = qobject->dynamicPropertyNames().indexOf(name); - if (index != -1) { - member->native(nameId, index, - QScriptValue::QObjectMember - | DYNAPROPERTY_ID); - // not cached because it can be removed - 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)) { - member->native(nameId, index, - QScriptValue::QObjectMember - | METHOD_ID - | MAYBE_OVERLOADED); -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - metaCache->registerMember(nameId, *member); -#endif - 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() == memberName) { - member->native(nameId, index, - QScriptValue::ReadOnly - | QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration - | CHILD_ID); - // not cached because it can be removed or change name - return true; - } - } - } - - if ((access & QScript::Write) && (opt & QScriptEngine::AutoCreateDynamicProperties)) { - member->native(nameId, -1, DYNAPROPERTY_ID); - return true; - } - - return false; - } - - virtual bool get(const QScriptValueImpl &obj, const QScript::Member &member, QScriptValueImpl *result) - { - if (! member.isNativeProperty()) - return false; - - QScriptEnginePrivate *eng = obj.engine(); - - ExtQObject::Instance *inst = ExtQObject::Instance::get(obj, m_classInfo); - QObject *qobject = inst->value; - if (!qobject) { - QScriptContextPrivate *ctx = eng->currentContext(); - *result = ctx->throwError( - QString::fromLatin1("cannot access member `%0' of deleted QObject") - .arg(member.nameId()->s)); - return true; - } - - switch (member.flags() & ID_MASK) { - case PROPERTY_ID: { - const QMetaObject *meta = qobject->metaObject(); - const int propertyIndex = member.id(); - QMetaProperty prop = meta->property(propertyIndex); - Q_ASSERT(prop.isScriptable()); - if (GeneratePropertyFunctions) { - QScriptValueImpl accessor; -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - QScriptMetaObject *metaCache = eng->cachedMetaObject(meta); - accessor = metaCache->findPropertyAccessor(propertyIndex); - if (!accessor.isValid()) { -#endif - accessor = eng->createFunction(new QtPropertyFunction(meta, propertyIndex)); -#ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE - metaCache->registerPropertyAccessor(propertyIndex, accessor); - } -#endif - *result = accessor; - } else { - QVariant v = prop.read(qobject); - *result = eng->valueFromVariant(v); - } - } break; - - case DYNAPROPERTY_ID: { - if (member.id() != -1) { - QVariant v = qobject->property(member.nameId()->s.toLatin1()); - *result = eng->valueFromVariant(v); - } else { - *result = eng->undefinedValue(); - } - } break; - - case METHOD_ID: { - QScript::Member m; - bool maybeOverloaded = (member.flags() & MAYBE_OVERLOADED) != 0; - *result = eng->createFunction(new QtFunction(obj, member.id(), - maybeOverloaded)); - // make it persist (otherwise Function.prototype.disconnect() would fail) - uint flags = QScriptValue::QObjectMember; - if (inst->options & QScriptEngine::SkipMethodsInEnumeration) - flags |= QScriptValue::SkipInEnumeration; - QScriptObject *instance = obj.objectValue(); - if (!instance->findMember(member.nameId(), &m)) - instance->createMember(member.nameId(), &m, flags); - instance->put(m, *result); - } break; - - case CHILD_ID: { - QObject *child = qobject->children().at(member.id()); - result->invalidate(); - QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; - eng->newQObject(result, child, QScriptEngine::QtOwnership, opt); - } break; - - } // switch - - return true; - } - - virtual bool put(QScriptValueImpl *object, const QScript::Member &member, const QScriptValueImpl &value) - { - if (! member.isNativeProperty() || ! member.isWritable()) - return false; - - ExtQObject::Instance *inst = ExtQObject::Instance::get(*object, m_classInfo); - QObject *qobject = inst->value; - if (!qobject) { - QScriptEnginePrivate *eng = object->engine(); - QScriptContextPrivate *ctx = eng->currentContext(); - ctx->throwError(QString::fromLatin1("cannot access member `%0' of deleted QObject") - .arg(member.nameId()->s)); - return true; - } - - switch (member.flags() & ID_MASK) { - case CHILD_ID: - return false; - - case METHOD_ID: { - QScript::Member m; - QScriptObject *instance = object->objectValue(); - if (!instance->findMember(member.nameId(), &m)) { - instance->createMember(member.nameId(), &m, - /*flags=*/0); - } - instance->put(m, value); - return true; - } - - case PROPERTY_ID: - if (GeneratePropertyFunctions) { - // we shouldn't get here, QScriptValueImpl::setProperty() messed up - Q_ASSERT_X(0, "put", "Q_PROPERTY access cannot be overridden"); - return false; - } else { - const QMetaObject *meta = qobject->metaObject(); - QMetaProperty prop = meta->property(member.id()); - Q_ASSERT(prop.isScriptable()); - QVariant v = variantFromValue(object->engine(), prop.userType(), value); - bool ok = prop.write(qobject, v); - return ok; - } - - case DYNAPROPERTY_ID: { - QVariant v = value.toVariant(); - return ! qobject->setProperty(member.nameId()->s.toLatin1(), v); - } - - } // switch - return false; - } - - virtual bool removeMember(const QScriptValueImpl &object, - const QScript::Member &member) - { - QObject *qobject = object.toQObject(); - if (!qobject || !member.isNativeProperty() || !member.isDeletable()) - return false; - - if ((member.flags() & ID_MASK) == DYNAPROPERTY_ID) { - qobject->setProperty(member.nameId()->s.toLatin1(), QVariant()); - return true; - } - - return false; - } - - virtual void mark(const QScriptValueImpl &, int) - { - } - - virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object) - { - return new ExtQObjectDataIterator(object); - } - -private: - QScriptClassInfo *m_classInfo; -}; - -struct QObjectConnection -{ - int slotIndex; - QScriptValueImpl receiver; - QScriptValueImpl slot; - QScriptValueImpl senderWrapper; - - QObjectConnection(int i, const QScriptValueImpl &r, const QScriptValueImpl &s, - const QScriptValueImpl &sw) - : slotIndex(i), receiver(r), slot(s), senderWrapper(sw) {} - QObjectConnection() : slotIndex(-1) {} - - bool hasTarget(const QScriptValueImpl &r, const QScriptValueImpl &s) const - { - if (r.isObject() != receiver.isObject()) - return false; - if ((r.isObject() && receiver.isObject()) - && (r.objectValue() != receiver.objectValue())) { - return false; - } - return (s.objectValue() == slot.objectValue()); - } - - void mark(int generation) - { - if (senderWrapper.isValid() && !senderWrapper.isMarked(generation)) { - // see if the sender should be marked or not - ExtQObject::Instance *inst = ExtQObject::Instance::get(senderWrapper); - if ((inst->ownership == QScriptEngine::ScriptOwnership) - || ((inst->ownership == QScriptEngine::AutoOwnership) - && inst->value && !inst->value->parent())) { - senderWrapper.invalidate(); - } else { - senderWrapper.mark(generation); - } - } - if (receiver.isValid()) - receiver.mark(generation); - if (slot.isValid()) - slot.mark(generation); - } -}; - -class QObjectConnectionManager: public QObject -{ -public: - QObjectConnectionManager(); - ~QObjectConnectionManager(); - - bool addSignalHandler(QObject *sender, int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &slot, - const QScriptValueImpl &senderWrapper, - Qt::ConnectionType type); - bool removeSignalHandler( - QObject *sender, int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &slot); - - static const QMetaObject staticMetaObject; - virtual const QMetaObject *metaObject() const; - virtual void *qt_metacast(const char *); - virtual int qt_metacall(QMetaObject::Call, int, void **argv); - - void execute(int slotIndex, void **argv); - - void mark(int generation); - -private: - int m_slotCounter; - QVector<QVector<QObjectConnection> > connections; -}; - -} // ::QScript - - - -QScript::ExtQObject::ExtQObject(QScriptEnginePrivate *eng): - Ecma::Core(eng, QLatin1String("QObject"), QScriptClassInfo::QObjectType) -{ - newQObject(&publicPrototype, new QScript::QObjectPrototype(), - QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassMethods - | QScriptEngine::ExcludeSuperClassProperties - | QScriptEngine::ExcludeChildObjects); - - eng->newConstructor(&ctor, this, publicPrototype); - addPrototypeFunction(QLatin1String("toString"), method_toString, 0); - addPrototypeFunction(QLatin1String("findChild"), method_findChild, 1); - addPrototypeFunction(QLatin1String("findChildren"), method_findChildren, 1); - - classInfo()->setData(new QScript::ExtQObjectData(classInfo())); -} - -QScript::ExtQObject::~ExtQObject() -{ -} - -void QScript::ExtQObject::execute(QScriptContextPrivate *context) -{ - QScriptValueImpl tmp; - newQObject(&tmp, 0); - context->setReturnValue(tmp); -} - -void QScript::ExtQObject::newQObject(QScriptValueImpl *result, QObject *value, - QScriptEngine::ValueOwnership ownership, - const QScriptEngine::QObjectWrapOptions &options) -{ - Instance *instance; - if (!result->isValid()) { - engine()->newObject(result, publicPrototype, classInfo()); - instance = new Instance(); - result->setObjectData(instance); - } else { - Q_ASSERT(result->isObject()); - if (result->classInfo() != classInfo()) { - result->destroyObjectData(); - result->setClassInfo(classInfo()); - instance = new Instance(); - result->setObjectData(instance); - } else { - instance = Instance::get(*result); - } - } - instance->value = value; - instance->ownership = ownership; - instance->options = options; -} - -QScriptValueImpl QScript::ExtQObject::method_findChild(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) { - QObject *obj = instance->value; - QString name = context->argument(0).toString(); - QObject *child = qFindChild<QObject*>(obj, name); - QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; - QScriptValueImpl result; - eng->newQObject(&result, child, QScriptEngine::QtOwnership, opt); - return result; - } - return eng->undefinedValue(); -} - -QScriptValueImpl QScript::ExtQObject::method_findChildren(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) { - QObject *obj = instance->value; - QList<QObject*> found; - QScriptValueImpl arg = context->argument(0); -#ifndef QT_NO_REGEXP - if (arg.isRegExp()) { - QRegExp re = arg.toRegExp(); - found = qFindChildren<QObject*>(obj, re); - } else -#endif - { - QString name = arg.isUndefined() ? QString() : arg.toString(); - found = qFindChildren<QObject*>(obj, name); - } - QScriptValueImpl result = eng->newArray(found.size()); - QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; - for (int i = 0; i < found.size(); ++i) { - QScriptValueImpl value; - eng->newQObject(&value, found.at(i), QScriptEngine::QtOwnership, opt); - result.setProperty(i, value); - } - return result; - } - return eng->undefinedValue(); -} - -QScriptValueImpl QScript::ExtQObject::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) { - QObject *obj = instance->value; - const QMetaObject *meta = obj ? obj->metaObject() : &QObject::staticMetaObject; - QString name = obj ? obj->objectName() : QString::fromUtf8("unnamed"); - - QString str = QString::fromUtf8("%0(name = \"%1\")") - .arg(QLatin1String(meta->className())).arg(name); - return QScriptValueImpl(eng, str); - } - return eng->undefinedValue(); -} - - - -static const uint qt_meta_data_QObjectConnectionManager[] = { - - // content: - 1, // revision - 0, // classname - 0, 0, // classinfo - 1, 10, // methods - 0, 0, // properties - 0, 0, // enums/sets - - // slots: signature, parameters, type, tag, flags - 35, 34, 34, 34, 0x0a, - - 0 // eod -}; - -static const char qt_meta_stringdata_QObjectConnectionManager[] = { - "QScript::QObjectConnectionManager\0\0execute()\0" -}; - -const QMetaObject QScript::QObjectConnectionManager::staticMetaObject = { - { &QObject::staticMetaObject, qt_meta_stringdata_QObjectConnectionManager, - qt_meta_data_QObjectConnectionManager, 0 } -}; - -const QMetaObject *QScript::QObjectConnectionManager::metaObject() const -{ - return &staticMetaObject; -} - -void *QScript::QObjectConnectionManager::qt_metacast(const char *_clname) -{ - if (!_clname) return 0; - if (!strcmp(_clname, qt_meta_stringdata_QObjectConnectionManager)) - return static_cast<void*>(const_cast<QObjectConnectionManager*>(this)); - return QObject::qt_metacast(_clname); -} - -int QScript::QObjectConnectionManager::qt_metacall(QMetaObject::Call _c, int _id, void **_a) -{ - _id = QObject::qt_metacall(_c, _id, _a); - if (_id < 0) - return _id; - if (_c == QMetaObject::InvokeMetaMethod) { - execute(_id, _a); - _id -= m_slotCounter; - } - return _id; -} - -void QScript::QObjectConnectionManager::execute(int slotIndex, void **argv) -{ - QScriptValueImpl receiver; - QScriptValueImpl slot; - QScriptValueImpl senderWrapper; - int signalIndex = -1; - for (int i = 0; i < connections.size(); ++i) { - const QVector<QObjectConnection> &cs = connections.at(i); - for (int j = 0; j < cs.size(); ++j) { - const QObjectConnection &c = cs.at(j); - if (c.slotIndex == slotIndex) { - receiver = c.receiver; - slot = c.slot; - senderWrapper = c.senderWrapper; - signalIndex = i; - break; - } - } - } - Q_ASSERT(slot.isValid()); - - QScriptEnginePrivate *eng = slot.engine(); - - if (eng->isCollecting()) { - // we can't do a script function call during GC, - // so we're forced to ignore this signal - return; - } - - QScriptFunction *fun = eng->convertToNativeFunction(slot); - if (fun == 0) { - // the signal handler has been GC'ed. This can only happen when - // a QObject is owned by the engine, the engine is destroyed, and - // there is a script function connected to the destroyed() signal - Q_ASSERT(signalIndex <= 1); // destroyed(QObject*) - return; - } - - const QMetaObject *meta = sender()->metaObject(); - const QMetaMethod method = meta->method(signalIndex); - - QList<QByteArray> parameterTypes = method.parameterTypes(); - int argc = parameterTypes.count(); - - QScriptValueImpl activation; - eng->newActivation(&activation); - QScriptObject *activation_data = activation.objectValue(); - activation_data->m_scope = slot.scope(); - - int formalCount = fun->formals.count(); - int mx = qMax(formalCount, argc); - activation_data->m_members.resize(mx + 1); - activation_data->m_values.resize(mx + 1); - for (int i = 0; i < mx; ++i) { - QScriptNameIdImpl *nameId; - if (i < formalCount) - nameId = fun->formals.at(i); - else - nameId = 0; - activation_data->m_members[i].object(nameId, i, - QScriptValue::Undeletable - | QScriptValue::SkipInEnumeration); - QScriptValueImpl actual; - if (i < argc) { - void *arg = argv[i + 1]; - QByteArray typeName = parameterTypes.at(i); - int argType = QMetaType::type(typeName); - if (!argType) { - if (typeName == "QVariant") { - actual = eng->valueFromVariant(*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 = eng->undefinedValue(); - } - } else { - actual = eng->create(argType, arg); - } - } else { - actual = eng->undefinedValue(); - } - activation_data->m_values[i] = actual; - } - - QScriptValueImpl senderObject; - if (senderWrapper.isQObject()) { - senderObject = senderWrapper; - } else { - QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; - eng->newQObject(&senderObject, sender(), QScriptEngine::QtOwnership, opt); - } - activation_data->m_members[mx].object(eng->idTable()->id___qt_sender__, mx, - QScriptValue::SkipInEnumeration); - activation_data->m_values[mx] = senderObject; - - QScriptValueImpl thisObject; - if (receiver.isObject()) - thisObject = receiver; - else - thisObject = eng->globalObject(); - - QScriptContextPrivate *context_data = eng->pushContext(); - context_data->m_activation = activation; - context_data->m_callee = slot; - context_data->m_thisObject = thisObject; - context_data->argc = argc; - context_data->args = const_cast<QScriptValueImpl*> (activation_data->m_values.constData()); - - fun->execute(context_data); - - eng->popContext(); - if (eng->hasUncaughtException()) - eng->emitSignalHandlerException(); -} - -QScript::QObjectConnectionManager::QObjectConnectionManager() - : m_slotCounter(0) -{ -} - -QScript::QObjectConnectionManager::~QObjectConnectionManager() -{ -} - -void QScript::QObjectConnectionManager::mark(int generation) -{ - for (int i = 0; i < connections.size(); ++i) { - QVector<QObjectConnection> &cs = connections[i]; - for (int j = 0; j < cs.size(); ++j) - cs[j].mark(generation); - } -} - -bool QScript::QObjectConnectionManager::addSignalHandler( - QObject *sender, int signalIndex, const QScriptValueImpl &receiver, - const QScriptValueImpl &function, const QScriptValueImpl &senderWrapper, - Qt::ConnectionType type) -{ - if (connections.size() <= signalIndex) - connections.resize(signalIndex+1); - QVector<QObjectConnection> &cs = connections[signalIndex]; - int absSlotIndex = m_slotCounter + metaObject()->methodOffset(); - bool ok = QMetaObject::connect(sender, signalIndex, this, absSlotIndex, type); - if (ok) { - cs.append(QScript::QObjectConnection(m_slotCounter++, receiver, function, senderWrapper)); - QMetaMethod signal = sender->metaObject()->method(signalIndex); - QByteArray signalString; - signalString.append('2'); // signal code - signalString.append(signal.signature()); - static_cast<QScript::QObjectNotifyCaller*>(sender)->callConnectNotify(signalString); - } - return ok; -} - -bool QScript::QObjectConnectionManager::removeSignalHandler( - QObject *sender, int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &slot) -{ - if (connections.size() <= signalIndex) - return false; - QVector<QObjectConnection> &cs = connections[signalIndex]; - for (int i = 0; i < cs.size(); ++i) { - const QObjectConnection &c = cs.at(i); - if (c.hasTarget(receiver, slot)) { - int absSlotIndex = c.slotIndex + metaObject()->methodOffset(); - bool ok = QMetaObject::disconnect(sender, signalIndex, this, absSlotIndex); - if (ok) { - cs.remove(i); - QMetaMethod signal = sender->metaObject()->method(signalIndex); - QByteArray signalString; - signalString.append('2'); // signal code - signalString.append(signal.signature()); - static_cast<QScript::QObjectNotifyCaller*>(sender)->callDisconnectNotify(signalString); - } - return ok; - } - } - return false; -} - - - -QString QScript::QtPropertyFunction::functionName() const -{ - QMetaProperty prop = m_meta->property(m_index); - return QLatin1String(prop.name()); -} - -void QScript::QtPropertyFunction::execute(QScriptContextPrivate *context) -{ - context->calleeMetaIndex = m_index; - - QScriptEnginePrivate *eng_p = context->engine(); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionEntry(context); -#endif - QScriptValueImpl result = eng_p->undefinedValue(); - - QScriptValueImpl object = context->thisObject(); - QObject *qobject = object.toQObject(); - while ((!qobject || (qobject->metaObject() != m_meta)) - && object.prototype().isObject()) { - object = object.prototype(); - qobject = object.toQObject(); - } - Q_ASSERT(qobject); - - QMetaProperty prop = m_meta->property(m_index); - Q_ASSERT(prop.isScriptable()); - if (context->argumentCount() == 0) { - // get - if (prop.isValid()) { - QScriptable *scriptable = scriptableFromQObject(qobject); - QScriptEngine *oldEngine = 0; - if (scriptable) { - oldEngine = QScriptablePrivate::get(scriptable)->engine; - QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(eng_p); - } - - QVariant v = prop.read(qobject); - - if (scriptable) - QScriptablePrivate::get(scriptable)->engine = oldEngine; - - result = eng_p->valueFromVariant(v); - } - } else { - // set - QScriptValueImpl arg = context->argument(0); - QVariant v; - if (prop.isEnumType() && arg.isString() - && !eng_p->demarshalFunction(prop.userType())) { - // give QMetaProperty::write() a chance to convert from - // string to enum value - v = arg.toString(); - } else { - v = variantFromValue(eng_p, prop.userType(), arg); - } - - QScriptable *scriptable = scriptableFromQObject(qobject); - QScriptEngine *oldEngine = 0; - if (scriptable) { - oldEngine = QScriptablePrivate::get(scriptable)->engine; - QScriptablePrivate::get(scriptable)->engine = QScriptEnginePrivate::get(eng_p); - } - - prop.write(qobject, v); - - if (scriptable) - QScriptablePrivate::get(scriptable)->engine = oldEngine; - - result = context->argument(0); - } - if (!eng_p->hasUncaughtException()) - context->m_result = result; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionExit(context); -#endif -} - -QString QScript::QtFunction::functionName() const -{ - const QMetaObject *meta = metaObject(); - if (!meta) - return QString(); - QMetaMethod method = meta->method(m_initialIndex); - return QLatin1String(methodName(method)); -} - -void QScript::QtFunction::mark(QScriptEnginePrivate *engine, int generation) -{ - if (m_object.isValid()) - engine->markObject(m_object, generation); - QScriptFunction::mark(engine, generation); -} - -void QScript::QtFunction::execute(QScriptContextPrivate *context) -{ - QScriptEnginePrivate *eng_p = context->engine(); - QObject *qobj = qobject(); - if (!qobj) { - context->calleeMetaIndex = m_initialIndex; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionEntry(context); -#endif - context->throwError(QLatin1String("cannot call function of deleted QObject")); -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionExit(context); -#endif - return; - } - - const QMetaObject *meta = qobj->metaObject(); - - QObject *thisQObject = context->thisObject().toQObject(); - if (!thisQObject) // ### TypeError - thisQObject = qobj; - - if (!meta->cast(thisQObject)) { -#if 0 - // ### find common superclass, see if initialIndex is - // in that class (or a superclass of that class), - // then it's still safe to execute it - funName = methodName(meta->method(m_initialIndex)); - context->throwError( - QString::fromUtf8("cannot execute %0: %1 does not inherit %2") - .arg(QLatin1String(funName)) - .arg(QLatin1String(thisQObject->metaObject()->className())) - .arg(QLatin1String(meta->className()))); - return; -#endif - // invoking a function in the prototype - thisQObject = qobj; - } - - callQtMethod(context, QMetaMethod::Method, thisQObject, - meta, m_initialIndex, m_maybeOverloaded); -} - -int QScript::QtFunction::mostGeneralMethod(QMetaMethod *out) const -{ - const QMetaObject *meta = metaObject(); - if (!meta) - return -1; - int index = m_initialIndex; - QMetaMethod method = meta->method(index); - if (maybeOverloaded() && (method.attributes() & QMetaMethod::Cloned)) { - // find the most general method - do { - method = meta->method(--index); - } while (method.attributes() & QMetaMethod::Cloned); - } - if (out) - *out = method; - return index; -} - -QList<int> QScript::QtFunction::overloadedIndexes() const -{ - if (!maybeOverloaded()) - return QList<int>(); - QList<int> result; - QString name = functionName(); - const QMetaObject *meta = metaObject(); - for (int index = mostGeneralMethod() - 1; index >= 0; --index) { - QString otherName = QString::fromLatin1(methodName(meta->method(index))); - if (otherName == name) - result.append(index); - } - return result; -} - -///////////////////////////////////////////////////////// - -namespace QScript -{ - -ExtQMetaObject::Instance *ExtQMetaObject::Instance::get(const QScriptValueImpl &object, - QScriptClassInfo *klass) -{ - if (! klass || klass == object.classInfo()) - return static_cast<Instance*> (object.objectData()); - - return 0; -} - -void ExtQMetaObject::Instance::execute(QScriptContextPrivate *context) -{ - if (ctor.isFunction()) { - QScriptValueImplList args; - for (int i = 0; i < context->argumentCount(); ++i) - args << context->argument(i); - QScriptEnginePrivate *eng = context->engine(); - context->m_result = eng->call(ctor, context->thisObject(), args, - context->isCalledAsConstructor()); - } else { - if (value->constructorCount() > 0) { - callQtMethod(context, QMetaMethod::Constructor, /*thisQObject=*/0, - value, value->constructorCount()-1, /*maybeOverloaded=*/true); - if (context->state() == QScriptContext::NormalState) { - ExtQObject::Instance *inst = ExtQObject::Instance::get(context->m_result); - Q_ASSERT(inst != 0); - inst->ownership = QScriptEngine::AutoOwnership; - context->m_result.setPrototype(prototype); - } - } else { - context->m_result = context->throwError( - QScriptContext::TypeError, - QString::fromUtf8("no constructor for %0") - .arg(QLatin1String(value->className()))); - } - } -} - -struct StaticQtMetaObject : public QObject -{ - static const QMetaObject *get() - { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; } -}; - -class ExtQMetaObjectData: public QScriptClassData -{ -public: - ExtQMetaObjectData(QScriptEnginePrivate *, QScriptClassInfo *classInfo); - - virtual bool resolve(const QScriptValueImpl &object, QScriptNameIdImpl *nameId, - QScript::Member *member, QScriptValueImpl *base, - QScript::AccessMode access); - virtual bool get(const QScriptValueImpl &object, const QScript::Member &member, - QScriptValueImpl *result); - virtual bool put(QScriptValueImpl *object, const QScript::Member &member, - const QScriptValueImpl &value); - virtual void mark(const QScriptValueImpl &object, int generation); - -private: - QScriptClassInfo *m_classInfo; -}; - -ExtQMetaObjectData::ExtQMetaObjectData(QScriptEnginePrivate *, - QScriptClassInfo *classInfo) - : m_classInfo(classInfo) -{ -} - -bool ExtQMetaObjectData::resolve(const QScriptValueImpl &object, - QScriptNameIdImpl *nameId, - QScript::Member *member, - QScriptValueImpl *base, - QScript::AccessMode /*access*/) -{ - const QMetaObject *meta = object.toQMetaObject(); - if (!meta) - return false; - - QScriptEnginePrivate *eng_p = object.engine(); - if (eng_p->idTable()->id_prototype == nameId) { - // prototype property is a proxy to constructor's prototype property - member->native(nameId, /*id=*/0, QScriptValue::Undeletable); - return true; - } - - QByteArray name = eng_p->toString(nameId).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())) { - member->native(nameId, e.value(j), - QScriptValue::ReadOnly - | QScriptValue::Undeletable); - *base = object; - return true; - } - } - } - - return false; -} - -bool ExtQMetaObjectData::get(const QScriptValueImpl &object, - const QScript::Member &member, - QScriptValueImpl *result) -{ - if (! member.isNativeProperty()) - return false; - - QScriptEnginePrivate *eng_p = object.engine(); - if (eng_p->idTable()->id_prototype == member.nameId()) { - ExtQMetaObject::Instance *inst = ExtQMetaObject::Instance::get(object, m_classInfo); - if (inst->ctor.isFunction()) - *result = inst->ctor.property(eng_p->idTable()->id_prototype); - else - *result = inst->prototype; - } else { - *result = QScriptValueImpl(member.id()); - } - return true; -} - -bool ExtQMetaObjectData::put(QScriptValueImpl *object, const Member &member, - const QScriptValueImpl &value) -{ - if (! member.isNativeProperty()) - return false; - - QScriptEnginePrivate *eng_p = object->engine(); - if (eng_p->idTable()->id_prototype == member.nameId()) { - ExtQMetaObject::Instance *inst = ExtQMetaObject::Instance::get(*object, m_classInfo); - if (inst->ctor.isFunction()) - inst->ctor.setProperty(eng_p->idTable()->id_prototype, value); - else - inst->prototype = value; - } - - return true; -} - -void ExtQMetaObjectData::mark(const QScriptValueImpl &object, int generation) -{ - ExtQMetaObject::Instance *inst = ExtQMetaObject::Instance::get(object, m_classInfo); - if (inst->ctor.isObject() || inst->ctor.isString()) - inst->ctor.mark(generation); -} - -} // namespace QScript - -QScript::ExtQMetaObject::ExtQMetaObject(QScriptEnginePrivate *eng) - : Ecma::Core(eng, QLatin1String("QMetaObject"), QScriptClassInfo::QMetaObjectType) -{ - newQMetaObject(&publicPrototype, QScript::StaticQtMetaObject::get()); - - eng->newConstructor(&ctor, this, publicPrototype); - addPrototypeFunction(QLatin1String("className"), method_className, 0); - - classInfo()->setData(new QScript::ExtQMetaObjectData(eng, classInfo())); -} - -QScript::ExtQMetaObject::~ExtQMetaObject() -{ -} - -void QScript::ExtQMetaObject::execute(QScriptContextPrivate *context) -{ - QScriptValueImpl tmp; - newQMetaObject(&tmp, 0); - context->setReturnValue(tmp); -} - -void QScript::ExtQMetaObject::newQMetaObject(QScriptValueImpl *result, const QMetaObject *value, - const QScriptValueImpl &ctor) -{ - Instance *instance = new Instance(); - instance->value = value; - if (ctor.isFunction()) { - instance->ctor = ctor; - } else { - instance->prototype = engine()->newObject(); - instance->prototype.setPrototype(engine()->qobjectConstructor->publicPrototype); - } - - engine()->newObject(result, publicPrototype, classInfo()); - result->setObjectData(instance); -} - -QScriptValueImpl QScript::ExtQMetaObject::method_className(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) { - return QScriptValueImpl(eng, QString::fromLatin1(instance->value->className())); - } - return eng->undefinedValue(); -} - -QScriptQObjectData::QScriptQObjectData() - : m_connectionManager(0) -{ -} - -QScriptQObjectData::~QScriptQObjectData() -{ - if (m_connectionManager) { - delete m_connectionManager; - m_connectionManager = 0; - } -} - -bool QScriptQObjectData::addSignalHandler(QObject *sender, - int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &slot, - const QScriptValueImpl &senderWrapper, - Qt::ConnectionType type) -{ - if (!m_connectionManager) - m_connectionManager = new QScript::QObjectConnectionManager(); - return m_connectionManager->addSignalHandler( - sender, signalIndex, receiver, slot, senderWrapper, type); -} - -bool QScriptQObjectData::removeSignalHandler(QObject *sender, - int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &slot) -{ - if (!m_connectionManager) - return false; - return m_connectionManager->removeSignalHandler( - sender, signalIndex, receiver, slot); -} - -bool QScriptQObjectData::findWrapper(QScriptEngine::ValueOwnership ownership, - const QScriptEngine::QObjectWrapOptions &options, - QScriptValueImpl *out) -{ - for (int i = 0; i < wrappers.size(); ++i) { - const QScriptQObjectWrapperInfo &info = wrappers.at(i); - if ((info.ownership == ownership) && (info.options == options)) { - *out = info.object; - return true; - } - } - return false; -} - -void QScriptQObjectData::registerWrapper(const QScriptValueImpl &wrapper, - QScriptEngine::ValueOwnership ownership, - const QScriptEngine::QObjectWrapOptions &options) -{ - wrappers.append(QScriptQObjectWrapperInfo(wrapper, ownership, options)); -} - -void QScriptQObjectData::mark(int generation) -{ - if (m_connectionManager) - m_connectionManager->mark(generation); - - { - QList<QScriptQObjectWrapperInfo>::iterator it; - for (it = wrappers.begin(); it != wrappers.end(); ) { - const QScriptQObjectWrapperInfo &info = *it; - if (info.object.isMarked(generation)) { - ++it; - } else { - it = wrappers.erase(it); - } - } - } -} - -QT_END_NAMESPACE - -#include "qscriptextqobject.moc" - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptextqobject_p.h b/src/script/qscriptextqobject_p.h deleted file mode 100644 index 212f96f..0000000 --- a/src/script/qscriptextqobject_p.h +++ /dev/null @@ -1,448 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTEXTQOBJECT_P_H -#define QSCRIPTEXTQOBJECT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QT_NO_QOBJECT - -#include "qscriptecmacore_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptclassdata_p.h" -#include "qscriptfunction_p.h" -#include "qscriptengine.h" -#include "qscriptmemberfwd_p.h" - -#include <QtCore/QHash> -#include <QtCore/QPointer> -#include <QtCore/QObject> -#include <QtCore/QVariant> -#include <QtCore/QVarLengthArray> -#include <QtCore/QVector> - -QT_BEGIN_NAMESPACE - -namespace QScript { - -class QObjectConnectionManager; - -class ExtQObject: public Ecma::Core -{ -public: - ExtQObject(QScriptEnginePrivate *engine); - virtual ~ExtQObject(); - - virtual void execute(QScriptContextPrivate *context); - - class Instance: public QScriptObjectData { - public: - Instance() : ownership(QScriptEngine::QtOwnership) { } - virtual void finalize(QScriptEnginePrivate *engine); - virtual ~Instance() {} - - static Instance *get(const QScriptValueImpl &object, QScriptClassInfo *klass = 0); - - public: - QPointer<QObject> value; - QScriptEngine::ValueOwnership ownership; - QScriptEngine::QObjectWrapOptions options; - }; - - inline Instance *get(const QScriptValueImpl &object) const - { return Instance::get(object, classInfo()); } - - void newQObject(QScriptValueImpl *result, QObject *value, - QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership, - const QScriptEngine::QObjectWrapOptions &options = 0); - -protected: - static QScriptValueImpl method_findChild(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - static QScriptValueImpl method_findChildren(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); - static QScriptValueImpl method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); -}; - -class QtFunction: public QScriptFunction -{ -public: - QtFunction(const QScriptValueImpl &object, int initialIndex, bool maybeOverloaded) - : m_object(object), m_initialIndex(initialIndex), - m_maybeOverloaded(maybeOverloaded) - { } - - virtual ~QtFunction() { } - - virtual void execute(QScriptContextPrivate *context); - - virtual Type type() const { return QScriptFunction::Qt; } - - virtual QString functionName() const; - - virtual void mark(QScriptEnginePrivate *engine, int generation); - - inline QScriptValueImpl object() const { return m_object; } - - inline QObject *qobject() const { - if (!m_object.isQObject()) - return 0; - return m_object.toQObject(); - } - - inline const QMetaObject *metaObject() const { - if (!m_object.isQObject()) - return 0; - QObject *qobj = m_object.toQObject(); - if (!qobj) - return 0; - return qobj->metaObject(); - } - - int mostGeneralMethod(QMetaMethod *out = 0) const; - QList<int> overloadedIndexes() const; - - inline int initialIndex() const { return m_initialIndex; } - inline bool maybeOverloaded() const { return m_maybeOverloaded; } - -private: - QScriptValueImpl m_object; - int m_initialIndex; - bool m_maybeOverloaded; -}; - -class ExtQMetaObject: public Ecma::Core -{ -public: - ExtQMetaObject(QScriptEnginePrivate *engine); - virtual ~ExtQMetaObject(); - - virtual void execute(QScriptContextPrivate *context); - - class Instance: public QScriptFunction { - public: - Instance() : value(0) { } - virtual ~Instance() { } - - static Instance *get(const QScriptValueImpl &object, QScriptClassInfo *klass); - - virtual void execute(QScriptContextPrivate *context); - - public: - const QMetaObject *value; - QScriptValueImpl ctor; - QScriptValueImpl prototype; - }; - - inline Instance *get(const QScriptValueImpl &object) const - { return Instance::get(object, classInfo()); } - - void newQMetaObject(QScriptValueImpl *result, const QMetaObject *value, - const QScriptValueImpl &ctor = QScriptValueImpl()); - -protected: - static QScriptValueImpl method_className(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo); -}; - -} // namespace QScript - -struct QScriptQObjectWrapperInfo -{ - QScriptQObjectWrapperInfo(const QScriptValueImpl &obj, - QScriptEngine::ValueOwnership own, - const QScriptEngine::QObjectWrapOptions &opt) - : object(obj), ownership(own), options(opt) {} - - QScriptValueImpl object; - QScriptEngine::ValueOwnership ownership; - QScriptEngine::QObjectWrapOptions options; -}; - -class QScriptQObjectData // : public QObjectUserData -{ -public: - QScriptQObjectData(); - ~QScriptQObjectData(); - - bool addSignalHandler(QObject *sender, - int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &slot, - const QScriptValueImpl &senderWrapper, - Qt::ConnectionType type); - bool removeSignalHandler(QObject *sender, - int signalIndex, - const QScriptValueImpl &receiver, - const QScriptValueImpl &slot); - - bool findWrapper(QScriptEngine::ValueOwnership ownership, - const QScriptEngine::QObjectWrapOptions &options, - QScriptValueImpl *out); - void registerWrapper(const QScriptValueImpl &wrapper, - QScriptEngine::ValueOwnership ownership, - const QScriptEngine::QObjectWrapOptions &options); - - void mark(int generation); - -private: - QScript::QObjectConnectionManager *m_connectionManager; - QList<QScriptQObjectWrapperInfo> wrappers; -}; - -class QScriptMetaType -{ -public: - enum Kind { - Invalid, - Variant, - MetaType, - Unresolved, - MetaEnum - }; - - inline QScriptMetaType() - : m_kind(Invalid), m_typeId(0) { } - - inline Kind kind() const - { return m_kind; } - - int typeId() const; - - inline bool isValid() const - { return (m_kind != Invalid); } - - inline bool isVariant() const - { return (m_kind == Variant); } - - inline bool isMetaType() const - { return (m_kind == MetaType); } - - inline bool isUnresolved() const - { return (m_kind == Unresolved); } - - inline bool isMetaEnum() const - { return (m_kind == MetaEnum); } - - QByteArray name() const; - - inline int enumeratorIndex() const - { Q_ASSERT(isMetaEnum()); return m_typeId; } - - inline bool operator==(const QScriptMetaType &other) const - { - return (m_kind == other.m_kind) && (m_typeId == other.m_typeId); - } - - static inline QScriptMetaType variant() - { return QScriptMetaType(Variant); } - - static inline QScriptMetaType metaType(int typeId, const QByteArray &name) - { return QScriptMetaType(MetaType, typeId, name); } - - static inline QScriptMetaType metaEnum(int enumIndex, const QByteArray &name) - { return QScriptMetaType(MetaEnum, enumIndex, name); } - - static inline QScriptMetaType unresolved(const QByteArray &name) - { return QScriptMetaType(Unresolved, /*typeId=*/0, name); } - -private: - inline QScriptMetaType(Kind kind, int typeId = 0, const QByteArray &name = QByteArray()) - : m_kind(kind), m_typeId(typeId), m_name(name) { } - - Kind m_kind; - int m_typeId; - QByteArray m_name; -}; - -class QScriptMetaMethod -{ -public: - inline QScriptMetaMethod() - : m_firstUnresolvedIndex(-1) - { } - inline QScriptMetaMethod(const QByteArray &name, const QVector<QScriptMetaType> &types) - : m_name(name), m_types(types), m_firstUnresolvedIndex(-1) - { - QVector<QScriptMetaType>::const_iterator it; - for (it = m_types.constBegin(); it != m_types.constEnd(); ++it) { - if ((*it).kind() == QScriptMetaType::Unresolved) { - m_firstUnresolvedIndex = it - m_types.constBegin(); - break; - } - } - } - inline bool isValid() const - { return !m_types.isEmpty(); } - - QByteArray name() const - { return m_name; } - - inline QScriptMetaType returnType() const - { return m_types.at(0); } - - inline int argumentCount() const - { return m_types.count() - 1; } - - inline QScriptMetaType argumentType(int arg) const - { return m_types.at(arg + 1); } - - inline bool fullyResolved() const - { return m_firstUnresolvedIndex == -1; } - - inline bool hasUnresolvedReturnType() const - { return (m_firstUnresolvedIndex == 0); } - - inline int firstUnresolvedIndex() const - { return m_firstUnresolvedIndex; } - - inline int count() const - { return m_types.count(); } - - inline QScriptMetaType type(int index) const - { return m_types.at(index); } - - inline QVector<QScriptMetaType> types() const - { return m_types; } - -private: - QByteArray m_name; - QVector<QScriptMetaType> m_types; - int m_firstUnresolvedIndex; -}; - -struct QScriptMetaArguments -{ - int matchDistance; - int index; - QScriptMetaMethod method; - QVarLengthArray<QVariant, 9> args; - - inline QScriptMetaArguments(int dist, int idx, const QScriptMetaMethod &mtd, - const QVarLengthArray<QVariant, 9> &as) - : matchDistance(dist), index(idx), method(mtd), args(as) { } - inline QScriptMetaArguments() - : matchDistance(0), index(-1) { } - - inline bool isValid() const - { return (index != -1); } -}; - -class QScriptMetaObject -{ -public: - inline QScriptMetaMethod findMethod(int index) const - { - return m_methods.value(index); - } - - inline void registerMethod(int index, const QScriptMetaMethod &method) - { - m_methods.insert(index, method); - } - - inline bool findMember(QScriptNameIdImpl *nameId, QScript::Member *member) const - { - QHash<QScriptNameIdImpl*, QScript::Member>::const_iterator it; - it = m_members.constFind(nameId); - if (it == m_members.constEnd()) - return false; - *member = it.value(); - return true; - } - - inline void registerMember(QScriptNameIdImpl *nameId, const QScript::Member &member) - { - m_members.insert(nameId, member); - } - - inline QList<QScriptNameIdImpl*> registeredMemberNames() const - { - return m_members.keys(); - } - - inline QScriptValueImpl findPropertyAccessor(int index) const - { - return m_propertyAccessors.value(index); - } - - inline void registerPropertyAccessor(int index, const QScriptValueImpl &accessor) - { - m_propertyAccessors.insert(index, accessor); - } - - inline QList<QScriptValueImpl> registeredPropertyAccessors() const - { - return m_propertyAccessors.values(); - } - - inline int methodLowerBound(int index) const - { - return m_methodBounds.value(index, 0); - } - - inline void setMethodLowerBound(int index, int bound) - { - m_methodBounds.insert(index, bound); - } - -private: - QHash<int, QScriptValueImpl> m_propertyAccessors; - QHash<int, QScriptMetaMethod> m_methods; - QHash<int, int> m_methodBounds; - QHash<QScriptNameIdImpl*, QScript::Member> m_members; -}; - -#endif // QT_NO_QOBJECT - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif // QSCRIPTEXTQOBJECT_P_H diff --git a/src/script/qscriptextvariant.cpp b/src/script/qscriptextvariant.cpp deleted file mode 100644 index 4ac2a4a..0000000 --- a/src/script/qscriptextvariant.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptextvariant_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -#include <QtCore/QtDebug> - -#include <QtCore/QStringList> - -#include <limits.h> - -QT_BEGIN_NAMESPACE - -namespace QScript { namespace Ext { - -Variant::Variant(QScriptEnginePrivate *eng): - Ecma::Core(eng, QLatin1String("QVariant"), QScriptClassInfo::VariantType) -{ - newVariant(&publicPrototype, QVariant()); - - eng->newConstructor(&ctor, this, publicPrototype); - - addPrototypeFunction(QLatin1String("toString"), method_toString, 0); - addPrototypeFunction(QLatin1String("valueOf"), method_valueOf, 0); -} - -Variant::~Variant() -{ -} - -Variant::Instance *Variant::Instance::get(const QScriptValueImpl &object, QScriptClassInfo *klass) -{ - if (! klass || klass == object.classInfo()) - return static_cast<Instance*> (object.objectData()); - - return 0; -} - -void Variant::execute(QScriptContextPrivate *context) -{ - QScriptValueImpl tmp; - newVariant(&tmp, QVariant()); - context->setReturnValue(tmp); -} - -void Variant::newVariant(QScriptValueImpl *result, const QVariant &value) -{ - Instance *instance; - if (!result->isValid()) { - engine()->newObject(result, publicPrototype, classInfo()); - instance = new Instance(); - result->setObjectData(instance); - } else { - Q_ASSERT(result->isObject()); - if (result->classInfo() != classInfo()) { - result->destroyObjectData(); - result->setClassInfo(classInfo()); - instance = new Instance(); - result->setObjectData(instance); - } else { - instance = Instance::get(*result, classInfo()); - } - } - instance->value = value; -} - -QScriptValueImpl Variant::method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) { - QString result; - QScriptValueImpl value = method_valueOf(context, eng, classInfo); - if (value.isObject()) { - result = instance->value.toString(); - if (result.isEmpty()) { - result = QString::fromLatin1("QVariant(%0)") - .arg(QLatin1String(instance->value.typeName())); - } - } else { - result = value.toString(); - } - return QScriptValueImpl(eng, result); - } - return context->throwError(QScriptContext::TypeError, - QLatin1String("QVariant.prototype.toString")); -} - -QScriptValueImpl Variant::method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *eng, QScriptClassInfo *classInfo) -{ - if (Instance *instance = Instance::get(context->thisObject(), classInfo)) { - QVariant v = instance->value; - switch (v.type ()) { - case QVariant::Invalid: - return eng->undefinedValue(); - case QVariant::String: - return (QScriptValueImpl(eng, v.toString())); - - case QVariant::Int: - return (QScriptValueImpl(v.toInt())); - - case QVariant::Bool: - return (QScriptValueImpl(v.toBool())); - - case QVariant::Double: - return (QScriptValueImpl(v.toDouble())); // ### hmmm - - case QVariant::Char: - return (QScriptValueImpl(v.toChar().unicode())); - - case QVariant::UInt: - return (QScriptValueImpl(v.toUInt())); - - default: - return context->thisObject(); - } // switch - } - return context->thisObject(); -} - -} } // namespace QScript::Ecma - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptextvariant_p.h b/src/script/qscriptextvariant_p.h deleted file mode 100644 index 070577f..0000000 --- a/src/script/qscriptextvariant_p.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTEXTVARIANT_P_H -#define QSCRIPTEXTVARIANT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QVariant> - -#include "qscriptecmacore_p.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_SCRIPT - -namespace QScript { namespace Ext { - -class Instance; - -class Variant: public Ecma::Core -{ -public: - Variant(QScriptEnginePrivate *engine); - virtual ~Variant(); - - virtual void execute(QScriptContextPrivate *context); - - class Instance: public QScriptObjectData { - public: - Instance() {} - virtual ~Instance() {} - - static Instance *get(const QScriptValueImpl &object, - QScriptClassInfo *klass); - - public: - QVariant value; - }; - - inline Instance *get(const QScriptValueImpl &object) const - { return Instance::get(object, classInfo()); } - - void newVariant(QScriptValueImpl *result, const QVariant &value); - -protected: - static QScriptValueImpl method_toString(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); - static QScriptValueImpl method_valueOf(QScriptContextPrivate *context, QScriptEnginePrivate *eng, - QScriptClassInfo *classInfo); -}; - -} } // namespace QScript::Ext - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif // QSCRIPTEXTVARIANT_P_H diff --git a/src/script/qscriptfunction.cpp b/src/script/qscriptfunction.cpp deleted file mode 100644 index 4d2cc07..0000000 --- a/src/script/qscriptfunction.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptfunction_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -QT_BEGIN_NAMESPACE - -QScriptFunction::~QScriptFunction() -{ -} - -QString QScriptFunction::toString(QScriptContextPrivate *) const -{ - QString result; - result += QLatin1String("function () { [native] }"); - return result; -} - -QString QScriptFunction::fileName() const -{ - return QString(); -} - -QString QScriptFunction::functionName() const -{ - return QString(); -} - -int QScriptFunction::startLineNumber() const -{ - return -1; -} - -int QScriptFunction::endLineNumber() const -{ - return -1; -} - -void QScriptFunction::mark(QScriptEnginePrivate *engine, int generation) -{ - for (int i = 0; i < formals.count(); ++i) - engine->markString(formals.at(i), generation); -} - -// public API function -void QScript::CFunction::execute(QScriptContextPrivate *context) -{ - QScriptEnginePrivate *eng_p = context->engine(); - - context->m_result = eng_p->undefinedValue(); - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionEntry(context); -#endif - - QScriptContext *publicContext = QScriptContextPrivate::get(eng_p->currentContext()); - QScriptEngine *publicEngine = QScriptEnginePrivate::get(eng_p); - QScriptValueImpl result = eng_p->toImpl((*m_funPtr)(publicContext, publicEngine)); - if (result.isValid() && !eng_p->shouldAbort() - && (context->state() == QScriptContext::NormalState)) { - context->m_result = result; - } - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionExit(context); -#endif -} - -QString QScript::CFunction::functionName() const -{ - return QString(); -} - -// internal API function -void QScript::C2Function::execute(QScriptContextPrivate *context) -{ - QScriptEnginePrivate *eng_p = context->engine(); - - bool blocked = eng_p->blockGC(true); - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionEntry(context); -#endif - - context->m_result = (*m_funPtr)(context, eng_p, m_classInfo); - Q_ASSERT(context->m_result.isValid()); - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionExit(context); -#endif - - eng_p->blockGC(blocked); -} - -QString QScript::C2Function::functionName() const -{ - if (!m_name.isEmpty()) - return m_name; - return QString(); -} - -void QScript::C3Function::execute(QScriptContextPrivate *context) -{ - QScriptEnginePrivate *eng_p = context->engine(); - - context->m_result = eng_p->undefinedValue(); - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionEntry(context); -#endif - - QScriptContext *publicContext = QScriptContextPrivate::get(eng_p->currentContext()); - QScriptEngine *publicEngine = QScriptEnginePrivate::get(eng_p); - QScriptValueImpl result = eng_p->toImpl((*m_funPtr)(publicContext, publicEngine, m_arg)); - if (result.isValid() && !eng_p->shouldAbort()) - context->m_result = result; - -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - eng_p->notifyFunctionExit(context); -#endif -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptfunction_p.h b/src/script/qscriptfunction_p.h deleted file mode 100644 index 09710c1..0000000 --- a/src/script/qscriptfunction_p.h +++ /dev/null @@ -1,219 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTFUNCTION_P_H -#define QSCRIPTFUNCTION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qscriptobjectdata_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptglobals_p.h" -#include "qscriptnodepool_p.h" - -#include <QtCore/QList> - -#ifndef QT_NO_QOBJECT -# include <QtCore/QPointer> -# include <QtCore/QMetaMethod> -#endif - -QT_BEGIN_NAMESPACE - -class QScriptContext; -class QScriptContextPrivate; -class QScriptNameIdImpl; - -class QScriptFunction: public QScriptObjectData -{ -public: - enum Type { - Unknown, - Script, - C, - C2, - C3, - Qt, - QtProperty - }; - - QScriptFunction(int len = 0) - : length(len) - { } - virtual ~QScriptFunction(); - - virtual void execute(QScriptContextPrivate *context) = 0; - virtual QString toString(QScriptContextPrivate *context) const; - - virtual Type type() const { return Unknown; } - - // name of the file the function is defined in - virtual QString fileName() const; - - virtual QString functionName() const; - - virtual int startLineNumber() const; - - virtual int endLineNumber() const; - - virtual void mark(QScriptEnginePrivate *engine, int generation); - -public: // ### private - int length; - QList<QScriptNameIdImpl*> formals; -}; - -namespace QScript { - -// public API function -class CFunction: public QScriptFunction -{ -public: - CFunction(QScriptFunctionSignature funPtr, int length) - : QScriptFunction(length), m_funPtr(funPtr) - { } - - virtual ~CFunction() { } - - virtual void execute(QScriptContextPrivate *context); - - virtual Type type() const { return QScriptFunction::C; } - - virtual QString functionName() const; - -private: - QScriptFunctionSignature m_funPtr; -}; - -// internal API function -class C2Function: public QScriptFunction -{ -public: - C2Function(QScriptInternalFunctionSignature funPtr, int length, - QScriptClassInfo *classInfo, const QString &name) - : QScriptFunction(length), m_funPtr(funPtr), - m_classInfo(classInfo), m_name(name) - { } - - virtual ~C2Function() {} - - virtual void execute(QScriptContextPrivate *context); - - virtual Type type() const { return QScriptFunction::C2; } - - virtual QString functionName() const; - -private: - QScriptInternalFunctionSignature m_funPtr; - QScriptClassInfo *m_classInfo; - QString m_name; -}; - -class C3Function: public QScriptFunction -{ -public: - C3Function(QScriptFunctionWithArgSignature funPtr, void *arg, int length) - : QScriptFunction(length), m_funPtr(funPtr), m_arg(arg) - { } - - virtual ~C3Function() { } - - virtual void execute(QScriptContextPrivate *context); - - virtual Type type() const { return QScriptFunction::C3; } - -private: - QScriptFunctionWithArgSignature m_funPtr; - void *m_arg; -}; - -namespace AST { - class FunctionExpression; -} - -// implemented in qscriptcontext_p.cpp -class ScriptFunction: public QScriptFunction -{ -public: - ScriptFunction(AST::FunctionExpression *definition, NodePool *astPool): - m_definition(definition), m_astPool(astPool), m_compiledCode(0) {} - - virtual ~ScriptFunction() {} - - virtual void execute(QScriptContextPrivate *context); - - virtual QString toString(QScriptContextPrivate *context) const; - - virtual Type type() const - { return QScriptFunction::Script; } - - virtual QString fileName() const; - - virtual QString functionName() const; - - virtual int startLineNumber() const; - - virtual int endLineNumber() const; - -private: - AST::FunctionExpression *m_definition; - QExplicitlySharedDataPointer<NodePool> m_astPool; - Code *m_compiledCode; -}; - -} // namespace QScript - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif // QSCRIPTFUNCTION_P_H diff --git a/src/script/qscriptgc_p.h b/src/script/qscriptgc_p.h deleted file mode 100644 index a1bf8c5..0000000 --- a/src/script/qscriptgc_p.h +++ /dev/null @@ -1,321 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTGC_P_H -#define QSCRIPTGC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#if defined(Q_OS_VXWORKS) && defined(m_free) -# undef m_free -#endif - -#include <QtCore/qglobal.h> - -#ifndef QT_NO_SCRIPT - -#include <QtCore/QtDebug> -#include <new> - -#include "qscriptmemorypool_p.h" - -QT_BEGIN_NAMESPACE - -namespace QScript { - -class GCBlock -{ -public: - GCBlock *next; - - union { - int generation; - uint flags; - }; - -public: - inline GCBlock(GCBlock *n): - next(n), flags(0) {} - - inline void *data() - { return reinterpret_cast<char *>(this) + sizeof(GCBlock); } - - inline static GCBlock *get(void *ptr) - { - char *where = reinterpret_cast<char *>(ptr); - return reinterpret_cast<GCBlock *>(where - sizeof(GCBlock)); - } -}; - -template <typename _Tp> -class GCAlloc -{ -private: - int m_new_allocated_blocks; - int m_free_blocks; - int m_new_allocated_extra_bytes; - GCBlock *m_head; - GCBlock *m_current; - GCBlock *m_free; - bool m_blocked_gc; - bool m_force_gc; - bool m_sweeping; - MemoryPool pool; - _Tp trivial; - -public: - enum { MaxNumberOfBlocks = 1 << 14 }; - enum { MaxNumberOfExtraBytes = 0x800000 }; - -public: - inline GCAlloc(): - m_new_allocated_blocks(0), - m_free_blocks(0), - m_new_allocated_extra_bytes(0), - m_head(0), - m_current(0), - m_free(0), - m_blocked_gc(false), - m_force_gc(false), - m_sweeping(false) { - trivial.reset(); - } - - inline ~GCAlloc() { - } - - inline void destruct() { - m_sweeping = true; - GCBlock *blk = m_free; - - if (! blk) { - blk = m_head; - m_head = 0; - } - - while (blk) { - GCBlock *was = blk; - blk = blk->next; - - Q_ASSERT(was->data()); - _Tp *data = reinterpret_cast<_Tp*>(was->data()); - data->~_Tp(); - blk->~GCBlock(); - - if (! blk && m_head) { - blk = m_head; - m_head = 0; - } - } - m_sweeping = false; - } - - inline int newAllocatedBlocks() const { return m_new_allocated_blocks; } - inline int freeBlocks() const { return m_free_blocks; } - - inline _Tp *operator()(int generation) - { - GCBlock *previous = m_current; - void *where = 0; - - if (! m_free) { - Q_ASSERT (m_free_blocks == 0); - where = pool.allocate(sizeof(GCBlock) + sizeof(_Tp)); - ++m_new_allocated_blocks; - (void) new (reinterpret_cast<char*>(where) + sizeof(GCBlock)) _Tp(); - } else { - --m_free_blocks; - where = m_free; - m_free = m_free->next; - - if (! m_free) - m_force_gc = true; - } - - m_current = new (where) GCBlock(0); - - if (! previous) { - Q_ASSERT(! m_head); - m_head = m_current; - } else { - previous->next = m_current; - } - m_current->generation = generation; - - return reinterpret_cast<_Tp*> (m_current->data()); - } - - inline bool blocked() const - { - return m_blocked_gc; - } - - inline bool sweeping() const - { - return m_sweeping; - } - - inline bool blockGC(bool block) - { - bool was = m_blocked_gc; - m_blocked_gc = block; - return was; - } - - inline void requestGC() - { - m_force_gc = true; - } - - inline void adjustBytesAllocated(int bytes) - { m_new_allocated_extra_bytes += bytes; } - - inline bool poll() - { - if (m_blocked_gc || ! m_head) - return false; - - else if (m_force_gc) { - m_force_gc = false; - return true; - } - - else if (m_free && ! m_free->next) - return true; - - return (m_new_allocated_blocks >= MaxNumberOfBlocks) - || ((m_new_allocated_extra_bytes >= MaxNumberOfExtraBytes) - && (m_new_allocated_blocks > 0)); - } - - inline int generation(_Tp *ptr) const - { return GCBlock::get(ptr)->generation; } - - inline GCBlock *head() const - { return m_head; } - - void sweep(int generation) - { - m_sweeping = true; - GCBlock *blk = m_head; - m_current = 0; - - m_new_allocated_blocks = 0; - m_new_allocated_extra_bytes = 0; - - while (blk != 0) { - if (blk->generation != generation) { - if (m_current) - m_current->next = blk->next; - - GCBlock *tmp = blk; - blk = blk->next; // advance the pointer - - tmp->next = m_free; // prepend the node to the free list... - m_free = tmp; - ++m_free_blocks; - - if (m_free == m_head) - m_head = blk; - - _Tp *data = reinterpret_cast<_Tp *>(tmp->data()); - data->finalize(); - tmp->~GCBlock(); - } else { - m_current = blk; - blk = blk->next; - } - } - - if (! m_current) - m_head = m_current; - m_sweeping = false; - } - - class const_iterator - { - public: - typedef _Tp value_type; - typedef const _Tp *pointer; - typedef const _Tp &reference; - inline const_iterator() : i(0) { } - inline const_iterator(GCBlock *block) : i(block) { } - inline const_iterator(const const_iterator &o) - { i = reinterpret_cast<const const_iterator &>(o).i; } - - inline const _Tp *data() const { return reinterpret_cast<_Tp*>(i->data()); } - inline const _Tp &value() const { return *reinterpret_cast<_Tp*>(i->data()); } - inline const _Tp &operator*() const { return *reinterpret_cast<_Tp*>(i->data()); } - inline const _Tp *operator->() const { return reinterpret_cast<_Tp*>(i->data()); } - inline bool operator==(const const_iterator &o) const { return i == o.i; } - inline bool operator!=(const const_iterator &o) const { return i != o.i; } - - inline const_iterator &operator++() { - i = i->next; - return *this; - } - private: - GCBlock *i; - }; - friend class const_iterator; - - inline const_iterator constBegin() const { return const_iterator(m_head); } - inline const_iterator constEnd() const { return const_iterator(0); } - -private: - Q_DISABLE_COPY(GCAlloc) -}; - -} // namespace QScript - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT -#endif // QSCRIPT_GC_H diff --git a/src/script/qscriptglobals_p.h b/src/script/qscriptglobals_p.h deleted file mode 100644 index 8fdd18e..0000000 --- a/src/script/qscriptglobals_p.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTGLOBALS_P_H -#define QSCRIPTGLOBALS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -class QScriptValue; -class QScriptValueImpl; -class QScriptClassInfo; -class QScriptEngine; -class QScriptEnginePrivate; -class QScriptContext; -class QScriptContextPrivate; - -typedef QScriptValueImpl (*QScriptInternalFunctionSignature)(QScriptContextPrivate *, QScriptEnginePrivate *, QScriptClassInfo *); -typedef QScriptValue (*QScriptFunctionSignature)(QScriptContext *, QScriptEngine *); -typedef QScriptValue (*QScriptFunctionWithArgSignature)(QScriptContext *, QScriptEngine *, void *); - -namespace QScript { - -enum Type { - InvalidType, - // standard types - UndefinedType, - NullType, - BooleanType, - StringType, - NumberType, - ObjectType, - // internal types - IntegerType, - ReferenceType, - PointerType, - LazyStringType -}; - -enum AccessMode { - Read = 0x01, - Write = 0x02, - ReadWrite = 0x03 -}; - -} // namespace QScript - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif // QSCRIPTGLOBALS_P_H diff --git a/src/script/qscriptmember_p.h b/src/script/qscriptmember_p.h deleted file mode 100644 index 67a6eae..0000000 --- a/src/script/qscriptmember_p.h +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTMEMBER_P_H -#define QSCRIPTMEMBER_P_H - -#include "qscriptmemberfwd_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -inline void QScript::Member::resetFlags(uint flags) -{ - m_flags = flags; -} - -inline void QScript::Member::setFlags(uint flags) -{ - m_flags |= flags; -} - -inline void QScript::Member::unsetFlags(uint flags) -{ - m_flags &= ~flags; -} - -inline uint QScript::Member::flags() const -{ - return m_flags; -} - -inline bool QScript::Member::testFlags(uint mask) const -{ - return m_flags & mask; -} - -inline bool QScript::Member::isValid() const -{ - return m_flags & 0x00000300; -} - -inline bool QScript::Member::isWritable() const -{ - return !(m_flags & QScriptValue::ReadOnly); -} - -inline bool QScript::Member::isDeletable() const -{ - return !(m_flags & QScriptValue::Undeletable); -} - -inline bool QScript::Member::dontEnum() const -{ - return m_flags & QScriptValue::SkipInEnumeration; -} - -inline bool QScript::Member::isObjectProperty() const -{ - return m_flags & ObjectProperty; -} - -inline bool QScript::Member::isNativeProperty() const -{ - return m_flags & NativeProperty; -} - -inline bool QScript::Member::isUninitializedConst() const -{ - return m_flags & UninitializedConst; -} - -inline bool QScript::Member::isGetter() const -{ - return m_flags & QScriptValue::PropertyGetter; -} - -inline bool QScript::Member::isSetter() const -{ - return m_flags & QScriptValue::PropertySetter; -} - -inline bool QScript::Member::isGetterOrSetter() const -{ - return m_flags & (QScriptValue::PropertyGetter | QScriptValue::PropertySetter); -} - -inline int QScript::Member::id() const -{ - return m_id; -} - -inline QScriptNameIdImpl *QScript::Member::nameId() const -{ - return m_nameId; -} - -inline QScript::Member QScript::Member::invalid() -{ - Member m; - m.m_flags = 0; - return m; -} - -inline void QScript::Member::invalidate() -{ - m_flags = 0; -} - -inline void QScript::Member::native(QScriptNameIdImpl *nameId, int id, uint flags) -{ - Q_ASSERT(! (flags & ObjectProperty)); - - m_nameId = nameId; - m_id = id; - m_flags = flags | NativeProperty; -} - -inline void QScript::Member::object(QScriptNameIdImpl *nameId, int id, uint flags) -{ - Q_ASSERT(! (flags & NativeProperty)); - - m_nameId = nameId; - m_id = id; - m_flags = flags | ObjectProperty; -} - -inline bool QScript::Member::operator==(const QScript::Member &other) const -{ - return m_nameId == other.m_nameId; -} - -inline bool QScript::Member::operator!=(const QScript::Member &other) const -{ - return m_nameId != other.m_nameId; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptmemberfwd_p.h b/src/script/qscriptmemberfwd_p.h deleted file mode 100644 index cdf4602..0000000 --- a/src/script/qscriptmemberfwd_p.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTMEMBERFWD_P_H -#define QSCRIPTMEMBERFWD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#if defined(Q_OS_VXWORKS) && defined(m_flags) -# undef m_flags -#endif - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_SCRIPT - -class QScriptNameIdImpl; - -namespace QScript { - - class Member - { - public: - enum PropertyFlag { - ObjectProperty = 0x00000100, // Stored in the member table - NativeProperty = 0x00000200, - - UninitializedConst = 0x00000800, // NB: shared with QScriptValue::KeepExistingFlags - - InternalRange = 0x0000ff00 // Not user-accessible (read as 0, don't change on write) - }; - - inline Member() : m_nameId(0), m_id(0), m_flags(0) {} - - inline void resetFlags(uint flags); - inline void setFlags(uint flags); - inline void unsetFlags(uint flags); - inline uint flags() const; - inline bool testFlags(uint mask) const; - - inline bool isValid() const; - - inline bool isWritable() const; - inline bool isDeletable() const; - - inline bool dontEnum() const; - - inline bool isObjectProperty() const; - inline bool isNativeProperty() const; - - inline bool isUninitializedConst() const; - - inline bool isGetter() const; - inline bool isSetter() const; - inline bool isGetterOrSetter() const; - - inline int id() const; - inline QScriptNameIdImpl *nameId() const; - - inline bool operator==(const Member &other) const; - inline bool operator!=(const Member &other) const; - - inline static Member invalid(); - inline void invalidate(); - - inline void native(QScriptNameIdImpl *nameId, int id, uint flags); - inline void object(QScriptNameIdImpl *nameId, int id, uint flags); - - private: - QScriptNameIdImpl *m_nameId; - int m_id; - uint m_flags; - }; - -} // namespace QScript - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptnameid_p.h b/src/script/qscriptnameid_p.h deleted file mode 100644 index 1babc5f..0000000 --- a/src/script/qscriptnameid_p.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTNAMEID_P_H -#define QSCRIPTNAMEID_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -class QScriptNameIdImpl -{ -public: - QString s; - uint h; - QScriptNameIdImpl *next; - uint used: 1; - uint persistent: 1; - uint unique: 1; - uint pad: 29; - - inline QScriptNameIdImpl(const QString &_s): - s(_s), h(0), next(0), used(0), persistent(0), unique(0), pad(0) { } -}; - -QT_END_NAMESPACE - -#endif // QSCRIPTNAMEID_P_H diff --git a/src/script/qscriptnodepool_p.h b/src/script/qscriptnodepool_p.h deleted file mode 100644 index d41e314..0000000 --- a/src/script/qscriptnodepool_p.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTNODEPOOL_P_H -#define QSCRIPTNODEPOOL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QHash> -#include <QtCore/QString> - -#include "qscriptmemorypool_p.h" - -QT_BEGIN_NAMESPACE - -class QScriptEnginePrivate; - -namespace QScript { - -namespace AST { -class Node; -} // namespace AST - -class Code; -class CompilationUnit; - -template <typename NodeType> -inline NodeType *makeAstNode(MemoryPool *storage) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(); - return node; -} - -template <typename NodeType, typename Arg1> -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1); - return node; -} - -template <typename NodeType, typename Arg1, typename Arg2> -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2); - return node; -} - -template <typename NodeType, typename Arg1, typename Arg2, typename Arg3> -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3); - return node; -} - -template <typename NodeType, typename Arg1, typename Arg2, typename Arg3, typename Arg4> -inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) -{ - NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4); - return node; -} - -class NodePool : public MemoryPool -{ -public: - NodePool(const QString &fileName, QScriptEnginePrivate *engine); - virtual ~NodePool(); - - Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation); - - inline QString fileName() const { return m_fileName; } - inline QScriptEnginePrivate *engine() const { return m_engine; } -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - inline qint64 id() const { return m_id; } -#endif - -private: - QHash<AST::Node*, Code*> m_codeCache; - QString m_fileName; - QScriptEnginePrivate *m_engine; -#ifndef Q_SCRIPT_NO_EVENT_NOTIFY - qint64 m_id; -#endif - -private: - Q_DISABLE_COPY(NodePool) -}; - -} // namespace QScript - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptobject_p.h b/src/script/qscriptobject_p.h deleted file mode 100644 index a599e1f..0000000 --- a/src/script/qscriptobject_p.h +++ /dev/null @@ -1,188 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTOBJECT_P_H -#define QSCRIPTOBJECT_P_H - -#include "qscriptobjectfwd_p.h" - -#ifndef QT_NO_SCRIPT - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -inline bool QScriptObject::findMember(QScriptNameIdImpl *nameId, - QScript::Member *m) const -{ - const QScript::Member *members = m_members.constData(); - const int size = m_members.size(); - - const QScript::Member *first = &members[-1]; - const QScript::Member *last = &members[size - 1]; - - for (const QScript::Member *it = last; it != first; --it) { - if (it->nameId() == nameId && it->isValid()) { - *m = *it; - return true; - } - } - - return false; -} - -// assumes that m already points to the setter -inline bool QScriptObject::findGetter(QScript::Member *m) const -{ - const QScript::Member *members = m_members.constData(); - const QScript::Member *first = &members[-1]; - const QScript::Member *last = &members[m->id() - 1]; - - for (const QScript::Member *it = last; it != first; --it) { - if (it->nameId() == m->nameId() && it->isValid() && it->isGetter()) { - *m = *it; - return true; - } - } - - return false; -} - -// assumes that m already points to the getter -inline bool QScriptObject::findSetter(QScript::Member *m) const -{ - const QScript::Member *members = m_members.constData(); - const QScript::Member *first = &members[-1]; - const QScript::Member *last = &members[m->id() - 1]; - - for (const QScript::Member *it = last; it != first; --it) { - if (it->nameId() == m->nameId() && it->isValid() && it->isSetter()) { - *m = *it; - return true; - } - } - - return false; -} - -inline int QScriptObject::memberCount() const -{ - return m_members.size(); -} - -inline void QScriptObject::createMember(QScriptNameIdImpl *nameId, - QScript::Member *member, uint flags) -{ - member->object(nameId, m_values.size(), flags); - m_members.append(*member); - m_values.append(QScriptValueImpl()); -} - -inline void QScriptObject::member(int index, QScript::Member *member) -{ - *member = m_members[index]; -} - -inline void QScriptObject::put(const QScript::Member &m, const QScriptValueImpl &v) -{ - m_values[m.id()] = v; -} - -inline QScriptValueImpl &QScriptObject::reference(const QScript::Member &m) -{ - return m_values[m.id()]; -} - -inline void QScriptObject::get(const QScript::Member &m, QScriptValueImpl *v) -{ - Q_ASSERT(m.isObjectProperty()); - *v = m_values[m.id()]; -} - -inline void QScriptObject::removeMember(const QScript::Member &member) -{ - m_members[member.id()].invalidate(); - m_values[member.id()].invalidate(); -} - -inline QScriptObject::~QScriptObject() -{ - finalize(); -} - -inline void QScriptObject::finalize() -{ - finalizeData(); -} - -inline void QScriptObject::finalizeData() -{ - if (m_data) { - m_data->finalize(m_class->engine()); - delete m_data; - m_data = 0; - } -} - -inline void QScriptObject::reset() -{ - m_prototype.invalidate(); - m_scope.invalidate(); - m_internalValue.invalidate(); - m_members.resize(0); - m_values.resize(0); - m_data = 0; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptobjectfwd_p.h b/src/script/qscriptobjectfwd_p.h deleted file mode 100644 index 10d7b27..0000000 --- a/src/script/qscriptobjectfwd_p.h +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTOBJECTFWD_P_H -#define QSCRIPTOBJECTFWD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -#ifndef QT_NO_SCRIPT - -#include "qscriptbuffer_p.h" -#include "qscriptmemberfwd_p.h" -#include "qscriptvalueimplfwd_p.h" - -QT_BEGIN_NAMESPACE - -class QScriptObjectData; - -class QScriptObject -{ -public: - inline void reset(); - inline ~QScriptObject(); - inline void finalize(); - inline void finalizeData(); - - inline bool findMember(QScriptNameIdImpl *nameId, - QScript::Member *m) const; - - inline bool findGetter(QScript::Member *m) const; - - inline bool findSetter(QScript::Member *m) const; - - inline int memberCount() const; - - inline void createMember(QScriptNameIdImpl *nameId, - QScript::Member *member, uint flags); - - inline void member(int index, QScript::Member *member); - - inline void put(const QScript::Member &m, const QScriptValueImpl &v); - - inline QScriptValueImpl &reference(const QScript::Member &m); - - inline void get(const QScript::Member &m, QScriptValueImpl *v); - - inline void removeMember(const QScript::Member &member); - - QScriptValueImpl m_prototype; - QScriptValueImpl m_scope; - QScriptValueImpl m_internalValue; // [[value]] - QScriptObjectData *m_data; - QScript::Buffer<QScript::Member> m_members; - QScript::Buffer<QScriptValueImpl> m_values; - qint64 m_id; - QScriptClassInfo *m_class; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptprettypretty.cpp b/src/script/qscriptprettypretty.cpp deleted file mode 100644 index c186be7..0000000 --- a/src/script/qscriptprettypretty.cpp +++ /dev/null @@ -1,1334 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptprettypretty_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptast_p.h" - -#include <QtCore/QString> -#include <QtCore/QTextStream> -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -namespace QScript { -QString numberToString(qsreal value); -} - -using namespace QScript; - -PrettyPretty::PrettyPretty(QTextStream &o): - out(o), m_indentLevel(0) -{ -} - -PrettyPretty::~PrettyPretty() -{ -} - -void PrettyPretty::acceptAsBlock(AST::Node *node) -{ - out << '{'; - pushIndentLevel(); - newlineAndIndent(); - accept(node); - popIndentLevel(); - newlineAndIndent(); - out << '}'; -} - -int PrettyPretty::operatorPrecedenceLevel(int op) -{ - switch (op) { - case QSOperator::Div: - case QSOperator::Mod: - case QSOperator::Mul: - return 5; - case QSOperator::Add: - case QSOperator::Sub: - return 6; - case QSOperator::LShift: - case QSOperator::RShift: - case QSOperator::URShift: - return 7; - case QSOperator::Ge: - case QSOperator::Gt: - case QSOperator::In: - case QSOperator::InstanceOf: - case QSOperator::Le: - case QSOperator::Lt: - return 8; - case QSOperator::Equal: - case QSOperator::NotEqual: - case QSOperator::StrictEqual: - case QSOperator::StrictNotEqual: - return 9; - case QSOperator::BitAnd: - return 10; - case QSOperator::BitXor: - return 11; - case QSOperator::BitOr: - return 12; - case QSOperator::And: - return 13; - case QSOperator::Or: - return 14; - case QSOperator::InplaceAnd: - case QSOperator::InplaceSub: - case QSOperator::InplaceDiv: - case QSOperator::InplaceAdd: - case QSOperator::InplaceLeftShift: - case QSOperator::InplaceMod: - case QSOperator::InplaceMul: - case QSOperator::InplaceOr: - case QSOperator::InplaceRightShift: - case QSOperator::InplaceURightShift: - case QSOperator::InplaceXor: - case QSOperator::Assign: - return 16; - default: - Q_ASSERT_X(false, "PrettyPretty::operatorPrecedenceLevel()", "bad operator"); - } - return 0; -} - -int PrettyPretty::compareOperatorPrecedence(int op1, int op2) -{ - int prec1 = operatorPrecedenceLevel(op1); - int prec2 = operatorPrecedenceLevel(op2); - if (prec1 == prec2) - return 0; - if (prec1 > prec2) - return -1; - return 1; -} - -QTextStream &PrettyPretty::operator () (AST::Node *node, int level) -{ - int was = indentLevel(level); - accept(node); - indentLevel(was); - return out; -} - -QTextStream &PrettyPretty::newlineAndIndent() -{ - enum { IND = 4 }; - out << endl << QString().fill(QLatin1Char(' '), m_indentLevel * IND); - return out; -} - -void PrettyPretty::accept(AST::Node *node) -{ - AST::Node::acceptChild(node, this); -} - -bool PrettyPretty::visit(AST::ThisExpression *node) -{ - Q_UNUSED(node); - out << "this"; - return true; -} - -void PrettyPretty::endVisit(AST::ThisExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::IdentifierExpression *node) -{ - out << QScriptEnginePrivate::toString(node->name); - return true; -} - -void PrettyPretty::endVisit(AST::IdentifierExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NullExpression *node) -{ - Q_UNUSED(node); - out << "null"; - return false; -} - -void PrettyPretty::endVisit(AST::NullExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::TrueLiteral *node) -{ - Q_UNUSED(node); - out << "true"; - return false; -} - -void PrettyPretty::endVisit(AST::TrueLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FalseLiteral *node) -{ - Q_UNUSED(node); - out << "false"; - return false; -} - -void PrettyPretty::endVisit(AST::FalseLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::StringLiteral *node) -{ - QString lit = QScriptEnginePrivate::toString(node->value); - lit.replace(QLatin1Char('\\'), QLatin1String("\\\\")); - out << '\"' << lit << '\"'; - return false; -} - -void PrettyPretty::endVisit(AST::StringLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NumericLiteral *node) -{ - out << QScript::numberToString(node->value); - return true; -} - -void PrettyPretty::endVisit(AST::NumericLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::RegExpLiteral *node) -{ - out << '/' << QScriptEnginePrivate::toString(node->pattern) << '/'; - if (node->flags) - out << QScript::Ecma::RegExp::flagsToString(node->flags); - - return true; -} - -void PrettyPretty::endVisit(AST::RegExpLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ArrayLiteral *node) -{ - out << '['; - accept(node->elements); - accept(node->elision); - out << ']'; - return false; -} - -void PrettyPretty::endVisit(AST::ArrayLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ObjectLiteral *node) -{ - out << '{'; - if (node->properties) { - pushIndentLevel(); - AST::PropertyNameAndValueList *prop; - for (prop = node->properties; prop != 0; prop = prop->next) { - newlineAndIndent(); - accept(prop); - if (prop->next) - out << ','; - } - popIndentLevel(); - newlineAndIndent(); - } - out << '}'; - return false; -} - -void PrettyPretty::endVisit(AST::ObjectLiteral *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ElementList *node) -{ - accept(node->elision); - accept(node->expression); - for (node = node->next; node != 0; node = node->next) { - out << ", "; - accept(node->elision); - accept(node->expression); - } - return false; -} - -void PrettyPretty::endVisit(AST::ElementList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Elision *node) -{ - out << ", "; - for (AST::Elision *eit = node->next; eit != 0; eit = eit->next) - out << ", "; - return false; -} - -void PrettyPretty::endVisit(AST::Elision *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::PropertyNameAndValueList *node) -{ - accept(node->name); - out << ": "; - accept(node->value); - return false; -} - -void PrettyPretty::endVisit(AST::PropertyNameAndValueList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::IdentifierPropertyName *node) -{ - out << QScriptEnginePrivate::toString(node->id); - return false; -} - -void PrettyPretty::endVisit(AST::IdentifierPropertyName *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::StringLiteralPropertyName *node) -{ - QString lit = QScriptEnginePrivate::toString(node->id); - lit.replace(QLatin1String("\\"), QLatin1String("\\\\")); - out << lit; - return false; -} - -void PrettyPretty::endVisit(AST::StringLiteralPropertyName *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NumericLiteralPropertyName *node) -{ - out << node->id; - return false; -} - -void PrettyPretty::endVisit(AST::NumericLiteralPropertyName *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ArrayMemberExpression *node) -{ - accept(node->base); - out << '['; - accept(node->expression); - out << ']'; - return false; -} - -void PrettyPretty::endVisit(AST::ArrayMemberExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FieldMemberExpression *node) -{ - accept(node->base); - out << '.' << QScriptEnginePrivate::toString(node->name); - return false; -} - -void PrettyPretty::endVisit(AST::FieldMemberExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NewMemberExpression *node) -{ - out << "new "; - accept(node->base); - out << '('; - accept(node->arguments); - out << ')'; - return false; -} - -void PrettyPretty::endVisit(AST::NewMemberExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NewExpression *node) -{ - Q_UNUSED(node); - out << "new "; - return true; -} - -void PrettyPretty::endVisit(AST::NewExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::CallExpression *node) -{ - accept(node->base); - out << '('; - accept(node->arguments); - out << ')'; - return false; -} - -void PrettyPretty::endVisit(AST::CallExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ArgumentList *node) -{ - accept(node->expression); - for (node = node->next; node != 0; node = node->next) { - out << ", "; - accept(node->expression); - } - return false; -} - -void PrettyPretty::endVisit(AST::ArgumentList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::PostIncrementExpression *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::PostIncrementExpression *node) -{ - Q_UNUSED(node); - out << "++"; -} - -bool PrettyPretty::visit(AST::PostDecrementExpression *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::PostDecrementExpression *node) -{ - Q_UNUSED(node); - out << "--"; -} - -bool PrettyPretty::visit(AST::DeleteExpression *node) -{ - Q_UNUSED(node); - out << "delete "; - return true; -} - -void PrettyPretty::endVisit(AST::DeleteExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::VoidExpression *node) -{ - Q_UNUSED(node); - out << "void "; - return true; -} - -void PrettyPretty::endVisit(AST::VoidExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::TypeOfExpression *node) -{ - Q_UNUSED(node); - out << "typeof "; - return true; -} - -void PrettyPretty::endVisit(AST::TypeOfExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::PreIncrementExpression *node) -{ - Q_UNUSED(node); - out << "++"; - return true; -} - -void PrettyPretty::endVisit(AST::PreIncrementExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::PreDecrementExpression *node) -{ - Q_UNUSED(node); - out << "--"; - return true; -} - -void PrettyPretty::endVisit(AST::PreDecrementExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::UnaryPlusExpression *node) -{ - out << '+'; - bool needParens = (node->expression->binaryExpressionCast() != 0); - if (needParens) - out << '('; - accept(node->expression); - if (needParens) - out << ')'; - return false; -} - -void PrettyPretty::endVisit(AST::UnaryPlusExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::UnaryMinusExpression *node) -{ - out << '-'; - bool needParens = (node->expression->binaryExpressionCast() != 0); - if (needParens) - out << '('; - accept(node->expression); - if (needParens) - out << ')'; - return false; -} - -void PrettyPretty::endVisit(AST::UnaryMinusExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::TildeExpression *node) -{ - out << '~'; - bool needParens = (node->expression->binaryExpressionCast() != 0); - if (needParens) - out << '('; - accept(node->expression); - if (needParens) - out << ')'; - return false; -} - -void PrettyPretty::endVisit(AST::TildeExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::NotExpression *node) -{ - out << '!'; - bool needParens = (node->expression->binaryExpressionCast() != 0); - if (needParens) - out << '('; - accept(node->expression); - if (needParens) - out << ')'; - return false; -} - -void PrettyPretty::endVisit(AST::NotExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::BinaryExpression *node) -{ - bool needParens = node->left->binaryExpressionCast() - && (compareOperatorPrecedence(node->left->binaryExpressionCast()->op, node->op) < 0); - if (needParens) - out << '('; - accept(node->left); - if (needParens) - out << ')'; - QString s; - switch (node->op) { - case QSOperator::Add: - s = QLatin1String("+"); break; - case QSOperator::And: - s = QLatin1String("&&"); break; - case QSOperator::InplaceAnd: - s = QLatin1String("&="); break; - case QSOperator::Assign: - s = QLatin1String("="); break; - case QSOperator::BitAnd: - s = QLatin1String("&"); break; - case QSOperator::BitOr: - s = QLatin1String("|"); break; - case QSOperator::BitXor: - s = QLatin1String("^"); break; - case QSOperator::InplaceSub: - s = QLatin1String("-="); break; - case QSOperator::Div: - s = QLatin1String("/"); break; - case QSOperator::InplaceDiv: - s = QLatin1String("/="); break; - case QSOperator::Equal: - s = QLatin1String("=="); break; - case QSOperator::Ge: - s = QLatin1String(">="); break; - case QSOperator::Gt: - s = QLatin1String(">"); break; - case QSOperator::In: - s = QLatin1String("in"); break; - case QSOperator::InplaceAdd: - s = QLatin1String("+="); break; - case QSOperator::InstanceOf: - s = QLatin1String("instanceof"); break; - case QSOperator::Le: - s = QLatin1String("<="); break; - case QSOperator::LShift: - s = QLatin1String("<<"); break; - case QSOperator::InplaceLeftShift: - s = QLatin1String("<<="); break; - case QSOperator::Lt: - s = QLatin1String("<"); break; - case QSOperator::Mod: - s = QLatin1String("%"); break; - case QSOperator::InplaceMod: - s = QLatin1String("%="); break; - case QSOperator::Mul: - s = QLatin1String("*"); break; - case QSOperator::InplaceMul: - s = QLatin1String("*="); break; - case QSOperator::NotEqual: - s = QLatin1String("!="); break; - case QSOperator::Or: - s = QLatin1String("||"); break; - case QSOperator::InplaceOr: - s = QLatin1String("|="); break; - case QSOperator::RShift: - s = QLatin1String(">>"); break; - case QSOperator::InplaceRightShift: - s = QLatin1String(">>="); break; - case QSOperator::StrictEqual: - s = QLatin1String("==="); break; - case QSOperator::StrictNotEqual: - s = QLatin1String("!=="); break; - case QSOperator::Sub: - s = QLatin1String("-"); break; - case QSOperator::URShift: - s = QLatin1String(">>>"); break; - case QSOperator::InplaceURightShift: - s = QLatin1String(">>>="); break; - case QSOperator::InplaceXor: - s = QLatin1String("^="); break; - default: - Q_ASSERT (0); - } - out << ' ' << s << ' '; - needParens = node->right->binaryExpressionCast() - && (compareOperatorPrecedence(node->right->binaryExpressionCast()->op, node->op) <= 0); - if (needParens) - out << '('; - accept(node->right); - if (needParens) - out << ')'; - return false; -} - -void PrettyPretty::endVisit(AST::BinaryExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ConditionalExpression *node) -{ - accept(node->expression); - out << " ? "; - accept(node->ok); - out << " : "; - accept(node->ko); - return false; -} - -void PrettyPretty::endVisit(AST::ConditionalExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Expression *node) -{ - accept(node->left); - out << ", "; - accept(node->right); - return false; -} - -void PrettyPretty::endVisit(AST::Expression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Block *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::Block *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::StatementList *node) -{ - accept(node->statement); - for (node = node->next; node != 0; node = node->next) { - newlineAndIndent(); - accept(node->statement); - } - return false; -} - -void PrettyPretty::endVisit(AST::StatementList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::VariableDeclarationList *node) -{ - AST::VariableDeclarationList *it = node; - - do { - it->declaration->accept(this); - it = it->next; - if (it) - out << ", "; - } while (it); - - return false; -} - -void PrettyPretty::endVisit(AST::VariableDeclarationList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::VariableStatement *node) -{ - out << "var "; - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::VariableStatement *node) -{ - Q_UNUSED(node); - out << ';'; -} - -bool PrettyPretty::visit(AST::VariableDeclaration *node) -{ - out << QScriptEnginePrivate::toString(node->name); - if (node->expression) { - out << " = "; - accept(node->expression); - } - return false; -} - -void PrettyPretty::endVisit(AST::VariableDeclaration *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::EmptyStatement *node) -{ - Q_UNUSED(node); - out << ';'; - return true; -} - -void PrettyPretty::endVisit(AST::EmptyStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ExpressionStatement *node) -{ - accept(node->expression); - out << ';'; - return false; -} - -void PrettyPretty::endVisit(AST::ExpressionStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::IfStatement *node) -{ - out << "if ("; - accept(node->expression); - out << ") "; - acceptAsBlock(node->ok); - if (node->ko) { - out << " else "; - acceptAsBlock(node->ko); - } - return false; -} - -void PrettyPretty::endVisit(AST::IfStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::DoWhileStatement *node) -{ - out << "do "; - acceptAsBlock(node->statement); - out << " while ("; - accept(node->expression); - out << ");"; - return false; -} - -void PrettyPretty::endVisit(AST::DoWhileStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::WhileStatement *node) -{ - out << "while ("; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::WhileStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ForStatement *node) -{ - out << "for ("; - accept(node->initialiser); - out << "; "; - accept(node->condition); - out << "; "; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::ForStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::LocalForStatement *node) -{ - out << "for (var "; - accept(node->declarations); - out << "; "; - accept(node->condition); - out << "; "; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::LocalForStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ForEachStatement *node) -{ - out << "for ("; - accept(node->initialiser); - out << " in "; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::ForEachStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::LocalForEachStatement *node) -{ - out << "for (var "; - accept(node->declaration); - out << " in "; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::LocalForEachStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ContinueStatement *node) -{ - out << "continue"; - if (node->label) { - out << ' ' << QScriptEnginePrivate::toString(node->label); - } - out << ';'; - return false; -} - -void PrettyPretty::endVisit(AST::ContinueStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::BreakStatement *node) -{ - out << "break"; - if (node->label) { - out << ' ' << QScriptEnginePrivate::toString(node->label); - } - out << ';'; - return false; -} - -void PrettyPretty::endVisit(AST::BreakStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ReturnStatement *node) -{ - out << "return"; - if (node->expression) { - out << ' '; - accept(node->expression); - } - out << ';'; - return false; -} - -void PrettyPretty::endVisit(AST::ReturnStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::WithStatement *node) -{ - out << "with ("; - accept(node->expression); - out << ") "; - acceptAsBlock(node->statement); - return false; -} - -void PrettyPretty::endVisit(AST::WithStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::SwitchStatement *node) -{ - out << "switch ("; - accept(node->expression); - out << ") "; - acceptAsBlock(node->block); - return false; -} - -void PrettyPretty::endVisit(AST::SwitchStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::CaseBlock *node) -{ - accept(node->clauses); - if (node->defaultClause) { - newlineAndIndent(); - accept(node->defaultClause); - } - if (node->moreClauses) { - newlineAndIndent(); - accept(node->moreClauses); - } - return false; -} - -void PrettyPretty::endVisit(AST::CaseBlock *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::CaseClauses *node) -{ - accept(node->clause); - for (node = node->next; node != 0; node = node->next) { - newlineAndIndent(); - accept(node->clause); - } - return false; -} - -void PrettyPretty::endVisit(AST::CaseClauses *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::CaseClause *node) -{ - out << "case "; - accept(node->expression); - out << ':'; - if (node->statements) { - newlineAndIndent(); - accept(node->statements); - } - return false; -} - -void PrettyPretty::endVisit(AST::CaseClause *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::DefaultClause *node) -{ - Q_UNUSED(node); - out << "default:"; - newlineAndIndent(); - return true; -} - -void PrettyPretty::endVisit(AST::DefaultClause *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::LabelledStatement *node) -{ - out << QScriptEnginePrivate::toString(node->label) << ": "; - return true; -} - -void PrettyPretty::endVisit(AST::LabelledStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::ThrowStatement *node) -{ - Q_UNUSED(node); - out << "throw "; - accept(node->expression); - out << ';'; - return false; -} - -void PrettyPretty::endVisit(AST::ThrowStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::TryStatement *node) -{ - out << "try "; - acceptAsBlock(node->statement); - if (node->catchExpression) { - out << " catch (" << QScriptEnginePrivate::toString(node->catchExpression->name) << ") "; - acceptAsBlock(node->catchExpression->statement); - } - if (node->finallyExpression) { - out << " finally "; - acceptAsBlock(node->finallyExpression->statement); - } - return false; -} - -void PrettyPretty::endVisit(AST::TryStatement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Catch *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::Catch *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Finally *node) -{ - Q_UNUSED(node); - out << "finally "; - return true; -} - -void PrettyPretty::endVisit(AST::Finally *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FunctionDeclaration *node) -{ - out << "function"; - - if (node->name) - out << ' ' << QScriptEnginePrivate::toString(node->name); - - // the arguments - out << '('; - for (AST::FormalParameterList *it = node->formals; it; it = it->next) { - if (it->name) - out << QScriptEnginePrivate::toString(it->name); - - if (it->next) - out << ", "; - } - out << ')'; - - // the function body - out << " {"; - - if (node->body) { - pushIndentLevel(); - newlineAndIndent(); - accept(node->body); - popIndentLevel(); - newlineAndIndent(); - } - - out << '}'; - - return false; -} - -void PrettyPretty::endVisit(AST::FunctionDeclaration *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FunctionExpression *node) -{ - out << "function"; - - if (node->name) - out << ' ' << QScriptEnginePrivate::toString(node->name); - - // the arguments - out << '('; - for (AST::FormalParameterList *it = node->formals; it; it = it->next) { - if (it->name) - out << QScriptEnginePrivate::toString(it->name); - - if (it->next) - out << ", "; - } - out << ')'; - - // the function body - out << " {"; - - if (node->body) { - pushIndentLevel(); - newlineAndIndent(); - accept(node->body); - popIndentLevel(); - newlineAndIndent(); - } - - out << '}'; - - return false; -} - -void PrettyPretty::endVisit(AST::FunctionExpression *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FormalParameterList *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::FormalParameterList *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FunctionBody *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::FunctionBody *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::Program *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::Program *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::SourceElements *node) -{ - Q_UNUSED(node); - accept(node->element); - for (node = node->next; node != 0; node = node->next) { - newlineAndIndent(); - accept(node->element); - } - return false; -} - -void PrettyPretty::endVisit(AST::SourceElements *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::FunctionSourceElement *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::FunctionSourceElement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::StatementSourceElement *node) -{ - Q_UNUSED(node); - return true; -} - -void PrettyPretty::endVisit(AST::StatementSourceElement *node) -{ - Q_UNUSED(node); -} - -bool PrettyPretty::visit(AST::DebuggerStatement *node) -{ - Q_UNUSED(node); - out << "debugger"; - return true; -} - -void PrettyPretty::endVisit(AST::DebuggerStatement *node) -{ - Q_UNUSED(node); - out << ';'; -} - -bool PrettyPretty::preVisit(AST::Node *node) -{ - Q_UNUSED(node); - return true; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptprettypretty_p.h b/src/script/qscriptprettypretty_p.h deleted file mode 100644 index 36568d1..0000000 --- a/src/script/qscriptprettypretty_p.h +++ /dev/null @@ -1,329 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTPRETTYPRETTY_P_H -#define QSCRIPTPRETTYPRETTY_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -#include "qscriptastvisitor_p.h" - -QT_BEGIN_NAMESPACE - -class QTextStream; - -namespace QScript { - -class PrettyPretty: protected AST::Visitor -{ -public: - PrettyPretty(QTextStream &out); - virtual ~PrettyPretty(); - - QTextStream &operator () (AST::Node *node, int level = 0); - -protected: - void accept(AST::Node *node); - - virtual bool preVisit(AST::Node *node); - - virtual bool visit(AST::ThisExpression *node); - virtual void endVisit(AST::ThisExpression *node); - - virtual bool visit(AST::IdentifierExpression *node); - virtual void endVisit(AST::IdentifierExpression *node); - - virtual bool visit(AST::NullExpression *node); - virtual void endVisit(AST::NullExpression *node); - - virtual bool visit(AST::TrueLiteral *node); - virtual void endVisit(AST::TrueLiteral *node); - - virtual bool visit(AST::FalseLiteral *node); - virtual void endVisit(AST::FalseLiteral *node); - - virtual bool visit(AST::StringLiteral *node); - virtual void endVisit(AST::StringLiteral *node); - - virtual bool visit(AST::NumericLiteral *node); - virtual void endVisit(AST::NumericLiteral *node); - - virtual bool visit(AST::RegExpLiteral *node); - virtual void endVisit(AST::RegExpLiteral *node); - - virtual bool visit(AST::ArrayLiteral *node); - virtual void endVisit(AST::ArrayLiteral *node); - - virtual bool visit(AST::ObjectLiteral *node); - virtual void endVisit(AST::ObjectLiteral *node); - - virtual bool visit(AST::ElementList *node); - virtual void endVisit(AST::ElementList *node); - - virtual bool visit(AST::Elision *node); - virtual void endVisit(AST::Elision *node); - - virtual bool visit(AST::PropertyNameAndValueList *node); - virtual void endVisit(AST::PropertyNameAndValueList *node); - - virtual bool visit(AST::IdentifierPropertyName *node); - virtual void endVisit(AST::IdentifierPropertyName *node); - - virtual bool visit(AST::StringLiteralPropertyName *node); - virtual void endVisit(AST::StringLiteralPropertyName *node); - - virtual bool visit(AST::NumericLiteralPropertyName *node); - virtual void endVisit(AST::NumericLiteralPropertyName *node); - - virtual bool visit(AST::ArrayMemberExpression *node); - virtual void endVisit(AST::ArrayMemberExpression *node); - - virtual bool visit(AST::FieldMemberExpression *node); - virtual void endVisit(AST::FieldMemberExpression *node); - - virtual bool visit(AST::NewMemberExpression *node); - virtual void endVisit(AST::NewMemberExpression *node); - - virtual bool visit(AST::NewExpression *node); - virtual void endVisit(AST::NewExpression *node); - - virtual bool visit(AST::CallExpression *node); - virtual void endVisit(AST::CallExpression *node); - - virtual bool visit(AST::ArgumentList *node); - virtual void endVisit(AST::ArgumentList *node); - - virtual bool visit(AST::PostIncrementExpression *node); - virtual void endVisit(AST::PostIncrementExpression *node); - - virtual bool visit(AST::PostDecrementExpression *node); - virtual void endVisit(AST::PostDecrementExpression *node); - - virtual bool visit(AST::DeleteExpression *node); - virtual void endVisit(AST::DeleteExpression *node); - - virtual bool visit(AST::VoidExpression *node); - virtual void endVisit(AST::VoidExpression *node); - - virtual bool visit(AST::TypeOfExpression *node); - virtual void endVisit(AST::TypeOfExpression *node); - - virtual bool visit(AST::PreIncrementExpression *node); - virtual void endVisit(AST::PreIncrementExpression *node); - - virtual bool visit(AST::PreDecrementExpression *node); - virtual void endVisit(AST::PreDecrementExpression *node); - - virtual bool visit(AST::UnaryPlusExpression *node); - virtual void endVisit(AST::UnaryPlusExpression *node); - - virtual bool visit(AST::UnaryMinusExpression *node); - virtual void endVisit(AST::UnaryMinusExpression *node); - - virtual bool visit(AST::TildeExpression *node); - virtual void endVisit(AST::TildeExpression *node); - - virtual bool visit(AST::NotExpression *node); - virtual void endVisit(AST::NotExpression *node); - - virtual bool visit(AST::BinaryExpression *node); - virtual void endVisit(AST::BinaryExpression *node); - - virtual bool visit(AST::ConditionalExpression *node); - virtual void endVisit(AST::ConditionalExpression *node); - - virtual bool visit(AST::Expression *node); - virtual void endVisit(AST::Expression *node); - - virtual bool visit(AST::Block *node); - virtual void endVisit(AST::Block *node); - - virtual bool visit(AST::StatementList *node); - virtual void endVisit(AST::StatementList *node); - - virtual bool visit(AST::VariableStatement *node); - virtual void endVisit(AST::VariableStatement *node); - - virtual bool visit(AST::VariableDeclarationList *node); - virtual void endVisit(AST::VariableDeclarationList *node); - - virtual bool visit(AST::VariableDeclaration *node); - virtual void endVisit(AST::VariableDeclaration *node); - - virtual bool visit(AST::EmptyStatement *node); - virtual void endVisit(AST::EmptyStatement *node); - - virtual bool visit(AST::ExpressionStatement *node); - virtual void endVisit(AST::ExpressionStatement *node); - - virtual bool visit(AST::IfStatement *node); - virtual void endVisit(AST::IfStatement *node); - - virtual bool visit(AST::DoWhileStatement *node); - virtual void endVisit(AST::DoWhileStatement *node); - - virtual bool visit(AST::WhileStatement *node); - virtual void endVisit(AST::WhileStatement *node); - - virtual bool visit(AST::ForStatement *node); - virtual void endVisit(AST::ForStatement *node); - - virtual bool visit(AST::LocalForStatement *node); - virtual void endVisit(AST::LocalForStatement *node); - - virtual bool visit(AST::ForEachStatement *node); - virtual void endVisit(AST::ForEachStatement *node); - - virtual bool visit(AST::LocalForEachStatement *node); - virtual void endVisit(AST::LocalForEachStatement *node); - - virtual bool visit(AST::ContinueStatement *node); - virtual void endVisit(AST::ContinueStatement *node); - - virtual bool visit(AST::BreakStatement *node); - virtual void endVisit(AST::BreakStatement *node); - - virtual bool visit(AST::ReturnStatement *node); - virtual void endVisit(AST::ReturnStatement *node); - - virtual bool visit(AST::WithStatement *node); - virtual void endVisit(AST::WithStatement *node); - - virtual bool visit(AST::SwitchStatement *node); - virtual void endVisit(AST::SwitchStatement *node); - - virtual bool visit(AST::CaseBlock *node); - virtual void endVisit(AST::CaseBlock *node); - - virtual bool visit(AST::CaseClauses *node); - virtual void endVisit(AST::CaseClauses *node); - - virtual bool visit(AST::CaseClause *node); - virtual void endVisit(AST::CaseClause *node); - - virtual bool visit(AST::DefaultClause *node); - virtual void endVisit(AST::DefaultClause *node); - - virtual bool visit(AST::LabelledStatement *node); - virtual void endVisit(AST::LabelledStatement *node); - - virtual bool visit(AST::ThrowStatement *node); - virtual void endVisit(AST::ThrowStatement *node); - - virtual bool visit(AST::TryStatement *node); - virtual void endVisit(AST::TryStatement *node); - - virtual bool visit(AST::Catch *node); - virtual void endVisit(AST::Catch *node); - - virtual bool visit(AST::Finally *node); - virtual void endVisit(AST::Finally *node); - - virtual bool visit(AST::FunctionDeclaration *node); - virtual void endVisit(AST::FunctionDeclaration *node); - - virtual bool visit(AST::FunctionExpression *node); - virtual void endVisit(AST::FunctionExpression *node); - - virtual bool visit(AST::FormalParameterList *node); - virtual void endVisit(AST::FormalParameterList *node); - - virtual bool visit(AST::FunctionBody *node); - virtual void endVisit(AST::FunctionBody *node); - - virtual bool visit(AST::Program *node); - virtual void endVisit(AST::Program *node); - - virtual bool visit(AST::SourceElements *node); - virtual void endVisit(AST::SourceElements *node); - - virtual bool visit(AST::FunctionSourceElement *node); - virtual void endVisit(AST::FunctionSourceElement *node); - - virtual bool visit(AST::StatementSourceElement *node); - virtual void endVisit(AST::StatementSourceElement *node); - - virtual bool visit(AST::DebuggerStatement *node); - virtual void endVisit(AST::DebuggerStatement *node); - - int indentLevel(int level) - { - int was = m_indentLevel; - m_indentLevel = level; - return was; - } - - void pushIndentLevel() - { ++m_indentLevel; } - - void popIndentLevel() - { --m_indentLevel; } - - QTextStream &newlineAndIndent(); - - void acceptAsBlock(AST::Node *node); - - static int operatorPrecedenceLevel(int op); - static int compareOperatorPrecedence(int op1, int op2); - -private: - QTextStream &out; - int m_indentLevel; - - Q_DISABLE_COPY(PrettyPretty) -}; - -} // namespace QScript - -QT_END_NAMESPACE - -#endif diff --git a/src/script/qscriptsyntaxcheckresult_p.h b/src/script/qscriptsyntaxcheckresult_p.h deleted file mode 100644 index 3be82ef..0000000 --- a/src/script/qscriptsyntaxcheckresult_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTSYNTAXCHECKRESULT_P_H -#define QSCRIPTSYNTAXCHECKRESULT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#if defined(Q_OS_VXWORKS) && defined(m_type) -# undef m_type -#endif - -#ifndef QT_NO_SCRIPT - -#include <QtCore/qatomic.h> -#include <QtCore/qstring.h> - -QT_BEGIN_NAMESPACE - -class QScriptSyntaxCheckResultPrivate -{ -public: - QScriptSyntaxCheckResultPrivate() { ref = 0; } - ~QScriptSyntaxCheckResultPrivate() {} - - QScriptSyntaxCheckResult::State state; - int errorColumnNumber; - int errorLineNumber; - QString errorMessage; - QBasicAtomicInt ref; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptvalue.cpp b/src/script/qscriptvalue.cpp deleted file mode 100644 index b70afe5..0000000 --- a/src/script/qscriptvalue.cpp +++ /dev/null @@ -1,1600 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptvalue.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptvalue_p.h" -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptclass.h" -#include "qscriptclass_p.h" - -#include <QtCore/QDateTime> -#include <QtCore/QRegExp> - -QT_BEGIN_NAMESPACE - -/*! - \since 4.3 - \class QScriptValue - - \brief The QScriptValue class acts as a container for the Qt Script data types. - - \ingroup script - - - QScriptValue supports the types defined in the \l{ECMA-262} - standard: The primitive types, which are Undefined, Null, Boolean, - Number, and String; and the Object type. Additionally, Qt Script - has built-in support for QVariant, QObject and QMetaObject. - - For the object-based types (including Date and RegExp), use the - newT() functions in QScriptEngine (e.g. QScriptEngine::newObject()) - to create a QScriptValue of the desired type. For the primitive types, - use one of the QScriptValue constructor overloads. - - The methods named isT() (e.g. isBool(), isUndefined()) can be - used to test if a value is of a certain type. The methods named - toT() (e.g. toBool(), toString()) can be used to convert a - QScriptValue to another type. You can also use the generic - qscriptvalue_cast() function. - - Object values have zero or more properties which are themselves - QScriptValues. Use setProperty() to set a property of an object, and - call property() to retrieve the value of a property. - - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 0 - - Each property can have a set of attributes; these are specified as - the third (optional) argument to setProperty(). The attributes of a - property can be queried by calling the propertyFlags() function. The - following code snippet creates a property that cannot be modified by - script code: - - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 1 - - If you want to iterate over the properties of a script object, use - the QScriptValueIterator class. - - Object values have an internal \c{prototype} property, which can be - accessed with prototype() and setPrototype(). Properties added to a - prototype are shared by all objects having that prototype; this is - referred to as prototype-based inheritance. In practice, it means - that (by default) the property() function will automatically attempt - to look up look the property in the prototype() (and in the - prototype of the prototype(), and so on), if the object itself does - not have the requested property. Note that this prototype-based - lookup is not performed by setProperty(); setProperty() will always - create the property in the script object itself. For more - information, see the \l{QtScript} documentation. - - Function objects (objects for which isFunction() returns true) can - be invoked by calling call(). Constructor functions can be used to - construct new objects by calling construct(). - - Use equals(), strictlyEquals() and lessThan() to compare a QScriptValue - to another. - - Object values can have custom data associated with them; see the - setData() and data() functions. By default, this data is not - accessible to scripts; it can be used to store any data you want to - associate with the script object. Typically this is used by custom - class objects (see QScriptClass) to store a C++ type that contains - the "native" object data. - - Note that a QScriptValue for which isObject() is true only carries a - reference to an actual object; copying the QScriptValue will only - copy the object reference, not the object itself. If you want to - clone an object (i.e. copy an object's properties to another - object), you can do so with the help of a \c{for-in} statement in - script code, or QScriptValueIterator in C++. - - \sa QScriptEngine, QScriptValueIterator -*/ - -/*! - \enum QScriptValue::SpecialValue - - This enum is used to specify a single-valued type. - - \value UndefinedValue An undefined value. - - \value NullValue A null value. -*/ - -/*! - \enum QScriptValue::PropertyFlag - - This enum describes the attributes of a property. - - \value ReadOnly The property is read-only. Attempts by Qt Script code to write to the property will be ignored. - - \value Undeletable Attempts by Qt Script code to \c{delete} the property will be ignored. - - \value SkipInEnumeration The property is not to be enumerated by a \c{for-in} enumeration. - - \value PropertyGetter The property is defined by a function which will be called to get the property value. - - \value PropertySetter The property is defined by a function which will be called to set the property value. - - \value QObjectMember This flag is used to indicate that an existing property is a QObject member (a property or method). - - \value KeepExistingFlags This value is used to indicate to setProperty() that the property's flags should be left unchanged. If the property doesn't exist, the default flags (0) will be used. - - \value UserRange Flags in this range are not used by Qt Script, and can be used for custom purposes. -*/ - -/*! - \enum QScriptValue::ResolveFlag - - This enum specifies how to look up a property of an object. - - \value ResolveLocal Only check the object's own properties. - - \value ResolvePrototype Check the object's own properties first, then search the prototype chain. This is the default. - - \value ResolveScope Check the object's own properties first, then search the scope chain. - - \value ResolveFull Check the object's own properties first, then search the prototype chain, and finally search the scope chain. -*/ - -/*! - Constructs an invalid QScriptValue. -*/ -QScriptValue::QScriptValue() - : d_ptr(0) -{ -} - -/*! - Destroys this QScriptValue. -*/ -QScriptValue::~QScriptValue() -{ - if (d_ptr && !d_ptr->ref.deref()) { - if (engine()) { - QScriptEnginePrivate::get(engine())->unregisterValue(d_ptr); - } else { - delete d_ptr; - } - d_ptr = 0; - } -} - -/*! - Constructs a new QScriptValue that is a copy of \a other. - - Note that if \a other is an object (i.e., isObject() would return - true), then only a reference to the underlying object is copied into - the new script value (i.e., the object itself is not copied). -*/ -QScriptValue::QScriptValue(const QScriptValue &other) - : d_ptr(other.d_ptr) -{ - if (d_ptr) - d_ptr->ref.ref(); -} - -/*! - \obsolete - - Constructs a new QScriptValue with the special \a value and - registers it with the script \a engine. -*/ -QScriptValue::QScriptValue(QScriptEngine *engine, QScriptValue::SpecialValue value) -{ - if (engine) { - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - d_ptr = eng_p->registerValue(QScriptValueImpl(value)); - d_ptr->ref.ref(); - } else { - d_ptr = 0; - } -} - -/*! - \obsolete - - \fn QScriptValue::QScriptValue(QScriptEngine *engine, bool value) - - Constructs a new QScriptValue with the boolean \a value and - registers it with the script \a engine. -*/ -QScriptValue::QScriptValue(QScriptEngine *engine, bool val) -{ - if (engine) { - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - d_ptr = eng_p->registerValue(QScriptValueImpl(val)); - d_ptr->ref.ref(); - } else { - d_ptr = 0; - } -} - -/*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, int value) - \obsolete - - Constructs a new QScriptValue with the integer \a value and - registers it with the script \a engine. -*/ -QScriptValue::QScriptValue(QScriptEngine *engine, int val) -{ - if (engine) { - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - d_ptr = eng_p->registerValue(QScriptValueImpl(val)); - d_ptr->ref.ref(); - } else { - d_ptr = 0; - } -} - -/*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, uint value) - \obsolete - - Constructs a new QScriptValue with the unsigned integer \a value and - registers it with the script \a engine. - */ -QScriptValue::QScriptValue(QScriptEngine *engine, uint val) -{ - if (engine) { - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - d_ptr = eng_p->registerValue(QScriptValueImpl(val)); - d_ptr->ref.ref(); - } else { - d_ptr = 0; - } -} - -/*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, qsreal value) - \obsolete - - Constructs a new QScriptValue with the qsreal \a value and - registers it with the script \a engine. -*/ -QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val) -{ - if (engine) { - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - d_ptr = eng_p->registerValue(QScriptValueImpl(val)); - d_ptr->ref.ref(); - } else { - d_ptr = 0; - } -} - -/*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, const QString &value) - \obsolete - - Constructs a new QScriptValue with the string \a value and - registers it with the script \a engine. -*/ -QScriptValue::QScriptValue(QScriptEngine *engine, const QString &val) -{ - if (engine) { - QScriptValueImpl v; - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - eng_p->newString(&v, val); - d_ptr = eng_p->registerValue(v); - d_ptr->ref.ref(); - } else { - d_ptr = 0; - } -} - -/*! - \fn QScriptValue::QScriptValue(QScriptEngine *engine, const char *value) - \obsolete - - Constructs a new QScriptValue with the string \a value and - registers it with the script \a engine. -*/ - -#ifndef QT_NO_CAST_FROM_ASCII -QScriptValue::QScriptValue(QScriptEngine *engine, const char *val) -{ - if (engine) { - QScriptValueImpl v; - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); - eng_p->newString(&v, QString::fromAscii(val)); - d_ptr = eng_p->registerValue(v); - d_ptr->ref.ref(); - } else { - d_ptr = 0; - } -} -#endif - -/*! - \since 4.5 - - Constructs a new QScriptValue with a special \a value. -*/ -QScriptValue::QScriptValue(SpecialValue value) - : d_ptr(new QScriptValuePrivate) -{ - d_ptr->value = QScriptValueImpl(value); - d_ptr->ref.ref(); -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a boolean \a value. -*/ -QScriptValue::QScriptValue(bool value) - : d_ptr(new QScriptValuePrivate) -{ - d_ptr->value = QScriptValueImpl(value); - d_ptr->ref.ref(); -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a number \a value. -*/ -QScriptValue::QScriptValue(int value) - : d_ptr(new QScriptValuePrivate) -{ - d_ptr->value = QScriptValueImpl(value); - d_ptr->ref.ref(); -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a number \a value. -*/ -QScriptValue::QScriptValue(uint value) - : d_ptr(new QScriptValuePrivate) -{ - d_ptr->value = QScriptValueImpl(value); - d_ptr->ref.ref(); -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a number \a value. -*/ -QScriptValue::QScriptValue(qsreal value) - : d_ptr(new QScriptValuePrivate) -{ - d_ptr->value = QScriptValueImpl(value); - d_ptr->ref.ref(); -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a string \a value. -*/ -QScriptValue::QScriptValue(const QString &value) - : d_ptr(new QScriptValuePrivate) -{ - d_ptr->value.m_type = QScript::LazyStringType; - d_ptr->value.m_lazy_string_value = new QString(value); - d_ptr->ref.ref(); -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a string \a value. -*/ -QScriptValue::QScriptValue(const QLatin1String &value) - : d_ptr(new QScriptValuePrivate) -{ - d_ptr->value.m_type = QScript::LazyStringType; - d_ptr->value.m_lazy_string_value = new QString(value); - d_ptr->ref.ref(); -} - -/*! - \since 4.5 - - Constructs a new QScriptValue with a string \a value. -*/ - -#ifndef QT_NO_CAST_FROM_ASCII -QScriptValue::QScriptValue(const char *value) - : d_ptr(new QScriptValuePrivate) -{ - d_ptr->value.m_type = QScript::LazyStringType; - d_ptr->value.m_lazy_string_value = new QString(QString::fromAscii(value)); - d_ptr->ref.ref(); -} -#endif - -/*! - Assigns the \a other value to this QScriptValue. - - Note that if \a other is an object (isObject() returns true), - only a reference to the underlying object will be assigned; - the object itself will not be copied. -*/ -QScriptValue &QScriptValue::operator=(const QScriptValue &other) -{ - if (d_ptr == other.d_ptr) - return *this; - if (d_ptr && !d_ptr->ref.deref()) { - if (engine()) { - QScriptEnginePrivate::get(engine())->unregisterValue(d_ptr); - } else { - delete d_ptr; - } - } - d_ptr = other.d_ptr; - if (d_ptr) - d_ptr->ref.ref(); - return *this; -} - -/*! - Returns true if this QScriptValue is an object of the Error class; - otherwise returns false. - - \sa QScriptContext::throwError() -*/ -bool QScriptValue::isError() const -{ - Q_D(const QScriptValue); - return d && d->value.isError(); -} - -/*! - Returns true if this QScriptValue is an object of the Array class; - otherwise returns false. - - \sa QScriptEngine::newArray() -*/ -bool QScriptValue::isArray() const -{ - Q_D(const QScriptValue); - return d && d->value.isArray(); -} - -/*! - Returns true if this QScriptValue is an object of the Date class; - otherwise returns false. - - \sa QScriptEngine::newDate() -*/ -bool QScriptValue::isDate() const -{ - Q_D(const QScriptValue); - return d && d->value.isDate(); -} - -/*! - Returns true if this QScriptValue is an object of the RegExp class; - otherwise returns false. - - \sa QScriptEngine::newRegExp() -*/ -bool QScriptValue::isRegExp() const -{ - Q_D(const QScriptValue); - return d && d->value.isRegExp(); -} - -/*! - If this QScriptValue is an object, returns the internal prototype - (\c{__proto__} property) of this object; otherwise returns an - invalid QScriptValue. - - \sa setPrototype(), isObject() -*/ -QScriptValue QScriptValue::prototype() const -{ - Q_D(const QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.prototype()); -} - -/*! - If this QScriptValue is an object, sets the internal prototype - (\c{__proto__} property) of this object to be \a prototype; - otherwise does nothing. - - The internal prototype should not be confused with the public - property with name "prototype"; the public prototype is usually - only set on functions that act as constructors. - - \sa prototype(), isObject() -*/ -void QScriptValue::setPrototype(const QScriptValue &prototype) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return; - if (prototype.isValid() && prototype.engine() - && (prototype.engine() != engine())) { - qWarning("QScriptValue::setPrototype() failed: " - "cannot set a prototype created in " - "a different engine"); - return; - } - QScriptValueImpl was = d->value.prototype(); - d->value.setPrototype(d->value.engine()->toImpl(prototype)); - if (d->value.detectedCycle()) { - qWarning("QScriptValue::setPrototype() failed: " - "cyclic prototype value"); - d->value.setPrototype(was); - } -} - -/*! - \since 4.6 - - Returns the scope object of this QScriptValue. This function is only - relevant for function objects. The scope determines how variables are - resolved when the function is invoked. -*/ -QScriptValue QScriptValue::scope() const -{ - Q_D(const QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.scope()); -} - -/*! - \since 4.6 - - Sets the \a scope object of this QScriptValue. This function is only - relevant for function objects. Changing the scope is useful when creating - closures; see \l{Nested Functions and the Scope Chain}. -*/ -void QScriptValue::setScope(const QScriptValue &scope) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return; - if (scope.isValid() && scope.engine() - && (scope.engine() != engine())) { - qWarning("QScriptValue::setScope() failed: " - "cannot set a scope object created in " - "a different engine"); - return; - } - d->value.setScope(d->value.engine()->toImpl(scope)); -} - -/*! - Returns true if this QScriptValue is an instance of - \a other; otherwise returns false. - - This QScriptValue is considered to be an instance of \a other if - \a other is a function and the value of the \c{prototype} - property of \a other is in the prototype chain of this - QScriptValue. -*/ -bool QScriptValue::instanceOf(const QScriptValue &other) const -{ - Q_D(const QScriptValue); - if (!isObject() || !other.isObject()) - return false; - if (other.engine() != engine()) { - qWarning("QScriptValue::instanceof: " - "cannot perform operation on a value created in " - "a different engine"); - return false; - } - return d->value.engine()->toImpl(*this) - .instanceOf(d->value.engine()->toImpl(other)); -} - -/*! - Returns true if this QScriptValue is less than \a other, otherwise - returns false. The comparison follows the behavior described in - \l{ECMA-262} section 11.8.5, "The Abstract Relational Comparison - Algorithm". - - Note that if this QScriptValue or the \a other value are objects, - calling this function has side effects on the script engine, since - the engine will call the object's valueOf() function (and possibly - toString()) in an attempt to convert the object to a primitive value - (possibly resulting in an uncaught script exception). - - \sa equals() -*/ -bool QScriptValue::lessThan(const QScriptValue &other) const -{ - if (!isValid() || !other.isValid()) - return false; - if (other.engine() && engine() && (other.engine() != engine())) { - qWarning("QScriptValue::lessThan: " - "cannot compare to a value created in " - "a different engine"); - return false; - } - return QScriptEnginePrivate::lessThan(QScriptValuePrivate::valueOf(*this), - QScriptValuePrivate::valueOf(other)); -} - -/*! - Returns true if this QScriptValue is equal to \a other, otherwise - returns false. The comparison follows the behavior described in - \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison - Algorithm". - - This function can return true even if the type of this QScriptValue - is different from the type of the \a other value; i.e. the - comparison is not strict. For example, comparing the number 9 to - the string "9" returns true; comparing an undefined value to a null - value returns true; comparing a \c{Number} object whose primitive - value is 6 to a \c{String} object whose primitive value is "6" - returns true; and comparing the number 1 to the boolean value - \c{true} returns true. If you want to perform a comparison - without such implicit value conversion, use strictlyEquals(). - - Note that if this QScriptValue or the \a other value are objects, - calling this function has side effects on the script engine, since - the engine will call the object's valueOf() function (and possibly - toString()) in an attempt to convert the object to a primitive value - (possibly resulting in an uncaught script exception). - - \sa strictlyEquals(), lessThan() -*/ -bool QScriptValue::equals(const QScriptValue &other) const -{ - if (!isValid() || !other.isValid()) - return isValid() == other.isValid(); - if (other.engine() && engine() && (other.engine() != engine())) { - qWarning("QScriptValue::equals: " - "cannot compare to a value created in " - "a different engine"); - return false; - } - return QScriptEnginePrivate::equals(QScriptValuePrivate::valueOf(*this), - QScriptValuePrivate::valueOf(other)); -} - -/*! - Returns true if this QScriptValue is equal to \a other using strict - comparison (no conversion), otherwise returns false. The comparison - follows the behavior described in \l{ECMA-262} section 11.9.6, "The - Strict Equality Comparison Algorithm". - - If the type of this QScriptValue is different from the type of the - \a other value, this function returns false. If the types are equal, - the result depends on the type, as shown in the following table: - - \table - \header \o Type \o Result - \row \o Undefined \o true - \row \o Null \o true - \row \o Boolean \o true if both values are true, false otherwise - \row \o Number \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise - \row \o String \o true if both values are exactly the same sequence of characters, false otherwise - \row \o Object \o true if both values refer to the same object, false otherwise - \endtable - - \sa equals() -*/ -bool QScriptValue::strictlyEquals(const QScriptValue &other) const -{ - if (!isValid() || !other.isValid()) - return isValid() == other.isValid(); - if (other.engine() && engine() && (other.engine() != engine())) { - qWarning("QScriptValue::strictlyEquals: " - "cannot compare to a value created in " - "a different engine"); - return false; - } - return QScriptEnginePrivate::strictlyEquals(QScriptValuePrivate::valueOf(*this), - QScriptValuePrivate::valueOf(other)); -} - -/*! - Returns the string value of this QScriptValue, as defined in - \l{ECMA-262} section 9.8, "ToString". - - Note that if this QScriptValue is an object, calling this function - has side effects on the script engine, since the engine will call - the object's toString() function (and possibly valueOf()) in an - attempt to convert the object to a primitive value (possibly - resulting in an uncaught script exception). - - \sa isString() -*/ -QString QScriptValue::toString() const -{ - Q_D(const QScriptValue); - if (!d) - return QString(); - return d->value.toString(); -} - -/*! - Returns the number value of this QScriptValue, as defined in - \l{ECMA-262} section 9.3, "ToNumber". - - Note that if this QScriptValue is an object, calling this function - has side effects on the script engine, since the engine will call - the object's valueOf() function (and possibly toString()) in an - attempt to convert the object to a primitive value (possibly - resulting in an uncaught script exception). - - \sa isNumber(), toInteger(), toInt32(), toUInt32(), toUInt16() -*/ -qsreal QScriptValue::toNumber() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->value.toNumber(); -} - -/*! - \obsolete - - Use toBool() instead. -*/ -bool QScriptValue::toBoolean() const -{ - Q_D(const QScriptValue); - if (!d) - return false; - return d->value.toBoolean(); -} - -/*! - \since 4.5 - - Returns the boolean value of this QScriptValue, using the conversion - rules described in \l{ECMA-262} section 9.2, "ToBoolean". - - Note that if this QScriptValue is an object, calling this function - has side effects on the script engine, since the engine will call - the object's valueOf() function (and possibly toString()) in an - attempt to convert the object to a primitive value (possibly - resulting in an uncaught script exception). - - \sa isBool() -*/ -bool QScriptValue::toBool() const -{ - Q_D(const QScriptValue); - if (!d) - return false; - return d->value.toBoolean(); -} - -/*! - Returns the signed 32-bit integer value of this QScriptValue, using - the conversion rules described in \l{ECMA-262} section 9.5, "ToInt32". - - Note that if this QScriptValue is an object, calling this function - has side effects on the script engine, since the engine will call - the object's valueOf() function (and possibly toString()) in an - attempt to convert the object to a primitive value (possibly - resulting in an uncaught script exception). - - \sa toNumber(), toUInt32() -*/ -qint32 QScriptValue::toInt32() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->value.toInt32(); -} - -/*! - Returns the unsigned 32-bit integer value of this QScriptValue, using - the conversion rules described in \l{ECMA-262} section 9.6, "ToUint32". - - Note that if this QScriptValue is an object, calling this function - has side effects on the script engine, since the engine will call - the object's valueOf() function (and possibly toString()) in an - attempt to convert the object to a primitive value (possibly - resulting in an uncaught script exception). - - \sa toNumber(), toInt32() -*/ -quint32 QScriptValue::toUInt32() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->value.toUInt32(); -} - -/*! - Returns the unsigned 16-bit integer value of this QScriptValue, using - the conversion rules described in \l{ECMA-262} section 9.7, "ToUint16". - - Note that if this QScriptValue is an object, calling this function - has side effects on the script engine, since the engine will call - the object's valueOf() function (and possibly toString()) in an - attempt to convert the object to a primitive value (possibly - resulting in an uncaught script exception). - - \sa toNumber() -*/ -quint16 QScriptValue::toUInt16() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->value.toUInt16(); -} - -/*! - Returns the integer value of this QScriptValue, using the conversion - rules described in \l{ECMA-262} section 9.4, "ToInteger". - - Note that if this QScriptValue is an object, calling this function - has side effects on the script engine, since the engine will call - the object's valueOf() function (and possibly toString()) in an - attempt to convert the object to a primitive value (possibly - resulting in an uncaught script exception). - - \sa toNumber() -*/ -qsreal QScriptValue::toInteger() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->value.toInteger(); -} - -/*! - Returns the QVariant value of this QScriptValue, if it can be - converted to a QVariant; otherwise returns an invalid QVariant. - The conversion is performed according to the following table: - - \table - \header \o Input Type \o Result - \row \o Undefined \o An invalid QVariant. - \row \o Null \o An invalid QVariant. - \row \o Boolean \o A QVariant containing the value of the boolean. - \row \o Number \o A QVariant containing the value of the number. - \row \o String \o A QVariant containing the value of the string. - \row \o QVariant Object \o The result is the QVariant value of the object (no conversion). - \row \o QObject Object \o A QVariant containing a pointer to the QObject. - \row \o Date Object \o A QVariant containing the date value (toDateTime()). - \row \o RegExp Object \o A QVariant containing the regular expression value (toRegExp()). - \row \o Array Object \o The array is converted to a QVariantList. - \row \o Object \o If the value is primitive, then the result is converted to a QVariant according to the above rules; otherwise, an invalid QVariant is returned. - \endtable - - \sa isVariant() -*/ -QVariant QScriptValue::toVariant() const -{ - Q_D(const QScriptValue); - if (!d) - return QVariant(); - return d->value.toVariant(); -} - -/*! - \obsolete - - This function is obsolete; use QScriptEngine::toObject() instead. -*/ -QScriptValue QScriptValue::toObject() const -{ - Q_D(const QScriptValue); - if (!d) - return QScriptValue(); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - if (!eng) - return QScriptValue(); - return eng->toPublic(eng->toObject(d->value)); -} - -/*! - Returns a QDateTime representation of this value, in local time. - If this QScriptValue is not a date, or the value of the date is NaN - (Not-a-Number), an invalid QDateTime is returned. - - \sa isDate() -*/ -QDateTime QScriptValue::toDateTime() const -{ - Q_D(const QScriptValue); - if (!d) - return QDateTime(); - return d->value.toDateTime(); -} - -#ifndef QT_NO_REGEXP -/*! - Returns the QRegExp representation of this value. - If this QScriptValue is not a regular expression, an empty - QRegExp is returned. - - \sa isRegExp() -*/ -QRegExp QScriptValue::toRegExp() const -{ - Q_D(const QScriptValue); - if (!d) - return QRegExp(); - return d->value.toRegExp(); -} -#endif // QT_NO_REGEXP - -/*! - If this QScriptValue is a QObject, returns the QObject pointer - that the QScriptValue represents; otherwise, returns 0. - - If the QObject that this QScriptValue wraps has been deleted, - this function returns 0 (i.e. it is possible for toQObject() - to return 0 even when isQObject() returns true). - - \sa isQObject() -*/ -QObject *QScriptValue::toQObject() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->value.toQObject(); -} - -/*! - If this QScriptValue is a QMetaObject, returns the QMetaObject pointer - that the QScriptValue represents; otherwise, returns 0. - - \sa isQMetaObject() -*/ -const QMetaObject *QScriptValue::toQMetaObject() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->value.toQMetaObject(); -} - -/*! - Sets the value of this QScriptValue's property with the given \a name to - the given \a value. - - If this QScriptValue is not an object, this function does nothing. - - If this QScriptValue does not already have a property with name \a name, - a new property is created; the given \a flags then specify how this - property may be accessed by script code. - - If \a value is invalid, the property is removed. - - If the property is implemented using a setter function (i.e. has the - PropertySetter flag set), calling setProperty() has side-effects on - the script engine, since the setter function will be called with the - given \a value as argument (possibly resulting in an uncaught script - exception). - - Note that you cannot specify custom getter or setter functions for - built-in properties, such as the \c{length} property of Array objects - or meta properties of QObject objects. - - \sa property() -*/ -void QScriptValue::setProperty(const QString &name, const QScriptValue &value, - const PropertyFlags &flags) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return; - if (value.engine() && (value.engine() != engine())) { - qWarning("QScriptValue::setProperty(%s) failed: " - "cannot set value created in a different engine", - qPrintable(name)); - return; - } - d->value.setProperty(name, d->value.engine()->toImpl(value), flags); -} - -/*! - Returns the value of this QScriptValue's property with the given \a name, - using the given \a mode to resolve the property. - - If no such property exists, an invalid QScriptValue is returned. - - If the property is implemented using a getter function (i.e. has the - PropertyGetter flag set), calling property() has side-effects on the - script engine, since the getter function will be called (possibly - resulting in an uncaught script exception). If an exception - occurred, property() returns the value that was thrown (typically - an \c{Error} object). - - \sa setProperty(), propertyFlags(), QScriptValueIterator -*/ -QScriptValue QScriptValue::property(const QString &name, - const ResolveFlags &mode) const -{ - Q_D(const QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.property(name, mode)); -} - -/*! - \overload - - Returns the property at the given \a arrayIndex, using the given \a - mode to resolve the property. - - This function is provided for convenience and performance when - working with array objects. - - If this QScriptValue is not an Array object, this function behaves - as if property() was called with the string representation of \a - arrayIndex. -*/ -QScriptValue QScriptValue::property(quint32 arrayIndex, - const ResolveFlags &mode) const -{ - Q_D(const QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.property(arrayIndex, mode)); -} - -/*! - \overload - - Sets the property at the given \a arrayIndex to the given \a value. - - This function is provided for convenience and performance when - working with array objects. - - If this QScriptValue is not an Array object, this function behaves - as if setProperty() was called with the string representation of \a - arrayIndex. -*/ -void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue &value, - const PropertyFlags &flags) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return; - if (value.engine() && (value.engine() != engine())) { - qWarning("QScriptValue::setProperty() failed: " - "cannot set value created in a different engine"); - return; - } - d->value.setProperty(arrayIndex, d->value.engine()->toImpl(value), flags); -} - -/*! - \since 4.4 - - Returns the value of this QScriptValue's property with the given \a name, - using the given \a mode to resolve the property. - - This overload of property() is useful when you need to look up the - same property repeatedly, since the lookup can be performed faster - when the name is represented as an interned string. - - \sa QScriptEngine::toStringHandle(), setProperty() -*/ -QScriptValue QScriptValue::property(const QScriptString &name, - const ResolveFlags &mode) const -{ - Q_D(const QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - if (!name.isValid()) - return QScriptValue(); - QScriptStringPrivate *s = QScriptStringPrivate::get(name); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.property(s->nameId, mode)); -} - -/*! - \since 4.4 - - Sets the value of this QScriptValue's property with the given \a - name to the given \a value. The given \a flags specify how this - property may be accessed by script code. - - This overload of setProperty() is useful when you need to set the - same property repeatedly, since the operation can be performed - faster when the name is represented as an interned string. - - \sa QScriptEngine::toStringHandle() -*/ -void QScriptValue::setProperty(const QScriptString &name, - const QScriptValue &value, - const PropertyFlags &flags) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject() || !name.isValid()) - return; - if (value.engine() && (value.engine() != engine())) { - qWarning("QScriptValue::setProperty() failed: " - "cannot set value created in a different engine"); - return; - } - QScriptStringPrivate *s = QScriptStringPrivate::get(name); - d->value.setProperty(s->nameId, d->value.engine()->toImpl(value), flags); -} - -/*! - Returns the flags of the property with the given \a name, using the - given \a mode to resolve the property. - - \sa property() -*/ -QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString &name, - const ResolveFlags &mode) const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->value.propertyFlags(name, mode); -} - -/*! - \since 4.4 - - Returns the flags of the property with the given \a name, using the - given \a mode to resolve the property. - - \sa property() -*/ -QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString &name, - const ResolveFlags &mode) const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - if (!name.isValid()) - return 0; - QScriptStringPrivate *s = QScriptStringPrivate::get(name); - return d->value.propertyFlags(s->nameId, mode); -} - -/*! - Calls this QScriptValue as a function, using \a thisObject as - the `this' object in the function call, and passing \a args - as arguments to the function. Returns the value returned from - the function. - - If this QScriptValue is not a function, call() does nothing - and returns an invalid QScriptValue. - - Note that if \a thisObject is not an object, the global object - (see \l{QScriptEngine::globalObject()}) will be used as the - `this' object. - - Calling call() can cause an exception to occur in the script engine; - in that case, call() returns the value that was thrown (typically an - \c{Error} object). You can call - QScriptEngine::hasUncaughtException() to determine if an exception - occurred. - - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2 - - \sa construct() -*/ -QScriptValue QScriptValue::call(const QScriptValue &thisObject, - const QScriptValueList &args) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - if (isFunction() && thisObject.isValid() && thisObject.engine() && - engine() && (thisObject.engine() != engine())) { - qWarning("QScriptValue::call() failed: " - "cannot call function with thisObject created in " - "a different engine"); - return QScriptValue(); - } - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.call(eng->toImpl(thisObject), - eng->toImplList(args))); -} - -/*! - Calls this QScriptValue as a function, using \a thisObject as - the `this' object in the function call, and passing \a arguments - as arguments to the function. Returns the value returned from - the function. - - If this QScriptValue is not a function, call() does nothing - and returns an invalid QScriptValue. - - \a arguments can be an arguments object, an array, null or - undefined; any other type will cause a TypeError to be thrown. - - Note that if \a thisObject is not an object, the global object - (see \l{QScriptEngine::globalObject()}) will be used as the - `this' object. - - One common usage of this function is to forward native function - calls to another function: - - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 3 - - \sa construct(), QScriptContext::argumentsObject() -*/ -QScriptValue QScriptValue::call(const QScriptValue &thisObject, - const QScriptValue &arguments) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - if (isFunction() && thisObject.isValid() && thisObject.engine() - && (thisObject.engine() != engine())) { - qWarning("QScriptValue::call() failed: " - "cannot call function with thisObject created in " - "a different engine"); - return QScriptValue(); - } - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.call(eng->toImpl(thisObject), - eng->toImpl(arguments))); -} - -/*! - Creates a new \c{Object} and calls this QScriptValue as a - constructor, using the created object as the `this' object and - passing \a args as arguments. If the return value from the - constructor call is an object, then that object is returned; - otherwise the default constructed object is returned. - - If this QScriptValue is not a function, construct() does nothing - and returns an invalid QScriptValue. - - Calling construct() can cause an exception to occur in the script - engine; in that case, construct() returns the value that was thrown - (typically an \c{Error} object). You can call - QScriptEngine::hasUncaughtException() to determine if an exception - occurred. - - \sa call(), QScriptEngine::newObject() -*/ -QScriptValue QScriptValue::construct(const QScriptValueList &args) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.construct(eng->toImplList(args))); -} - -/*! - Creates a new \c{Object} and calls this QScriptValue as a - constructor, using the created object as the `this' object and - passing \a arguments as arguments. If the return value from the - constructor call is an object, then that object is returned; - otherwise the default constructed object is returned. - - If this QScriptValue is not a function, construct() does nothing - and returns an invalid QScriptValue. - - \a arguments can be an arguments object, an array, null or - undefined. Any other type will cause a TypeError to be thrown. - - \sa call(), QScriptEngine::newObject(), QScriptContext::argumentsObject() -*/ -QScriptValue QScriptValue::construct(const QScriptValue &arguments) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.construct(eng->toImpl(arguments))); -} - -/*! - Returns the QScriptEngine that created this QScriptValue, - or 0 if this QScriptValue is invalid or the value is not - associated with a particular engine. -*/ -QScriptEngine *QScriptValue::engine() const -{ - Q_D(const QScriptValue); - if (!d) - return 0; - return d->engine; -} - -/*! - \obsolete - - Use isBool() instead. -*/ -bool QScriptValue::isBoolean() const -{ - Q_D(const QScriptValue); - return d && d->value.isBoolean(); -} - -/*! - \since 4.5 - - Returns true if this QScriptValue is of the primitive type Boolean; - otherwise returns false. - - \sa toBool() -*/ -bool QScriptValue::isBool() const -{ - Q_D(const QScriptValue); - return d && d->value.isBoolean(); -} - -/*! - Returns true if this QScriptValue is of the primitive type Number; - otherwise returns false. - - \sa toNumber() -*/ -bool QScriptValue::isNumber() const -{ - Q_D(const QScriptValue); - return d && d->value.isNumber(); -} - -/*! - Returns true if this QScriptValue is of the primitive type String; - otherwise returns false. - - \sa toString() -*/ -bool QScriptValue::isString() const -{ - Q_D(const QScriptValue); - return d && d->value.isString(); -} - -/*! - Returns true if this QScriptValue is a function; otherwise returns - false. - - \sa call() -*/ -bool QScriptValue::isFunction() const -{ - Q_D(const QScriptValue); - return d && d->value.isFunction(); -} - -/*! - Returns true if this QScriptValue is of the primitive type Null; - otherwise returns false. - - \sa QScriptEngine::nullValue() -*/ -bool QScriptValue::isNull() const -{ - Q_D(const QScriptValue); - return d && d->value.isNull(); -} - -/*! - Returns true if this QScriptValue is of the primitive type Undefined; - otherwise returns false. - - \sa QScriptEngine::undefinedValue() -*/ -bool QScriptValue::isUndefined() const -{ - Q_D(const QScriptValue); - return d && d->value.isUndefined(); -} - -/*! - Returns true if this QScriptValue is of the Object type; otherwise - returns false. - - Note that function values, variant values, and QObject values are - objects, so this function returns true for such values. - - \sa QScriptEngine::toObject(), QScriptEngine::newObject() -*/ -bool QScriptValue::isObject() const -{ - Q_D(const QScriptValue); - return d && d->value.isObject(); -} - -/*! - Returns true if this QScriptValue is a variant value; - otherwise returns false. - - \sa toVariant(), QScriptEngine::newVariant() -*/ -bool QScriptValue::isVariant() const -{ - Q_D(const QScriptValue); - return d && d->value.isVariant(); -} - -/*! - Returns true if this QScriptValue is a QObject; otherwise returns - false. - - Note: This function returns true even if the QObject that this - QScriptValue wraps has been deleted. - - \sa toQObject(), QScriptEngine::newQObject() -*/ -bool QScriptValue::isQObject() const -{ - Q_D(const QScriptValue); - return d && d->value.isQObject(); -} - -/*! - Returns true if this QScriptValue is a QMetaObject; otherwise returns - false. - - \sa toQMetaObject(), QScriptEngine::newQMetaObject() -*/ -bool QScriptValue::isQMetaObject() const -{ - Q_D(const QScriptValue); - return d && d->value.isQMetaObject(); -} - -/*! - Returns true if this QScriptValue is valid; otherwise returns - false. -*/ -bool QScriptValue::isValid() const -{ - Q_D(const QScriptValue); - return d && d->value.isValid(); -} - -/*! - \since 4.4 - - Returns the internal data of this QScriptValue object. QtScript uses - this property to store the primitive value of Date, String, Number - and Boolean objects. For other types of object, custom data may be - stored using setData(). -*/ -QScriptValue QScriptValue::data() const -{ - Q_D(const QScriptValue); - if (!d || !d->value.isObject()) - return QScriptValue(); - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - return eng->toPublic(d->value.internalValue()); -} - -/*! - \since 4.4 - - Sets the internal \a data of this QScriptValue object. You can use - this function to set object-specific data that won't be directly - accessible to scripts, but may be retrieved in C++ using the data() - function. -*/ -void QScriptValue::setData(const QScriptValue &data) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return; - QScriptEnginePrivate *eng = QScriptEnginePrivate::get(engine()); - d->value.setInternalValue(eng->toImpl(data)); -} - -/*! - \since 4.4 - - Returns the custom script class that this script object is an - instance of, or 0 if the object is not of a custom class. - - \sa setScriptClass() -*/ -QScriptClass *QScriptValue::scriptClass() const -{ - Q_D(const QScriptValue); - if (!d || !d->value.isObject()) - return 0; - QScriptClassInfo *info = d->value.classInfo(); - if ((info->type() & QScriptClassInfo::TypeMask) < QScriptClassInfo::CustomType) - return 0; - return QScriptClassPrivate::classFromInfo(info); -} - -/*! - \since 4.4 - - Sets the custom script class of this script object to \a scriptClass. - This can be used to "promote" a plain script object (e.g. created - by the "new" operator in a script, or by QScriptEngine::newObject() in C++) - to an object of a custom type. - - If \a scriptClass is 0, the object will be demoted to a plain - script object. - - \sa scriptClass(), setData() -*/ -void QScriptValue::setScriptClass(QScriptClass *scriptClass) -{ - Q_D(QScriptValue); - if (!d || !d->value.isObject()) - return; - if (!scriptClass) { - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine()); - d->value.setClassInfo(eng_p->m_class_object); - } else { - QScriptClassPrivate *cls_p = QScriptClassPrivate::get(scriptClass); - d->value.setClassInfo(cls_p->classInfo()); - } -} - -/*! - \internal - - Returns the ID of this object, or -1 if this QScriptValue is not an - object. - - \sa QScriptEngine::objectById() -*/ -qint64 QScriptValue::objectId() const -{ - Q_D(const QScriptValue); - if (!d || !d->value.isObject()) - return -1; - return d->value.m_object_value->m_id; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptvalue_p.h b/src/script/qscriptvalue_p.h deleted file mode 100644 index 629d86c..0000000 --- a/src/script/qscriptvalue_p.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTVALUE_P_H -#define QSCRIPTVALUE_P_H - -#include "qscriptvaluefwd_p.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_SCRIPT - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -inline QScriptValuePrivate::QScriptValuePrivate() -{ - engine = 0; - ref = 0; -} - -inline QScriptValuePrivate::~QScriptValuePrivate() -{ - if (value.type() == QScript::LazyStringType) - delete value.m_lazy_string_value; -} - -inline QScriptValuePrivate *QScriptValuePrivate::create() -{ - return new QScriptValuePrivate(); -} - -inline QScriptValuePrivate *QScriptValuePrivate::get(const QScriptValue &value) -{ - return const_cast<QScriptValuePrivate*>(value.d_func()); -} - -inline QScriptValueImpl QScriptValuePrivate::valueOf(const QScriptValue &value) -{ - QScriptValuePrivate *p = const_cast<QScriptValuePrivate*>(value.d_func()); - if (!p) - return QScriptValueImpl(); - return p->value; -} - -inline void QScriptValuePrivate::init(QScriptValue &value, QScriptValuePrivate *p) -{ - value.d_ptr = p; - value.d_ptr->ref.ref(); -} - -inline void QScriptValuePrivate::invalidate() -{ - engine = 0; - value.invalidate(); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptvalueimpl.cpp b/src/script/qscriptvalueimpl.cpp deleted file mode 100644 index 58fb363..0000000 --- a/src/script/qscriptvalueimpl.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptvalueimpl_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -QT_BEGIN_NAMESPACE - -static void dfs(QScriptObject *instance, QHash<QScriptObject*, int> &dfn, int n) -{ - bool found = dfn.contains(instance); - dfn[instance] = n; - - if (found) - return; - - if (instance->m_prototype.isObject()) - dfs (instance->m_prototype.m_object_value, dfn, n + 1); - - if (instance->m_scope.isObject()) - dfs (instance->m_scope.m_object_value, dfn, n + 1); -} - - -static bool checkCycle(QScriptObject *instance, const QHash<QScriptObject*, int> &dfn) -{ - int n = dfn.value(instance); - - if (instance->m_prototype.isObject()) { - if (n >= dfn.value(instance->m_prototype.m_object_value)) - return true; - } - - if (instance->m_scope.isObject()) { - if (n >= dfn.value(instance->m_scope.m_object_value)) - return true; - } - - return false; -} - -bool QScriptValueImpl::detectedCycle() const -{ - QHash<QScriptObject*, int> dfn; - dfs(m_object_value, dfn, 0); - return checkCycle(m_object_value, dfn); -} - -bool QScriptValueImpl::instanceOf(const QScriptValueImpl &value) const -{ - if (! isObject() || ! value.isObject() || !value.implementsHasInstance()) - return false; - return value.hasInstance(*this); -} - -bool QScriptValueImpl::implementsHasInstance() const -{ - Q_ASSERT(isObject()); - if (isFunction()) - return true; - if (QScriptClassData *odata = classInfo()->data()) { - return odata->implementsHasInstance(*this); - } - return false; -} - -bool QScriptValueImpl::hasInstance(const QScriptValueImpl &value) const -{ - Q_ASSERT(isObject()); - - if (QScriptClassData *odata = classInfo()->data()) { - if (odata->implementsHasInstance(*this)) - return odata->hasInstance(*this, value); - } - if (!isFunction()) - return false; - - // [[HasInstance] for function objects - - if (!value.isObject()) - return false; - - QScriptEnginePrivate *eng = engine(); - QScriptValueImpl proto = property(eng->idTable()->id_prototype); - if (!proto.isObject()) { - QScriptContextPrivate *ctx = eng->currentContext(); - ctx->throwTypeError(QLatin1String("instanceof: 'prototype' property is not an object")); - return false; - } - - QScriptObject *target = proto.m_object_value; - QScriptValueImpl v = value; - while (true) { - v = v.prototype(); - if (!v.isObject()) - break; - if (target == v.m_object_value) - return true; - } - return false; -} - -bool QScriptValueImpl::resolve_helper(QScriptNameIdImpl *nameId, QScript::Member *member, - QScriptValueImpl *object, QScriptValue::ResolveFlags mode, - QScript::AccessMode access) const -{ - QScriptObject *object_data = m_object_value; - - QScriptEnginePrivate *eng_p = engine(); - - if (nameId == eng_p->idTable()->id___proto__) { - member->native(nameId, /*id=*/0, QScriptValue::Undeletable); - *object = *this; - return true; - } - - // If not found anywhere else, search in the extra members. - if (QScriptClassData *odata = classInfo()->data()) { - *object = *this; - - if (odata->resolve(*this, nameId, member, object, access)) - return true; - } - - if (mode & QScriptValue::ResolvePrototype) { - // For values and other non object based types, search in class's prototype - const QScriptValueImpl &proto = object_data->m_prototype; - - if (proto.isObject() - && proto.resolve(nameId, member, object, mode, access)) { - return true; - } - } - - if ((mode & QScriptValue::ResolveScope) && object_data->m_scope.isValid()) - return object_data->m_scope.resolve(nameId, member, object, mode, access); - - return false; -} - -void QScriptValueImpl::setProperty(QScriptNameIdImpl *nameId, - const QScriptValueImpl &value, - const QScriptValue::PropertyFlags &flags) -{ - if (!isObject()) - return; - - QScriptValueImpl base; - QScript::Member member; - - QScriptValue::ResolveFlags mode = QScriptValue::ResolveLocal; - // if we are not setting a setter or getter, look in prototype too - if (!(flags & (QScriptValue::PropertyGetter | QScriptValue::PropertySetter))) - mode |= QScriptValue::ResolvePrototype; - - if (resolve(nameId, &member, &base, mode, QScript::ReadWrite)) { - // we resolved an existing property with that name - if (flags & (QScriptValue::PropertyGetter | QScriptValue::PropertySetter)) { - // setting the getter or setter of a property in this object - if (member.isNativeProperty()) { - if (value.isValid()) { - qWarning("QScriptValue::setProperty() failed: " - "cannot set getter or setter of native property `%s'", - qPrintable(nameId->s)); - } - return; - } - if (member.isSetter()) { - // the property we resolved is a setter - if (!(flags & QScriptValue::PropertySetter) && !member.isGetter()) { - // find the getter, if not, create one - if (!m_object_value->findGetter(&member)) { - if (!value.isValid()) - return; // don't create property for invalid value - createMember(nameId, &member, flags); - } - } - } else if (member.isGetter()) { - // the property we resolved is a getter - if (!(flags & QScriptValue::PropertyGetter)) { - // find the setter, if not, create one - if (!m_object_value->findSetter(&member)) { - if (!value.isValid()) - return; // don't create property for invalid value - createMember(nameId, &member, flags); - } - } - } else { - // the property is a normal property -- change the flags - uint newFlags = flags & ~QScript::Member::InternalRange; - newFlags |= QScript::Member::ObjectProperty; - member.resetFlags(newFlags); - base.m_object_value->m_members[member.id()].resetFlags(newFlags); - } - Q_ASSERT(member.isValid()); - if (!value.isValid()) { - // remove the property - removeMember(member); - return; - } - } else { - // setting the value - if (member.isGetterOrSetter()) { - // call the setter - QScriptValueImpl setter; - if (member.isObjectProperty() && !member.isSetter()) { - if (!base.m_object_value->findSetter(&member)) { - qWarning("QScriptValue::setProperty() failed: " - "property '%s' has a getter but no setter", - qPrintable(nameId->s)); - return; - } - } - base.get(member, &setter); - setter.call(*this, QScriptValueImplList() << value); - return; - } else { - if (base.m_object_value != m_object_value) { - if (!value.isValid()) - return; // don't create property for invalid value - createMember(nameId, &member, flags); - base = *this; - } else { - if (!value.isValid()) { - // remove the property - removeMember(member); - return; - } - } - if (flags != QScriptValue::KeepExistingFlags) { - // change flags - if (member.isNativeProperty()) { - qWarning("QScriptValue::setProperty(%s): " - "cannot change flags of a native property", - qPrintable(nameId->s)); - } else { - uint newFlags = member.flags() & QScript::Member::InternalRange; - newFlags |= flags & ~QScript::Member::InternalRange; - base.m_object_value->m_members[member.id()].resetFlags(newFlags); - } - } - } - } - } else { - // property does not exist - if (!value.isValid()) - return; // don't create property for invalid value - createMember(nameId, &member, flags & ~QScript::Member::InternalRange); - base = *this; - } - - base.put(member, value); -} - -QVariant QScriptValueImpl::toVariant() const -{ - switch (m_type) { - case QScript::InvalidType: - return QVariant(); - - case QScript::UndefinedType: - case QScript::NullType: - case QScript::PointerType: - case QScript::ReferenceType: - break; - - case QScript::BooleanType: - return QVariant(m_bool_value); - - case QScript::IntegerType: - return QVariant(m_int_value); - - case QScript::NumberType: - return QVariant(m_number_value); - - case QScript::StringType: - return QVariant(m_string_value->s); - - case QScript::LazyStringType: - return QVariant(*m_lazy_string_value); - - case QScript::ObjectType: - if (isDate()) - return QVariant(toDateTime()); - -#ifndef QT_NO_REGEXP - if (isRegExp()) - return QVariant(toRegExp()); -#endif - if (isVariant()) - return variantValue(); - -#ifndef QT_NO_QOBJECT - if (isQObject()) - return qVariantFromValue(toQObject()); -#endif - if (isArray()) - return QScriptEnginePrivate::variantListFromArray(*this); - - QScriptValueImpl v = engine()->toPrimitive(*this); - if (!v.isObject()) - return v.toVariant(); - break; - } // switch - return QVariant(); -} - -QDebug &operator<<(QDebug &d, const QScriptValueImpl &object) -{ - d.nospace() << "QScriptValue("; - - switch (object.type()) { - case QScript::InvalidType: - d.nospace() << "Invalid)"; - return d; - - case QScript::BooleanType: - d.nospace() << "bool=" << object.toBoolean(); - break; - - case QScript::IntegerType: - d.nospace() << "int=" << object.toInt32(); - break; - - case QScript::NumberType: - d.nospace() << "qsreal=" << object.toNumber(); - break; - - case QScript::LazyStringType: - case QScript::StringType: - d.nospace() << "string=" << object.toString(); - break; - - case QScript::ReferenceType: - d.nospace() << "reference"; - break; - - case QScript::NullType: - d.nospace() << "null"; - break; - - case QScript::UndefinedType: - d.nospace() << "undefined"; - break; - - case QScript::PointerType: - d.nospace() << "pointer"; - break; - - case QScript::ObjectType: - d.nospace() << object.classInfo()->name() << ",{"; - QScriptObject *od = object.objectValue(); - for (int i=0; i<od->memberCount(); ++i) { - if (i != 0) - d << ','; - - QScript::Member m; - od->member(i, &m); - - if (m.isValid() && m.isObjectProperty()) { - d << object.engine()->toString(m.nameId()); - QScriptValueImpl o; - od->get(m, &o); - d.nospace() << QLatin1Char(':') - << (o.classInfo() - ? o.classInfo()->name() - : QLatin1String("?")); - } - } - - d.nospace() << "} scope={"; - QScriptValueImpl scope = object.scope(); - while (scope.isValid()) { - Q_ASSERT(scope.isObject()); - d.nospace() << ' ' << scope.objectValue(); - scope = scope.scope(); - } - d.nospace() << '}'; - break; - } - - d << ')'; - return d; -} - -void QScriptValueImpl::destroyObjectData() -{ - Q_ASSERT(isObject()); - m_object_value->finalizeData(); -} - -bool QScriptValueImpl::isMarked(int generation) const -{ - if (isString()) - return (m_string_value->used != 0); - else if (isObject()) { - QScript::GCBlock *block = QScript::GCBlock::get(m_object_value); - return (block->generation == generation); - } - return false; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptvalueimpl_p.h b/src/script/qscriptvalueimpl_p.h deleted file mode 100644 index d1fdf43..0000000 --- a/src/script/qscriptvalueimpl_p.h +++ /dev/null @@ -1,786 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTVALUEIMPL_P_H -#define QSCRIPTVALUEIMPL_P_H - -#include "qscriptvalueimplfwd_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptclassinfo_p.h" -#include "qscriptecmaarray_p.h" -#include "qscriptecmadate_p.h" -#include "qscriptecmaerror_p.h" -#include "qscriptecmaregexp_p.h" -#include "qscriptextqobject_p.h" -#include "qscriptextvariant_p.h" -#include "qscriptvaluefwd_p.h" -#include "qscriptnameid_p.h" -#include "qscriptenginefwd_p.h" -#include "qscriptcontextfwd_p.h" - -#include <QtCore/QDateTime> - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -inline QScriptValueImpl::QScriptValueImpl() - : m_type(QScript::InvalidType) {} - -inline QScriptValueImpl::QScriptValueImpl(QScriptValue::SpecialValue val) -{ - if (val == QScriptValue::NullValue) - m_type = QScript::NullType; - else if (val == QScriptValue::UndefinedValue) - m_type = QScript::UndefinedType; - else - m_type = QScript::InvalidType; -} - -inline QScriptValueImpl::QScriptValueImpl(bool val) - : m_type(QScript::BooleanType), m_bool_value(val) -{ -} - -inline QScriptValueImpl::QScriptValueImpl(int val) - : m_type(QScript::NumberType), m_number_value(val) -{ -} - -inline QScriptValueImpl::QScriptValueImpl(uint val) - : m_type(QScript::NumberType), m_number_value(val) -{ -} - -inline QScriptValueImpl::QScriptValueImpl(qsreal val) - : m_type(QScript::NumberType), m_number_value(val) -{ -} - -inline QScriptValueImpl::QScriptValueImpl(QScriptEnginePrivate *engine, const QString &val) -{ - engine->newString(this, val); -} - -inline QScriptValueImpl::QScriptValueImpl(QScriptNameIdImpl *val) - : m_type(QScript::StringType), m_string_value(val) -{ -} - -inline QScript::Type QScriptValueImpl::type() const -{ - return m_type; -} - -inline QScriptEnginePrivate *QScriptValueImpl::engine() const -{ - if (!isObject()) - return 0; - return m_object_value->m_class->engine(); -} - -inline QScriptClassInfo *QScriptValueImpl::classInfo() const -{ - if (!isObject()) - return 0; - return m_object_value->m_class; -} - -inline void QScriptValueImpl::setClassInfo(QScriptClassInfo *cls) -{ - Q_ASSERT(isObject()); - m_object_value->m_class = cls; -} - -inline QScriptNameIdImpl *QScriptValueImpl::stringValue() const -{ - Q_ASSERT(isString()); - return m_string_value; -} - -inline QScriptObject *QScriptValueImpl::objectValue() const -{ - Q_ASSERT(isObject()); - return m_object_value; -} - -inline void QScriptValueImpl::incr() -{ - ++m_number_value; -} - -inline void QScriptValueImpl::decr() -{ - --m_number_value; -} - -inline void QScriptValueImpl::invalidate() -{ - m_type = QScript::InvalidType; -} - -inline bool QScriptValueImpl::isValid() const -{ - return m_type != QScript::InvalidType; -} - -inline bool QScriptValueImpl::isUndefined() const -{ - return (m_type == QScript::UndefinedType); -} - -inline bool QScriptValueImpl::isNull() const -{ - return (m_type == QScript::NullType); -} - -inline bool QScriptValueImpl::isBoolean() const -{ - return (m_type == QScript::BooleanType); -} - -inline bool QScriptValueImpl::isNumber() const -{ - return (m_type == QScript::NumberType); -} - -inline bool QScriptValueImpl::isString() const -{ - return (m_type == QScript::StringType) - || (m_type == QScript::LazyStringType); -} - -inline bool QScriptValueImpl::isReference() const -{ - return (m_type == QScript::ReferenceType); -} - -inline bool QScriptValueImpl::isObject() const -{ - return (m_type == QScript::ObjectType); -} - -inline bool QScriptValueImpl::isFunction() const -{ - return (m_type == QScript::ObjectType) - && (classInfo()->type() & QScriptClassInfo::FunctionBased); -} - -inline bool QScriptValueImpl::isVariant() const -{ - return (m_type == QScript::ObjectType) - && (classInfo()->type() == QScriptClassInfo::VariantType); -} - -inline bool QScriptValueImpl::isQObject() const -{ - return (m_type == QScript::ObjectType) - && (classInfo()->type() == QScriptClassInfo::QObjectType); -} - -inline bool QScriptValueImpl::isQMetaObject() const -{ - return (m_type == QScript::ObjectType) - && (classInfo()->type() == QScriptClassInfo::QMetaObjectType); -} - -inline bool QScriptValueImpl::isArray() const -{ - if (!isObject()) - return false; - return classInfo() == engine()->arrayConstructor->classInfo(); -} - -inline bool QScriptValueImpl::isDate() const -{ - if (!isObject()) - return false; - return classInfo() == engine()->dateConstructor->classInfo(); -} - -inline bool QScriptValueImpl::isError() const -{ - if (!isObject()) - return false; - return classInfo() == engine()->errorConstructor->classInfo(); -} - -inline bool QScriptValueImpl::isRegExp() const -{ - if (!isObject()) - return false; - return classInfo() == engine()->regexpConstructor->classInfo(); -} - -inline qsreal QScriptValueImpl::toNumber() const -{ - if (!isValid()) - return 0; - return QScriptEnginePrivate::convertToNativeDouble(*this); -} - -inline bool QScriptValueImpl::toBoolean() const -{ - if (!isValid()) - return false; - return QScriptEnginePrivate::convertToNativeBoolean(*this); -} - -inline QString QScriptValueImpl::toString() const -{ - if (!isValid()) - return QString(); - return QScriptEnginePrivate::convertToNativeString(*this); -} - -inline qint32 QScriptValueImpl::toInt32() const -{ - if (!isValid()) - return 0; - double d = QScriptEnginePrivate::convertToNativeDouble(*this); - return QScriptEnginePrivate::toInt32(d); -} - -inline quint32 QScriptValueImpl::toUInt32() const -{ - if (!isValid()) - return 0; - double d = QScriptEnginePrivate::convertToNativeDouble(*this); - return QScriptEnginePrivate::toUint32(d); -} - -inline quint16 QScriptValueImpl::toUInt16() const -{ - if (!isValid()) - return 0; - double d = QScriptEnginePrivate::convertToNativeDouble(*this); - return QScriptEnginePrivate::toUint16(d); -} - -inline qsreal QScriptValueImpl::toInteger() const -{ - if (!isValid()) - return 0; - double d = QScriptEnginePrivate::convertToNativeDouble(*this); - return QScriptEnginePrivate::toInteger(d); -} - -inline QDateTime QScriptValueImpl::toDateTime() const -{ - if (!isDate()) - return QDateTime(); - return engine()->toDateTime(*this); -} - -#ifndef QT_NO_REGEXP -inline QRegExp QScriptValueImpl::toRegExp() const -{ - if (!isRegExp()) - return QRegExp(); - return engine()->regexpConstructor->toRegExp(*this); -} -#endif // QT_NO_REGEXP - -inline QObject *QScriptValueImpl::toQObject() const -{ -#ifndef QT_NO_QOBJECT - if (isQObject()) { - QScript::ExtQObject *ctor = engine()->qobjectConstructor; - Q_ASSERT(ctor != 0); - - QScript::ExtQObject::Instance *data = ctor->get(*this); - Q_ASSERT(data != 0); - - return data->value; - } else if (isVariant()) { - int type = variantValue().userType(); - if ((type == QMetaType::QObjectStar) || (type == QMetaType::QWidgetStar)) - return *reinterpret_cast<QObject* const *>(variantValue().constData()); - } -#endif - return 0; -} - -inline const QMetaObject *QScriptValueImpl::toQMetaObject() const -{ -#ifndef QT_NO_QOBJECT - if (isQMetaObject()) { - QScript::ExtQMetaObject *ctor = engine()->qmetaObjectConstructor; - Q_ASSERT(ctor != 0); - - QScript::ExtQMetaObject::Instance *data = ctor->get(*this); - Q_ASSERT(data != 0); - - return data->value; - } -#endif - return 0; -} - -inline QScriptValueImpl QScriptValueImpl::prototype() const -{ - if (!isObject()) - return QScriptValueImpl(); - return m_object_value->m_prototype; -} - -inline void QScriptValueImpl::setPrototype(const QScriptValueImpl &prototype) -{ - if (isObject()) - m_object_value->m_prototype = prototype; -} - -inline QScriptObjectData *QScriptValueImpl::objectData() const -{ - Q_ASSERT(isObject()); - return m_object_value->m_data; -} - -inline void QScriptValueImpl::setObjectData(QScriptObjectData *data) -{ - Q_ASSERT(isObject()); - m_object_value->m_data = data; -} - -inline bool QScriptValueImpl::resolve(QScriptNameIdImpl *nameId, QScript::Member *member, - QScriptValueImpl *object, QScriptValue::ResolveFlags mode, - QScript::AccessMode access) const -{ - Q_ASSERT(isValid()); - Q_ASSERT(isObject()); - Q_ASSERT(member); - Q_ASSERT(object); - - Q_ASSERT(nameId->unique); - - QScriptObject *object_data = m_object_value; - - // Search in properties... - if (object_data->findMember(nameId, member)) { - *object = *this; - return true; - } - - return resolve_helper(nameId, member, object, mode, access); -} - -inline void QScriptValueImpl::get(const QScript::Member &member, QScriptValueImpl *out) const -{ - Q_ASSERT(out); - Q_ASSERT(isObject()); - Q_ASSERT(member.isValid()); - - if (! member.isObjectProperty()) { - get_helper(member, out); - return; - } - - Q_ASSERT(member.id() >= 0); - Q_ASSERT(member.id() < m_object_value->memberCount()); - - m_object_value->get(member, out); -} - -inline void QScriptValueImpl::get(QScriptNameIdImpl *nameId, QScriptValueImpl *out) -{ - QScript::Member m; - QScriptValueImpl o; - if (resolve(nameId, &m, &o, QScriptValue::ResolvePrototype, QScript::Read)) - o.get(m, out); - else - *out = QScriptValueImpl(QScriptValue::UndefinedValue); -} - -inline void QScriptValueImpl::get_helper(const QScript::Member &member, QScriptValueImpl *out) const -{ - if (member.nameId() == engine()->idTable()->id___proto__) { - *out = prototype(); - - if (!out->isValid()) - *out = QScriptValueImpl(QScriptValue::UndefinedValue); - - return; - } - - if (QScriptClassData *data = classInfo()->data()) { - if (data->get(*this, member, out)) - return; - } - - out->invalidate(); -} - -inline void QScriptValueImpl::put(const QScript::Member &member, const QScriptValueImpl &value) -{ - Q_ASSERT(isObject()); - Q_ASSERT(member.isValid()); - // Q_ASSERT(member.isWritable()); - - QScriptEnginePrivate *eng_p = engine(); - - if (member.isObjectProperty()) { - Q_ASSERT(member.nameId()->unique); - Q_ASSERT(member.id() >= 0); - Q_ASSERT(member.id() < m_object_value->memberCount()); - m_object_value->put(member, value); - } - - else if (member.nameId() == eng_p->idTable()->id___proto__) { - if (value.isNull()) // only Object.prototype.__proto__ can be null - setPrototype(eng_p->undefinedValue()); - else { - QScriptValueImpl was = prototype(); - setPrototype(value); - if (detectedCycle()) { - eng_p->currentContext()->throwError(QLatin1String("cycle in prototype chain")); - setPrototype(was); - } - } - } - - else { - Q_ASSERT(classInfo()->data()); - classInfo()->data()->put(this, member, value); - } -} - -inline void QScriptValueImpl::setQObjectValue(QObject *object) -{ -#ifndef QT_NO_QOBJECT - Q_ASSERT(isQObject()); - - QScript::ExtQObject *ctor = engine()->qobjectConstructor; - Q_ASSERT(ctor != 0); - - QScript::ExtQObject::Instance *data = ctor->get(*this); - Q_ASSERT(data != 0); - - data->value = object; -#else - Q_UNUSED(object); -#endif -} - -inline QVariant &QScriptValueImpl::variantValue() const -{ - Q_ASSERT(isVariant()); - - QScript::Ext::Variant *ctor = engine()->variantConstructor; - Q_ASSERT(ctor != 0); - - QScript::Ext::Variant::Instance *data = ctor->get(*this); - Q_ASSERT(data != 0); - - return data->value; -} - -inline void QScriptValueImpl::setVariantValue(const QVariant &value) -{ - if (!isVariant()) - return; - - QScript::Ext::Variant *ctor = engine()->variantConstructor; - Q_ASSERT(ctor != 0); - - QScript::Ext::Variant::Instance *data = ctor->get(*this); - Q_ASSERT(data != 0); - - data->value = value; -} - -inline QScriptValueImpl QScriptValueImpl::internalValue() const -{ - Q_ASSERT(isObject()); - return m_object_value->m_internalValue; -} - -inline void QScriptValueImpl::setInternalValue(const QScriptValueImpl &internalValue) -{ - Q_ASSERT(isObject()); - m_object_value->m_internalValue = internalValue; -} - -inline void QScriptValueImpl::removeMember(const QScript::Member &member) -{ - if (member.isObjectProperty()) - m_object_value->removeMember(member); - - else if (QScriptClassData *data = classInfo()->data()) - data->removeMember(*this, member); -} - -inline void QScriptValueImpl::createMember(QScriptNameIdImpl *nameId, - QScript::Member *member, uint flags) -{ - Q_ASSERT(isObject()); - - QScriptObject *object_data = m_object_value; - object_data->createMember(nameId, member, flags); - Q_ASSERT(member->isObjectProperty()); -} - -inline QScriptValueImpl QScriptValueImpl::scope() const -{ - Q_ASSERT(isObject()); - return m_object_value->m_scope; -} - -inline void QScriptValueImpl::setScope(const QScriptValueImpl &scope) -{ - Q_ASSERT(isObject()); - m_object_value->m_scope = scope; -} - -inline int QScriptValueImpl::memberCount() const -{ - Q_ASSERT(isObject()); - return m_object_value->memberCount(); -} - -inline void QScriptValueImpl::member(int index, QScript::Member *member) const -{ - Q_ASSERT(isObject()); - Q_ASSERT(index >= 0); - Q_ASSERT(index < m_object_value->memberCount()); - m_object_value->member(index, member); -} - -inline QScriptFunction *QScriptValueImpl::toFunction() const -{ - if (!isFunction()) - return 0; - return engine()->convertToNativeFunction(*this); -} - -inline QScriptValueImpl QScriptValueImpl::property(QScriptNameIdImpl *nameId, - const QScriptValue::ResolveFlags &mode) const -{ - if (!isObject()) - return QScriptValueImpl(); - - QScriptValueImpl base; - QScript::Member member; - - if (! resolve(nameId, &member, &base, mode, QScript::Read)) - return QScriptValueImpl(); - - QScriptValueImpl value; - base.get(member, &value); - if (member.isGetterOrSetter()) { - QScriptValueImpl getter; - if (member.isObjectProperty() && !member.isGetter()) { - if (!base.m_object_value->findGetter(&member)) - return QScriptValueImpl(); - } - base.get(member, &getter); - value = getter.call(*this); - } - return value; -} - -inline void QScriptValueImpl::setProperty(const QString &name, const QScriptValueImpl &value, - const QScriptValue::PropertyFlags &flags) -{ - if (!isObject()) - return; - QScriptNameIdImpl *nameId = engine()->nameId(name); - setProperty(nameId, value, flags); -} - -inline QScriptValueImpl QScriptValueImpl::property(const QString &name, - const QScriptValue::ResolveFlags &mode) const -{ - if (!isObject()) - return QScriptValueImpl(); - QScriptNameIdImpl *nameId = engine()->nameId(name); - return property(nameId, mode); -} - -inline QScriptValueImpl QScriptValueImpl::property(quint32 arrayIndex, - const QScriptValue::ResolveFlags &mode) const -{ - if (!isObject()) - return QScriptValueImpl(); - - QScriptEnginePrivate *eng_p = engine(); - QScript::Ecma::Array::Instance *instance = eng_p->arrayConstructor->get(*this); - if (instance && (arrayIndex != 0xFFFFFFFF)) - return instance->value.at(arrayIndex); - - return property(QScriptValueImpl(arrayIndex).toString(), mode); -} - -inline void QScriptValueImpl::setProperty(quint32 arrayIndex, const QScriptValueImpl &value, - const QScriptValue::PropertyFlags &flags) -{ - if (!isObject()) - return; - - QScriptEnginePrivate *eng_p = engine(); - QScript::Ecma::Array::Instance *instance = eng_p->arrayConstructor->get(*this); - if (instance && (arrayIndex != 0xFFFFFFFF)) { - instance->value.assign(arrayIndex, value); - return; - } - - setProperty(QScriptValueImpl(arrayIndex).toString(), value, flags); -} - -inline QScriptValue::PropertyFlags QScriptValueImpl::propertyFlags(const QString &name, - const QScriptValue::ResolveFlags &mode) const -{ - QScriptNameIdImpl *nameId = engine()->nameId(name); - return propertyFlags(nameId, mode); -} - -inline QScriptValue::PropertyFlags QScriptValueImpl::propertyFlags(QScriptNameIdImpl *nameId, - const QScriptValue::ResolveFlags &mode) const -{ - if (!isObject()) - return 0; - - QScriptValueImpl base; - QScript::Member member; - if (! resolve(nameId, &member, &base, mode, QScript::ReadWrite)) - return 0; - - return QScriptValue::PropertyFlags(member.flags() & ~QScript::Member::InternalRange); -} - -inline bool QScriptValueImpl::deleteProperty(QScriptNameIdImpl *nameId, - const QScriptValue::ResolveFlags &mode) -{ - if (!isObject()) - return true; - QScript::Member member; - QScriptValueImpl base; - if (resolve(nameId, &member, &base, mode, QScript::Write)) { - if (!member.isDeletable()) - return false; - base.removeMember(member); - if (member.isGetterOrSetter() && (member.isGetter() != member.isSetter())) { - // delete the "other half" of the property too (getter or setter) - return deleteProperty(nameId, mode); - } - } - return true; -} - -inline QScriptValueImpl QScriptValueImpl::call(const QScriptValueImpl &thisObject, - const QScriptValueImplList &args) -{ - if (!isFunction()) - return QScriptValueImpl(); - - return engine()->call(*this, thisObject, args, /*asConstructor=*/false); -} - -inline QScriptValueImpl QScriptValueImpl::call(const QScriptValueImpl &thisObject, - const QScriptValueImpl &args) -{ - if (!isFunction()) - return QScriptValueImpl(); - - return engine()->call(*this, thisObject, args, /*asConstructor=*/false); -} - -inline QScriptValueImpl QScriptValueImpl::construct(const QScriptValueImplList &args) -{ - if (!isFunction()) - return QScriptValueImpl(); - - QScriptEnginePrivate *eng_p = engine(); - - QScriptValueImpl proto = property(QLatin1String("prototype"), QScriptValue::ResolveLocal); - QScriptValueImpl object; - eng_p->newObject(&object, proto); - - QScriptValueImpl result = eng_p->call(*this, object, args, /*asConstructor=*/true); - if (result.isObject()) - return result; - return object; -} - -inline QScriptValueImpl QScriptValueImpl::construct(const QScriptValueImpl &args) -{ - if (!isFunction()) - return QScriptValueImpl(); - - QScriptEnginePrivate *eng_p = engine(); - - QScriptValueImpl proto = property(QLatin1String("prototype"), QScriptValue::ResolveLocal); - QScriptValueImpl object; - eng_p->newObject(&object, proto); - - QScriptValueImpl result = eng_p->call(*this, object, args, /*asConstructor=*/true); - if (result.isObject()) - return result; - return object; -} - -inline void QScriptValueImpl::mark(int generation) const -{ - if (! isValid()) - return; - - else if (isString()) - engine()->markString(m_string_value, generation); - - else if (isObject()) - engine()->markObject(*this, generation); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptvalueimplfwd_p.h b/src/script/qscriptvalueimplfwd_p.h deleted file mode 100644 index 5baaa99..0000000 --- a/src/script/qscriptvalueimplfwd_p.h +++ /dev/null @@ -1,241 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTVALUEIMPLFWD_P_H -#define QSCRIPTVALUEIMPLFWD_P_H - -#include "qscriptglobals_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptvalue.h" - -#include <QtCore/qstring.h> -#include <QtCore/qlist.h> - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#if defined(Q_OS_VXWORKS) && defined(m_type) -# undef m_type -#endif - -class QScriptValueImpl; -typedef QList<QScriptValueImpl> QScriptValueImplList; - -class QScriptClassInfo; -class QScriptObject; -class QScriptObjectData; -class QScriptNameIdImpl; -class QScriptFunction; -class QScriptEnginePrivate; - -namespace QScript -{ - class Member; -} - -class QScriptValueImpl -{ -public: - enum TypeHint { - NoTypeHint, - NumberTypeHint, - StringTypeHint - }; - - inline QScriptValueImpl(); - inline QScriptValueImpl(QScriptValue::SpecialValue val); - inline QScriptValueImpl(bool val); - inline QScriptValueImpl(int val); - inline QScriptValueImpl(uint val); - inline QScriptValueImpl(qsreal val); - inline QScriptValueImpl(QScriptEnginePrivate *engine, const QString &val); - inline QScriptValueImpl(QScriptNameIdImpl *val); - - inline QScript::Type type() const; - inline QScriptEnginePrivate *engine() const; - inline QScriptClassInfo *classInfo() const; - inline void setClassInfo(QScriptClassInfo *cls); - inline QScriptNameIdImpl *stringValue() const; - inline QScriptObject *objectValue() const; - inline void incr(); - inline void decr(); - - inline void invalidate(); - inline bool isValid() const; - inline bool isBoolean() const; - inline bool isNumber() const; - inline bool isString() const; - inline bool isFunction() const; - inline bool isObject() const; - inline bool isUndefined() const; - inline bool isNull() const; - inline bool isVariant() const; - inline bool isQObject() const; - inline bool isQMetaObject() const; - inline bool isReference() const; - - inline bool isError() const; - inline bool isArray() const; - inline bool isDate() const; - inline bool isRegExp() const; - - inline QString toString() const; - inline qsreal toNumber() const; - inline bool toBoolean() const; - inline qsreal toInteger() const; - inline qint32 toInt32() const; - inline quint32 toUInt32() const; - inline quint16 toUInt16() const; - QVariant toVariant() const; - inline QObject *toQObject() const; - inline const QMetaObject *toQMetaObject() const; - inline QDateTime toDateTime() const; -#ifndef QT_NO_REGEXP - inline QRegExp toRegExp() const; -#endif - - inline QVariant &variantValue() const; - inline void setVariantValue(const QVariant &v); - - bool instanceOf(const QScriptValueImpl &value) const; - bool instanceOf_helper(const QScriptValueImpl &value) const; - - bool implementsHasInstance() const; - bool hasInstance(const QScriptValueImpl &value) const; - - inline QScriptValueImpl prototype() const; - inline void setPrototype(const QScriptValueImpl &prototype); - - inline QScriptValueImpl property(QScriptNameIdImpl *nameId, - const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; - void setProperty(QScriptNameIdImpl *nameId, const QScriptValueImpl &value, - const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); - - inline QScriptValueImpl property(const QString &name, - const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; - inline void setProperty(const QString &name, const QScriptValueImpl &value, - const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); - - inline QScriptValueImpl property(quint32 arrayIndex, - const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; - inline void setProperty(quint32 arrayIndex, const QScriptValueImpl &value, - const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); - - inline QScriptValue::PropertyFlags propertyFlags(const QString &name, - const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; - inline QScriptValue::PropertyFlags propertyFlags(QScriptNameIdImpl *nameId, - const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; - - inline bool deleteProperty(QScriptNameIdImpl *nameId, - const QScriptValue::ResolveFlags &mode = QScriptValue::ResolveLocal); - - inline QScriptValueImpl call(const QScriptValueImpl &thisObject = QScriptValueImpl(), - const QScriptValueImplList &args = QScriptValueImplList()); - inline QScriptValueImpl call(const QScriptValueImpl &thisObject, - const QScriptValueImpl &arguments); - inline QScriptValueImpl construct(const QScriptValueImplList &args = QScriptValueImplList()); - inline QScriptValueImpl construct(const QScriptValueImpl &arguments); - - inline void mark(int) const; - bool isMarked(int) const; - - inline QScriptValueImpl internalValue() const; - inline void setInternalValue(const QScriptValueImpl &internalValue); - - inline void setQObjectValue(QObject *object); - - inline QScriptObjectData *objectData() const; - inline void setObjectData(QScriptObjectData *data); - void destroyObjectData(); - - inline void createMember(QScriptNameIdImpl *nameId, - QScript::Member *member, uint flags); // ### remove me - inline int memberCount() const; - inline void member(int index, QScript::Member *member) const; - - inline bool resolve(QScriptNameIdImpl *nameId, QScript::Member *member, - QScriptValueImpl *object, QScriptValue::ResolveFlags mode, - QScript::AccessMode access) const; - bool resolve_helper(QScriptNameIdImpl *nameId, QScript::Member *member, - QScriptValueImpl *object, QScriptValue::ResolveFlags mode, - QScript::AccessMode access) const; - inline void get(const QScript::Member &member, QScriptValueImpl *out) const; - inline void get_helper(const QScript::Member &member, QScriptValueImpl *out) const; - inline void get(QScriptNameIdImpl *nameId, QScriptValueImpl *out); - inline void put(const QScript::Member &member, const QScriptValueImpl &value); - inline void removeMember(const QScript::Member &member); - - inline QScriptValueImpl scope() const; - inline void setScope(const QScriptValueImpl &scope); - - inline QScriptFunction *toFunction() const; - - bool detectedCycle() const; - - QScript::Type m_type; - union { - bool m_bool_value; - int m_int_value; - qsreal m_number_value; - void *m_ptr_value; - QScriptObject *m_object_value; - QScriptNameIdImpl *m_string_value; - QString *m_lazy_string_value; - }; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif // QSCRIPTVALUEIMPLFWD_P_H diff --git a/src/script/qscriptvalueiteratorimpl.cpp b/src/script/qscriptvalueiteratorimpl.cpp deleted file mode 100644 index 35b5241..0000000 --- a/src/script/qscriptvalueiteratorimpl.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptvalueiteratorimpl_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptengine_p.h" -#include "qscriptcontext_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" - -QT_BEGIN_NAMESPACE - -namespace QScript { - -extern QString numberToString(qsreal value); - -} // namespace - -QScriptValueIteratorImpl::QScriptValueIteratorImpl(const QScriptValueImpl &obj) -{ - Q_ASSERT(obj.isObject()); - m_frontObject = obj; - m_member.invalidate(); - m_foundMember.invalidate(); - m_foundForward = false; - m_object = obj; - m_searchIndex = 0; - m_searchClassDataIterator = false; - m_classDataIterator = 0; - m_ignoresDontEnum = true; - m_enumerateProto = false; -} - -QScriptValueIteratorImpl::~QScriptValueIteratorImpl() -{ - if (m_classDataIterator) { - delete m_classDataIterator; - m_classDataIterator = 0; - } -} - -bool QScriptValueIteratorImpl::ignoresDontEnum() const -{ - return m_ignoresDontEnum; -} - -void QScriptValueIteratorImpl::setIgnoresDontEnum(bool ignore) -{ - m_ignoresDontEnum = ignore; -} - -bool QScriptValueIteratorImpl::enumeratePrototype() const -{ - return m_enumerateProto; -} - -void QScriptValueIteratorImpl::setEnumeratePrototype(bool enable) -{ - m_enumerateProto = enable; -} - -bool QScriptValueIteratorImpl::acceptsMember(const QScriptValueImpl &o, - const QScript::Member &m) const -{ - if (!m.isValid() || (!m_ignoresDontEnum && m.dontEnum()) - || (m.isSetter() && !m.isGetter())) { - return false; - } - - if (!m_enumerateProto || QScriptEnginePrivate::strictlyEquals(o, m_frontObject)) - return true; - - // make sure it's not a shadowed property - QScript::Member dummy; - QScriptValueImpl base; - QScriptNameIdImpl *id; - if (m.nameId()) { - id = m.nameId(); - } else { - QScriptEnginePrivate *eng_p = m_frontObject.engine(); - id = eng_p->nameId(QScript::numberToString(m.id())); - } - m_frontObject.resolve(id, &dummy, &base, QScriptValue::ResolvePrototype, QScript::Read); - return QScriptEnginePrivate::strictlyEquals(base, o); -} - -bool QScriptValueIteratorImpl::hasNext() -{ - if (m_foundMember.isValid() && m_foundForward) { - // we have the information about the next element already - return true; - } - - int idx, count; - QScriptValueImpl obj = m_object; - - if (m_searchClassDataIterator) { - Q_ASSERT(m_classDataIterator != 0); - if (m_foundMember.isValid()) { - // undo effect of hasPrevious() - m_foundMember.invalidate(); - QScript::Member dummy; - m_classDataIterator->next(&dummy); - } - goto LSearchClassData; - } - - idx = m_searchIndex; - if (m_foundMember.isValid()) { - // undo effect of hasPrevious() - m_foundMember.invalidate(); - ++idx; - } - - LSearchObjectData: - count = obj.memberCount(); - for (int i = idx; i < count; ++i) { - QScript::Member m; - obj.member(i, &m); - if (acceptsMember(obj, m)) { - m_foundObject = obj; - m_foundMember = m; - m_foundForward = true; - m_searchIndex = i + 1; - return true; - } - } - - if (!m_classDataIterator) { - QScriptClassData *data = obj.classInfo()->data(); - if (!data) - goto LNext; - m_classDataIterator = data->newIterator(obj); - if (!m_classDataIterator) - goto LNext; - } - m_searchClassDataIterator = true; - - LSearchClassData: - Q_ASSERT(m_classDataIterator != 0); - while (m_classDataIterator->hasNext()) { - QScript::Member m; - m_classDataIterator->next(&m); - if (acceptsMember(obj, m)) { - m_foundObject = obj; - m_foundMember = m; - m_foundForward = true; - return true; - } - } - - LNext: - if (!m_enumerateProto || !obj.prototype().isObject()) - return false; - - // look in prototype - obj = obj.prototype(); - idx = 0; - if (m_classDataIterator) { - delete m_classDataIterator; - m_classDataIterator = 0; - m_searchClassDataIterator = false; - } - goto LSearchObjectData; -} - -void QScriptValueIteratorImpl::next() -{ - (void)hasNext(); // sync the next-element info - m_object = m_foundObject; - m_member = m_foundMember; - m_foundObject = QScriptValueImpl(); - m_foundMember.invalidate(); -} - -bool QScriptValueIteratorImpl::hasPrevious() -{ - if (m_foundMember.isValid() && !m_foundForward) { - // we have the information about the previous element already - return true; - } - - QScriptValueImpl obj = m_object; - - if (m_searchClassDataIterator) { - Q_ASSERT(m_classDataIterator != 0); - if (m_foundMember.isValid()) { - // undo effect of hasNext() - m_foundMember.invalidate(); - QScript::Member dummy; - m_classDataIterator->previous(&dummy); - } - while (m_classDataIterator->hasPrevious()) { - QScript::Member m; - m_classDataIterator->previous(&m); - if (acceptsMember(obj, m)) { - m_foundObject = obj; - m_foundMember = m; - m_foundForward = false; - return true; - } - } - m_searchClassDataIterator = false; - m_searchIndex = obj.memberCount(); - m_foundMember.invalidate(); - } - - // search object members - int i = m_searchIndex - 1; - if (m_foundMember.isValid()) { - // undo effect of hasPrevious() - m_foundMember.invalidate(); - --i; - } - for ( ; i >= 0; --i) { - QScript::Member m; - obj.member(i, &m); - if (acceptsMember(obj, m)) { - m_foundObject = obj; - m_foundMember = m; - m_foundForward = false; - m_searchIndex = i; - return true; - } - } - - return false; -} - -void QScriptValueIteratorImpl::previous() -{ - (void)hasPrevious(); // sync the previous-element info - m_object = m_foundObject; - m_member = m_foundMember; - m_foundObject = QScriptValueImpl(); - m_foundMember.invalidate(); -} - -QScript::Member *QScriptValueIteratorImpl::member() -{ - return &m_member; -} - -QScriptNameIdImpl *QScriptValueIteratorImpl::nameId() const -{ - return m_member.nameId(); -} - -QString QScriptValueIteratorImpl::name() const -{ - if (!m_member.isValid()) - return QString(); - if (m_member.nameId()) - return m_member.nameId()->s; - else - return QScript::numberToString(m_member.id()); -} - -QScriptValueImpl QScriptValueIteratorImpl::value() const -{ - if (!m_member.isValid()) - return QScriptValueImpl(); - QScriptValueImpl result; - m_object.get(m_member, &result); - if (m_member.isGetterOrSetter()) { - // find and call the getter - QScriptValueImpl getter; - if (m_member.isObjectProperty() && !m_member.isGetter()) { - QScript::Member mb; - QScriptObject *obj = m_object.m_object_value; - mb.object(m_member.nameId(), obj->memberCount(), 0); - if (!obj->findGetter(&mb)) - return QScriptValueImpl(); - m_object.get(mb, &getter); - } else { - getter = result; - } - result = getter.call(m_object); - } - return result; -} - -void QScriptValueIteratorImpl::setValue(const QScriptValueImpl &value) -{ - if (!m_member.isValid()) - return; - if (m_member.isGetterOrSetter()) { - // find and call the setter - QScriptValueImpl setter; - if (m_member.isObjectProperty() && !m_member.isSetter()) { - QScript::Member mb; - QScriptObject *obj = m_object.m_object_value; - mb.object(m_member.nameId(), obj->memberCount(), 0); - if (!obj->findSetter(&mb)) - return; - m_object.get(mb, &setter); - } else { - m_object.get(m_member, &setter); - } - setter.call(m_object, QScriptValueImplList() << value); - } else { - m_object.put(m_member, value); - } -} - -uint QScriptValueIteratorImpl::flags() const -{ - return m_member.flags(); -} - -QScriptValueImpl QScriptValueIteratorImpl::object() const -{ - return m_object; -} - -void QScriptValueIteratorImpl::setObject(const QScriptValueImpl &obj) -{ - Q_ASSERT(obj.isObject()); - m_object = obj; - if (m_classDataIterator) { - delete m_classDataIterator; - m_classDataIterator = 0; - } - toFront(); -} - -void QScriptValueIteratorImpl::remove() -{ - if (m_member.isValid()) - m_object.removeMember(m_member); -} - -void QScriptValueIteratorImpl::toFront() -{ - if (m_classDataIterator) { - if (!m_enumerateProto || QScriptEnginePrivate::strictlyEquals(m_object, m_frontObject)) { - m_classDataIterator->toFront(); - } else { - delete m_classDataIterator; - m_classDataIterator = 0; - } - } - - m_member.invalidate(); - m_object = m_frontObject; - - m_foundObject = QScriptValueImpl(); - m_foundMember.invalidate(); - m_searchIndex = 0; - m_searchClassDataIterator = false; -} - -void QScriptValueIteratorImpl::toBack() -{ - m_member.invalidate(); - - m_foundObject = QScriptValueImpl(); - m_foundMember.invalidate(); - - if (!m_classDataIterator) { - QScriptClassData *data = m_object.classInfo()->data(); - if (data) - m_classDataIterator = data->newIterator(m_object); - } - if (m_classDataIterator) - m_classDataIterator->toBack(); - else - m_searchIndex = m_object.memberCount(); - m_searchClassDataIterator = (m_classDataIterator != 0); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptvalueiteratorimpl_p.h b/src/script/qscriptvalueiteratorimpl_p.h deleted file mode 100644 index d72295e..0000000 --- a/src/script/qscriptvalueiteratorimpl_p.h +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTVALUEITERATORIMPL_P_H -#define QSCRIPTVALUEITERATORIMPL_P_H - -#include "qscriptvalueimplfwd_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptmemberfwd_p.h" - -QT_BEGIN_NAMESPACE - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -class QScriptClassDataIterator; -class QScriptNameIdImpl; - -class QScriptValueIteratorImpl -{ -public: - QScriptValueIteratorImpl(const QScriptValueImpl &obj); - ~QScriptValueIteratorImpl(); - - bool ignoresDontEnum() const; - void setIgnoresDontEnum(bool ignore); - - bool enumeratePrototype() const; - void setEnumeratePrototype(bool enable); - - bool hasNext(); - void next(); - - bool hasPrevious(); - void previous(); - - QScript::Member *member(); - - QScriptNameIdImpl *nameId() const; - QString name() const; - - QScriptValueImpl value() const; - void setValue(const QScriptValueImpl &value); - - uint flags() const; - - void remove(); - - void toFront(); - void toBack(); - - QScriptValueImpl object() const; - void setObject(const QScriptValueImpl &obj); - -private: - bool acceptsMember(const QScriptValueImpl &o, const QScript::Member &m) const; - QScriptClassDataIterator *getClassDataIterator(); - - QScriptValueImpl m_frontObject; - - bool m_ignoresDontEnum; - bool m_enumerateProto; - - QScriptValueImpl m_object; - QScript::Member m_member; - - int m_searchIndex; - QScriptValueImpl m_foundObject; - QScript::Member m_foundMember; - bool m_foundForward; - QScriptClassDataIterator *m_classDataIterator; - bool m_searchClassDataIterator; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT - -#endif diff --git a/src/script/qscriptxmlgenerator.cpp b/src/script/qscriptxmlgenerator.cpp deleted file mode 100644 index 254bfcd..0000000 --- a/src/script/qscriptxmlgenerator.cpp +++ /dev/null @@ -1,1118 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptxmlgenerator_p.h" - -#ifndef QT_NO_SCRIPT - -#include "qscriptast_p.h" -#include "qscriptengine_p.h" -#include "qscriptvalueimpl_p.h" -#include "qscriptcontext_p.h" -#include "qscriptmember_p.h" -#include "qscriptobject_p.h" -#include "qscriptlexer_p.h" -#include "qscriptparser_p.h" - -#include <QtCore/qstring.h> -#include <QtCore/qtextstream.h> - -QT_BEGIN_NAMESPACE - -namespace QScript { - -extern QString numberToString(qsreal value); - -// copy of Qt::escape() (it's in QtGui :-( ) - -static QString escape(const QString& plain) -{ - QString rich; - rich.reserve(int(plain.length() * 1.1)); - for (int i = 0; i < plain.length(); ++i) { - if (plain.at(i) == QLatin1Char('<')) - rich += QLatin1String("<"); - else if (plain.at(i) == QLatin1Char('>')) - rich += QLatin1String(">"); - else if (plain.at(i) == QLatin1Char('&')) - rich += QLatin1String("&"); - else - rich += plain.at(i); - } - return rich; -} - -XmlGenerator::XmlGenerator(QTextStream &o): - out(o), m_indentLevel(-1), m_formatOutput(false) -{ -} - -XmlGenerator::~XmlGenerator() -{ -} - -QTextStream &XmlGenerator::operator()(const QString &program, int lineNumber) -{ - QScriptEnginePrivate priv; - NodePool *pool = new NodePool(/*fileName=*/QString(), &priv); - priv.setNodePool(pool); - - Lexer lex(&priv); - priv.setLexer(&lex); - lex.setCode(program, lineNumber); - - QScriptParser parser; - if (parser.parse(&priv)) { - accept(priv.abstractSyntaxTree()); - } - - delete pool; - - return out; -} - -QTextStream &XmlGenerator::newlineAndIndent() -{ - enum { IND = 2 }; - if (m_formatOutput) - out << endl << QString().fill(QLatin1Char(' '), m_indentLevel * IND); - return out; -} - -QTextStream &XmlGenerator::startTag(const QString &name, AST::Node *locationNode) -{ - pushIndentLevel(); - newlineAndIndent(); - out << QLatin1Char('<') << name; - if (locationNode) - out << QLatin1String(" line=\"") << locationNode->startLine << QLatin1Char('\"'); - out << QLatin1Char('>'); - return out; -} - -QTextStream &XmlGenerator::endTag(const QString &name) -{ - newlineAndIndent(); - popIndentLevel(); - out << QLatin1String("</") << escape(name) << QLatin1Char('>'); - return out; -} - -void XmlGenerator::accept(AST::Node *node) -{ - AST::Node::acceptChild(node, this); -} - -bool XmlGenerator::visit(AST::ThisExpression *) -{ - pushIndentLevel(); - newlineAndIndent(); - out << QLatin1String("<this/>"); - popIndentLevel(); - return true; -} - -void XmlGenerator::endVisit(AST::ThisExpression *) -{ -} - -bool XmlGenerator::visit(AST::IdentifierExpression *node) -{ - startTag(QLatin1String("identifier")); - out << escape(QScriptEnginePrivate::toString(node->name)); - out << QLatin1String("</identifier>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::IdentifierExpression *) -{ -} - -bool XmlGenerator::visit(AST::NullExpression *) -{ - pushIndentLevel(); - newlineAndIndent(); - out << QLatin1String("<null/>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::NullExpression *) -{ -} - -bool XmlGenerator::visit(AST::TrueLiteral *) -{ - pushIndentLevel(); - newlineAndIndent(); - out << QLatin1String("<true/>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::TrueLiteral *) -{ -} - -bool XmlGenerator::visit(AST::FalseLiteral *) -{ - pushIndentLevel(); - newlineAndIndent(); - out << QLatin1String("<false/>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::FalseLiteral *) -{ -} - -bool XmlGenerator::visit(AST::StringLiteral *node) -{ - startTag(QLatin1String("string")); - out << escape(QScriptEnginePrivate::toString(node->value)) << QLatin1String("</string>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::StringLiteral *) -{ -} - -bool XmlGenerator::visit(AST::NumericLiteral *node) -{ - startTag(QLatin1String("number")); - out << QString::number(node->value) << QLatin1String("</number>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::NumericLiteral *) -{ -} - -bool XmlGenerator::visit(AST::RegExpLiteral *node) -{ - startTag(QLatin1String("regexp")); - out << QLatin1Char('/') << escape(QScriptEnginePrivate::toString(node->pattern)) << QLatin1Char('/'); - if (node->flags) - out << QScript::Ecma::RegExp::flagsToString(node->flags); - out << QLatin1String("</regexp>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::RegExpLiteral *) -{ -} - -bool XmlGenerator::visit(AST::ArrayLiteral *) -{ - startTag(QLatin1String("array-literal")); - return true; -} - -void XmlGenerator::endVisit(AST::ArrayLiteral *) -{ - endTag(QLatin1String("array-literal")); -} - -bool XmlGenerator::visit(AST::ObjectLiteral *) -{ - startTag(QLatin1String("object-literal")); - return true; -} - -void XmlGenerator::endVisit(AST::ObjectLiteral *) -{ - endTag(QLatin1String("object-literal")); -} - -bool XmlGenerator::visit(AST::ElementList *) -{ - startTag(QLatin1String("element-list")); - return true; -} - -void XmlGenerator::endVisit(AST::ElementList *) -{ - endTag(QLatin1String("element-list")); -} - -bool XmlGenerator::visit(AST::Elision *) -{ - startTag(QLatin1String("elision")); // ### count - return true; -} - -void XmlGenerator::endVisit(AST::Elision *) -{ - endTag(QLatin1String("elision")); -} - -bool XmlGenerator::visit(AST::PropertyNameAndValueList *) -{ - startTag(QLatin1String("property-name-and-value-list")); - return true; -} - -void XmlGenerator::endVisit(AST::PropertyNameAndValueList *) -{ - endTag(QLatin1String("property-name-and-value-list")); -} - -bool XmlGenerator::visit(AST::IdentifierPropertyName *node) -{ - startTag(QLatin1String("identifier")); - out << escape(QScriptEnginePrivate::toString(node->id)) << QLatin1String("</identifier>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::IdentifierPropertyName *) -{ -} - -bool XmlGenerator::visit(AST::StringLiteralPropertyName *node) -{ - startTag(QLatin1String("string")); - out << escape(QScriptEnginePrivate::toString(node->id)) << QLatin1String("</string>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::StringLiteralPropertyName *) -{ -} - -bool XmlGenerator::visit(AST::NumericLiteralPropertyName *node) -{ - startTag(QLatin1String("number")); - out << escape(QScript::numberToString(node->id)) << QLatin1String("</number>"); - popIndentLevel(); - return false; -} - -void XmlGenerator::endVisit(AST::NumericLiteralPropertyName *) -{ -} - -bool XmlGenerator::visit(AST::ArrayMemberExpression *) -{ - startTag(QLatin1String("array-member-expression")); - return true; -} - -void XmlGenerator::endVisit(AST::ArrayMemberExpression *) -{ - endTag(QLatin1String("array-member-expression")); -} - -bool XmlGenerator::visit(AST::FieldMemberExpression *) -{ - startTag(QLatin1String("field-member-expression")); - return true; -} - -void XmlGenerator::endVisit(AST::FieldMemberExpression *node) -{ - startTag(QLatin1String("identifier")); - out << escape(QScriptEnginePrivate::toString(node->name)); - out << QLatin1String("</identifier>"); - popIndentLevel(); - endTag(QLatin1String("field-member-expression")); -} - -bool XmlGenerator::visit(AST::NewMemberExpression *) -{ - startTag(QLatin1String("new-member-expression")); - return true; -} - -void XmlGenerator::endVisit(AST::NewMemberExpression *) -{ - endTag(QLatin1String("new-member-expression")); -} - -bool XmlGenerator::visit(AST::NewExpression *) -{ - startTag(QLatin1String("new")); - return true; -} - -void XmlGenerator::endVisit(AST::NewExpression *) -{ - endTag(QLatin1String("new")); -} - -bool XmlGenerator::visit(AST::CallExpression *) -{ - startTag(QLatin1String("call")); - return true; -} - -void XmlGenerator::endVisit(AST::CallExpression *) -{ - endTag(QLatin1String("call")); -} - -bool XmlGenerator::visit(AST::ArgumentList *) -{ - startTag(QLatin1String("argument-list")); - return true; -} - -void XmlGenerator::endVisit(AST::ArgumentList *) -{ - endTag(QLatin1String("argument-list")); -} - -bool XmlGenerator::visit(AST::PostIncrementExpression *) -{ - startTag(QLatin1String("post-increment")); - return true; -} - -void XmlGenerator::endVisit(AST::PostIncrementExpression *) -{ - endTag(QLatin1String("post-increment")); -} - -bool XmlGenerator::visit(AST::PostDecrementExpression *) -{ - startTag(QLatin1String("post-decrement")); - return true; -} - -void XmlGenerator::endVisit(AST::PostDecrementExpression *) -{ - endTag(QLatin1String("post-decrement")); -} - -bool XmlGenerator::visit(AST::DeleteExpression *) -{ - startTag(QLatin1String("delete")); - return true; -} - -void XmlGenerator::endVisit(AST::DeleteExpression *) -{ - endTag(QLatin1String("delete")); -} - -bool XmlGenerator::visit(AST::VoidExpression *) -{ - startTag(QLatin1String("void")); - return true; -} - -void XmlGenerator::endVisit(AST::VoidExpression *) -{ - endTag(QLatin1String("void")); -} - -bool XmlGenerator::visit(AST::TypeOfExpression *) -{ - startTag(QLatin1String("typeof")); - return true; -} - -void XmlGenerator::endVisit(AST::TypeOfExpression *) -{ - endTag(QLatin1String("typeof")); -} - -bool XmlGenerator::visit(AST::PreIncrementExpression *) -{ - startTag(QLatin1String("pre-increment")); - return true; -} - -void XmlGenerator::endVisit(AST::PreIncrementExpression *) -{ - endTag(QLatin1String("pre-increment")); -} - -bool XmlGenerator::visit(AST::PreDecrementExpression *) -{ - startTag(QLatin1String("pre-decrement")); - return true; -} - -void XmlGenerator::endVisit(AST::PreDecrementExpression *) -{ - endTag(QLatin1String("pre-decrement")); -} - -bool XmlGenerator::visit(AST::UnaryPlusExpression *) -{ - startTag(QLatin1String("unary-plus")); - return true; -} - -void XmlGenerator::endVisit(AST::UnaryPlusExpression *) -{ - endTag(QLatin1String("unary-plus")); -} - -bool XmlGenerator::visit(AST::UnaryMinusExpression *) -{ - startTag(QLatin1String("unary-minus")); - return true; -} - -void XmlGenerator::endVisit(AST::UnaryMinusExpression *) -{ - endTag(QLatin1String("unary-minus")); -} - -bool XmlGenerator::visit(AST::TildeExpression *) -{ - startTag(QLatin1String("bitwise-not")); - return true; -} - -void XmlGenerator::endVisit(AST::TildeExpression *) -{ - endTag(QLatin1String("bitwise-not")); -} - -bool XmlGenerator::visit(AST::NotExpression *) -{ - startTag(QLatin1String("logical-not")); - return true; -} - -void XmlGenerator::endVisit(AST::NotExpression *) -{ - endTag(QLatin1String("logical-not")); -} - -bool XmlGenerator::visit(AST::BinaryExpression *node) -{ - QString s; - switch (node->op) { - case QSOperator::Add: - s = QLatin1String("+"); break; - case QSOperator::And: - s = QLatin1String("&&"); break; - case QSOperator::InplaceAnd: - s = QLatin1String("&="); break; - case QSOperator::Assign: - s = QLatin1String("="); break; - case QSOperator::BitAnd: - s = QLatin1String("&"); break; - case QSOperator::BitOr: - s = QLatin1String("|"); break; - case QSOperator::BitXor: - s = QLatin1String("^"); break; - case QSOperator::InplaceSub: - s = QLatin1String("-="); break; - case QSOperator::Div: - s = QLatin1String("/"); break; - case QSOperator::InplaceDiv: - s = QLatin1String("/="); break; - case QSOperator::Equal: - s = QLatin1String("=="); break; - case QSOperator::Ge: - s = QLatin1String(">="); break; - case QSOperator::Gt: - s = QLatin1String(">"); break; - case QSOperator::In: - s = QLatin1String("in"); break; - case QSOperator::InplaceAdd: - s = QLatin1String("+="); break; - case QSOperator::InstanceOf: - s = QLatin1String("instanceof"); break; - case QSOperator::Le: - s = QLatin1String("<="); break; - case QSOperator::LShift: - s = QLatin1String("<<"); break; - case QSOperator::InplaceLeftShift: - s = QLatin1String("<<="); break; - case QSOperator::Lt: - s = QLatin1String("<"); break; - case QSOperator::Mod: - s = QLatin1String("%"); break; - case QSOperator::InplaceMod: - s = QLatin1String("%="); break; - case QSOperator::Mul: - s = QLatin1String("*"); break; - case QSOperator::InplaceMul: - s = QLatin1String("*="); break; - case QSOperator::NotEqual: - s = QLatin1String("!="); break; - case QSOperator::Or: - s = QLatin1String("||"); break; - case QSOperator::InplaceOr: - s = QLatin1String("|="); break; - case QSOperator::RShift: - s = QLatin1String(">>"); break; - case QSOperator::InplaceRightShift: - s = QLatin1String(">>="); break; - case QSOperator::StrictEqual: - s = QLatin1String("==="); break; - case QSOperator::StrictNotEqual: - s = QLatin1String("!=="); break; - case QSOperator::Sub: - s = QLatin1String("-"); break; - case QSOperator::URShift: - s = QLatin1String(">>>"); break; - case QSOperator::InplaceURightShift: - s = QLatin1String(">>>="); break; - case QSOperator::InplaceXor: - s = QLatin1String("^="); break; - default: - Q_ASSERT (0); - } - pushIndentLevel(); - newlineAndIndent(); - out << QLatin1String("<binary-expression op=\"") << s << QLatin1String("\">"); - return true; -} - -void XmlGenerator::endVisit(AST::BinaryExpression *) -{ - endTag(QLatin1String("binary-expression")); -} - -bool XmlGenerator::visit(AST::ConditionalExpression *) -{ - startTag(QLatin1String("conditional")); - return true; -} - -void XmlGenerator::endVisit(AST::ConditionalExpression *) -{ - endTag(QLatin1String("conditional")); -} - -bool XmlGenerator::visit(AST::Expression *) -{ - startTag(QLatin1String("comma-expression")); - return true; -} - -void XmlGenerator::endVisit(AST::Expression *) -{ - endTag(QLatin1String("comma-expression")); -} - -bool XmlGenerator::visit(AST::Block *) -{ - startTag(QLatin1String("block")); - return true; -} - -void XmlGenerator::endVisit(AST::Block *) -{ - endTag(QLatin1String("block")); -} - -bool XmlGenerator::visit(AST::StatementList *) -{ - startTag(QLatin1String("statement-list")); - return true; -} - -void XmlGenerator::endVisit(AST::StatementList *) -{ - endTag(QLatin1String("statement-list")); -} - -bool XmlGenerator::visit(AST::VariableDeclarationList *) -{ - startTag(QLatin1String("variable-declaration-list")); - return true; -} - -void XmlGenerator::endVisit(AST::VariableDeclarationList *) -{ - endTag(QLatin1String("variable-declaration-list")); -} - -bool XmlGenerator::visit(AST::VariableStatement *node) -{ - startTag(QLatin1String("variable-statement"), node); - return true; -} - -void XmlGenerator::endVisit(AST::VariableStatement *) -{ - endTag(QLatin1String("variable-statement")); -} - -bool XmlGenerator::visit(AST::VariableDeclaration *node) -{ - startTag(QLatin1String("variable-declaration"), node); - startTag(QLatin1String("name")); - out << escape(QScriptEnginePrivate::toString(node->name)); - out << QLatin1String("</name>"); - popIndentLevel(); - return true; -} - -void XmlGenerator::endVisit(AST::VariableDeclaration *) -{ - endTag(QLatin1String("variable-declaration")); -} - -bool XmlGenerator::visit(AST::EmptyStatement *node) -{ - startTag(QLatin1String("empty-statement"), node); - return true; -} - -void XmlGenerator::endVisit(AST::EmptyStatement *) -{ - endTag(QLatin1String("empty-statement")); -} - -bool XmlGenerator::visit(AST::ExpressionStatement *node) -{ - startTag(QLatin1String("expression-statement"), node); - return true; -} - -void XmlGenerator::endVisit(AST::ExpressionStatement *) -{ - endTag(QLatin1String("expression-statement")); -} - -bool XmlGenerator::visit(AST::IfStatement *node) -{ - startTag(QLatin1String("if"), node); - return true; -} - -void XmlGenerator::endVisit(AST::IfStatement *) -{ - endTag(QLatin1String("if")); -} - -bool XmlGenerator::visit(AST::DoWhileStatement *node) -{ - startTag(QLatin1String("do-while"), node); - return true; -} - -void XmlGenerator::endVisit(AST::DoWhileStatement *) -{ - endTag(QLatin1String("do-while")); -} - -bool XmlGenerator::visit(AST::WhileStatement *node) -{ - startTag(QLatin1String("while"), node); - return true; -} - -void XmlGenerator::endVisit(AST::WhileStatement *) -{ - endTag(QLatin1String("while")); -} - -bool XmlGenerator::visit(AST::ForStatement *node) -{ - startTag(QLatin1String("for"), node); - return true; -} - -void XmlGenerator::endVisit(AST::ForStatement *) -{ - endTag(QLatin1String("for")); -} - -bool XmlGenerator::visit(AST::LocalForStatement *node) -{ - startTag(QLatin1String("for"), node); - return true; -} - -void XmlGenerator::endVisit(AST::LocalForStatement *) -{ - endTag(QLatin1String("for")); -} - -bool XmlGenerator::visit(AST::ForEachStatement *node) -{ - startTag(QLatin1String("for-in"), node); - return false; -} - -void XmlGenerator::endVisit(AST::ForEachStatement *) -{ - endTag(QLatin1String("for-in")); -} - -bool XmlGenerator::visit(AST::LocalForEachStatement *node) -{ - startTag(QLatin1String("for-in"), node); - return true; -} - -void XmlGenerator::endVisit(AST::LocalForEachStatement *) -{ - endTag(QLatin1String("for-in")); -} - -bool XmlGenerator::visit(AST::ContinueStatement *node) -{ - startTag(QLatin1String("continue"), node); - if (node->label) { - startTag(QLatin1String("label")); - out << escape(QScriptEnginePrivate::toString(node->label)); - out << QLatin1String("</label>"); - popIndentLevel(); - } - return true; -} - -void XmlGenerator::endVisit(AST::ContinueStatement *) -{ - endTag(QLatin1String("continue")); -} - -bool XmlGenerator::visit(AST::BreakStatement *node) -{ - startTag(QLatin1String("break"), node); - if (node->label) { - startTag(QLatin1String("label")); - out << escape(QScriptEnginePrivate::toString(node->label)); - out << QLatin1String("</label>"); - popIndentLevel(); - } - return true; -} - -void XmlGenerator::endVisit(AST::BreakStatement *) -{ - endTag(QLatin1String("break")); -} - -bool XmlGenerator::visit(AST::ReturnStatement *node) -{ - startTag(QLatin1String("return"), node); - return true; -} - -void XmlGenerator::endVisit(AST::ReturnStatement *) -{ - endTag(QLatin1String("return")); -} - -bool XmlGenerator::visit(AST::WithStatement *node) -{ - startTag(QLatin1String("with"), node); - return true; -} - -void XmlGenerator::endVisit(AST::WithStatement *) -{ - endTag(QLatin1String("with")); -} - -bool XmlGenerator::visit(AST::SwitchStatement *node) -{ - startTag(QLatin1String("switch"), node); - return true; -} - -void XmlGenerator::endVisit(AST::SwitchStatement *) -{ - endTag(QLatin1String("switch")); -} - -bool XmlGenerator::visit(AST::CaseBlock *) -{ - startTag(QLatin1String("case-block")); - return true; -} - -void XmlGenerator::endVisit(AST::CaseBlock *) -{ - endTag(QLatin1String("case-block")); -} - -bool XmlGenerator::visit(AST::CaseClauses *) -{ - startTag(QLatin1String("case-clauses")); - return true; -} - -void XmlGenerator::endVisit(AST::CaseClauses *) -{ - endTag(QLatin1String("case-clauses")); -} - -bool XmlGenerator::visit(AST::CaseClause *) -{ - startTag(QLatin1String("case-clause")); - return true; -} - -void XmlGenerator::endVisit(AST::CaseClause *) -{ - endTag(QLatin1String("case-clause")); -} - -bool XmlGenerator::visit(AST::DefaultClause *) -{ - startTag(QLatin1String("default-clause")); - return true; -} - -void XmlGenerator::endVisit(AST::DefaultClause *) -{ - endTag(QLatin1String("default-clause")); -} - -bool XmlGenerator::visit(AST::LabelledStatement *node) -{ - startTag(QLatin1String("labelled-statement"), node); - startTag(QLatin1String("label")); - out << escape(QScriptEnginePrivate::toString(node->label)); - out << QLatin1String("</label>"); - popIndentLevel(); - return true; -} - -void XmlGenerator::endVisit(AST::LabelledStatement *) -{ - endTag(QLatin1String("labelled-statement")); -} - -bool XmlGenerator::visit(AST::ThrowStatement *node) -{ - startTag(QLatin1String("throw"), node); - return true; -} - -void XmlGenerator::endVisit(AST::ThrowStatement *) -{ - endTag(QLatin1String("throw")); -} - -bool XmlGenerator::visit(AST::TryStatement *node) -{ - startTag(QLatin1String("try"), node); - return true; -} - -void XmlGenerator::endVisit(AST::TryStatement *) -{ - endTag(QLatin1String("try")); -} - -bool XmlGenerator::visit(AST::Catch *node) -{ - startTag(QLatin1String("catch")); - startTag(QLatin1String("identifier")); - out << escape(QScriptEnginePrivate::toString(node->name)); - out << QLatin1String("</identifier>"); - popIndentLevel(); - return true; -} - -void XmlGenerator::endVisit(AST::Catch *) -{ - endTag(QLatin1String("catch")); -} - -bool XmlGenerator::visit(AST::Finally *) -{ - startTag(QLatin1String("finally")); - return true; -} - -void XmlGenerator::endVisit(AST::Finally *) -{ - endTag(QLatin1String("finally")); -} - -bool XmlGenerator::visit(AST::FunctionDeclaration *node) -{ - startTag(QLatin1String("function-declaration"), node); - startTag(QLatin1String("name")); - if (node->name) - out << escape(QScriptEnginePrivate::toString(node->name)); - out << QLatin1String("</name>"); - popIndentLevel(); - if (!node->formals) { - startTag(QLatin1String("formal-parameter-list")); - endTag(QLatin1String("formal-parameter-list")); - } - if (!node->body) { - startTag(QLatin1String("function-body")); - endTag(QLatin1String("function-body")); - } - return true; -} - -void XmlGenerator::endVisit(AST::FunctionDeclaration *) -{ - endTag(QLatin1String("function-declaration")); -} - -bool XmlGenerator::visit(AST::FunctionExpression *node) -{ - startTag(QLatin1String("function-expression"), node); - startTag(QLatin1String("name")); - if (node->name) - out << escape(QScriptEnginePrivate::toString(node->name)); - out << QLatin1String("</name>"); - if (!node->formals) { - startTag(QLatin1String("formal-parameter-list")); - endTag(QLatin1String("formal-parameter-list")); - } - if (!node->body) { - startTag(QLatin1String("function-body")); - endTag(QLatin1String("function-body")); - } - return true; -} - -void XmlGenerator::endVisit(AST::FunctionExpression *) -{ - endTag(QLatin1String("function-expression")); -} - -bool XmlGenerator::visit(AST::FormalParameterList *node) -{ - Q_UNUSED(node); - startTag(QLatin1String("formal-parameter-list")); - for (AST::FormalParameterList *it = node; it; it = it->next) { - startTag(QLatin1String("identifier")); - out << escape(QScriptEnginePrivate::toString(it->name)); - out << QLatin1String("</identifier>"); - popIndentLevel(); - } - return true; -} - -void XmlGenerator::endVisit(AST::FormalParameterList *) -{ - endTag(QLatin1String("formal-parameter-list")); -} - -bool XmlGenerator::visit(AST::FunctionBody *) -{ - startTag(QLatin1String("function-body")); - return true; -} - -void XmlGenerator::endVisit(AST::FunctionBody *) -{ - endTag(QLatin1String("function-body")); -} - -bool XmlGenerator::visit(AST::Program *) -{ - startTag(QLatin1String("program")); - return true; -} - -void XmlGenerator::endVisit(AST::Program *) -{ - endTag(QLatin1String("program")); -} - -bool XmlGenerator::visit(AST::SourceElements *) -{ - startTag(QLatin1String("source-elements")); - return true; -} - -void XmlGenerator::endVisit(AST::SourceElements *) -{ - endTag(QLatin1String("source-elements")); -} - -bool XmlGenerator::visit(AST::FunctionSourceElement *) -{ - return true; -} - -void XmlGenerator::endVisit(AST::FunctionSourceElement *) -{ -} - -bool XmlGenerator::visit(AST::StatementSourceElement *) -{ - return true; -} - -void XmlGenerator::endVisit(AST::StatementSourceElement *) -{ -} - -bool XmlGenerator::visit(AST::DebuggerStatement *node) -{ - startTag(QLatin1String("debugger-statement"), node); - return true; -} - -void XmlGenerator::endVisit(AST::DebuggerStatement *) -{ - endTag(QLatin1String("debugger-statement")); -} - -bool XmlGenerator::preVisit(AST::Node *) -{ - return true; -} - -} // namespace QScript - -Q_SCRIPT_EXPORT QString qt_scriptToXml(const QString &program, int lineNumber = 1) -{ - QString result; - QTextStream out(&result, QIODevice::WriteOnly); - QScript::XmlGenerator gen(out); - gen(program, lineNumber); - out.flush(); - return result; -} - -QT_END_NAMESPACE - -#endif // QT_NO_SCRIPT diff --git a/src/script/qscriptxmlgenerator_p.h b/src/script/qscriptxmlgenerator_p.h deleted file mode 100644 index 265bb5f..0000000 --- a/src/script/qscriptxmlgenerator_p.h +++ /dev/null @@ -1,330 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTXMLGENERATOR_P_H -#define QSCRIPTXMLGENERATOR_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qobjectdefs.h> - -#ifndef QT_NO_SCRIPT - -#include "qscriptastvisitor_p.h" - -QT_BEGIN_NAMESPACE - -class QTextStream; - -namespace QScript { - -class XmlGenerator: protected AST::Visitor -{ -public: - XmlGenerator(QTextStream &out); - virtual ~XmlGenerator(); - - QTextStream &operator()(const QString &program, int lineNumber = 1); - -protected: - void accept(AST::Node *node); - - virtual bool preVisit(AST::Node *node); - - virtual bool visit(AST::ThisExpression *node); - virtual void endVisit(AST::ThisExpression *node); - - virtual bool visit(AST::IdentifierExpression *node); - virtual void endVisit(AST::IdentifierExpression *node); - - virtual bool visit(AST::NullExpression *node); - virtual void endVisit(AST::NullExpression *node); - - virtual bool visit(AST::TrueLiteral *node); - virtual void endVisit(AST::TrueLiteral *node); - - virtual bool visit(AST::FalseLiteral *node); - virtual void endVisit(AST::FalseLiteral *node); - - virtual bool visit(AST::StringLiteral *node); - virtual void endVisit(AST::StringLiteral *node); - - virtual bool visit(AST::NumericLiteral *node); - virtual void endVisit(AST::NumericLiteral *node); - - virtual bool visit(AST::RegExpLiteral *node); - virtual void endVisit(AST::RegExpLiteral *node); - - virtual bool visit(AST::ArrayLiteral *node); - virtual void endVisit(AST::ArrayLiteral *node); - - virtual bool visit(AST::ObjectLiteral *node); - virtual void endVisit(AST::ObjectLiteral *node); - - virtual bool visit(AST::ElementList *node); - virtual void endVisit(AST::ElementList *node); - - virtual bool visit(AST::Elision *node); - virtual void endVisit(AST::Elision *node); - - virtual bool visit(AST::PropertyNameAndValueList *node); - virtual void endVisit(AST::PropertyNameAndValueList *node); - - virtual bool visit(AST::IdentifierPropertyName *node); - virtual void endVisit(AST::IdentifierPropertyName *node); - - virtual bool visit(AST::StringLiteralPropertyName *node); - virtual void endVisit(AST::StringLiteralPropertyName *node); - - virtual bool visit(AST::NumericLiteralPropertyName *node); - virtual void endVisit(AST::NumericLiteralPropertyName *node); - - virtual bool visit(AST::ArrayMemberExpression *node); - virtual void endVisit(AST::ArrayMemberExpression *node); - - virtual bool visit(AST::FieldMemberExpression *node); - virtual void endVisit(AST::FieldMemberExpression *node); - - virtual bool visit(AST::NewMemberExpression *node); - virtual void endVisit(AST::NewMemberExpression *node); - - virtual bool visit(AST::NewExpression *node); - virtual void endVisit(AST::NewExpression *node); - - virtual bool visit(AST::CallExpression *node); - virtual void endVisit(AST::CallExpression *node); - - virtual bool visit(AST::ArgumentList *node); - virtual void endVisit(AST::ArgumentList *node); - - virtual bool visit(AST::PostIncrementExpression *node); - virtual void endVisit(AST::PostIncrementExpression *node); - - virtual bool visit(AST::PostDecrementExpression *node); - virtual void endVisit(AST::PostDecrementExpression *node); - - virtual bool visit(AST::DeleteExpression *node); - virtual void endVisit(AST::DeleteExpression *node); - - virtual bool visit(AST::VoidExpression *node); - virtual void endVisit(AST::VoidExpression *node); - - virtual bool visit(AST::TypeOfExpression *node); - virtual void endVisit(AST::TypeOfExpression *node); - - virtual bool visit(AST::PreIncrementExpression *node); - virtual void endVisit(AST::PreIncrementExpression *node); - - virtual bool visit(AST::PreDecrementExpression *node); - virtual void endVisit(AST::PreDecrementExpression *node); - - virtual bool visit(AST::UnaryPlusExpression *node); - virtual void endVisit(AST::UnaryPlusExpression *node); - - virtual bool visit(AST::UnaryMinusExpression *node); - virtual void endVisit(AST::UnaryMinusExpression *node); - - virtual bool visit(AST::TildeExpression *node); - virtual void endVisit(AST::TildeExpression *node); - - virtual bool visit(AST::NotExpression *node); - virtual void endVisit(AST::NotExpression *node); - - virtual bool visit(AST::BinaryExpression *node); - virtual void endVisit(AST::BinaryExpression *node); - - virtual bool visit(AST::ConditionalExpression *node); - virtual void endVisit(AST::ConditionalExpression *node); - - virtual bool visit(AST::Expression *node); - virtual void endVisit(AST::Expression *node); - - virtual bool visit(AST::Block *node); - virtual void endVisit(AST::Block *node); - - virtual bool visit(AST::StatementList *node); - virtual void endVisit(AST::StatementList *node); - - virtual bool visit(AST::VariableStatement *node); - virtual void endVisit(AST::VariableStatement *node); - - virtual bool visit(AST::VariableDeclarationList *node); - virtual void endVisit(AST::VariableDeclarationList *node); - - virtual bool visit(AST::VariableDeclaration *node); - virtual void endVisit(AST::VariableDeclaration *node); - - virtual bool visit(AST::EmptyStatement *node); - virtual void endVisit(AST::EmptyStatement *node); - - virtual bool visit(AST::ExpressionStatement *node); - virtual void endVisit(AST::ExpressionStatement *node); - - virtual bool visit(AST::IfStatement *node); - virtual void endVisit(AST::IfStatement *node); - - virtual bool visit(AST::DoWhileStatement *node); - virtual void endVisit(AST::DoWhileStatement *node); - - virtual bool visit(AST::WhileStatement *node); - virtual void endVisit(AST::WhileStatement *node); - - virtual bool visit(AST::ForStatement *node); - virtual void endVisit(AST::ForStatement *node); - - virtual bool visit(AST::LocalForStatement *node); - virtual void endVisit(AST::LocalForStatement *node); - - virtual bool visit(AST::ForEachStatement *node); - virtual void endVisit(AST::ForEachStatement *node); - - virtual bool visit(AST::LocalForEachStatement *node); - virtual void endVisit(AST::LocalForEachStatement *node); - - virtual bool visit(AST::ContinueStatement *node); - virtual void endVisit(AST::ContinueStatement *node); - - virtual bool visit(AST::BreakStatement *node); - virtual void endVisit(AST::BreakStatement *node); - - virtual bool visit(AST::ReturnStatement *node); - virtual void endVisit(AST::ReturnStatement *node); - - virtual bool visit(AST::WithStatement *node); - virtual void endVisit(AST::WithStatement *node); - - virtual bool visit(AST::SwitchStatement *node); - virtual void endVisit(AST::SwitchStatement *node); - - virtual bool visit(AST::CaseBlock *node); - virtual void endVisit(AST::CaseBlock *node); - - virtual bool visit(AST::CaseClauses *node); - virtual void endVisit(AST::CaseClauses *node); - - virtual bool visit(AST::CaseClause *node); - virtual void endVisit(AST::CaseClause *node); - - virtual bool visit(AST::DefaultClause *node); - virtual void endVisit(AST::DefaultClause *node); - - virtual bool visit(AST::LabelledStatement *node); - virtual void endVisit(AST::LabelledStatement *node); - - virtual bool visit(AST::ThrowStatement *node); - virtual void endVisit(AST::ThrowStatement *node); - - virtual bool visit(AST::TryStatement *node); - virtual void endVisit(AST::TryStatement *node); - - virtual bool visit(AST::Catch *node); - virtual void endVisit(AST::Catch *node); - - virtual bool visit(AST::Finally *node); - virtual void endVisit(AST::Finally *node); - - virtual bool visit(AST::FunctionDeclaration *node); - virtual void endVisit(AST::FunctionDeclaration *node); - - virtual bool visit(AST::FunctionExpression *node); - virtual void endVisit(AST::FunctionExpression *node); - - virtual bool visit(AST::FormalParameterList *node); - virtual void endVisit(AST::FormalParameterList *node); - - virtual bool visit(AST::FunctionBody *node); - virtual void endVisit(AST::FunctionBody *node); - - virtual bool visit(AST::Program *node); - virtual void endVisit(AST::Program *node); - - virtual bool visit(AST::SourceElements *node); - virtual void endVisit(AST::SourceElements *node); - - virtual bool visit(AST::FunctionSourceElement *node); - virtual void endVisit(AST::FunctionSourceElement *node); - - virtual bool visit(AST::StatementSourceElement *node); - virtual void endVisit(AST::StatementSourceElement *node); - - virtual bool visit(AST::DebuggerStatement *node); - virtual void endVisit(AST::DebuggerStatement *node); - -private: - int indentLevel(int level) - { - int was = m_indentLevel; - m_indentLevel = level; - return was; - } - - void pushIndentLevel() - { ++m_indentLevel; } - - void popIndentLevel() - { --m_indentLevel; } - - QTextStream &newlineAndIndent(); - QTextStream &startTag(const QString &name, AST::Node *locationNode = 0); - QTextStream &endTag(const QString &name); - -private: - QTextStream &out; - int m_indentLevel; - bool m_formatOutput; -}; - -} // namespace QScript - -#endif // QT_NO_SCRIPT - -QT_END_NAMESPACE - -#endif diff --git a/src/script/script.pri b/src/script/script.pri index 15e68de..2ee1a82 100644 --- a/src/script/script.pri +++ b/src/script/script.pri @@ -1,124 +1,4 @@ - -*-g++:DEFINES += Q_SCRIPT_DIRECT_CODE - -SOURCES += \ - $$PWD/qscriptasm.cpp \ - $$PWD/qscriptast.cpp \ - $$PWD/qscriptastvisitor.cpp \ - $$PWD/qscriptcompiler.cpp \ - $$PWD/qscriptecmaarray.cpp \ - $$PWD/qscriptecmaboolean.cpp \ - $$PWD/qscriptecmacore.cpp \ - $$PWD/qscriptecmadate.cpp \ - $$PWD/qscriptecmafunction.cpp \ - $$PWD/qscriptecmaglobal.cpp \ - $$PWD/qscriptecmamath.cpp \ - $$PWD/qscriptecmanumber.cpp \ - $$PWD/qscriptecmaobject.cpp \ - $$PWD/qscriptecmaregexp.cpp \ - $$PWD/qscriptecmastring.cpp \ - $$PWD/qscriptecmaerror.cpp \ - $$PWD/qscriptcontext_p.cpp \ - $$PWD/qscriptengine.cpp \ - $$PWD/qscriptengine_p.cpp \ - $$PWD/qscriptengineagent.cpp \ - $$PWD/qscriptextenumeration.cpp \ - $$PWD/qscriptextvariant.cpp \ - $$PWD/qscriptcontext.cpp \ - $$PWD/qscriptcontextinfo.cpp \ - $$PWD/qscriptfunction.cpp \ - $$PWD/qscriptgrammar.cpp \ - $$PWD/qscriptlexer.cpp \ - $$PWD/qscriptclassdata.cpp \ - $$PWD/qscriptparser.cpp \ - $$PWD/qscriptprettypretty.cpp \ - $$PWD/qscriptxmlgenerator.cpp \ - $$PWD/qscriptsyntaxchecker.cpp \ - $$PWD/qscriptstring.cpp \ - $$PWD/qscriptclass.cpp \ - $$PWD/qscriptclasspropertyiterator.cpp \ - $$PWD/qscriptvalueiteratorimpl.cpp \ - $$PWD/qscriptvalueiterator.cpp \ - $$PWD/qscriptvalueimpl.cpp \ - $$PWD/qscriptvalue.cpp - -HEADERS += \ - $$PWD/qscriptarray_p.h \ - $$PWD/qscriptasm_p.h \ - $$PWD/qscriptastfwd_p.h \ - $$PWD/qscriptast_p.h \ - $$PWD/qscriptastvisitor_p.h \ - $$PWD/qscriptbuffer_p.h \ - $$PWD/qscriptcompiler_p.h \ - $$PWD/qscriptcontext.h \ - $$PWD/qscriptcontextfwd_p.h \ - $$PWD/qscriptcontext_p.h \ - $$PWD/qscriptcontextinfo.h \ - $$PWD/qscriptcontextinfo_p.h \ - $$PWD/qscriptecmaarray_p.h \ - $$PWD/qscriptecmaboolean_p.h \ - $$PWD/qscriptecmacore_p.h \ - $$PWD/qscriptecmadate_p.h \ - $$PWD/qscriptecmafunction_p.h \ - $$PWD/qscriptecmaglobal_p.h \ - $$PWD/qscriptecmamath_p.h \ - $$PWD/qscriptecmanumber_p.h \ - $$PWD/qscriptecmaobject_p.h \ - $$PWD/qscriptecmaregexp_p.h \ - $$PWD/qscriptecmastring_p.h \ - $$PWD/qscriptecmaerror_p.h \ - $$PWD/qscriptengine.h \ - $$PWD/qscriptenginefwd_p.h \ - $$PWD/qscriptengine_p.h \ - $$PWD/qscriptengineagent.h \ - $$PWD/qscriptengineagent_p.h \ - $$PWD/qscriptable.h \ - $$PWD/qscriptable_p.h \ - $$PWD/qscriptextenumeration_p.h \ - $$PWD/qscriptextvariant_p.h \ - $$PWD/qscriptfunction_p.h \ - $$PWD/qscriptgc_p.h \ - $$PWD/qscriptglobals_p.h \ - $$PWD/qscriptgrammar_p.h \ - $$PWD/qscriptobjectdata_p.h \ - $$PWD/qscriptobjectfwd_p.h \ - $$PWD/qscriptobject_p.h \ - $$PWD/qscriptlexer_p.h \ - $$PWD/qscriptmemberfwd_p.h \ - $$PWD/qscriptmember_p.h \ - $$PWD/qscriptmemorypool_p.h \ - $$PWD/qscriptnodepool_p.h \ - $$PWD/qscriptclassinfo_p.h \ - $$PWD/qscriptparser_p.h \ - $$PWD/qscriptprettypretty_p.h \ - $$PWD/qscriptsyntaxcheckresult_p.h \ - $$PWD/qscriptxmlgenerator_p.h \ - $$PWD/qscriptrepository_p.h \ - $$PWD/qscriptsyntaxchecker_p.h \ - $$PWD/qscriptstring.h \ - $$PWD/qscriptstring_p.h \ - $$PWD/qscriptclass.h \ - $$PWD/qscriptclass_p.h \ - $$PWD/qscriptclasspropertyiterator.h \ - $$PWD/qscriptclasspropertyiterator_p.h \ - $$PWD/qscriptvalue.h \ - $$PWD/qscriptvaluefwd_p.h \ - $$PWD/qscriptvalue_p.h \ - $$PWD/qscriptvalueimplfwd_p.h \ - $$PWD/qscriptvalueimpl_p.h \ - $$PWD/qscriptvalueiteratorimpl_p.h \ - $$PWD/qscriptvalueiterator.h \ - $$PWD/qscriptvalueiterator_p.h \ - $$PWD/qscriptextensioninterface.h \ - $$PWD/qscriptextensionplugin.h \ - $$PWD/qscriptnameid_p.h \ - $$PWD/qscriptclassdata_p.h - -!contains(DEFINES, QT_NO_QOBJECT) { - HEADERS += $$PWD/qscriptextqobject_p.h - SOURCES += $$PWD/qscriptextqobject.cpp \ - $$PWD/qscriptable.cpp \ - $$PWD/qscriptextensionplugin.cpp -} else { - INCLUDEPATH += $$PWD -} +include($$PWD/api/api.pri) +include($$PWD/bridge/bridge.pri) +include($$PWD/parser/parser.pri) +include($$PWD/utils/utils.pri) diff --git a/src/script/script.pro b/src/script/script.pro index 9aa9bc2..03dc341 100644 --- a/src/script/script.pro +++ b/src/script/script.pro @@ -9,4 +9,68 @@ DEFINES += QLALR_NO_QSCRIPTGRAMMAR_DEBUG_INFO unix:QMAKE_PKGCONFIG_REQUIRES = QtCore include(../qbase.pri) + +# disable JIT for now +DEFINES += ENABLE_JIT=0 +# FIXME: shared the statically built JavaScriptCore + +# Fetch the base WebKit directory from the WEBKITDIR environment variable; +# fall back to src/3rdparty otherwise +WEBKITDIR = $$(WEBKITDIR) +isEmpty(WEBKITDIR) { + WEBKITDIR = $$PWD/../3rdparty/webkit + + # 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 +} else { + CONFIG += building-libs + CONFIG -= QTDIR_build + include($$WEBKITDIR/WebKit.pri) +} + +# Windows CE-specific stuff copied from WebCore.pro +# ### Should rather be in JavaScriptCore.pri? +wince* { + INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/os-wince + INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/os-win32 + LIBS += -lmmtimer +} + +# 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) +} + +include($$WEBKITDIR/JavaScriptCore/JavaScriptCore.pri) + +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/parser +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/bytecompiler +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/debugger +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/runtime +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/wtf +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/unicode +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/interpreter +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/jit +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/profiler +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/wrec +INCLUDEPATH += $$WEBKITDIR/JavaScriptCore/API +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 +DEFINES += NDEBUG + +INCLUDEPATH += $$PWD + include(script.pri) + diff --git a/src/script/utils/qscriptdate.cpp b/src/script/utils/qscriptdate.cpp new file mode 100644 index 0000000..4f235f6 --- /dev/null +++ b/src/script/utils/qscriptdate.cpp @@ -0,0 +1,383 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qscriptdate_p.h" + +#include <QtCore/qnumeric.h> +#include <QtCore/qstringlist.h> + +#include <math.h> + +#ifndef Q_WS_WIN +# include <time.h> +# include <sys/time.h> +#else +# include <windows.h> +#endif + +QT_BEGIN_NAMESPACE + +namespace QScript { + +qsreal ToInteger(qsreal n); + +static const qsreal HoursPerDay = 24.0; +static const qsreal MinutesPerHour = 60.0; +static const qsreal SecondsPerMinute = 60.0; +static const qsreal msPerSecond = 1000.0; +static const qsreal msPerMinute = 60000.0; +static const qsreal msPerHour = 3600000.0; +static const qsreal msPerDay = 86400000.0; + +static qsreal LocalTZA = 0.0; // initialized at startup + +static inline qsreal TimeWithinDay(qsreal t) +{ + qsreal r = ::fmod(t, msPerDay); + return (r >= 0) ? r : r + msPerDay; +} + +static inline int HourFromTime(qsreal t) +{ + int r = int(::fmod(::floor(t / msPerHour), HoursPerDay)); + return (r >= 0) ? r : r + int(HoursPerDay); +} + +static inline int MinFromTime(qsreal t) +{ + int r = int(::fmod(::floor(t / msPerMinute), MinutesPerHour)); + return (r >= 0) ? r : r + int(MinutesPerHour); +} + +static inline int SecFromTime(qsreal t) +{ + int r = int(::fmod(::floor(t / msPerSecond), SecondsPerMinute)); + return (r >= 0) ? r : r + int(SecondsPerMinute); +} + +static inline int msFromTime(qsreal t) +{ + int r = int(::fmod(t, msPerSecond)); + return (r >= 0) ? r : r + int(msPerSecond); +} + +static inline qsreal Day(qsreal t) +{ + return ::floor(t / msPerDay); +} + +static inline qsreal DaysInYear(qsreal y) +{ + if (::fmod(y, 4)) + return 365; + + else if (::fmod(y, 100)) + return 366; + + else if (::fmod(y, 400)) + return 365; + + return 366; +} + +static inline qsreal DayFromYear(qsreal y) +{ + return 365 * (y - 1970) + + ::floor((y - 1969) / 4) + - ::floor((y - 1901) / 100) + + ::floor((y - 1601) / 400); +} + +static inline qsreal TimeFromYear(qsreal y) +{ + return msPerDay * DayFromYear(y); +} + +static inline qsreal YearFromTime(qsreal t) +{ + int y = 1970; + y += (int) ::floor(t / (msPerDay * 365.2425)); + + qsreal t2 = TimeFromYear(y); + return (t2 > t) ? y - 1 : ((t2 + msPerDay * DaysInYear(y)) <= t) ? y + 1 : y; +} + +static inline bool InLeapYear(qsreal t) +{ + qsreal x = DaysInYear(YearFromTime(t)); + if (x == 365) + return 0; + + Q_ASSERT (x == 366); + return 1; +} + +static inline qsreal DayWithinYear(qsreal t) +{ + return Day(t) - DayFromYear(YearFromTime(t)); +} + +static inline qsreal MonthFromTime(qsreal t) +{ + qsreal d = DayWithinYear(t); + qsreal l = InLeapYear(t); + + if (d < 31.0) + return 0; + + else if (d < 59.0 + l) + return 1; + + else if (d < 90.0 + l) + return 2; + + else if (d < 120.0 + l) + return 3; + + else if (d < 151.0 + l) + return 4; + + else if (d < 181.0 + l) + return 5; + + else if (d < 212.0 + l) + return 6; + + else if (d < 243.0 + l) + return 7; + + else if (d < 273.0 + l) + return 8; + + else if (d < 304.0 + l) + return 9; + + else if (d < 334.0 + l) + return 10; + + else if (d < 365.0 + l) + return 11; + + return qSNaN(); // ### assert? +} + +static inline qsreal DateFromTime(qsreal t) +{ + int m = (int) ToInteger(MonthFromTime(t)); + qsreal d = DayWithinYear(t); + qsreal l = InLeapYear(t); + + switch (m) { + case 0: return d + 1.0; + case 1: return d - 30.0; + case 2: return d - 58.0 - l; + case 3: return d - 89.0 - l; + case 4: return d - 119.0 - l; + case 5: return d - 150.0 - l; + case 6: return d - 180.0 - l; + case 7: return d - 211.0 - l; + case 8: return d - 242.0 - l; + case 9: return d - 272.0 - l; + case 10: return d - 303.0 - l; + case 11: return d - 333.0 - l; + } + + return qSNaN(); // ### assert +} + +static inline qsreal WeekDay(qsreal t) +{ + qsreal r = ::fmod (Day(t) + 4.0, 7.0); + return (r >= 0) ? r : r + 7.0; +} + + +static inline qsreal MakeTime(qsreal hour, qsreal min, qsreal sec, qsreal ms) +{ + return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms; +} + +static inline qsreal DayFromMonth(qsreal month, qsreal leap) +{ + switch ((int) month) { + case 0: return 0; + case 1: return 31.0; + case 2: return 59.0 + leap; + case 3: return 90.0 + leap; + case 4: return 120.0 + leap; + case 5: return 151.0 + leap; + case 6: return 181.0 + leap; + case 7: return 212.0 + leap; + case 8: return 243.0 + leap; + case 9: return 273.0 + leap; + case 10: return 304.0 + leap; + case 11: return 334.0 + leap; + } + + return qSNaN(); // ### assert? +} + +static qsreal MakeDay(qsreal year, qsreal month, qsreal day) +{ + year += ::floor(month / 12.0); + + month = ::fmod(month, 12.0); + if (month < 0) + month += 12.0; + + qsreal t = TimeFromYear(year); + qsreal leap = InLeapYear(t); + + day += ::floor(t / msPerDay); + day += DayFromMonth(month, leap); + + return day - 1; +} + +static inline qsreal MakeDate(qsreal day, qsreal time) +{ + return day * msPerDay + time; +} + +static inline qsreal DaylightSavingTA(double t) +{ +#ifndef Q_WS_WIN + long int tt = (long int)(t / msPerSecond); + struct tm *tmtm = localtime((const time_t*)&tt); + if (! tmtm) + return 0; + return (tmtm->tm_isdst > 0) ? msPerHour : 0; +#else + Q_UNUSED(t); + /// ### implement me + return 0; +#endif +} + +static inline qsreal LocalTime(qsreal t) +{ + return t + LocalTZA + DaylightSavingTA(t); +} + +static inline qsreal UTC(qsreal t) +{ + return t - LocalTZA - DaylightSavingTA(t - LocalTZA); +} + +static inline qsreal TimeClip(qsreal t) +{ + if (! qIsFinite(t) || fabs(t) > 8.64e15) + return qSNaN(); + return ToInteger(t); +} + +static qsreal getLocalTZA() +{ +#ifndef Q_WS_WIN + struct tm* t; + time_t curr; + time(&curr); + t = localtime(&curr); + time_t locl = mktime(t); + t = gmtime(&curr); + time_t globl = mktime(t); + return double(locl - globl) * 1000.0; +#else + TIME_ZONE_INFORMATION tzInfo; + GetTimeZoneInformation(&tzInfo); + return -tzInfo.Bias * 60.0 * 1000.0; +#endif +} + +/*! + \internal + + Converts the QDateTime \dt to an ECMA Date value (in UTC form). +*/ +qsreal FromDateTime(const QDateTime &dt) +{ + if (!dt.isValid()) + return qSNaN(); + if (!LocalTZA) // ### move + LocalTZA = getLocalTZA(); + QDate date = dt.date(); + QTime taim = dt.time(); + int year = date.year(); + int month = date.month() - 1; + int day = date.day(); + int hours = taim.hour(); + int mins = taim.minute(); + int secs = taim.second(); + int ms = taim.msec(); + double t = MakeDate(MakeDay(year, month, day), + MakeTime(hours, mins, secs, ms)); + if (dt.timeSpec() == Qt::LocalTime) + t = UTC(t); + return TimeClip(t); +} + +/*! + \internal + + Converts the ECMA Date value \tt (in UTC form) to QDateTime + according to \a spec. +*/ +QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec) +{ + if (qIsNaN(t)) + return QDateTime(); + if (!LocalTZA) // ### move + LocalTZA = getLocalTZA(); + if (spec == Qt::LocalTime) + t = LocalTime(t); + int year = int(YearFromTime(t)); + int month = int(MonthFromTime(t) + 1); + int day = int(DateFromTime(t)); + int hours = HourFromTime(t); + int mins = MinFromTime(t); + int secs = SecFromTime(t); + int ms = msFromTime(t); + return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec); +} + +} // namespace QScript + +QT_END_NAMESPACE diff --git a/src/script/qscriptvalueiterator_p.h b/src/script/utils/qscriptdate_p.h index 3c0e3b6..218650d 100644 --- a/src/script/qscriptvalueiterator_p.h +++ b/src/script/utils/qscriptdate_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QSCRIPTVALUEITERATOR_P_H -#define QSCRIPTVALUEITERATOR_P_H +#ifndef QSCRIPTDATE_P_H +#define QSCRIPTDATE_P_H // // W A R N I N G @@ -53,23 +53,18 @@ // We mean it. // +#include <QtCore/qdatetime.h> + QT_BEGIN_NAMESPACE -class QScriptValueIteratorImpl; +typedef double qsreal; -class QScriptValueIterator; -class QScriptValueIteratorPrivate +namespace QScript { - Q_DECLARE_PUBLIC(QScriptValueIterator) -public: - QScriptValueIteratorPrivate(); - ~QScriptValueIteratorPrivate(); - - QScriptValueIterator *q_ptr; - - QScriptValueIteratorImpl *it; -}; + qsreal FromDateTime(const QDateTime &dt); + QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec); +} QT_END_NAMESPACE -#endif // QSCRIPTVALUEITERATOR_P_H +#endif diff --git a/src/script/utils/utils.pri b/src/script/utils/utils.pri new file mode 100644 index 0000000..d8302d5 --- /dev/null +++ b/src/script/utils/utils.pri @@ -0,0 +1,5 @@ +SOURCES += \ + $$PWD/qscriptdate.cpp + +HEADERS += \ + $$PWD/qscriptdate_p.h diff --git a/src/scripttools/debugging/qscriptdebugger.cpp b/src/scripttools/debugging/qscriptdebugger.cpp index 40f4d6c..c9bc650 100644 --- a/src/scripttools/debugging/qscriptdebugger.cpp +++ b/src/scripttools/debugging/qscriptdebugger.cpp @@ -993,7 +993,8 @@ public: m_debugger->scriptsModel->addScript(scriptId, data); // ### could be slow, might want to do this in a separate thread - QString xml = qt_scriptToXml(data.contents(), data.baseLineNumber()); +// Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); + QString xml; // = qt_scriptToXml(data.contents(), data.baseLineNumber()); QScriptXmlParser::Result extraInfo = QScriptXmlParser::parse(xml); m_debugger->scriptsModel->addExtraScriptInfo( scriptId, extraInfo.functionsInfo, extraInfo.executableLineNumbers); diff --git a/src/scripttools/debugging/qscriptdebuggeragent.cpp b/src/scripttools/debugging/qscriptdebuggeragent.cpp index a263f8a..492b79f 100644 --- a/src/scripttools/debugging/qscriptdebuggeragent.cpp +++ b/src/scripttools/debugging/qscriptdebuggeragent.cpp @@ -88,7 +88,7 @@ QScriptDebuggerAgentPrivate *QScriptDebuggerAgentPrivate::get( */ QScriptDebuggerAgent::QScriptDebuggerAgent( QScriptDebuggerBackendPrivate *backend, QScriptEngine *engine) - : QScriptEngineAgent(*new QScriptDebuggerAgentPrivate, engine) + : QScriptEngineAgent(engine), d_ptr(new QScriptDebuggerAgentPrivate()) { Q_D(QScriptDebuggerAgent); d->backend = backend; @@ -110,6 +110,7 @@ QScriptDebuggerAgent::~QScriptDebuggerAgent() Q_D(QScriptDebuggerAgent); if (d->backend) d->backend->agentDestroyed(this); + delete d; } /*! diff --git a/src/scripttools/debugging/qscriptdebuggeragent_p.h b/src/scripttools/debugging/qscriptdebuggeragent_p.h index da06726..805efc1 100644 --- a/src/scripttools/debugging/qscriptdebuggeragent_p.h +++ b/src/scripttools/debugging/qscriptdebuggeragent_p.h @@ -125,6 +125,7 @@ public: const QVariant &argument = QVariant()); private: + QScriptDebuggerAgentPrivate *d_ptr; Q_DECLARE_PRIVATE(QScriptDebuggerAgent) Q_DISABLE_COPY(QScriptDebuggerAgent) }; diff --git a/src/scripttools/debugging/qscriptdebuggeragent_p_p.h b/src/scripttools/debugging/qscriptdebuggeragent_p_p.h index 7c229a4..09d0121 100644 --- a/src/scripttools/debugging/qscriptdebuggeragent_p_p.h +++ b/src/scripttools/debugging/qscriptdebuggeragent_p_p.h @@ -53,8 +53,6 @@ // We mean it. // -#include <private/qscriptengineagent_p.h> - #include <QtScript/qscriptvalue.h> #include <QtCore/qdatetime.h> #include <QtCore/qhash.h> @@ -68,9 +66,7 @@ QT_BEGIN_NAMESPACE class QScriptDebuggerAgent; class QScriptDebuggerAgentPrivate - : public QScriptEngineAgentPrivate { - Q_DECLARE_PUBLIC(QScriptDebuggerAgent) public: enum State { NoState, diff --git a/src/scripttools/debugging/qscriptdebuggerconsoleglobalobject.cpp b/src/scripttools/debugging/qscriptdebuggerconsoleglobalobject.cpp index adb4f33..73049d5 100644 --- a/src/scripttools/debugging/qscriptdebuggerconsoleglobalobject.cpp +++ b/src/scripttools/debugging/qscriptdebuggerconsoleglobalobject.cpp @@ -361,6 +361,7 @@ void QScriptDebuggerConsoleGlobalObject::warning(const QString &text, int lineNumber, int columnNumber) { Q_D(QScriptDebuggerConsoleGlobalObject); + Q_ASSERT(d->messageHandler != 0); d->messageHandler->message(QtWarningMsg, text, fileName, lineNumber, columnNumber); } @@ -369,6 +370,7 @@ void QScriptDebuggerConsoleGlobalObject::message(const QString &text, int lineNumber, int columnNumber) { Q_D(QScriptDebuggerConsoleGlobalObject); + Q_ASSERT(d->messageHandler != 0); d->messageHandler->message(QtDebugMsg, text, fileName, lineNumber, columnNumber); } @@ -377,6 +379,7 @@ void QScriptDebuggerConsoleGlobalObject::error(const QString &text, int lineNumber, int columnNumber) { Q_D(QScriptDebuggerConsoleGlobalObject); + Q_ASSERT(d->messageHandler != 0); d->messageHandler->message(QtCriticalMsg, text, fileName, lineNumber, columnNumber); } diff --git a/src/scripttools/debugging/qscriptdebuggerstackmodel.cpp b/src/scripttools/debugging/qscriptdebuggerstackmodel.cpp index 651b062..a6bb78b 100644 --- a/src/scripttools/debugging/qscriptdebuggerstackmodel.cpp +++ b/src/scripttools/debugging/qscriptdebuggerstackmodel.cpp @@ -131,11 +131,14 @@ QVariant QScriptDebuggerStackModel::data(const QModelIndex &index, int role) con name = QString::fromLatin1("<anonymous>"); return name; } else if (index.column() == 2) { - if (info.lineNumber() == -1) - return QString::fromLatin1("<native>"); QString fn = QFileInfo(info.fileName()).fileName(); - if (fn.isEmpty()) - fn = QString::fromLatin1("<anonymous script, id=%0>").arg(info.scriptId()); + if (fn.isEmpty()) { + if (info.functionType() == QScriptContextInfo::ScriptFunction) + fn = QString::fromLatin1("<anonymous script, id=%0>").arg(info.scriptId()); + else + fn = QString::fromLatin1("<native>"); + + } return QString::fromLatin1("%0:%1").arg(fn).arg(info.lineNumber()); } } else if (role == Qt::ToolTipRole) { diff --git a/src/scripttools/debugging/qscriptedit.cpp b/src/scripttools/debugging/qscriptedit.cpp index 4f76695..a0c7199 100644 --- a/src/scripttools/debugging/qscriptedit.cpp +++ b/src/scripttools/debugging/qscriptedit.cpp @@ -156,6 +156,16 @@ void QScriptEdit::setExecutableLineNumbers(const QSet<int> &lineNumbers) m_executableLineNumbers = lineNumbers; } +bool QScriptEdit::isExecutableLine(int lineNumber) const +{ +#if 0 // ### enable me once we have information about the script again + return m_executableLineNumbers.contains(lineNumber); +#else + Q_UNUSED(lineNumber); + return true; +#endif +} + int QScriptEdit::currentLineNumber() const { return textCursor().blockNumber() + m_baseLineNumber; @@ -342,7 +352,7 @@ void QScriptEdit::extraAreaPaintEvent(QPaintEvent *e) icon.paint(&painter, r, Qt::AlignCenter); } - if (!m_executableLineNumbers.contains(lineNumber)) + if (!isExecutableLine(lineNumber)) painter.setPen(pal.color(QPalette::Mid)); else painter.setPen(QColor(Qt::darkCyan)); @@ -369,7 +379,7 @@ void QScriptEdit::extraAreaMouseEvent(QMouseEvent *e) if (e->type() == QEvent::MouseMove && e->buttons() == 0) { // mouse tracking bool hand = (e->pos().x() <= markWidth); int lineNumber = cursor.blockNumber() + m_baseLineNumber; - hand = hand && m_executableLineNumbers.contains(lineNumber); + hand = hand && isExecutableLine(lineNumber); #ifndef QT_NO_CURSOR if (hand != (m_extraArea->cursor().shape() == Qt::PointingHandCursor)) m_extraArea->setCursor(hand ? Qt::PointingHandCursor : Qt::ArrowCursor); @@ -379,7 +389,7 @@ void QScriptEdit::extraAreaMouseEvent(QMouseEvent *e) if (e->type() == QEvent::MouseButtonPress) { if (e->button() == Qt::LeftButton) { int lineNumber = cursor.blockNumber() + m_baseLineNumber; - bool executable = m_executableLineNumbers.contains(lineNumber); + bool executable = isExecutableLine(lineNumber); if ((e->pos().x() <= markWidth) && executable) m_extraAreaToggleBlockNumber = cursor.blockNumber(); else @@ -394,7 +404,7 @@ void QScriptEdit::extraAreaMouseEvent(QMouseEvent *e) } } else if (e->button() == Qt::RightButton) { int lineNumber = cursor.blockNumber() + m_baseLineNumber; - if (!m_executableLineNumbers.contains(lineNumber)) + if (!isExecutableLine(lineNumber)) return; bool has = m_breakpoints.contains(lineNumber); QMenu *popup = new QMenu(); diff --git a/src/scripttools/debugging/qscriptedit_p.h b/src/scripttools/debugging/qscriptedit_p.h index 2db2d7c..ee3dfc1 100644 --- a/src/scripttools/debugging/qscriptedit_p.h +++ b/src/scripttools/debugging/qscriptedit_p.h @@ -75,6 +75,7 @@ public: int executionLineNumber() const; void setExecutionLineNumber(int lineNumber, bool error); void setExecutableLineNumbers(const QSet<int> &lineNumbers); + bool isExecutableLine(int lineNumber) const; int currentLineNumber() const; void gotoLine(int lineNumber); diff --git a/src/scripttools/scripttools.pro b/src/scripttools/scripttools.pro index faf0936a..0ba5948 100644 --- a/src/scripttools/scripttools.pro +++ b/src/scripttools/scripttools.pro @@ -9,4 +9,5 @@ unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui QtScript include(../qbase.pri) + include(debugging/debugging.pri) diff --git a/src/src.pro b/src/src.pro index 54ed6da..8af75c7 100644 --- a/src/src.pro +++ b/src/src.pro @@ -4,9 +4,9 @@ TEMPLATE = subdirs unset(SRC_SUBDIRS) win32:SRC_SUBDIRS += src_winmain wince*:{ - SRC_SUBDIRS += src_corelib src_xml src_gui src_sql src_network src_script src_testlib + SRC_SUBDIRS += src_corelib src_xml src_gui src_sql src_network src_testlib } else { - SRC_SUBDIRS += src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic src_corelib src_xml src_network src_gui src_sql src_script src_testlib + SRC_SUBDIRS += src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic src_corelib src_xml src_network src_gui src_sql src_testlib !vxworks:contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_qt3support contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus !cross_compile { @@ -28,6 +28,7 @@ contains(QT_CONFIG, webkit) { #exists($$QT_SOURCE_TREE/src/3rdparty/webkit/JavaScriptCore/JavaScriptCore.pro): SRC_SUBDIRS += src_javascriptcore SRC_SUBDIRS += src_webkit } +contains(QT_CONFIG, script): SRC_SUBDIRS += src_script contains(QT_CONFIG, scripttools): SRC_SUBDIRS += src_scripttools SRC_SUBDIRS += src_plugins diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp index ace4cb8..ef2dd5a 100644 --- a/src/svg/qsvggenerator.cpp +++ b/src/svg/qsvggenerator.cpp @@ -921,7 +921,8 @@ void QSvgPaintEngine::drawImage(const QRectF &r, const QImage &image, stream() << "x=\""<<r.x()<<"\" " "y=\""<<r.y()<<"\" " "width=\""<<r.width()<<"\" " - "height=\""<<r.height()<<"\" "; + "height=\""<<r.height()<<"\" " + "preserveAspectRatio=\"none\" "; QByteArray data; QBuffer buffer(&data); diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index a79e4a0..adfe468 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -2012,6 +2012,14 @@ static bool parseAimateMotionNode(QSvgNode *parent, return true; } +static void parseNumberTriplet(QVector<qreal> &values, const QChar *&s) +{ + QVector<qreal> list = parseNumbersList(s); + values << list; + for (int i = 3 - list.size(); i > 0; --i) + values.append(0.0); +} + static bool parseAnimateTransformNode(QSvgNode *parent, const QXmlStreamAttributes &attributes, QSvgHandler *handler) @@ -2025,28 +2033,47 @@ static bool parseAnimateTransformNode(QSvgNode *parent, QString fillStr = attributes.value(QLatin1String("fill")).toString(); QString fromStr = attributes.value(QLatin1String("from")).toString(); QString toStr = attributes.value(QLatin1String("to")).toString(); + QString byStr = attributes.value(QLatin1String("by")).toString(); + QString addtv = attributes.value(QLatin1String("additive")).toString(); + + QSvgAnimateTransform::Additive additive = QSvgAnimateTransform::Replace; + if (addtv == QLatin1String("sum")) + additive = QSvgAnimateTransform::Sum; QVector<qreal> vals; if (values.isEmpty()) { - const QChar *s = fromStr.constData(); - QVector<qreal> lst = parseNumbersList(s); - while (lst.count() < 3) - lst.append(0.0); - vals << lst; - - s = toStr.constData(); - lst = parseNumbersList(s); - while (lst.count() < 3) - lst.append(0.0); - vals << lst; + const QChar *s; + if (fromStr.isEmpty()) { + if (!byStr.isEmpty()) { + // By-animation. + additive = QSvgAnimateTransform::Sum; + vals.append(0.0); + vals.append(0.0); + vals.append(0.0); + parseNumberTriplet(vals, s = byStr.constData()); + } else { + // To-animation not defined. + return false; + } + } else { + if (!toStr.isEmpty()) { + // From-to-animation. + parseNumberTriplet(vals, s = fromStr.constData()); + parseNumberTriplet(vals, s = toStr.constData()); + } else if (!byStr.isEmpty()) { + // From-by-animation. + parseNumberTriplet(vals, s = fromStr.constData()); + parseNumberTriplet(vals, s = byStr.constData()); + for (int i = vals.size() - 3; i < vals.size(); ++i) + vals[i] += vals[i - 3]; + } else { + return false; + } + } } else { const QChar *s = values.constData(); while (s && *s != QLatin1Char(0)) { - QVector<qreal> tmpVals = parseNumbersList(s); - while (tmpVals.count() < 3) - tmpVals.append(0.0); - - vals << tmpVals; + parseNumberTriplet(vals, s); if (*s == QLatin1Char(0)) break; ++s; @@ -2088,7 +2115,7 @@ static bool parseAnimateTransformNode(QSvgNode *parent, } QSvgAnimateTransform *anim = new QSvgAnimateTransform(begin, end, 0); - anim->setArgs(type, vals); + anim->setArgs(type, additive, vals); anim->setFreeze(fillStr == QLatin1String("freeze")); anim->setRepeatCount( (repeatStr == QLatin1String("indefinite"))? -1 : diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 1ecf870..e1a7049 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -509,10 +509,25 @@ void QSvgStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgExtra //animated transforms have to be applied //_after_ the original object transformations if (!animateTransforms.isEmpty()) { - QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr; - for (itr = animateTransforms.constBegin(); itr != animateTransforms.constEnd(); - ++itr) { - (*itr)->apply(p, rect, node, states); + qreal totalTimeElapsed = node->document()->currentElapsed(); + // Find the last animateTransform with additive="replace", since this will override all + // previous animateTransforms. + QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr = animateTransforms.constEnd(); + do { + --itr; + if ((*itr)->animActive(totalTimeElapsed) + && (*itr)->additiveType() == QSvgAnimateTransform::Replace) { + // An animateTransform with additive="replace" will replace the transform attribute. + if (transform) + transform->revert(p, states); + break; + } + } while (itr != animateTransforms.constBegin()); + + // Apply the animateTransforms after and including the last one with additive="replace". + for (; itr != animateTransforms.constEnd(); ++itr) { + if ((*itr)->animActive(totalTimeElapsed)) + (*itr)->apply(p, rect, node, states); } } @@ -558,13 +573,15 @@ void QSvgStyle::revert(QPainter *p, QSvgExtraStates &states) //animated transforms need to be reverted _before_ //the native transforms if (!animateTransforms.isEmpty()) { - QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr; - itr = animateTransforms.constBegin(); - //only need to rever the first one because that - //one has the original world matrix for the primitve - if (itr != animateTransforms.constEnd()) { - (*itr)->revert(p, states); + QList<QSvgRefCounter<QSvgAnimateTransform> >::const_iterator itr = animateTransforms.constBegin(); + for (; itr != animateTransforms.constEnd(); ++itr) { + if ((*itr)->transformApplied()) { + (*itr)->revert(p, states); + break; + } } + for (; itr != animateTransforms.constEnd(); ++itr) + (*itr)->clearTransformApplied(); } if (transform) { @@ -587,15 +604,16 @@ void QSvgStyle::revert(QPainter *p, QSvgExtraStates &states) QSvgAnimateTransform::QSvgAnimateTransform(int startMs, int endMs, int byMs ) : QSvgStyleProperty(), m_from(startMs), m_to(endMs), m_by(byMs), - m_type(Empty), m_count(0), m_finished(false) + m_type(Empty), m_count(0), m_finished(false), m_additive(Replace), m_transformApplied(false) { m_totalRunningTime = m_to - m_from; } -void QSvgAnimateTransform::setArgs(TransformType type, const QVector<qreal> &args) +void QSvgAnimateTransform::setArgs(TransformType type, Additive additive, const QVector<qreal> &args) { m_type = type; m_args = args; + m_additive = additive; Q_ASSERT(!(args.count()%3)); m_count = args.count() / 3; } @@ -604,15 +622,14 @@ void QSvgAnimateTransform::apply(QPainter *p, const QRectF &, QSvgNode *node, QS { m_oldWorldTransform = p->worldTransform(); resolveMatrix(node); - if (!m_finished || m_freeze) - p->setWorldTransform(m_transform, true); + p->setWorldTransform(m_transform, true); + m_transformApplied = true; } void QSvgAnimateTransform::revert(QPainter *p, QSvgExtraStates &) { - if (!m_finished || m_freeze) { - p->setWorldTransform(m_oldWorldTransform, false /* don't combine */); - } + p->setWorldTransform(m_oldWorldTransform, false /* don't combine */); + m_transformApplied = false; } void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) @@ -622,11 +639,14 @@ void QSvgAnimateTransform::resolveMatrix(QSvgNode *node) if (totalTimeElapsed < m_from || m_finished) return; - qreal animationFrame = (totalTimeElapsed - m_from) / m_to; + qreal animationFrame = 0; + if (m_totalRunningTime != 0) { + animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime; - if (m_repeatCount >= 0 && m_repeatCount < animationFrame) { - m_finished = true; - animationFrame = m_repeatCount; + if (m_repeatCount >= 0 && m_repeatCount < animationFrame) { + m_finished = true; + animationFrame = m_repeatCount; + } } qreal percentOfAnimation = animationFrame; diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index c18a265..056b73b 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -250,7 +250,7 @@ public: { return m_style; } - + void setGradientId(const QString &Id) { m_gradientId = Id; @@ -529,20 +529,56 @@ public: SkewX, SkewY }; + enum Additive + { + Sum, + Replace + }; public: QSvgAnimateTransform(int startMs, int endMs, int by = 0); - void setArgs(TransformType type, const QVector<qreal> &args); + void setArgs(TransformType type, Additive additive, const QVector<qreal> &args); void setFreeze(bool freeze); void setRepeatCount(qreal repeatCount); virtual void apply(QPainter *p, const QRectF &, QSvgNode *node, QSvgExtraStates &states); virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; + QSvgAnimateTransform::Additive additiveType() const + { + return m_additive; + } + + bool animActive(qreal totalTimeElapsed) + { + if (totalTimeElapsed < m_from) + return false; + if (m_freeze || m_repeatCount < 0) // fill="freeze" or repeat="indefinite" + return true; + if (m_totalRunningTime == 0) + return false; + qreal animationFrame = (totalTimeElapsed - m_from) / m_totalRunningTime; + if (animationFrame > m_repeatCount) + return false; + return true; + } + + bool transformApplied() const + { + return m_transformApplied; + } + + // Call this instead of revert if you know that revert is unnecessary. + void clearTransformApplied() + { + m_transformApplied = false; + } + protected: void resolveMatrix(QSvgNode *node); private: qreal m_from, m_to, m_by; qreal m_totalRunningTime; TransformType m_type; + Additive m_additive; QVector<qreal> m_args; int m_count; QTransform m_transform; @@ -550,6 +586,7 @@ private: bool m_finished; bool m_freeze; qreal m_repeatCount; + bool m_transformApplied; }; |