/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ScriptElement.h" #include "ScriptLoader.h" #include "mozilla/BasicEvents.h" #include "mozilla/EventDispatcher.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/Element.h" #include "nsContentUtils.h" #include "nsPresContext.h" #include "nsIParser.h" #include "nsGkAtoms.h" #include "nsContentSink.h" using namespace mozilla; using namespace mozilla::dom; NS_IMETHODIMP ScriptElement::ScriptAvailable(nsresult aResult, nsIScriptElement* aElement, bool aIsInlineClassicScript, nsIURI* aURI, int32_t aLineNo) { if (!aIsInlineClassicScript && NS_FAILED(aResult)) { nsCOMPtr parser = do_QueryReferent(mCreatorParser); if (parser) { parser->IncrementScriptNestingLevel(); } nsresult rv = FireErrorEvent(); if (parser) { parser->DecrementScriptNestingLevel(); } return rv; } return NS_OK; } /* virtual */ nsresult ScriptElement::FireErrorEvent() { nsCOMPtr cont = do_QueryInterface((nsIScriptElement*)this); return nsContentUtils::DispatchTrustedEvent( cont->OwnerDoc(), cont, u"error"_ns, CanBubble::eNo, Cancelable::eNo); } NS_IMETHODIMP ScriptElement::ScriptEvaluated(nsresult aResult, nsIScriptElement* aElement, bool aIsInline) { nsresult rv = NS_OK; if (!aIsInline) { nsCOMPtr cont = do_QueryInterface((nsIScriptElement*)this); RefPtr presContext = nsContentUtils::GetContextForContent(cont); nsEventStatus status = nsEventStatus_eIgnore; EventMessage message = NS_SUCCEEDED(aResult) ? eLoad : eLoadError; WidgetEvent event(true, message); // Load event doesn't bubble. event.mFlags.mBubbles = (message != eLoad); EventDispatcher::Dispatch(cont, presContext, &event, nullptr, &status); } return rv; } void ScriptElement::CharacterDataChanged(nsIContent* aContent, const CharacterDataChangeInfo&) { MaybeProcessScript(); } void ScriptElement::AttributeChanged(Element* aElement, int32_t aNameSpaceID, nsAtom* aAttribute, int32_t aModType, const nsAttrValue* aOldValue) { MaybeProcessScript(); } void ScriptElement::ContentAppended(nsIContent* aFirstNewContent) { MaybeProcessScript(); } void ScriptElement::ContentInserted(nsIContent* aChild) { MaybeProcessScript(); } bool ScriptElement::MaybeProcessScript() { nsCOMPtr cont = do_QueryInterface((nsIScriptElement*)this); NS_ASSERTION(cont->DebugGetSlots()->mMutationObservers.Contains(this), "You forgot to add self as observer"); if (mAlreadyStarted || !mDoneAddingChildren || !cont->GetComposedDoc() || mMalformed || !HasScriptContent()) { return false; } Document* ownerDoc = cont->OwnerDoc(); FreezeExecutionAttrs(ownerDoc); mAlreadyStarted = true; nsCOMPtr parser = ((nsIScriptElement*)this)->GetCreatorParser(); if (parser) { nsCOMPtr sink = parser->GetContentSink(); if (sink) { nsCOMPtr parserDoc = do_QueryInterface(sink->GetTarget()); if (ownerDoc != parserDoc) { // Willful violation of HTML5 as of 2010-12-01 return false; } } } RefPtr loader = ownerDoc->ScriptLoader(); return loader->ProcessScriptElement(this); }