예제 #1
0
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();
  }
}
예제 #2
0
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();
    }
  }
}
예제 #3
0
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;
}
예제 #5
0
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());
}
예제 #6
0
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;
}
예제 #7
0
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);
}
예제 #8
0
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();
}
예제 #9
0
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();
  }
}
예제 #10
0
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
    }
}
예제 #11
0
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;
  }
}