mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 807226 part 3. Change event handlers to call their WebIDL callbacks directly. r=smaug
This commit is contained in:
parent
bf51164dc8
commit
d15bb45f3e
@ -24,6 +24,8 @@
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include "nspr.h" // PR_fprintf
|
||||
@ -38,6 +40,7 @@ public:
|
||||
static EventListenerCounter sEventListenerCounter;
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
/*
|
||||
@ -149,115 +152,98 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
if (!target || !mContext || !mHandler.HasEventHandler())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> iargv;
|
||||
if (mHandler.Type() == nsEventHandler::eOnError) {
|
||||
MOZ_ASSERT(mEventName == nsGkAtoms::onerror);
|
||||
|
||||
nsString errorMsg, file;
|
||||
EventOrString msgOrEvent;
|
||||
Optional<nsAString> fileName;
|
||||
Optional<uint32_t> lineNumber;
|
||||
Optional<uint32_t> columnNumber;
|
||||
|
||||
bool handledScriptError = false;
|
||||
if (mEventName == nsGkAtoms::onerror) {
|
||||
NS_ENSURE_TRUE(aEvent, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsEvent* event = aEvent->GetInternalNSEvent();
|
||||
if (event->message == NS_LOAD_ERROR &&
|
||||
event->eventStructType == NS_SCRIPT_ERROR_EVENT) {
|
||||
nsScriptErrorEvent *scriptEvent =
|
||||
static_cast<nsScriptErrorEvent*>(event);
|
||||
// Create a temp argv for the error event.
|
||||
iargv = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// Append the event args.
|
||||
nsCOMPtr<nsIWritableVariant>
|
||||
var(do_CreateInstance(NS_VARIANT_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = var->SetAsWString(scriptEvent->errorMsg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = iargv->AppendElement(var, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// filename
|
||||
var = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = var->SetAsWString(scriptEvent->fileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = iargv->AppendElement(var, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// line number
|
||||
var = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = var->SetAsUint32(scriptEvent->lineNr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = iargv->AppendElement(var, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
errorMsg = scriptEvent->errorMsg;
|
||||
msgOrEvent.SetAsString() = static_cast<nsAString*>(&errorMsg);
|
||||
|
||||
handledScriptError = true;
|
||||
file = scriptEvent->fileName;
|
||||
fileName = &file;
|
||||
|
||||
lineNumber.Construct();
|
||||
lineNumber.Value() = scriptEvent->lineNr;
|
||||
} else {
|
||||
msgOrEvent.SetAsEvent() = aEvent;
|
||||
}
|
||||
|
||||
nsRefPtr<OnErrorEventHandlerNonNull> handler =
|
||||
mHandler.OnErrorEventHandler();
|
||||
ErrorResult rv;
|
||||
bool handled = handler->Call(mTarget, msgOrEvent, fileName, lineNumber,
|
||||
columnNumber, rv);
|
||||
if (rv.Failed()) {
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
aEvent->PreventDefault();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!handledScriptError) {
|
||||
iargv = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_TRUE(iargv != nullptr, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = iargv->AppendElement(aEvent, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (mHandler.Type() == nsEventHandler::eOnBeforeUnload) {
|
||||
MOZ_ASSERT(mEventName == nsGkAtoms::onbeforeunload);
|
||||
|
||||
// mContext is the same context which event listener manager pushes
|
||||
// to JS context stack.
|
||||
#ifdef DEBUG
|
||||
JSContext* cx = nullptr;
|
||||
nsCOMPtr<nsIJSContextStack> stack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
NS_ASSERTION(stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx &&
|
||||
GetScriptContextFromJSContext(cx) == mContext,
|
||||
"JSEventListener has wrong script context?");
|
||||
#endif
|
||||
nsCOMPtr<nsIVariant> vrv;
|
||||
xpc_UnmarkGrayObject(mScopeObject);
|
||||
rv = mContext->CallEventHandler(mTarget, mScopeObject,
|
||||
mHandler.Ptr()->Callable(),
|
||||
iargv, getter_AddRefs(vrv));
|
||||
nsRefPtr<BeforeUnloadEventHandlerNonNull> handler =
|
||||
mHandler.BeforeUnloadEventHandler();
|
||||
ErrorResult rv;
|
||||
nsString retval;
|
||||
handler->Call(mTarget, aEvent, retval, rv);
|
||||
if (rv.Failed()) {
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
uint16_t dataType = nsIDataType::VTYPE_VOID;
|
||||
if (vrv)
|
||||
vrv->GetDataType(&dataType);
|
||||
nsCOMPtr<nsIDOMBeforeUnloadEvent> beforeUnload = do_QueryInterface(aEvent);
|
||||
NS_ENSURE_STATE(beforeUnload);
|
||||
|
||||
if (mEventName == nsGkAtoms::onbeforeunload) {
|
||||
nsCOMPtr<nsIDOMBeforeUnloadEvent> beforeUnload = do_QueryInterface(aEvent);
|
||||
NS_ENSURE_STATE(beforeUnload);
|
||||
if (!DOMStringIsNull(retval)) {
|
||||
aEvent->PreventDefault();
|
||||
|
||||
if (dataType != nsIDataType::VTYPE_VOID) {
|
||||
aEvent->PreventDefault();
|
||||
nsAutoString text;
|
||||
beforeUnload->GetReturnValue(text);
|
||||
nsAutoString text;
|
||||
beforeUnload->GetReturnValue(text);
|
||||
|
||||
// Set the text in the beforeUnload event as long as it wasn't
|
||||
// already set (through event.returnValue, which takes
|
||||
// precedence over a value returned from a JS function in IE)
|
||||
if ((dataType == nsIDataType::VTYPE_DOMSTRING ||
|
||||
dataType == nsIDataType::VTYPE_CHAR_STR ||
|
||||
dataType == nsIDataType::VTYPE_WCHAR_STR ||
|
||||
dataType == nsIDataType::VTYPE_STRING_SIZE_IS ||
|
||||
dataType == nsIDataType::VTYPE_WSTRING_SIZE_IS ||
|
||||
dataType == nsIDataType::VTYPE_CSTRING ||
|
||||
dataType == nsIDataType::VTYPE_ASTRING)
|
||||
&& text.IsEmpty()) {
|
||||
vrv->GetAsDOMString(text);
|
||||
beforeUnload->SetReturnValue(text);
|
||||
}
|
||||
}
|
||||
} else if (dataType == nsIDataType::VTYPE_BOOL) {
|
||||
// If the handler returned false and its sense is not reversed,
|
||||
// or the handler returned true and its sense is reversed from
|
||||
// the usual (false means cancel), then prevent default.
|
||||
bool brv;
|
||||
if (NS_SUCCEEDED(vrv->GetAsBool(&brv)) &&
|
||||
brv == (mEventName == nsGkAtoms::onerror ||
|
||||
mEventName == nsGkAtoms::onmouseover)) {
|
||||
aEvent->PreventDefault();
|
||||
// Set the text in the beforeUnload event as long as it wasn't
|
||||
// already set (through event.returnValue, which takes
|
||||
// precedence over a value returned from a JS function in IE)
|
||||
if (text.IsEmpty()) {
|
||||
beforeUnload->SetReturnValue(retval);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
MOZ_ASSERT(mHandler.Type() == nsEventHandler::eNormal);
|
||||
ErrorResult rv;
|
||||
nsRefPtr<EventHandlerNonNull> handler = mHandler.EventHandler();
|
||||
JS::Value retval = handler->Call(mTarget, aEvent, rv);
|
||||
if (rv.Failed()) {
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
// If the handler returned false and its sense is not reversed,
|
||||
// or the handler returned true and its sense is reversed from
|
||||
// the usual (false means cancel), then prevent default.
|
||||
if (retval.isBoolean() &&
|
||||
retval.toBoolean() == (mEventName == nsGkAtoms::onerror ||
|
||||
mEventName == nsGkAtoms::onmouseover)) {
|
||||
aEvent->PreventDefault();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user