Files
UXP-mirror/dom/html/HTMLScriptElement.cpp
T

364 lines
9.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsIDocument.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsContentUtils.h"
#include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator()
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsIXPConnect.h"
#include "nsServiceManagerUtils.h"
#include "nsError.h"
#include "nsIArray.h"
#include "nsTArray.h"
#include "nsDOMJSUtils.h"
#include "nsISupportsImpl.h"
#include "mozilla/dom/HTMLScriptElement.h"
#include "mozilla/dom/HTMLScriptElementBinding.h"
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Script)
namespace mozilla {
namespace dom {
JSObject*
HTMLScriptElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
{
return HTMLScriptElementBinding::Wrap(aCx, this, aGivenProto);
}
HTMLScriptElement::HTMLScriptElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLElement(aNodeInfo)
, ScriptElement(aFromParser)
{
AddMutationObserver(this);
}
HTMLScriptElement::~HTMLScriptElement()
{
}
NS_IMPL_ISUPPORTS_INHERITED(HTMLScriptElement, nsGenericHTMLElement,
nsIDOMHTMLScriptElement,
nsIScriptLoaderObserver,
nsIScriptElement,
nsIMutationObserver)
nsresult
HTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers)
{
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (GetComposedDoc()) {
MaybeProcessScript();
}
return NS_OK;
}
bool
HTMLScriptElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::crossorigin) {
ParseCORSValue(aValue, aResult);
return true;
}
if (aAttribute == nsGkAtoms::integrity) {
aResult.ParseStringOrAtom(aValue);
return true;
}
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}
nsresult
HTMLScriptElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
{
*aResult = nullptr;
already_AddRefed<mozilla::dom::NodeInfo> ni = RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
HTMLScriptElement* it = new HTMLScriptElement(ni, NOT_FROM_PARSER);
nsCOMPtr<nsINode> kungFuDeathGrip = it;
nsresult rv = const_cast<HTMLScriptElement*>(this)->CopyInnerTo(it);
NS_ENSURE_SUCCESS(rv, rv);
// The clone should be marked evaluated if we are.
it->mAlreadyStarted = mAlreadyStarted;
it->mLineNumber = mLineNumber;
it->mMalformed = mMalformed;
kungFuDeathGrip.swap(*aResult);
return NS_OK;
}
NS_IMETHODIMP
HTMLScriptElement::GetText(nsAString& aValue)
{
if (!nsContentUtils::GetNodeTextContent(this, false, aValue, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
NS_IMETHODIMP
HTMLScriptElement::SetText(const nsAString& aValue)
{
ErrorResult rv;
SetText(aValue, rv);
return rv.StealNSResult();
}
void
HTMLScriptElement::SetText(const nsAString& aValue, ErrorResult& rv)
{
rv = nsContentUtils::SetNodeTextContent(this, aValue, true);
}
NS_IMPL_STRING_ATTR(HTMLScriptElement, Charset, charset)
NS_IMPL_BOOL_ATTR(HTMLScriptElement, Defer, defer)
// If this ever gets changed to return "" if the attr value is "" (see
// https://github.com/whatwg/html/issues/1739 for why it might not get changed),
// it may be worth it to use GetSrc instead of GetAttr and manual
// NewURIWithDocumentCharset in FreezeUriAsyncDefer.
NS_IMPL_URI_ATTR(HTMLScriptElement, Src, src)
NS_IMPL_STRING_ATTR(HTMLScriptElement, Type, type)
NS_IMPL_STRING_ATTR(HTMLScriptElement, HtmlFor, _for)
NS_IMPL_STRING_ATTR(HTMLScriptElement, Event, event)
void
HTMLScriptElement::SetCharset(const nsAString& aCharset, ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::charset, aCharset, rv);
}
void
HTMLScriptElement::SetDefer(bool aDefer, ErrorResult& rv)
{
SetHTMLBoolAttr(nsGkAtoms::defer, aDefer, rv);
}
bool
HTMLScriptElement::Defer()
{
return GetBoolAttr(nsGkAtoms::defer);
}
void
HTMLScriptElement::SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, rv);
}
void
HTMLScriptElement::SetType(const nsAString& aType, ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::type, aType, rv);
}
void
HTMLScriptElement::SetHtmlFor(const nsAString& aHtmlFor, ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::_for, aHtmlFor, rv);
}
void
HTMLScriptElement::SetEvent(const nsAString& aEvent, ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::event, aEvent, rv);
}
nsresult
HTMLScriptElement::GetAsync(bool* aValue)
{
*aValue = Async();
return NS_OK;
}
bool
HTMLScriptElement::Async()
{
return mForceAsync || GetBoolAttr(nsGkAtoms::async);
}
nsresult
HTMLScriptElement::SetAsync(bool aValue)
{
ErrorResult rv;
SetAsync(aValue, rv);
return rv.StealNSResult();
}
void
HTMLScriptElement::SetAsync(bool aValue, ErrorResult& rv)
{
mForceAsync = false;
SetHTMLBoolAttr(nsGkAtoms::async, aValue, rv);
}
bool
HTMLScriptElement::NoModule()
{
return GetBoolAttr(nsGkAtoms::nomodule);
}
void
HTMLScriptElement::SetNoModule(bool aValue, ErrorResult& aRv)
{
SetHTMLBoolAttr(nsGkAtoms::nomodule, aValue, aRv);
}
nsresult
HTMLScriptElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
nsIPrincipal* aMaybeScriptedPrincipal,
bool aNotify)
{
if (aName == nsGkAtoms::async && aNameSpaceID == kNameSpaceID_None) {
mForceAsync = false;
}
if (aName == nsGkAtoms::src && aNameSpaceID == kNameSpaceID_None) {
mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
this, aValue ? aValue->GetStringValue() : EmptyString(),
aMaybeScriptedPrincipal);
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aOldValue,
aMaybeScriptedPrincipal,
aNotify);
}
NS_IMETHODIMP
HTMLScriptElement::GetInnerHTML(nsAString& aInnerHTML)
{
if (!nsContentUtils::GetNodeTextContent(this, false, aInnerHTML, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
void
HTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML,
ErrorResult& aError)
{
aError = nsContentUtils::SetNodeTextContent(this, aInnerHTML, true);
}
// variation of this code in nsSVGScriptElement - check if changes
// need to be transfered when modifying
bool
HTMLScriptElement::GetScriptType(nsAString& type)
{
return GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
}
void
HTMLScriptElement::GetScriptText(nsAString& text)
{
GetText(text);
}
void
HTMLScriptElement::GetScriptCharset(nsAString& charset)
{
GetCharset(charset);
}
void
HTMLScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
{
if (mFrozen) {
return;
}
MOZ_ASSERT((mKind != ScriptKind::Module) &&
(mKind != ScriptKind::ImportMap) &&
!mAsync && !mDefer && !mExternal);
// Determine whether this is a(n) classic/module/importmap script.
nsAutoString type;
GetScriptType(type);
if (!type.IsEmpty()) {
if (aOwnerDoc->ModuleScriptsEnabled() &&
type.LowerCaseEqualsASCII("module")) {
mKind = ScriptKind::Module;
}
// https://wicg.github.io/import-maps/#integration-prepare-a-script
// If the script block’s type string is an ASCII case-insensitive match
// for the string "importmap", the script’s type is "importmap".
if (type.LowerCaseEqualsASCII("importmap")) {
mKind = ScriptKind::ImportMap;
}
}
// variation of this code in nsSVGScriptElement - check if changes
// need to be transfered when modifying. Note that we don't use GetSrc here
// because it will return the base URL when the attr value is "".
nsAutoString src;
if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
// Empty src should be treated as invalid URL.
if (!src.IsEmpty()) {
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(mUri),
src, OwnerDoc(), baseURI);
}
// At this point mUri will be null for invalid URLs.
mExternal = true;
}
bool defer, async;
GetAsync(&async);
mAsync = (mExternal || mKind == ScriptKind::Module) && async;
GetDefer(&defer);
mDefer = mExternal && !async && defer;
mFrozen = true;
}
CORSMode
HTMLScriptElement::GetCORSMode() const
{
return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
}
mozilla::net::ReferrerPolicy
HTMLScriptElement::GetReferrerPolicy()
{
return GetReferrerPolicyAsEnum();
}
bool
HTMLScriptElement::HasScriptContent()
{
return (mFrozen ? mExternal : HasAttr(kNameSpaceID_None, nsGkAtoms::src)) ||
nsContentUtils::HasNonEmptyTextContent(this);
}
} // namespace dom
} // namespace mozilla