bool JSEventListener::reportError(const String& message, const String& url, int lineNumber)
{
    JSLock lock(SilenceAssertionsOnly);

    JSObject* jsFunction = this->jsFunction();
    if (!jsFunction)
        return false;

    JSDOMGlobalObject* globalObject = m_globalObject;
    if (!globalObject)
        return false;

    ExecState* exec = globalObject->globalExec();

    CallData callData;
    CallType callType = jsFunction->getCallData(callData);

    if (callType == CallTypeNone)
        return false;

    MarkedArgumentBuffer args;
    args.append(jsString(exec, message));
    args.append(jsString(exec, url));
    args.append(jsNumber(exec, lineNumber));

    // If this event handler is the first JavaScript to execute, then the
    // dynamic global object should be set to the global object of the
    // window in which the event occurred.
    JSGlobalData* globalData = globalObject->globalData();
    DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);    

    JSValue thisValue = globalObject->toThisObject(exec);

    globalObject->globalData()->timeoutChecker.start();
    JSValue returnValue = call(exec, jsFunction, callType, callData, thisValue, args);
    globalObject->globalData()->timeoutChecker.stop();

    // If an error occurs while handling the script error, it should be bubbled up.
    if (exec->hadException()) {
        exec->clearException();
        return false;
    }
    
    bool bubbleEvent;
    return returnValue.getBoolean(bubbleEvent) && !bubbleEvent;
}
void JSWorkerContextErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
    ASSERT(scriptExecutionContext);
    if (!scriptExecutionContext)
        return;

    JSLock lock(SilenceAssertionsOnly);

    JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, isolatedWorld());
    if (!globalObject)
        return;

    ExecState* exec = globalObject->globalExec();

    CallData callData;
    CallType callType = jsFunction->getCallData(callData);

    if (callType != CallTypeNone) {

        ref();

        Event* savedEvent = globalObject->currentEvent();
        globalObject->setCurrentEvent(event);

        ASSERT(event->isErrorEvent());
        ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event);

        MarkedArgumentBuffer args;
        args.append(jsString(exec, errorEvent->message()));
        args.append(jsString(exec, errorEvent->filename()));
        args.append(jsNumber(exec, errorEvent->lineno()));

        JSGlobalData* globalData = globalObject->globalData();
        DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);    

        JSValue thisValue = globalObject->toThisObject(exec);

        globalData->timeoutChecker.start();
        JSValue returnValue = JSC::call(exec, jsFunction, callType, callData, thisValue, args);
        globalData->timeoutChecker.stop();

        globalObject->setCurrentEvent(savedEvent);

        if (exec->hadException())
            reportCurrentException(exec);
        else {
            bool retvalbool;
            if (returnValue.getBoolean(retvalbool) && !retvalbool)
                event->preventDefault();
        }

        deref();
    }
}
void JSErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
    if (!event->hasInterface(eventNames().interfaceForErrorEvent))
        return JSEventListener::handleEvent(scriptExecutionContext, event);

    ASSERT(scriptExecutionContext);
    if (!scriptExecutionContext)
        return;

    ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event);

    JSLock lock(SilenceAssertionsOnly);

    JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, isolatedWorld());
    if (!globalObject)
        return;

    ExecState* exec = globalObject->globalExec();

    CallData callData;
    CallType callType = jsFunction->methodTable()->getCallData(jsFunction, callData);

    if (callType != CallTypeNone) {
        RefPtr<JSErrorHandler> protectedctor(this);

        Event* savedEvent = globalObject->currentEvent();
        globalObject->setCurrentEvent(event);

        MarkedArgumentBuffer args;
        args.append(jsString(exec, errorEvent->message()));
        args.append(jsString(exec, errorEvent->filename()));
        args.append(jsNumber(errorEvent->lineno()));

        JSGlobalData& globalData = globalObject->globalData();
        DynamicGlobalObjectScope globalObjectScope(globalData, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject);

        JSValue thisValue = globalObject->methodTable()->toThisObject(globalObject, exec);

        globalData.timeoutChecker.start();
        JSValue returnValue = scriptExecutionContext->isDocument()
            ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, thisValue, args)
            : JSC::call(exec, jsFunction, callType, callData, thisValue, args);
        globalData.timeoutChecker.stop();

        globalObject->setCurrentEvent(savedEvent);

        if (exec->hadException())
            reportCurrentException(exec);
        else {
            if (returnValue.isTrue())
                event->preventDefault();
        }
    }
}
void JSMutationCallback::call(const Vector<RefPtr<MutationRecord> >& mutations, MutationObserver* observer)
{
    if (!canInvokeCallback())
        return;

    RefPtr<JSMutationCallback> protect(this);

    JSLockHolder lock(m_isolatedWorld->globalData());

    if (!m_callback)
        return;

    JSValue callback = m_callback.get();
    CallData callData;
    CallType callType = getCallData(callback, callData);
    if (callType == CallTypeNone) {
        ASSERT_NOT_REACHED();
        return;
    }

    ScriptExecutionContext* context = scriptExecutionContext();
    if (!context)
        return;
    ASSERT(context->isDocument());

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get());
    ExecState* exec = globalObject->globalExec();

    JSValue jsObserver = toJS(exec, globalObject, observer);

    MarkedArgumentBuffer args;
    args.append(jsArray(exec, globalObject, mutations));
    args.append(jsObserver);

    globalObject->globalData().timeoutChecker.start();
    InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);

    JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args);

    InspectorInstrumentation::didCallFunction(cookie);
    globalObject->globalData().timeoutChecker.stop();

    if (exec->hadException())
        reportCurrentException(exec);
}
Exemple #5
0
bool JSEventListener::reportError(ScriptExecutionContext* context, const String& message, const String& url, int lineNumber)
{
    JSLock lock(SilenceAssertionsOnly);

    JSObject* jsFunction = this->jsFunction(context);
    if (!jsFunction)
        return false;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, m_isolatedWorld.get());
    ExecState* exec = globalObject->globalExec();

    CallData callData;
    CallType callType = jsFunction->getCallData(callData);

    if (callType == CallTypeNone)
        return false;

    MarkedArgumentBuffer args;
    args.append(jsString(exec, message));
    args.append(jsString(exec, url));
    args.append(jsNumber(exec, lineNumber));

    JSGlobalData* globalData = globalObject->globalData();
    DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);    

    JSValue thisValue = globalObject->toThisObject(exec);

    globalData->timeoutChecker.start();
    JSValue returnValue = JSC::call(exec, jsFunction, callType, callData, thisValue, args);
    globalData->timeoutChecker.stop();

    // If an error occurs while handling the script error, it should be bubbled up.
    if (exec->hadException()) {
        exec->clearException();
        return false;
    }
    
    bool bubbleEvent;
    return returnValue.getBoolean(bubbleEvent) && !bubbleEvent;
}
Exemple #6
0
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
    ASSERT(scriptExecutionContext);
    if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionTerminated())
        return;

    JSLock lock(SilenceAssertionsOnly);

    JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld.get());
    if (!globalObject)
        return;

    if (scriptExecutionContext->isDocument()) {
        JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
        Frame* frame = window->impl()->frame();
        if (!frame)
            return;
        // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>.
        // FIXME: A better fix for this may be to change DOMWindow::frame() to not return a frame the detached window used to be in.
        if (frame->domWindow() != window->impl())
            return;
        // FIXME: Is this check needed for other contexts?
        ScriptController* script = frame->script();
        if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused())
            return;
    }

    ExecState* exec = globalObject->globalExec();
    JSValue handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent"));

    CallData callData;
    CallType callType = handleEventFunction.getCallData(callData);
    if (callType == CallTypeNone) {
        handleEventFunction = JSValue();
        callType = jsFunction->getCallData(callData);
    }

    if (callType != CallTypeNone) {
        ref();

        MarkedArgumentBuffer args;
        args.append(toJS(exec, globalObject, event));

        Event* savedEvent = globalObject->currentEvent();
        globalObject->setCurrentEvent(event);

        JSGlobalData* globalData = globalObject->globalData();
        DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);

        globalData->timeoutChecker.start();
        JSValue retval = handleEventFunction
            ? JSC::call(exec, handleEventFunction, callType, callData, jsFunction, args)
            : JSC::call(exec, jsFunction, callType, callData, toJS(exec, globalObject, event->currentTarget()), args);
        globalData->timeoutChecker.stop();

        globalObject->setCurrentEvent(savedEvent);

        if (exec->hadException())
