зеркало из https://github.com/mozilla/gecko-dev.git
Bug 941876 part 2. When compiling script attached to DOM elements, tell the JS engine what element is involved and which attribute is involved, if any. r=smaug
This commit is contained in:
Родитель
eeac8ea60c
Коммит
bb3703e06b
|
@ -999,7 +999,7 @@ nsScriptLoader::GetScriptGlobalObject()
|
|||
|
||||
void
|
||||
nsScriptLoader::FillCompileOptionsForRequest(nsScriptLoadRequest *aRequest,
|
||||
JS::Handle<JSObject *> scopeChain,
|
||||
JS::Handle<JSObject *> aScopeChain,
|
||||
JS::CompileOptions *aOptions)
|
||||
{
|
||||
// It's very important to use aRequest->mURI, not the final URI of the channel
|
||||
|
@ -1008,13 +1008,28 @@ nsScriptLoader::FillCompileOptionsForRequest(nsScriptLoadRequest *aRequest,
|
|||
|
||||
aOptions->setFileAndLine(aRequest->mURL.get(), aRequest->mLineNo);
|
||||
aOptions->setVersion(JSVersion(aRequest->mJSVersion));
|
||||
aOptions->setCompileAndGo(JS_IsGlobalObject(scopeChain));
|
||||
aOptions->setCompileAndGo(JS_IsGlobalObject(aScopeChain));
|
||||
if (aRequest->mHasSourceMapURL) {
|
||||
aOptions->setSourceMapURL(aRequest->mSourceMapURL.get());
|
||||
}
|
||||
if (aRequest->mOriginPrincipal) {
|
||||
aOptions->setOriginPrincipals(nsJSPrincipals::get(aRequest->mOriginPrincipal));
|
||||
}
|
||||
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> elementVal(cx);
|
||||
MOZ_ASSERT(aRequest->mElement);
|
||||
// XXXbz this is super-fragile, because the code that _uses_ the
|
||||
// JS::CompileOptions is nowhere near us, but we have to coordinate
|
||||
// compartments with it... and in particular, it will compile in the
|
||||
// compartment of aScopeChain, so we want to wrap into that compartment as
|
||||
// well.
|
||||
if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, aScopeChain,
|
||||
aRequest->mElement, &elementVal,
|
||||
/* aAllowWrapping = */ true))) {
|
||||
MOZ_ASSERT(elementVal.isObject());
|
||||
aOptions->setElement(&elementVal.toObject());
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -282,7 +282,7 @@ private:
|
|||
|
||||
already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
|
||||
void FillCompileOptionsForRequest(nsScriptLoadRequest *aRequest,
|
||||
JS::Handle<JSObject *> scopeChain,
|
||||
JS::Handle<JSObject *> aScopeChain,
|
||||
JS::CompileOptions *aOptions);
|
||||
|
||||
nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -789,24 +791,28 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
|
|||
AutoPushJSContext cx(context->GetNativeContext());
|
||||
JS::Rooted<JSObject*> handler(cx);
|
||||
|
||||
JS::Rooted<JSObject*> scope(cx, listener->GetEventScope());
|
||||
|
||||
nsIAtom* attrName = aListenerStruct->mTypeAtom;
|
||||
|
||||
if (aListenerStruct->mHandlerIsString) {
|
||||
// OK, we didn't find an existing compiled event handler. Flag us
|
||||
// as not a string so we don't keep trying to compile strings
|
||||
// which can't be compiled
|
||||
aListenerStruct->mHandlerIsString = false;
|
||||
|
||||
// mTarget may not be an nsIContent if it's a window and we're
|
||||
// mTarget may not be an Element if it's a window and we're
|
||||
// getting an inline event listener forwarded from <html:body> or
|
||||
// <html:frameset> or <xul:window> or the like.
|
||||
// XXX I don't like that we have to reference content from
|
||||
// here. The alternative is to store the event handler string on
|
||||
// the nsIJSEventListener itself, and that still doesn't address
|
||||
// the arg names issue.
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mTarget);
|
||||
nsCOMPtr<Element> element = do_QueryInterface(mTarget);
|
||||
MOZ_ASSERT(element || aBody, "Where will we get our body?");
|
||||
nsAutoString handlerBody;
|
||||
const nsAString* body = aBody;
|
||||
if (content && !aBody) {
|
||||
nsIAtom* attrName = aListenerStruct->mTypeAtom;
|
||||
if (!aBody) {
|
||||
if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGLoad)
|
||||
attrName = nsGkAtoms::onload;
|
||||
else if (aListenerStruct->mTypeAtom == nsGkAtoms::onSVGUnload)
|
||||
|
@ -828,29 +834,24 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
|
|||
else if (aListenerStruct->mTypeAtom == nsGkAtoms::onendEvent)
|
||||
attrName = nsGkAtoms::onend;
|
||||
|
||||
content->GetAttr(kNameSpaceID_None, attrName, handlerBody);
|
||||
element->GetAttr(kNameSpaceID_None, attrName, handlerBody);
|
||||
body = &handlerBody;
|
||||
aElement = element;
|
||||
}
|
||||
|
||||
uint32_t lineNo = 0;
|
||||
nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
|
||||
if (doc) {
|
||||
nsIURI *uri = doc->GetDocumentURI();
|
||||
if (uri) {
|
||||
uri->GetSpec(url);
|
||||
lineNo = 1;
|
||||
}
|
||||
MOZ_ASSERT(body);
|
||||
MOZ_ASSERT(aElement);
|
||||
nsIURI *uri = aElement->OwnerDoc()->GetDocumentURI();
|
||||
if (uri) {
|
||||
uri->GetSpec(url);
|
||||
lineNo = 1;
|
||||
}
|
||||
|
||||
uint32_t argCount;
|
||||
const char **argNames;
|
||||
// If no content, then just use kNameSpaceID_None for the
|
||||
// namespace ID. In practice, it doesn't matter since SVG is
|
||||
// the only thing with weird arg names and SVG doesn't map event
|
||||
// listeners to the window.
|
||||
nsContentUtils::GetEventArgNames(content ?
|
||||
content->GetNameSpaceID() :
|
||||
kNameSpaceID_None,
|
||||
nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(),
|
||||
aListenerStruct->mTypeAtom,
|
||||
&argCount, &argNames);
|
||||
|
||||
|
@ -859,6 +860,25 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
|
|||
options.setFileAndLine(url.get(), lineNo)
|
||||
.setVersion(SCRIPTVERSION_DEFAULT);
|
||||
|
||||
JS::Rooted<JS::Value> targetVal(cx);
|
||||
// Go ahead and wrap into the current compartment of cx directly.
|
||||
JS::Rooted<JSObject*> wrapScope(cx, JS::CurrentGlobalOrNull(cx));
|
||||
if (WrapNewBindingObject(cx, wrapScope, aElement, &targetVal)) {
|
||||
MOZ_ASSERT(targetVal.isObject());
|
||||
|
||||
nsDependentAtomString str(attrName);
|
||||
// Most of our names are short enough that we don't even have to malloc
|
||||
// the JS string stuff, so don't worry about playing games with
|
||||
// refcounting XPCOM stringbuffers.
|
||||
JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx,
|
||||
str.BeginReading(),
|
||||
str.Length()));
|
||||
NS_ENSURE_TRUE(jsStr, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
options.setElement(&targetVal.toObject())
|
||||
.setElementAttributeName(jsStr);
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> handlerFun(cx);
|
||||
result = nsJSUtils::CompileFunction(cx, JS::NullPtr(), options,
|
||||
nsAtomCString(aListenerStruct->mTypeAtom),
|
||||
|
@ -872,7 +892,6 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
|
|||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
|
||||
// Bind it
|
||||
JS::Rooted<JSObject*> boundHandler(cx);
|
||||
JS::Rooted<JSObject*> scope(cx, listener->GetEventScope());
|
||||
context->BindCompiledEventHandler(mTarget, scope, handler, &boundHandler);
|
||||
aListenerStruct = nullptr;
|
||||
// Note - We pass null for aIncumbentGlobal below. We could also pass the
|
||||
|
|
Загрузка…
Ссылка в новой задаче