QVariant KJSProxyImpl::evaluate(QString filename, int baseLine, const QString&str, const DOM::Node &n, Completion *completion) { // evaluate code. Returns the JS return value or an invalid QVariant // if there was none, an error occured or the type couldn't be converted. initScript(); // inlineCode is true for <a href="javascript:doSomething()"> // and false for <script>doSomething()</script>. Check if it has the // expected value in all cases. // See smart window.open policy for where this is used. bool inlineCode = filename.isNull(); //kdDebug(6070) << "KJSProxyImpl::evaluate inlineCode=" << inlineCode << endl; #ifdef KJS_DEBUGGER if (inlineCode) filename = "(unknown file)"; if (KJSDebugWin::instance()) { KJSDebugWin::instance()->attach(m_script); KJSDebugWin::instance()->setNextSourceInfo(filename,baseLine); // KJSDebugWin::instance()->setMode(KJSDebugWin::Step); } #else Q_UNUSED(baseLine); #endif m_script->setInlineCode(inlineCode); Window* window = Window::retrieveWindow( m_part ); KJS::Value thisNode = n.isNull() ? Window::retrieve( m_part ) : getDOMNode(m_script->globalExec(),n); UString code( str ); KJSCPUGuard guard; guard.start(); Completion comp = m_script->evaluate(code, thisNode); guard.stop(); bool success = ( comp.complType() == Normal ) || ( comp.complType() == ReturnValue ); if (completion) *completion = comp; #ifdef KJS_DEBUGGER // KJSDebugWin::instance()->setCode(QString::null); #endif window->afterScriptExecution(); // let's try to convert the return value if (success && !comp.value().isNull()) return ValueToVariant( m_script->globalExec(), comp.value()); else { if ( comp.complType() == Throw ) { UString msg = comp.value().toString(m_script->globalExec()); kdWarning(6070) << "Script threw exception: " << msg.qstring() << endl; } return QVariant(); } }
void KJSProxyImpl::clear() { // clear resources allocated by the interpreter, and make it ready to be used by another page // We have to keep it, so that the Window object for the part remains the same. // (we used to delete and re-create it, previously) if (m_script) { #ifdef KJS_DEBUGGER //KJSDebugWin *debugWin = KJSDebugWin::instance(); //if (debugWin && debugWin->currentScript() == m_script) { // debugWin->setMode(KJSDebugWin::Stop); // debugWin->leaveSession(); //} #endif m_script->clear(); Window *win = static_cast<Window *>(m_script->globalObject().imp()); if (win) { win->clear( m_script->globalExec() ); // re-add "debug", clear() removed it m_script->globalObject().put(m_script->globalExec(), "debug", Value(new TestFunctionImp()), Internal); if ( !win->part().isNull() ) applyUserAgent(); } } }
KJS::JSValue* toJS(KJS::ExecState* exec, Event* event) { KJS::JSLock lock; if (!event) return KJS::jsNull(); KJS::ScriptInterpreter* interp = static_cast<KJS::ScriptInterpreter*>(exec->dynamicInterpreter()); KJS::DOMObject* ret = interp->getDOMObject(event); if (ret) return ret; if (event->isKeyboardEvent()) ret = new JSKeyboardEvent(exec, static_cast<KeyboardEvent*>(event)); else if (event->isTextEvent()) ret = new JSTextEvent(exec, static_cast<TextEvent*>(event)); else if (event->isMouseEvent()) ret = new JSMouseEvent(exec, static_cast<MouseEvent*>(event)); else if (event->isWheelEvent()) ret = new JSWheelEvent(exec, static_cast<WheelEvent*>(event)); else if (event->isUIEvent()) ret = new JSUIEvent(exec, static_cast<UIEvent*>(event)); else if (event->isMutationEvent()) ret = new JSMutationEvent(exec, static_cast<MutationEvent*>(event)); else if (event->isOverflowEvent()) ret = new JSOverflowEvent(exec, static_cast<OverflowEvent*>(event)); else ret = new JSEvent(exec, event); interp->putDOMObject(event, ret); return ret; }
KJS::JSValue* toJS(KJS::ExecState* exec, CSSValue* value) { if (!value) return KJS::jsNull(); KJS::ScriptInterpreter* interp = static_cast<KJS::ScriptInterpreter*>(exec->dynamicInterpreter()); KJS::DOMObject* ret = interp->getDOMObject(value); if (ret) return ret; if (value->isValueList()) ret = new JSCSSValueList(exec, static_cast<CSSValueList*>(value)); #if ENABLE(SVG) else if (value->isSVGColor()) ret = new JSSVGColor(exec, static_cast<SVGColor*>(value)); else if (value->isSVGPaint()) ret = new JSSVGPaint(exec, static_cast<SVGPaint*>(value)); #endif else if (value->isPrimitiveValue()) ret = new JSCSSPrimitiveValue(exec, static_cast<CSSPrimitiveValue*>(value)); else ret = new JSCSSValue(exec, value); interp->putDOMObject(value, ret); return ret; }
void KJSProxyImpl::finishedWithEvent(const DOM::Event &event) { // This is called when the DOM implementation has finished with a particular event. This // is the case in sitations where an event has been created just for temporary usage, // e.g. an image load or mouse move. Once the event has been dispatched, it is forgotten // by the DOM implementation and so does not need to be cached still by the interpreter m_script->forgetDOMObject(event.handle()); }
KJS::JSValue* toJS(KJS::ExecState* exec, StyleSheet* styleSheet) { if (!styleSheet) return KJS::jsNull(); KJS::ScriptInterpreter* interp = static_cast<KJS::ScriptInterpreter*>(exec->dynamicInterpreter()); KJS::DOMObject* ret = interp->getDOMObject(styleSheet); if (ret) return ret; if (styleSheet->isCSSStyleSheet()) ret = new JSCSSStyleSheet(exec, static_cast<CSSStyleSheet*>(styleSheet)); else ret = new JSStyleSheet(exec, styleSheet); interp->putDOMObject(styleSheet, ret); return ret; }
DOM::EventListener *KJSProxyImpl::createHTMLEventHandler(QString sourceUrl, QString code) { #ifdef KJS_DEBUGGER if (KJSDebugWin::instance()) KJSDebugWin::instance()->setNextSourceInfo(sourceUrl,m_handlerLineno); #else Q_UNUSED(sourceUrl); #endif initScript(); //KJS::Constructor constr(KJS::Global::current().get("Function").imp()); KJS::Object constr = m_script->builtinFunction(); KJS::List args; args.append(KJS::String("event")); args.append(KJS::String(code)); Object handlerFunc = constr.construct(m_script->globalExec(), args); // ### is globalExec ok ? return KJS::Window::retrieveWindow(m_part)->getJSEventListener(handlerFunc,true); }
void KJSProxyImpl::initScript() { if (m_script) return; // Build the global object - which is a Window instance Object globalObject( new Window(m_part) ); // Create a KJS interpreter for this part m_script = new KJS::ScriptInterpreter(globalObject, m_part); static_cast<ObjectImp*>(globalObject.imp())->setPrototype(m_script->builtinObjectPrototype()); #ifdef KJS_DEBUGGER //m_script->setDebuggingEnabled(m_debugEnabled); #endif //m_script->enableDebug(); globalObject.put(m_script->globalExec(), "debug", Value(new TestFunctionImp()), Internal); applyUserAgent(); }
void JSEventListener::handleEvent(DOM::Event &evt) { KHTMLPart *part = qobject_cast<KHTMLPart*>(static_cast<Window*>(win.get())->part()); KJSProxy *proxy = 0L; if (part) proxy = part->jScript(); if (proxy && listener && listener->implementsCall()) { #ifdef KJS_DEBUGGER //### This is the wrong place to do this --- we need // a more global/general stategy to prevent unwanted event loop recursion issues. if (proxy->debugEnabled() && DebugWindow::window()->inSession()) return; #endif ref(); KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter()); ExecState *exec = interpreter->globalExec(); List args; args.append(getDOMEvent(exec,evt.handle())); JSObject *thisObj = 0; // Check whether handler is a function or an object with handleEvent method if (listener == compareListenerImp) { // Set "this" to the event's current target thisObj = getEventTarget(exec,evt.handle()->currentTarget())->getObject(); } else { thisObj = compareListenerImp; } if ( !thisObj ) { // ### can this still happen? eventTarget should be window on Window events now. thisObj = win; } Window *window = static_cast<Window*>(win.get()); // Set the event we're handling in the Window object window->setCurrentEvent( evt.handle() ); // ... and in the interpreter interpreter->setCurrentEvent( &evt ); interpreter->startCPUGuard(); JSValue *retval = listener->call(exec, thisObj, args); interpreter->stopCPUGuard(); window->setCurrentEvent( 0 ); interpreter->setCurrentEvent( 0 ); if ( exec->hadException() ) exec->clearException(); else if (html) { QVariant ret = ValueToVariant(exec, retval); if (ret.type() == QVariant::Bool && ret.toBool() == false) evt.preventDefault(); } window->afterScriptExecution(); deref(); } }
void KJSProxyImpl::applyUserAgent() { assert( m_script ); QString userAgent = KProtocolManager::userAgentForHost(m_part->url().host()); if (userAgent.find(QString::fromLatin1("Microsoft")) >= 0 || userAgent.find(QString::fromLatin1("MSIE")) >= 0) { m_script->setCompatMode(Interpreter::IECompat); #ifdef KJS_VERBOSE kdDebug() << "Setting IE compat mode" << endl; #endif } else // If we find "Mozilla" but not "(compatible, ...)" we are a real Netscape if (userAgent.find(QString::fromLatin1("Mozilla")) >= 0 && userAgent.find(QString::fromLatin1("compatible")) == -1) { m_script->setCompatMode(Interpreter::NetscapeCompat); #ifdef KJS_VERBOSE kdDebug() << "Setting NS compat mode" << endl; #endif } }
void JSLazyEventListener::parseCode() const { if (!parsed) { KHTMLPart *part = qobject_cast<KHTMLPart*>(static_cast<Window*>(win.get())->part()); KJSProxy *proxy = 0L; if (part) proxy = part->jScript(); if (proxy) { KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter()); ExecState *exec = interpreter->globalExec(); //KJS::Constructor constr(KJS::Global::current().get("Function").imp()); KJS::FunctionObjectImp *constr = static_cast<KJS::FunctionObjectImp*>(interpreter->builtinFunction()); KJS::List args; if (svg) args.append(jsString("evt")); else args.append(jsString("event")); args.append(jsString(code)); listener = constr->construct(exec, args, Identifier(UString(name)), url, lineNum); // ### is globalExec ok ? compareListenerImp = listener; if (exec->hadException()) { exec->clearException(); // failed to parse, so let's just make this listener a no-op listener = 0; } else if (!listener->inherits(&DeclaredFunctionImp::info)) { listener = 0;// Error creating function } else { DeclaredFunctionImp *declFunc = static_cast<DeclaredFunctionImp*>(listener.get()); if (originalNode) { // Add the event's home element to the scope // (and the document, and the form - see KJS::HTMLElement::eventHandlerScope) ScopeChain scope = declFunc->scope(); JSObject *thisObj = getDOMNode(exec, originalNode)->getObject(); if (thisObj) { static_cast<DOMNode*>(thisObj)->pushEventHandlerScope(exec, scope); declFunc->setScope(scope); } } } } // no more need to keep the unparsed code around code.clear(); if (listener) { static_cast<Window*>(win.get())->jsEventListeners.insert(QPair<void*, bool>(compareListenerImp.get(), true), (KJS::JSEventListener *)(this)); } parsed = true; } }