#if PLATFORM(APOLLO)
            reportApolloException(globalObject);
#else
            reportCurrentException(exec);
#endif
        else {
            if (!retval.isUndefinedOrNull() && event->storesResultAsString())
Exemple #7
0
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
    ASSERT(scriptExecutionContext);
    if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden())
        return;

    JSLock lock(SilenceAssertionsOnly);

    JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld.get());
    if (!globalObject)
        return;

    if (scriptExecutionContext->isDocument()) {
        JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
        Frame* frame = window->impl()->frame();
        if (!frame)
            return;
        // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>.
        // FIXME: A better fix for this may be to change DOMWindow::frame() to not return a frame the detached window used to be in.
        if (frame->domWindow() != window->impl())
            return;
        // FIXME: Is this check needed for other contexts?
        ScriptController* script = frame->script();
        if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused())
            return;
    }

    ExecState* exec = globalObject->globalExec();
    JSValue handleEventFunction = jsFunction;

    CallData callData;
    CallType callType = getCallData(handleEventFunction, callData);
    // If jsFunction is not actually a function, see if it implements the EventListener interface and use that
    if (callType == CallTypeNone) {
        handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent"));
        callType = getCallData(handleEventFunction, callData);
    }

    if (callType != CallTypeNone) {
        RefPtr<JSEventListener> protect(this);

        MarkedArgumentBuffer args;
        args.append(toJS(exec, globalObject, event));

        Event* savedEvent = globalObject->currentEvent();
        globalObject->setCurrentEvent(event);

        JSGlobalData& globalData = globalObject->globalData();
        DynamicGlobalObjectScope globalObjectScope(globalData, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject);

        globalData.timeoutChecker.start();
        JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction;
        JSValue retval = scriptExecutionContext->isDocument()
                         ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args)
                         : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args);
        globalData.timeoutChecker.stop();

        globalObject->setCurrentEvent(savedEvent);

