Files
tubestation/dom/script/ScriptLoadRequest.h
Andreea Pavel 5c486b2ecc Backed out 8 changesets (bug 1475228) for wpt failures e.g. html/semantics/scripting-1/the-script-element/execution-timing/088.html on a CLOSED TREE
Backed out changeset b2d18ea619ec (bug 1475228)
Backed out changeset 45d3ffe3308e (bug 1475228)
Backed out changeset 02b27f8441be (bug 1475228)
Backed out changeset b82c2cf4b3f1 (bug 1475228)
Backed out changeset 2bc8f24dc3fc (bug 1475228)
Backed out changeset 6104ea971587 (bug 1475228)
Backed out changeset 7c83633262db (bug 1475228)
Backed out changeset 34fb24d52f08 (bug 1475228)
2018-07-30 16:49:02 +03:00

334 lines
8.8 KiB
C++

/* -*- 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/. */
#ifndef mozilla_dom_ScriptLoadRequest_h
#define mozilla_dom_ScriptLoadRequest_h
#include "mozilla/CORSMode.h"
#include "mozilla/dom/SRIMetadata.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h"
#include "mozilla/net/ReferrerPolicy.h"
#include "mozilla/Variant.h"
#include "mozilla/Vector.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIScriptElement.h"
class nsICacheInfoChannel;
namespace mozilla {
namespace dom {
class ModuleLoadRequest;
class ScriptLoadRequestList;
enum class ScriptKind {
eClassic,
eModule
};
/*
* A class that handles loading and evaluation of <script> elements.
*/
class ScriptLoadRequest : public nsISupports,
private mozilla::LinkedListElement<ScriptLoadRequest>
{
typedef LinkedListElement<ScriptLoadRequest> super;
// Allow LinkedListElement<ScriptLoadRequest> to cast us to itself as needed.
friend class mozilla::LinkedListElement<ScriptLoadRequest>;
friend class ScriptLoadRequestList;
protected:
virtual ~ScriptLoadRequest();
public:
ScriptLoadRequest(ScriptKind aKind,
nsIURI* aURI,
nsIScriptElement* aElement,
mozilla::CORSMode aCORSMode,
const SRIMetadata &aIntegrity,
nsIURI* aReferrer,
mozilla::net::ReferrerPolicy aReferrerPolicy);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ScriptLoadRequest)
bool IsModuleRequest() const
{
return mKind == ScriptKind::eModule;
}
ModuleLoadRequest* AsModuleRequest();
void FireScriptAvailable(nsresult aResult)
{
bool isInlineClassicScript = mIsInline && !IsModuleRequest();
mElement->ScriptAvailable(aResult, mElement, isInlineClassicScript, mURI,
mLineNo);
}
void FireScriptEvaluated(nsresult aResult)
{
mElement->ScriptEvaluated(aResult, mElement, mIsInline);
}
bool IsPreload()
{
return mElement == nullptr;
}
virtual void Cancel();
bool IsCanceled() const
{
return mIsCanceled;
}
virtual void SetReady();
JS::OffThreadToken** OffThreadTokenPtr()
{
return mOffThreadToken ? &mOffThreadToken : nullptr;
}
bool IsTracking() const
{
return mIsTracking;
}
void SetIsTracking()
{
MOZ_ASSERT(!mIsTracking);
mIsTracking = true;
}
enum class Progress : uint8_t {
eLoading, // Request either source or bytecode
eLoading_Source, // Explicitly Request source stream
eCompiling,
eFetchingImports,
eReady
};
bool IsReadyToRun() const
{
return mProgress == Progress::eReady;
}
bool IsLoading() const
{
return mProgress == Progress::eLoading ||
mProgress == Progress::eLoading_Source;
}
bool IsLoadingSource() const
{
return mProgress == Progress::eLoading_Source;
}
bool InCompilingStage() const
{
return mProgress == Progress::eCompiling ||
(IsReadyToRun() && mWasCompiledOMT);
}
// Type of data provided by the nsChannel.
enum class DataType : uint8_t {
eUnknown,
eTextSource,
eBinASTSource,
eBytecode
};
bool IsUnknownDataType() const
{
return mDataType == DataType::eUnknown;
}
bool IsTextSource() const
{
return mDataType == DataType::eTextSource;
}
bool IsBinASTSource() const
{
#ifdef JS_BUILD_BINAST
return mDataType == DataType::eBinASTSource;
#else
return false;
#endif
}
bool IsSource() const
{
return IsTextSource() || IsBinASTSource();
}
bool IsBytecode() const
{
return mDataType == DataType::eBytecode;
}
void SetUnknownDataType();
void SetTextSource();
void SetBinASTSource();
void SetBytecode();
const Vector<char16_t>& ScriptText() const {
MOZ_ASSERT(IsTextSource());
return mScriptData->as<Vector<char16_t>>();
}
Vector<char16_t>& ScriptText() {
MOZ_ASSERT(IsTextSource());
return mScriptData->as<Vector<char16_t>>();
}
const Vector<uint8_t>& ScriptBinASTData() const {
MOZ_ASSERT(IsBinASTSource());
return mScriptData->as<Vector<uint8_t>>();
}
Vector<uint8_t>& ScriptBinASTData() {
MOZ_ASSERT(IsBinASTSource());
return mScriptData->as<Vector<uint8_t>>();
}
enum class ScriptMode : uint8_t {
eBlocking,
eDeferred,
eAsync
};
void SetScriptMode(bool aDeferAttr, bool aAsyncAttr);
bool IsBlockingScript() const
{
return mScriptMode == ScriptMode::eBlocking;
}
bool IsDeferredScript() const
{
return mScriptMode == ScriptMode::eDeferred;
}
bool IsAsyncScript() const
{
return mScriptMode == ScriptMode::eAsync;
}
virtual bool IsTopLevel() const
{
// Classic scripts are always top level.
return true;
}
bool ShouldAcceptBinASTEncoding() const;
void ClearScriptSource();
void MaybeCancelOffThreadScript();
void DropBytecodeCacheReferences();
using super::getNext;
using super::isInList;
const ScriptKind mKind;
nsCOMPtr<nsIScriptElement> mElement;
bool mScriptFromHead; // Synchronous head script block loading of other non js/css content.
Progress mProgress; // Are we still waiting for a load to complete?
DataType mDataType; // Does this contain Source or Bytecode?
ScriptMode mScriptMode; // Whether this is a blocking, defer or async script.
bool mIsInline; // Is the script inline or loaded?
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
bool mInDeferList; // True if we live in mDeferRequests.
bool mInAsyncList; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
bool mIsXSLT; // True if we live in mXSLTRequests.
bool mIsCanceled; // True if we have been explicitly canceled.
bool mWasCompiledOMT; // True if the script has been compiled off main thread.
bool mIsTracking; // True if the script comes from a source on our tracking protection list.
JS::OffThreadToken* mOffThreadToken; // Off-thread parsing token.
nsString mSourceMapURL; // Holds source map url for loaded scripts
// Holds the top-level JSScript that corresponds to the current source, once
// it is parsed, and planned to be saved in the bytecode cache.
JS::Heap<JSScript*> mScript;
// Holds script source data for non-inline scripts. Don't use nsString so we
// can give ownership to jsapi. Holds either char16_t source text characters
// or BinAST encoded bytes depending on mSourceEncoding.
Maybe<Variant<Vector<char16_t>, Vector<uint8_t>>> mScriptData;
// Holds the SRI serialized hash and the script bytecode for non-inline
// scripts.
mozilla::Vector<uint8_t> mScriptBytecode;
uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode
const nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
int32_t mLineNo;
const mozilla::CORSMode mCORSMode;
const SRIMetadata mIntegrity;
const nsCOMPtr<nsIURI> mReferrer;
const mozilla::net::ReferrerPolicy mReferrerPolicy;
// Holds the Cache information, which is used to register the bytecode
// on the cache entry, such that we can load it the next time.
nsCOMPtr<nsICacheInfoChannel> mCacheInfo;
};
class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest>
{
typedef mozilla::LinkedList<ScriptLoadRequest> super;
public:
~ScriptLoadRequestList();
void Clear();
#ifdef DEBUG
bool Contains(ScriptLoadRequest* aElem) const;
#endif // DEBUG
using super::getFirst;
using super::isEmpty;
void AppendElement(ScriptLoadRequest* aElem)
{
MOZ_ASSERT(!aElem->isInList());
NS_ADDREF(aElem);
insertBack(aElem);
}
MOZ_MUST_USE
already_AddRefed<ScriptLoadRequest> Steal(ScriptLoadRequest* aElem)
{
aElem->removeFrom(*this);
return dont_AddRef(aElem);
}
MOZ_MUST_USE
already_AddRefed<ScriptLoadRequest> StealFirst()
{
MOZ_ASSERT(!isEmpty());
return Steal(getFirst());
}
void Remove(ScriptLoadRequest* aElem)
{
aElem->removeFrom(*this);
NS_RELEASE(aElem);
}
};
void
ImplCycleCollectionUnlink(ScriptLoadRequestList& aField);
void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
ScriptLoadRequestList& aField,
const char* aName,
uint32_t aFlags);
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ScriptLoadRequest_h