#if ENABLE(WORKERS)
        if (scriptExecutionContext->isWorkerContext()) {
            bool terminatorCausedException = (exec->hadException() && isTerminatedExecutionException(exec->exception()));
            if (terminatorCausedException || globalData.terminator.shouldTerminate())
                static_cast<WorkerContext*>(scriptExecutionContext)->script()->forbidExecution();
        }
#endif

        if (exec->hadException()) {
            event->target()->uncaughtExceptionInEventHandler();
            reportCurrentException(exec);
        } else {
            if (!retval.isUndefinedOrNull() && event->storesResultAsString())
                event->storeResult(ustringToString(retval.toString(exec)->value(exec)));
            if (m_isAttribute) {
                if (retval.isFalse())
                    event->preventDefault();
            }
        }
    }
}
void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
{
    JSLock lock(SilenceAssertionsOnly);

    JSObject* jsFunction = this->jsFunction();
    if (!jsFunction)
        return;

    JSDOMGlobalObject* globalObject = m_globalObject;
    // Null check as clearGlobalObject() can clear this and we still get called back by
    // xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275
    // FIXME: Is this check still necessary? Requests are supposed to be stopped before clearGlobalObject() is called.
    ASSERT(globalObject);
    if (!globalObject)
        return;

    ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();
    if (!scriptExecutionContext)
        return;

    if (scriptExecutionContext->isDocument()) {
        JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
        Frame* frame = window->impl()->frame();
        if (!frame)
            return;
        // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>.
        // FIXME: A better fix for this may be to change DOMWindow::frame() to not return a frame the detached window used to be in.
        if (frame->domWindow() != window->impl())
            return;
        // FIXME: Is this check needed for other contexts?
        ScriptController* script = frame->script();
        if (!script->isEnabled() || script->isPaused())
            return;
    }

    ExecState* exec = globalObject->globalExec();

    JSValue handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent"));
    CallData callData;
    CallType callType = handleEventFunction.getCallData(callData);
    if (callType == CallTypeNone) {
        handleEventFunction = JSValue();
        callType = jsFunction->getCallData(callData);
    }

    if (callType != CallTypeNone) {
        ref();

        MarkedArgumentBuffer args;
        args.append(toJS(exec, globalObject, event));

        Event* savedEvent = globalObject->currentEvent();
        globalObject->setCurrentEvent(event);

        // If this event handler is the first JavaScript to execute, then the
        // dynamic global object should be set to the global object of the
        // window in which the event occurred.
        JSGlobalData* globalData = globalObject->globalData();
        DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);

        JSValue retval;
        if (handleEventFunction) {
            globalObject->globalData()->timeoutChecker.start();
            retval = call(exec, handleEventFunction, callType, callData, jsFunction, args);
        } else {
            JSValue thisValue;
            if (isWindowEvent)
                thisValue = globalObject->toThisObject(exec);
            else
                thisValue = toJS(exec, globalObject, event->currentTarget());
            globalObject->globalData()->timeoutChecker.start();
            retval = call(exec, jsFunction, callType, callData, thisValue, args);
        }
        globalObject->globalData()->timeoutChecker.stop();

        globalObject->setCurrentEvent(savedEvent);

        if (exec->hadException())
            reportCurrentException(exec);
        else {
            if (!retval.isUndefinedOrNull() && event->storesResultAsString())
                event->storeResult(retval.toString(exec));
            if (m_isAttribute) {
                bool retvalbool;
                if (retval.getBoolean(retvalbool) && !retvalbool)
                    event->preventDefault();
            }
        }

        if (scriptExecutionContext->isDocument())
            Document::updateStyleForAllDocuments();
        deref();
    }
}