Merge inbound to central, a=merge

MozReview-Commit-ID: 2k4filK9zyX
This commit is contained in:
Wes Kocher 2017-06-16 17:58:58 -07:00
Родитель 4a2da759a0 ed880d0d06
Коммит 39066d6984
97 изменённых файлов: 1065 добавлений и 483 удалений

Просмотреть файл

@ -231,9 +231,9 @@ var TabsInTitlebar = {
}
// Then add a negative margin to the titlebar, so that the following elements
// will overlap it by the lesser of the titlebar height or the tabstrip+menu.
let minTitlebarOrTabsHeight = Math.min(titlebarContentHeight, tabAndMenuHeight);
titlebar.style.marginBottom = "-" + minTitlebarOrTabsHeight + "px";
// will overlap it by the greater of the titlebar height or the tabstrip+menu.
let maxTitlebarOrTabsHeight = Math.max(titlebarContentHeight, tabAndMenuHeight);
titlebar.style.marginBottom = "-" + maxTitlebarOrTabsHeight + "px";
// Finally, size the placeholders:
if (AppConstants.platform == "macosx") {

Просмотреть файл

@ -47,20 +47,42 @@ const startupPhases = {
// For the following phases of startup we have only a black list for now
// We are at this phase after creating the first browser window (ie. after final-ui-startup).
"before opening first browser window": {},
"before opening first browser window": {blacklist: {
components: new Set([
"nsAsyncShutdown.js",
]),
modules: new Set([
"resource://gre/modules/PlacesBackups.jsm",
"resource://gre/modules/PlacesUtils.jsm",
])
}},
// We reach this phase right after showing the first browser window.
// This means that anything already loaded at this point has been loaded
// before first paint and delayed it.
"before first paint": {blacklist: {
components: new Set([
"nsSearchService.js",
"PageIconProtocolHandler.js",
"PlacesCategoriesStarter.js",
"UnifiedComplete.js",
"nsPlacesExpiration.js",
"nsSearchService.js",
]),
modules: new Set([
"resource://gre/modules/ContextualIdentityService.jsm"
"resource:///modules/AboutNewTab.jsm",
"resource:///modules/DirectoryLinksProvider.jsm",
"resource://gre/modules/BookmarkHTMLUtils.jsm",
"resource://gre/modules/Bookmarks.jsm",
"resource://gre/modules/ContextualIdentityService.jsm",
"resource://gre/modules/NewTabUtils.jsm",
"resource://gre/modules/PageThumbs.jsm",
"resource://gre/modules/PlacesSyncUtils.jsm",
"resource://gre/modules/Sqlite.jsm",
]),
services: new Set([
"@mozilla.org/browser/annotation-service;1",
"@mozilla.org/browser/favicon-service;1",
"@mozilla.org/browser/nav-bookmarks-service;1",
"@mozilla.org/browser/search-service;1",
])
}},

Просмотреть файл

@ -119,7 +119,7 @@
#PopupAutoCompleteRichResult > deck[anonid="search-suggestions-notification"][animate] hbox[anonid="search-suggestions-hint-typing"] {
overflow: hidden;
max-width: 8ch;
max-width: 12ch;
width: 0;
animation-name: search-suggestions-hint-typing;
animation-duration: 500ms;
@ -137,7 +137,7 @@
@keyframes search-suggestions-hint-typing {
from { width: 0; }
to { width: 8ch; }
to { width: 12ch; }
}
#PopupAutoCompleteRichResult > deck[anonid="search-suggestions-notification"][animate] hbox[anonid="search-suggestions-hint-box"] {

Просмотреть файл

@ -127,7 +127,7 @@ def using_ccache(ccache, ccache_is_sccache):
@depends_if(ccache, ccache_is_sccache)
def using_sccache(ccache, ccache_is_sccache):
return True
return ccache and ccache_is_sccache
set_config('MOZ_USING_CCACHE', using_ccache)
set_config('MOZ_USING_SCCACHE', using_sccache)

Просмотреть файл

@ -677,6 +677,9 @@ FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb,
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mLabelsList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mLabelsList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
cb.NoteXPCOMChild(mClassList.get());
@ -711,6 +714,7 @@ FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL)
mShadowRoot = nullptr;
mContainingShadow = nullptr;
mChildrenList = nullptr;
mLabelsList = nullptr;
mCustomElementData = nullptr;
mClassList = nullptr;
mRegisteredIntersectionObservers.Clear();

Просмотреть файл

@ -25,6 +25,7 @@
class ContentUnbinder;
class nsContentList;
class nsLabelsNodeList;
class nsDOMAttributeMap;
class nsDOMTokenList;
class nsIControllers;
@ -313,6 +314,11 @@ public:
*/
RefPtr<nsDOMTokenList> mClassList;
/*
* An object implementing the .labels property for this element.
*/
RefPtr<nsLabelsNodeList> mLabelsList;
/**
* ShadowRoot bound to the element.
*/

Просмотреть файл

@ -253,19 +253,6 @@ const nsCacheableFuncStringContentList::ContentListType
nsCacheableFuncStringHTMLCollection::sType = nsCacheableFuncStringContentList::eHTMLCollection;
#endif
JSObject*
nsCacheableFuncStringNodeList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
{
return NodeListBinding::Wrap(cx, this, aGivenProto);
}
JSObject*
nsCacheableFuncStringHTMLCollection::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
{
return HTMLCollectionBinding::Wrap(cx, this, aGivenProto);
}
// Hashtable for storing nsCacheableFuncStringContentList
static PLDHashTable* gFuncStringContentListHashTable;
@ -378,6 +365,7 @@ NS_GetFuncStringHTMLCollection(nsINode* aRootNode,
aString);
}
//-----------------------------------------------------
// nsContentList implementation
nsContentList::nsContentList(nsINode* aRootNode,
@ -659,7 +647,7 @@ nsContentList::AttributeChanged(nsIDocument *aDocument, Element* aElement,
const nsAttrValue* aOldValue)
{
NS_PRECONDITION(aElement, "Must have a content node to work with");
if (!mFunc || !mFuncMayDependOnAttr || mState == LIST_DIRTY ||
!MayContainRelevantNodes(aElement->GetParentNode()) ||
!nsContentUtils::IsInSameAnonymousTree(mRootNode, aElement)) {
@ -805,7 +793,7 @@ nsContentList::ContentInserted(nsIDocument *aDocument,
ASSERT_IN_SYNC;
}
void
nsContentList::ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
@ -1074,3 +1062,126 @@ nsContentList::AssertInSync()
NS_ASSERTION(cnt == mElements.Length(), "Too few elements");
}
#endif
//-----------------------------------------------------
// nsCacheableFuncStringNodeList
JSObject*
nsCacheableFuncStringNodeList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
{
return NodeListBinding::Wrap(cx, this, aGivenProto);
}
//-----------------------------------------------------
// nsCacheableFuncStringHTMLCollection
JSObject*
nsCacheableFuncStringHTMLCollection::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
{
return HTMLCollectionBinding::Wrap(cx, this, aGivenProto);
}
//-----------------------------------------------------
// nsLabelsNodeList
JSObject*
nsLabelsNodeList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
{
return NodeListBinding::Wrap(cx, this, aGivenProto);
}
void
nsLabelsNodeList::AttributeChanged(nsIDocument* aDocument, Element* aElement,
int32_t aNameSpaceID, nsIAtom* aAttribute,
int32_t aModType,
const nsAttrValue* aOldValue)
{
MOZ_ASSERT(aElement, "Must have a content node to work with");
if (mState == LIST_DIRTY ||
!nsContentUtils::IsInSameAnonymousTree(mRootNode, aElement)) {
return;
}
// We need to handle input type changes to or from "hidden".
if (aElement->IsHTMLElement(nsGkAtoms::input) &&
aAttribute == nsGkAtoms::type && aNameSpaceID == kNameSpaceID_None) {
SetDirty();
return;
}
}
void
nsLabelsNodeList::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aFirstNewContent,
int32_t aNewIndexInContainer)
{
// If a labelable element is moved to outside or inside of
// nested associated labels, we're gonna have to modify
// the content list.
if (mState != LIST_DIRTY ||
nsContentUtils::IsInSameAnonymousTree(mRootNode, aContainer)) {
SetDirty();
return;
}
}
void
nsLabelsNodeList::ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
int32_t aIndexInContainer)
{
// If a labelable element is moved to outside or inside of
// nested associated labels, we're gonna have to modify
// the content list.
if (mState != LIST_DIRTY ||
nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild)) {
SetDirty();
return;
}
}
void
nsLabelsNodeList::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
int32_t aIndexInContainer,
nsIContent* aPreviousSibling)
{
// If a labelable element is removed, we're gonna have to clean
// the content list.
if (mState != LIST_DIRTY ||
nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild)) {
SetDirty();
return;
}
}
void
nsLabelsNodeList::MaybeResetRoot(nsINode* aRootNode)
{
MOZ_ASSERT(aRootNode, "Must have root");
if (mRootNode == aRootNode) {
return;
}
mRootNode->RemoveMutationObserver(this);
mRootNode = aRootNode;
mRootNode->AddMutationObserver(this);
SetDirty();
}
void
nsLabelsNodeList::PopulateSelf(uint32_t aNeededLength)
{
MOZ_ASSERT(mRootNode, "Must have root");
// Start searching at the root.
nsINode* cur = mRootNode;
if (mElements.IsEmpty() && cur->IsElement() && Match(cur->AsElement())) {
mElements.AppendElement(cur->AsElement());
}
nsContentList::PopulateSelf(aNeededLength);
}

Просмотреть файл

@ -376,9 +376,9 @@ protected:
* traversed the whole document (or both).
*
* @param aNeededLength the length the list should have when we are
* done (unless it exhausts the document)
* done (unless it exhausts the document)
*/
void PopulateSelf(uint32_t aNeededLength);
virtual void PopulateSelf(uint32_t aNeededLength);
/**
* @param aContainer a content node which must be a descendant of
@ -589,4 +589,40 @@ public:
#endif
};
class nsLabelsNodeList final : public nsContentList
{
public:
nsLabelsNodeList(nsINode* aRootNode,
nsContentListMatchFunc aFunc,
nsContentListDestroyFunc aDestroyFunc,
void* aData)
: nsContentList(aRootNode, aFunc, aDestroyFunc, aData)
{
}
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
/**
* Reset root, mutation observer, and clear content list
* if the root has been changed.
*
* @param aRootNode The node under which to limit our search.
*/
void MaybeResetRoot(nsINode* aRootNode);
private:
/**
* Start searching at the last one if we already have nodes, otherwise
* start searching at the root.
*
* @param aNeededLength The list of length should have when we are
* done (unless it exhausts the document).
*/
void PopulateSelf(uint32_t aNeededLength) override;
};
#endif // nsContentList_h___

Просмотреть файл

@ -339,17 +339,6 @@ nsContentSink::ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
return rv;
}
}
else if (aHeader == nsGkAtoms::msthemecompatible) {
// Disable theming for the presshell if the value is no.
// XXXbz don't we want to support this as an HTTP header too?
nsAutoString value(aValue);
if (value.LowerCaseEqualsLiteral("no")) {
nsIPresShell* shell = mDocument->GetShell();
if (shell) {
shell->DisableThemeSupport();
}
}
}
return rv;
}

Просмотреть файл

@ -598,6 +598,7 @@ GK_ATOM(keytext, "keytext")
GK_ATOM(keyup, "keyup")
GK_ATOM(kind, "kind")
GK_ATOM(label, "label")
GK_ATOM(labels, "labels")
GK_ATOM(lang, "lang")
GK_ATOM(language, "language")
GK_ATOM(last, "last")
@ -709,7 +710,6 @@ GK_ATOM(mozprivatebrowsing, "mozprivatebrowsing")
GK_ATOM(moz_opaque, "moz-opaque")
GK_ATOM(moz_action_hint, "mozactionhint")
GK_ATOM(x_moz_errormessage, "x-moz-errormessage")
GK_ATOM(msthemecompatible, "msthemecompatible")
GK_ATOM(multicol, "multicol")
GK_ATOM(multiple, "multiple")
GK_ATOM(muted, "muted")

Просмотреть файл

@ -1995,7 +1995,7 @@ InterSliceGCRunnerFired(TimeStamp aDeadline, void* aData)
}
TimeStamp startTimeStamp = TimeStamp::Now();
TimeDuration duration = sGCUnnotifiedTotalTime;
uintptr_t reason = reinterpret_cast<uintptr_t>(aData);
nsJSContext::GarbageCollectNow(aData ?
static_cast<JS::gcreason::Reason>(reason) :
@ -2004,20 +2004,20 @@ InterSliceGCRunnerFired(TimeStamp aDeadline, void* aData)
nsJSContext::NonShrinkingGC,
budget);
TimeDuration duration = sGCUnnotifiedTotalTime;
sGCUnnotifiedTotalTime = TimeDuration();
TimeStamp now = TimeStamp::Now();
TimeDuration sliceDuration = now - startTimeStamp;
duration += sliceDuration;
if (duration.ToSeconds()) {
TimeDuration idleDuration;
if (!aDeadline.IsNull()) {
TimeStamp now = TimeStamp::Now();
if (aDeadline < now) {
// This slice overflowed the idle period.
idleDuration = aDeadline - startTimeStamp;
} else {
// Note, we don't want to use duration here, since it may contain
// data also from JS engine triggered GC slices.
idleDuration = now - startTimeStamp;
idleDuration = sliceDuration;
}
}

Просмотреть файл

@ -8157,6 +8157,16 @@ HTMLInputElement::GetWebkitEntries(nsTArray<RefPtr<FileSystemEntry>>& aSequence)
aSequence.AppendElements(mFileData->mEntries);
}
already_AddRefed<nsINodeList>
HTMLInputElement::GetLabels()
{
if (!IsLabelable()) {
return nullptr;
}
return nsGenericHTMLElement::Labels();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -735,6 +735,8 @@ public:
// XPCOM GetCustomVisibility() is OK
already_AddRefed<nsINodeList> GetLabels();
// XPCOM Select() is OK
Nullable<uint32_t> GetSelectionStart(ErrorResult& aRv);

Просмотреть файл

@ -14,6 +14,7 @@
#include "nsFocusManager.h"
#include "nsIDOMMouseEvent.h"
#include "nsQueryObject.h"
#include "mozilla/dom/ShadowRoot.h"
// construction, destruction
@ -268,17 +269,23 @@ HTMLLabelElement::GetLabeledElement() const
return GetFirstLabelableDescendant();
}
// We have a @for. The id has to be linked to an element in the same document
// We have a @for. The id has to be linked to an element in the same tree
// and this element should be a labelable form control.
//XXXsmaug It is unclear how this should work in case the element is in
// Shadow DOM.
// See https://www.w3.org/Bugs/Public/show_bug.cgi?id=26365.
nsIDocument* doc = GetUncomposedDoc();
if (!doc) {
return nullptr;
nsINode* root = SubtreeRoot();
ShadowRoot* shadow = ShadowRoot::FromNode(root);
Element* element = nullptr;
if (shadow) {
element = shadow->GetElementById(elementId);
} else {
nsIDocument* doc = GetUncomposedDoc();
if (doc) {
element = doc->GetElementById(elementId);
} else {
element = nsContentUtils::MatchElementId(root->AsContent(), elementId);
}
}
Element* element = doc->GetElementById(elementId);
if (element && element->IsLabelable()) {
return static_cast<nsGenericHTMLElement*>(element);
}

Просмотреть файл

@ -107,6 +107,7 @@
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "ReferrerPolicy.h"
#include "mozilla/dom/HTMLLabelElement.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -511,6 +512,14 @@ nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
}
}
// We need to consider a labels element is moved to another subtree
// with different root, it needs to update labels list and its root
// as well.
nsDOMSlots* slots = GetExistingDOMSlots();
if (slots && slots->mLabelsList) {
slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
}
return rv;
}
@ -531,6 +540,13 @@ nsGenericHTMLElement::UnbindFromTree(bool aDeep, bool aNullParent)
}
}
// We need to consider a labels element is removed from tree,
// it needs to update labels list and its root as well.
nsDOMSlots* slots = GetExistingDOMSlots();
if (slots && slots->mLabelsList) {
slots->mLabelsList->MaybeResetRoot(SubtreeRoot());
}
nsStyledElement::UnbindFromTree(aDeep, aNullParent);
}
@ -1679,6 +1695,30 @@ nsGenericHTMLElement::IsLabelable() const
return IsAnyOfHTMLElements(nsGkAtoms::progress, nsGkAtoms::meter);
}
/* static */ bool
nsGenericHTMLElement::MatchLabelsElement(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData)
{
HTMLLabelElement* element = HTMLLabelElement::FromContent(aElement);
return element && element->GetControl() == aData;
}
already_AddRefed<nsINodeList>
nsGenericHTMLElement::Labels()
{
MOZ_ASSERT(IsLabelable(),
"Labels() only allow labelable elements to use it.");
nsDOMSlots* slots = DOMSlots();
if (!slots->mLabelsList) {
slots->mLabelsList = new nsLabelsNodeList(SubtreeRoot(), MatchLabelsElement,
nullptr, this);
}
RefPtr<nsLabelsNodeList> labels = slots->mLabelsList;
return labels.forget();
}
bool
nsGenericHTMLElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
{

Просмотреть файл

@ -851,6 +851,12 @@ public:
}
virtual bool IsLabelable() const override;
static bool MatchLabelsElement(Element* aElement, int32_t aNamespaceID,
nsIAtom* aAtom, void* aData);
already_AddRefed<nsINodeList> Labels();
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
static bool TouchEventsEnabled(JSContext* /* unused */, JSObject* /* unused */);

Просмотреть файл

@ -128,9 +128,12 @@ is(typeof(document.createElement("button").setCustomValidity), "function",
"button.setCustomValidity should be a function");
// .labels
todo("labels" in document.createElement("button"),
"button.labels isn't implemented yet");
ok("labels" in document.createElement("button"),
"button.labels should be an IDL attribute of the button element");
is(typeof(document.createElement("button").labels), "object",
"button.labels should be an object");
ok(document.createElement("button").labels instanceof NodeList,
"button.labels sohuld be an instance of NodeList");
</script>
</pre>
</body>

Просмотреть файл

@ -43,6 +43,5 @@ interface HTMLButtonElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
// Not yet implemented:
// readonly attribute NodeList labels;
readonly attribute NodeList labels;
};

Просмотреть файл

@ -112,7 +112,7 @@ interface HTMLInputElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
// Bug 850365 readonly attribute NodeList labels;
readonly attribute NodeList? labels;
void select();

Просмотреть файл

@ -26,9 +26,5 @@ interface HTMLMeterElement : HTMLElement {
attribute double high;
[SetterThrows]
attribute double optimum;
/**
* The labels attribute will be done with bug 556743.
*/
//readonly attribute NodeList labels;
readonly attribute NodeList labels;
};

Просмотреть файл

@ -34,6 +34,5 @@ interface HTMLOutputElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
// Not yet implemented (bug 556743).
// readonly attribute NodeList labels;
readonly attribute NodeList labels;
};

Просмотреть файл

@ -18,9 +18,5 @@ interface HTMLProgressElement : HTMLElement {
[SetterThrows]
attribute double max;
readonly attribute double position;
/**
* The labels attribute will be done with bug 567740.
*/
//readonly attribute NodeList labels;
readonly attribute NodeList labels;
};

Просмотреть файл

@ -54,7 +54,7 @@ interface HTMLSelectElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
// NYI: readonly attribute NodeList labels;
readonly attribute NodeList labels;
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=20720
void remove();

Просмотреть файл

@ -58,7 +58,7 @@ interface HTMLTextAreaElement : HTMLElement {
boolean reportValidity();
void setCustomValidity(DOMString error);
// readonly attribute NodeList labels;
readonly attribute NodeList labels;
void select();
[Throws]

Просмотреть файл

@ -201,7 +201,8 @@ XMLHttpRequestMainThread::XMLHttpRequestMainThread()
mResultJSON(JS::UndefinedValue()),
mResultArrayBuffer(nullptr),
mIsMappedArrayBuffer(false),
mXPCOMifier(nullptr)
mXPCOMifier(nullptr),
mEventDispatchingSuspended(false)
{
mozilla::HoldJSObjects(this);
}
@ -1368,7 +1369,7 @@ XMLHttpRequestMainThread::FireReadystatechangeEvent()
event->InitEvent(kLiteralString_readystatechange, false, false);
// We assume anyone who managed to call CreateReadystatechangeEvent is trusted
event->SetTrusted(true);
DispatchDOMEvent(nullptr, event, nullptr, nullptr);
DispatchOrStoreEvent(this, event);
return NS_OK;
}
@ -1411,7 +1412,7 @@ XMLHttpRequestMainThread::DispatchProgressEvent(DOMEventTargetHelper* aTarget,
ProgressEvent::Constructor(aTarget, typeString, init);
event->SetTrusted(true);
aTarget->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
DispatchOrStoreEvent(aTarget, event);
if (aType == ProgressEventType::progress) {
mInLoadProgressEvent = false;
@ -1434,6 +1435,45 @@ XMLHttpRequestMainThread::DispatchProgressEvent(DOMEventTargetHelper* aTarget,
}
}
void
XMLHttpRequestMainThread::DispatchOrStoreEvent(DOMEventTargetHelper* aTarget,
Event* aEvent)
{
MOZ_ASSERT(aTarget);
MOZ_ASSERT(aEvent);
if (mEventDispatchingSuspended) {
PendingEvent* event = mPendingEvents.AppendElement();
event->mTarget = aTarget;
event->mEvent = aEvent;
return;
}
aTarget->DispatchDOMEvent(nullptr, aEvent, nullptr, nullptr);
}
void
XMLHttpRequestMainThread::SuspendEventDispatching()
{
MOZ_ASSERT(!mEventDispatchingSuspended);
mEventDispatchingSuspended = true;
}
void
XMLHttpRequestMainThread::ResumeEventDispatching()
{
MOZ_ASSERT(mEventDispatchingSuspended);
mEventDispatchingSuspended = false;
nsTArray<PendingEvent> pendingEvents;
pendingEvents.SwapElements(mPendingEvents);
for (uint32_t i = 0; i < pendingEvents.Length(); ++i) {
pendingEvents[i].mTarget->
DispatchDOMEvent(nullptr, pendingEvents[i].mEvent, nullptr, nullptr);
}
}
already_AddRefed<nsIHttpChannel>
XMLHttpRequestMainThread::GetCurrentHttpChannel()
{
@ -2409,10 +2449,6 @@ XMLHttpRequestMainThread::ChangeStateToDone()
mTimeoutTimer->Cancel();
}
if (mFlagSynchronous) {
UnsuppressEventHandlingAndResume();
}
// Per spec, fire the last download progress event, if any,
// before readystatechange=4/done. (Note that 0-sized responses
// will have not sent a progress event yet, so one must be sent here).
@ -3033,6 +3069,7 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody)
}
}
SuspendEventDispatching();
StopProgressEventTimer();
SyncTimeoutType syncTimeoutType = MaybeStartSyncTimeoutTimer();
@ -3056,6 +3093,7 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody)
}
UnsuppressEventHandlingAndResume();
ResumeEventDispatching();
} else {
// Now that we've successfully opened the channel, we can change state. Note
// that this needs to come after the AsyncOpen() and rv check, because this

Просмотреть файл

@ -401,7 +401,8 @@ public:
ErrorResult& aRv);
void
Abort() {
Abort()
{
ErrorResult rv;
Abort(rv);
MOZ_ASSERT(!rv.Failed());
@ -607,8 +608,21 @@ protected:
nsresult DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable);
void DispatchOrStoreEvent(DOMEventTargetHelper* aTarget, Event* aEvent);
already_AddRefed<nsXMLHttpRequestXPCOMifier> EnsureXPCOMifier();
void SuspendEventDispatching();
void ResumeEventDispatching();
struct PendingEvent
{
RefPtr<DOMEventTargetHelper> mTarget;
RefPtr<Event> mEvent;
};
nsTArray<PendingEvent> mPendingEvents;
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIChannel> mChannel;
@ -837,6 +851,10 @@ protected:
// Helper object to manage our XPCOM scriptability bits
nsXMLHttpRequestXPCOMifier* mXPCOMifier;
// When this is set to true, the event dispatching is suspended. This is
// useful to change the correct state when XHR is working sync.
bool mEventDispatchingSuspended;
static bool sDontWarnAboutSyncXHR;
};

Просмотреть файл

@ -195,7 +195,10 @@ WebRenderBridgeParent::RecvAddImage(const wr::ImageKey& aImageKey,
return IPC_OK();
}
MOZ_ASSERT(mApi);
MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(aImageKey)) == mActiveImageKeys.end());
wr::ImageDescriptor descriptor(aSize, aStride, aFormat);
mActiveImageKeys.insert(wr::AsUint64(aImageKey));
mApi->AddImage(aImageKey, descriptor,
aBuffer.AsSlice());
@ -213,7 +216,10 @@ WebRenderBridgeParent::RecvAddBlobImage(const wr::ImageKey& aImageKey,
return IPC_OK();
}
MOZ_ASSERT(mApi);
MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(aImageKey)) == mActiveImageKeys.end());
wr::ImageDescriptor descriptor(aSize, aStride, aFormat);
mActiveImageKeys.insert(wr::AsUint64(aImageKey));
mApi->AddBlobImage(aImageKey, descriptor,
aBuffer.AsSlice());
@ -229,7 +235,10 @@ WebRenderBridgeParent::RecvAddRawFont(const wr::FontKey& aFontKey,
return IPC_OK();
}
MOZ_ASSERT(mApi);
MOZ_ASSERT(mFontKeys.find(wr::AsUint64(aFontKey)) == mFontKeys.end());
auto slice = aBuffer.AsSlice();
mFontKeys.insert(wr::AsUint64(aFontKey));
mApi->AddRawFont(aFontKey, slice, aFontIndex);
return IPC_OK();
@ -242,7 +251,14 @@ WebRenderBridgeParent::RecvDeleteFont(const wr::FontKey& aFontKey)
return IPC_OK();
}
MOZ_ASSERT(mApi);
mApi->DeleteFont(aFontKey);
if (mFontKeys.find(wr::AsUint64(aFontKey)) != mFontKeys.end()) {
mFontKeys.erase(wr::AsUint64(aFontKey));
mApi->DeleteFont(aFontKey);
} else {
MOZ_ASSERT_UNREACHABLE("invalid FontKey");
}
return IPC_OK();
}
@ -269,10 +285,12 @@ WebRenderBridgeParent::RecvDeleteImage(const wr::ImageKey& aImageKey)
return IPC_OK();
}
MOZ_ASSERT(mApi);
if (mActiveKeys.Get(wr::AsUint64(aImageKey), nullptr)) {
mActiveKeys.Remove(wr::AsUint64(aImageKey));
if (mActiveImageKeys.find(wr::AsUint64(aImageKey)) != mActiveImageKeys.end()) {
mActiveImageKeys.erase(wr::AsUint64(aImageKey));
mKeysToDelete.push_back(aImageKey);
} else {
MOZ_ASSERT_UNREACHABLE("invalid ImageKey");
}
mKeysToDelete.push_back(aImageKey);
return IPC_OK();
}
@ -465,8 +483,8 @@ WebRenderBridgeParent::ProcessWebRenderParentCommands(InfallibleTArray<WebRender
const OpAddExternalImage& op = cmd.get_OpAddExternalImage();
Range<const wr::ImageKey> keys(&op.key(), 1);
MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(op.externalImageId())).get());
MOZ_ASSERT(!mActiveKeys.Get(wr::AsUint64(keys[0]), nullptr));
mActiveKeys.Put(wr::AsUint64(keys[0]), keys[0]);
MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(keys[0])) == mActiveImageKeys.end());
mActiveImageKeys.insert(wr::AsUint64(keys[0]));
RefPtr<WebRenderImageHost> host = mExternalImageIds.Get(wr::AsUint64(op.externalImageId()));
if (!host) {
@ -1029,10 +1047,14 @@ WebRenderBridgeParent::ClearResources()
mApi->ClearRootDisplayList(wr::NewEpoch(mWrEpoch), mPipelineId);
// Schedule composition to clean up Pipeline
mCompositorScheduler->ScheduleComposition();
for (auto iter = mActiveKeys.Iter(); !iter.Done(); iter.Next()) {
mKeysToDelete.push_back(iter.Data());
iter.Remove();
for (std::unordered_set<uint64_t>::iterator iter = mFontKeys.begin(); iter != mFontKeys.end(); iter++) {
mApi->DeleteFont(wr::AsFontKey(*iter));
}
mFontKeys.clear();
for (std::unordered_set<uint64_t>::iterator iter = mActiveImageKeys.begin(); iter != mActiveImageKeys.end(); iter++) {
mKeysToDelete.push_back(wr::AsImageKey(*iter));
}
mActiveImageKeys.clear();
DeleteOldImages();
for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->ClearWrBridge();

Просмотреть файл

@ -247,8 +247,10 @@ private:
RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
RefPtr<CompositorAnimationStorage> mAnimStorage;
std::vector<wr::ImageKey> mKeysToDelete;
// XXX How to handle active keys of non-ExternalImages?
nsDataHashtable<nsUint64HashKey, wr::ImageKey> mActiveKeys;
// mActiveImageKeys and mFontKeys are used to avoid leaking animations when
// WebRenderBridgeParent is destroyed abnormally and Tab move between different windows.
std::unordered_set<uint64_t> mActiveImageKeys;
std::unordered_set<uint64_t> mFontKeys;
// mActiveAnimations is used to avoid leaking animations when WebRenderBridgeParent is
// destroyed abnormally and Tab move between different windows.
std::unordered_set<uint64_t> mActiveAnimations;

Просмотреть файл

@ -115,6 +115,26 @@ inline uint64_t AsUint64(const ImageKey& aId) {
+ static_cast<uint64_t>(aId.mHandle);
}
inline ImageKey AsImageKey(const uint64_t& aId) {
ImageKey imageKey;
imageKey.mNamespace = aId >> 32;
imageKey.mHandle = aId;
return imageKey;
}
// Whenever possible, use wr::FontKey instead of manipulating uint64_t.
inline uint64_t AsUint64(const FontKey& aId) {
return (static_cast<uint64_t>(aId.mNamespace) << 32)
+ static_cast<uint64_t>(aId.mHandle);
}
inline FontKey AsFontKey(const uint64_t& aId) {
FontKey fontKey;
fontKey.mNamespace = aId >> 32;
fontKey.mHandle = aId;
return fontKey;
}
// Whenever possible, use wr::PipelineId instead of manipulating uint64_t.
inline uint64_t AsUint64(const PipelineId& aId) {
return (static_cast<uint64_t>(aId.mNamespace) << 32)

Просмотреть файл

@ -553,20 +553,6 @@ class JS_PUBLIC_API(AutoAssertNoAlloc)
#endif
};
/**
* Assert if a GC barrier is invoked while this class is live. This class does
* not disable the static rooting hazard analysis.
*/
class JS_PUBLIC_API(AutoAssertOnBarrier)
{
JSContext* context;
bool prev;
public:
explicit AutoAssertOnBarrier(JSContext* cx);
~AutoAssertOnBarrier();
};
/**
* Disable the static rooting hazard analysis in the live region and assert if
* any allocation that could potentially trigger a GC occurs while this guard
@ -645,9 +631,6 @@ UnmarkGrayGCThingRecursively(GCCellPtr thing);
namespace js {
namespace gc {
extern JS_FRIEND_API(bool)
BarriersAreAllowedOnCurrentThread();
static MOZ_ALWAYS_INLINE void
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
{
@ -662,8 +645,6 @@ ExposeGCThingToActiveJS(JS::GCCellPtr thing)
if (thing.mayBeOwnedByOtherRuntime())
return;
MOZ_DIAGNOSTIC_ASSERT(BarriersAreAllowedOnCurrentThread());
if (IsIncrementalBarrierNeededOnTenuredGCThing(thing))
JS::IncrementalReadBarrier(thing);
else if (js::gc::detail::TenuredCellIsMarkedGray(thing.asCell()))

Просмотреть файл

@ -69,6 +69,10 @@ class GCHashMap : public js::HashMap<Key, Value, HashPolicy, AllocPolicy>
}
}
bool needsSweep() const {
return this->initialized() && !this->empty();
}
void sweep() {
if (!this->initialized())
return;
@ -246,6 +250,10 @@ class GCHashSet : public js::HashSet<T, HashPolicy, AllocPolicy>
GCPolicy<T>::trace(trc, &e.mutableFront(), "hashset element");
}
bool needsSweep() const {
return this->initialized() && !this->empty();
}
void sweep() {
if (!this->initialized())
return;

Просмотреть файл

@ -135,6 +135,10 @@ class GCVector
GCPolicy<T>::trace(trc, &elem, "vector element");
}
bool needsSweep() const {
return !this->empty();
}
void sweep() {
uint32_t src, dst = 0;
for (src = 0; src < length(); src++) {

Просмотреть файл

@ -1613,6 +1613,7 @@ class HashTable : private AllocPolicy
{
METER(stats.rehashes++);
removedCount = 0;
gen++;
for (size_t i = 0; i < capacity(); ++i)
table[i].unsetCollision();
@ -1797,6 +1798,9 @@ class HashTable : private AllocPolicy
if (!p.isValid())
return false;
MOZ_ASSERT(p.generation == generation());
MOZ_ASSERT(p.mutationCount == mutationCount);
// Changing an entry from removed to live does not affect whether we
// are overloaded and can be handled separately.
if (p.entry_->isRemoved()) {
@ -1880,6 +1884,7 @@ class HashTable : private AllocPolicy
MOZ_ASSERT(table);
mozilla::ReentrancyGuard g(*this);
MOZ_ASSERT(p.found());
MOZ_ASSERT(p.generation == generation());
remove(*p.entry_);
checkUnderloaded();
}
@ -1889,6 +1894,7 @@ class HashTable : private AllocPolicy
MOZ_ASSERT(table);
mozilla::ReentrancyGuard g(*this);
MOZ_ASSERT(p.found());
MOZ_ASSERT(p.generation == generation());
typename HashTableEntry<T>::NonConstT t(mozilla::Move(*p));
HashPolicy::setKey(t, const_cast<Key&>(k));
remove(*p.entry_);

Просмотреть файл

@ -168,6 +168,7 @@ struct Zone
bool isGCSweeping() const { return gcState_ == Sweep; }
bool isGCFinished() const { return gcState_ == Finished; }
bool isGCCompacting() const { return gcState_ == Compact; }
bool isGCMarking() const { return gcState_ == Mark || gcState_ == MarkGray; }
bool isGCSweepingOrCompacting() const { return gcState_ == Sweep || gcState_ == Compact; }
static MOZ_ALWAYS_INLINE JS::shadow::Zone* asShadowZone(JS::Zone* zone) {

Просмотреть файл

@ -38,6 +38,7 @@ class WeakCacheBase : public mozilla::LinkedListElement<WeakCacheBase>
virtual ~WeakCacheBase() {}
virtual void sweep() = 0;
virtual bool needsSweep() = 0;
};
} // namespace detail
@ -69,6 +70,10 @@ class WeakCache : protected detail::WeakCacheBase,
void sweep() override {
GCPolicy<T>::sweep(&cache);
}
bool needsSweep() override {
return cache.needsSweep();
}
};
} // namespace JS

Просмотреть файл

@ -712,13 +712,6 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
if (!NameFunctions(cx, pn))
return false;
// XDR the newly delazified function.
if (script->scriptSource()->hasEncoder() &&
!script->scriptSource()->xdrEncodeFunction(cx, fun, sourceObject))
{
return false;
}
return true;
}

Просмотреть файл

@ -685,7 +685,7 @@ class HeapSlot : public WriteBarrieredBase<Value>
const Value& target) const;
#endif
void set(NativeObject* owner, Kind kind, uint32_t slot, const Value& v) {
MOZ_ALWAYS_INLINE void set(NativeObject* owner, Kind kind, uint32_t slot, const Value& v) {
MOZ_ASSERT(preconditionForSet(owner, kind, slot));
pre();
value = v;

Просмотреть файл

@ -340,26 +340,26 @@ ShouldTraceCrossCompartment(JSTracer* trc, JSObject* src, const Value& val)
}
static void
AssertZoneIsMarking(Cell* thing)
AssertShouldMarkInZone(Cell* thing)
{
MOZ_ASSERT(TenuredCell::fromPointer(thing)->zone()->isGCMarking());
MOZ_ASSERT(thing->asTenured().zone()->shouldMarkInZone());
}
static void
AssertZoneIsMarking(JSString* str)
AssertShouldMarkInZone(JSString* str)
{
#ifdef DEBUG
Zone* zone = TenuredCell::fromPointer(str)->zone();
MOZ_ASSERT(zone->isGCMarking() || zone->isAtomsZone());
Zone* zone = str->asTenured().zone();
MOZ_ASSERT(zone->shouldMarkInZone() || zone->isAtomsZone());
#endif
}
static void
AssertZoneIsMarking(JS::Symbol* sym)
AssertShouldMarkInZone(JS::Symbol* sym)
{
#ifdef DEBUG
Zone* zone = TenuredCell::fromPointer(sym)->zone();
MOZ_ASSERT(zone->isGCMarking() || zone->isAtomsZone());
Zone* zone = sym->asTenured().zone();
MOZ_ASSERT(zone->shouldMarkInZone() || zone->isAtomsZone());
#endif
}
@ -771,35 +771,35 @@ GCMarker::markImplicitEdges(T* thing)
template <typename T>
static inline bool
MustSkipMarking(GCMarker* gcmarker, T thing)
ShouldMark(GCMarker* gcmarker, T thing)
{
// Don't trace things that are owned by another runtime.
if (IsOwnedByOtherRuntime(gcmarker->runtime(), thing))
return true;
return false;
// Don't mark things outside a zone if we are in a per-zone GC.
return !thing->zone()->isGCMarking();
return thing->zone()->shouldMarkInZone();
}
template <>
bool
MustSkipMarking<JSObject*>(GCMarker* gcmarker, JSObject* obj)
ShouldMark<JSObject*>(GCMarker* gcmarker, JSObject* obj)
{
// Don't trace things that are owned by another runtime.
if (IsOwnedByOtherRuntime(gcmarker->runtime(), obj))
return true;
return false;
// We may mark a Nursery thing outside the context of the
// MinorCollectionTracer because of a pre-barrier. The pre-barrier is not
// needed in this case because we perform a minor collection before each
// incremental slice.
if (IsInsideNursery(obj))
return true;
return false;
// Don't mark things outside a zone if we are in a per-zone GC. It is
// faster to check our own arena, which we can do since we know that
// the object is tenured.
return !TenuredCell::fromPointer(obj)->zone()->isGCMarking();
return obj->asTenured().zone()->shouldMarkInZone();
}
template <typename T>
@ -807,7 +807,7 @@ void
DoMarking(GCMarker* gcmarker, T* thing)
{
// Do per-type marking precondition checks.
if (MustSkipMarking(gcmarker, thing))
if (!ShouldMark(gcmarker, thing))
return;
CheckTracedThing(gcmarker, thing);
@ -834,7 +834,7 @@ void
NoteWeakEdge(GCMarker* gcmarker, T** thingp)
{
// Do per-type marking precondition checks.
if (MustSkipMarking(gcmarker, *thingp))
if (!ShouldMark(gcmarker, *thingp))
return;
CheckTracedThing(gcmarker, *thingp);
@ -990,7 +990,7 @@ template <typename T>
bool
js::GCMarker::mark(T* thing)
{
AssertZoneIsMarking(thing);
AssertShouldMarkInZone(thing);
MOZ_ASSERT(!IsInsideNursery(gc::TenuredCell::fromPointer(thing)));
return gc::ParticipatesInCC<T>::value
? gc::TenuredCell::fromPointer(thing)->markIfUnmarked(markColor())
@ -1125,7 +1125,7 @@ JSString::traceBase(JSTracer* trc)
inline void
js::GCMarker::eagerlyMarkChildren(JSLinearString* linearStr)
{
AssertZoneIsMarking(linearStr);
AssertShouldMarkInZone(linearStr);
MOZ_ASSERT(linearStr->isMarked());
MOZ_ASSERT(linearStr->JSString::isLinear());
@ -1135,7 +1135,7 @@ js::GCMarker::eagerlyMarkChildren(JSLinearString* linearStr)
MOZ_ASSERT(linearStr->JSString::isLinear());
if (linearStr->isPermanentAtom())
break;
AssertZoneIsMarking(linearStr);
AssertShouldMarkInZone(linearStr);
if (!mark(static_cast<JSString*>(linearStr)))
break;
}
@ -1188,7 +1188,7 @@ js::GCMarker::eagerlyMarkChildren(JSRope* rope)
JS_DIAGNOSTICS_ASSERT(rope->getTraceKind() == JS::TraceKind::String);
JS_DIAGNOSTICS_ASSERT(rope->JSString::isRope());
AssertZoneIsMarking(rope);
AssertShouldMarkInZone(rope);
MOZ_ASSERT(rope->isMarked());
JSRope* next = nullptr;
@ -1674,7 +1674,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
case MarkStack::ObjectTag: {
obj = stack.popPtr().as<JSObject>();
AssertZoneIsMarking(obj);
AssertShouldMarkInZone(obj);
goto scan_obj;
}
@ -1738,7 +1738,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget)
scan_obj:
{
AssertZoneIsMarking(obj);
AssertShouldMarkInZone(obj);
budget.step();
if (budget.isOverBudget()) {

Просмотреть файл

@ -251,8 +251,8 @@ Zone::discardJitCode(FreeOp* fop, bool discardBaselineCode)
void
JS::Zone::checkUniqueIdTableAfterMovingGC()
{
for (UniqueIdMap::Enum e(uniqueIds()); !e.empty(); e.popFront())
js::gc::CheckGCThingAfterMovingGC(e.front().key());
for (auto r = uniqueIds().all(); !r.empty(); r.popFront())
js::gc::CheckGCThingAfterMovingGC(r.front().key());
}
#endif

Просмотреть файл

@ -242,11 +242,8 @@ struct Zone : public JS::shadow::Zone,
return CurrentThreadIsHeapMajorCollecting() && !rt->gc.isHeapCompacting() && gcState_ != NoGC;
}
bool isGCMarking() {
if (CurrentThreadIsHeapCollecting())
return gcState_ == Mark || gcState_ == MarkGray;
else
return needsIncrementalBarrier();
bool shouldMarkInZone() const {
return needsIncrementalBarrier() || isGCMarking();
}
// Get a number that is incremented whenever this zone is collected, and

Просмотреть файл

@ -0,0 +1,10 @@
class C { }
class D extends C { }
function f()
{
for (var i = 0; i < 2000; ++i)
new D();
}
f();

Просмотреть файл

@ -0,0 +1,29 @@
load(libdir + 'bytecode-cache.js');
var test = "";
gczeal(0);
// Check that a GC can relazify decoded functions.
//
// Generations 0 and 3 are executed from the source, thus f is not executed yet.
// Generations 1 and 2 are decoded, thus we recorded the delazified f function.
test = `
function f() { return 1; };
assertEq(isLazyFunction(f), generation == 0 || generation == 3);
f();
expect = isRelazifiableFunction(f);
assertEq(isLazyFunction(f), false);
`;
evalWithCache(test, {
checkAfter: function (ctx) {
gc(ctx.global.f, "shrinking"); // relazify f, if possible.
evaluate("assertEq(isLazyFunction(f), expect);", ctx);
}
});
evalWithCache(test, {
incremental: true,
checkAfter: function (ctx) {
gc(ctx.global.f, "shrinking"); // relazify f, if possible.
evaluate("assertEq(isLazyFunction(f), expect);", ctx);
}
});

Просмотреть файл

@ -1414,6 +1414,11 @@ static const VMFunction ThrowUninitializedThisInfo =
FunctionInfo<ThrowUninitializedThisFn>(BaselineThrowUninitializedThis,
"BaselineThrowUninitializedThis");
typedef bool (*ThrowInitializedThisFn)(JSContext*, BaselineFrame* frame);
static const VMFunction ThrowInitializedThisInfo =
FunctionInfo<ThrowInitializedThisFn>(BaselineThrowInitializedThis,
"BaselineThrowInitializedThis");
bool
BaselineCompiler::emit_JSOP_CHECKTHIS()
{
@ -1424,18 +1429,35 @@ BaselineCompiler::emit_JSOP_CHECKTHIS()
}
bool
BaselineCompiler::emitCheckThis(ValueOperand val)
BaselineCompiler::emit_JSOP_CHECKTHISREINIT()
{
frame.syncStack(0);
masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
return emitCheckThis(R0, /* reinit = */true);
}
bool
BaselineCompiler::emitCheckThis(ValueOperand val, bool reinit)
{
Label thisOK;
masm.branchTestMagic(Assembler::NotEqual, val, &thisOK);
if (reinit)
masm.branchTestMagic(Assembler::Equal, val, &thisOK);
else
masm.branchTestMagic(Assembler::NotEqual, val, &thisOK);
prepareVMCall();
masm.loadBaselineFramePtr(BaselineFrameReg, val.scratchReg());
pushArg(val.scratchReg());
if (!callVM(ThrowUninitializedThisInfo))
return false;
if (reinit) {
if (!callVM(ThrowInitializedThisInfo))
return false;
} else {
if (!callVM(ThrowUninitializedThisInfo))
return false;
}
masm.bind(&thisOK);
return true;
@ -4224,6 +4246,56 @@ BaselineCompiler::emit_JSOP_SUPERBASE()
return true;
}
typedef JSObject* (*SuperFunOperationFn)(JSContext*, HandleObject);
static const VMFunction SuperFunOperationInfo =
FunctionInfo<SuperFunOperationFn>(SuperFunOperation, "SuperFunOperation");
bool
BaselineCompiler::emit_JSOP_SUPERFUN()
{
frame.syncStack(0);
Register callee = R0.scratchReg();
Register proto = R1.scratchReg();
Register scratch = R2.scratchReg();
// Lookup callee object of environment containing [[ThisValue]]
getThisEnvironmentCallee(callee);
// Load prototype of callee
masm.loadObjProto(callee, proto);
// Use VMCall for missing or lazy proto
Label needVMCall;
MOZ_ASSERT(uintptr_t(TaggedProto::LazyProto) == 1);
masm.branchPtr(Assembler::BelowOrEqual, proto, ImmWord(1), &needVMCall);
// Use VMCall for non-JSFunction objects (eg. Proxy)
masm.branchTestObjClass(Assembler::NotEqual, proto, scratch, &JSFunction::class_, &needVMCall);
// Use VMCall if not constructor
masm.load16ZeroExtend(Address(proto, JSFunction::offsetOfFlags()), scratch);
masm.branchTest32(Assembler::Zero, scratch, Imm32(JSFunction::CONSTRUCTOR), &needVMCall);
// Valid constructor
Label hasSuperFun;
masm.jump(&hasSuperFun);
// Slow path VM Call
masm.bind(&needVMCall);
prepareVMCall();
pushArg(callee);
if (!callVM(SuperFunOperationInfo))
return false;
masm.movePtr(ReturnReg, proto);
// Box prototype and return
masm.bind(&hasSuperFun);
masm.tagValue(JSVAL_TYPE_OBJECT, proto, R1);
frame.push(R1);
return true;
}
typedef bool (*NewArgumentsObjectFn)(JSContext*, BaselineFrame*, MutableHandleValue);
static const VMFunction NewArgumentsObjectInfo =
FunctionInfo<NewArgumentsObjectFn>(jit::NewArgumentsObject, "NewArgumentsObject");

Просмотреть файл

@ -217,6 +217,7 @@ namespace jit {
_(JSOP_RESUME) \
_(JSOP_CALLEE) \
_(JSOP_SUPERBASE) \
_(JSOP_SUPERFUN) \
_(JSOP_GETRVAL) \
_(JSOP_SETRVAL) \
_(JSOP_RETRVAL) \
@ -226,6 +227,7 @@ namespace jit {
_(JSOP_CHECKISOBJ) \
_(JSOP_CHECKISCALLABLE) \
_(JSOP_CHECKTHIS) \
_(JSOP_CHECKTHISREINIT) \
_(JSOP_CHECKRETURN) \
_(JSOP_NEWTARGET) \
_(JSOP_SUPERCALL) \
@ -295,7 +297,7 @@ class BaselineCompiler : public BaselineCompilerSpecific
private:
MethodStatus emitBody();
MOZ_MUST_USE bool emitCheckThis(ValueOperand val);
MOZ_MUST_USE bool emitCheckThis(ValueOperand val, bool reinit=false);
void emitLoadReturnValue(ValueOperand val);
void emitInitializeLocals();

Просмотреть файл

@ -2397,7 +2397,7 @@ DoCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_, uint
FallbackICSpew(cx, stub, "Call(%s)", CodeName[op]);
MOZ_ASSERT(argc == GET_ARGC(pc));
bool constructing = (op == JSOP_NEW);
bool constructing = (op == JSOP_NEW || op == JSOP_SUPERCALL);
bool ignoresReturnValue = (op == JSOP_CALL_IGNORES_RV);
// Ensure vp array is rooted - we may GC in here.
@ -2432,7 +2432,7 @@ DoCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_, uint
}
}
if (op == JSOP_NEW) {
if (constructing) {
if (!ConstructFromStack(cx, callArgs))
return false;
res.set(callArgs.rval());
@ -2506,7 +2506,7 @@ DoSpreadCallFallback(JSContext* cx, BaselineFrame* frame, ICCall_Fallback* stub_
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(script);
JSOp op = JSOp(*pc);
bool constructing = (op == JSOP_SPREADNEW);
bool constructing = (op == JSOP_SPREADNEW || op == JSOP_SPREADSUPERCALL);
FallbackICSpew(cx, stub, "SpreadCall(%s)", CodeName[op]);
// Ensure vp array is rooted - we may GC in here.

Просмотреть файл

@ -4860,6 +4860,9 @@ IonBuilder::createThisScriptedBaseline(MDefinition* callee)
if (!target || !target->hasScript())
return nullptr;
if (target->isBoundFunction() || target->isDerivedClassConstructor())
return nullptr;
JSObject* templateObject = inspector->getTemplateObject(pc);
if (!templateObject)
return nullptr;

Просмотреть файл

@ -1037,6 +1037,8 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branchPtr(Condition cond, const Address& lhs, ImmGCPtr rhs, Label* label) PER_SHARED_ARCH;
inline void branchPtr(Condition cond, const Address& lhs, ImmWord rhs, Label* label) PER_SHARED_ARCH;
inline void branchPtr(Condition cond, const BaseIndex& lhs, ImmWord rhs, Label* label) PER_SHARED_ARCH;
inline void branchPtr(Condition cond, const AbsoluteAddress& lhs, Register rhs, Label* label)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
inline void branchPtr(Condition cond, const AbsoluteAddress& lhs, ImmWord rhs, Label* label)
@ -1654,6 +1656,8 @@ class MacroAssembler : public MacroAssemblerSpecific
if (type == MIRType::Value)
branchTestGCThing(Assembler::NotEqual, address, &done);
else if (type == MIRType::Object || type == MIRType::String)
branchPtr(Assembler::Equal, address, ImmWord(0), &done);
Push(PreBarrierReg);
computeEffectiveAddress(address, PreBarrierReg);

Просмотреть файл

@ -2386,6 +2386,7 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac
MOZ_ASSERT(frame->isFunctionFrame() || frame->isEvalFrame());
MOZ_ASSERT(stub->monitorsThis() ||
*GetNextPc(pc) == JSOP_CHECKTHIS ||
*GetNextPc(pc) == JSOP_CHECKTHISREINIT ||
*GetNextPc(pc) == JSOP_CHECKRETURN);
if (stub->monitorsThis())
TypeScript::SetThis(cx, script, TypeSet::UnknownType());

Просмотреть файл

@ -1433,15 +1433,15 @@ MarkValueFromIon(JSRuntime* rt, Value* vp)
void
MarkStringFromIon(JSRuntime* rt, JSString** stringp)
{
if (*stringp)
TraceManuallyBarrieredEdge(&rt->gc.marker, stringp, "write barrier");
MOZ_ASSERT(*stringp);
TraceManuallyBarrieredEdge(&rt->gc.marker, stringp, "write barrier");
}
void
MarkObjectFromIon(JSRuntime* rt, JSObject** objp)
{
if (*objp)
TraceManuallyBarrieredEdge(&rt->gc.marker, objp, "write barrier");
MOZ_ASSERT(*objp);
TraceManuallyBarrieredEdge(&rt->gc.marker, objp, "write barrier");
}
void
@ -1497,6 +1497,12 @@ BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame)
return ThrowUninitializedThis(cx, frame);
}
bool
BaselineThrowInitializedThis(JSContext* cx, BaselineFrame* frame)
{
return ThrowInitializedThis(cx, frame);
}
bool
ThrowObjectCoercible(JSContext* cx, HandleValue v)

Просмотреть файл

@ -831,6 +831,9 @@ ThrowReadOnlyError(JSContext* cx, HandleObject obj, int32_t index);
MOZ_MUST_USE bool
BaselineThrowUninitializedThis(JSContext* cx, BaselineFrame* frame);
MOZ_MUST_USE bool
BaselineThrowInitializedThis(JSContext* cx, BaselineFrame* frame);
MOZ_MUST_USE bool
ThrowBadDerivedReturn(JSContext* cx, HandleValue v);

Просмотреть файл

@ -1457,6 +1457,12 @@ MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rh
branchPtr(cond, scratch2, rhs, label);
}
void
MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, ImmWord rhs, Label* label)
{
branch32(cond, lhs, Imm32(rhs.value), label);
}
template <typename T>
inline CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)

Просмотреть файл

@ -1032,6 +1032,17 @@ MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rh
branchPtr(cond, scratch, rhs, label);
}
void
MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, ImmWord rhs, Label* label)
{
vixl::UseScratchRegisterScope temps(this);
const Register scratch = temps.AcquireX().asUnsized();
MOZ_ASSERT(scratch != lhs.base);
MOZ_ASSERT(scratch != lhs.index);
loadPtr(lhs, scratch);
branchPtr(cond, scratch, rhs, label);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)

Просмотреть файл

@ -571,6 +571,13 @@ MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rh
branchPtr(cond, SecondScratchReg, rhs, label);
}
void
MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, ImmWord rhs, Label* label)
{
loadPtr(lhs, SecondScratchReg);
branchPtr(cond, SecondScratchReg, rhs, label);
}
template <typename T>
CodeOffsetJump
MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)

Просмотреть файл

@ -871,6 +871,9 @@ class Assembler : public AssemblerX86Shared
case Operand::MEM_REG_DISP:
masm.cmpq_im(rhs.value, lhs.disp(), lhs.base());
break;
case Operand::MEM_SCALE:
masm.cmpq_im(rhs.value, lhs.disp(), lhs.base(), lhs.index(), lhs.scale());
break;
case Operand::MEM_ADDRESS32:
masm.cmpq_im(rhs.value, lhs.address());
break;

Просмотреть файл

@ -582,6 +582,12 @@ MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs, Label
branchPtrImpl(cond, lhs, rhs, label);
}
void
MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, ImmWord rhs, Label* label)
{
branchPtrImpl(cond, lhs, rhs, label);
}
template <typename T, typename S, typename L>
void
MacroAssembler::branchPtrImpl(Condition cond, const T& lhs, const S& rhs, L label)

Просмотреть файл

@ -1347,7 +1347,6 @@ JSContext::JSContext(JSRuntime* runtime, const JS::ContextOptions& options)
dtoaState(nullptr),
heapState(JS::HeapState::Idle),
suppressGC(0),
allowGCBarriers(true),
#ifdef DEBUG
ionCompiling(false),
ionCompilingSafeForMinorGC(false),

Просмотреть файл

@ -474,10 +474,6 @@ struct JSContext : public JS::RootingContext,
*/
js::ThreadLocalData<int32_t> suppressGC;
// In some cases, invoking GC barriers (incremental or otherwise) will break
// things. These barriers assert if this flag is set.
js::ThreadLocalData<bool> allowGCBarriers;
#ifdef DEBUG
// Whether this thread is actively Ion compiling.
js::ThreadLocalData<bool> ionCompiling;

Просмотреть файл

@ -1567,6 +1567,14 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
// Only functions without inner functions are re-lazified.
script->setLazyScript(lazy);
}
// XDR the newly delazified function.
if (script->scriptSource()->hasEncoder()) {
RootedScriptSource sourceObject(cx, lazy->sourceObject());
if (!script->scriptSource()->xdrEncodeFunction(cx, fun, sourceObject))
return false;
}
return true;
}

Просмотреть файл

@ -5233,6 +5233,9 @@ PrepareWeakCacheTasks(JSRuntime* rt)
// Build a vector of sweep tasks to run on a helper thread.
WeakCacheTaskVector tasks;
bool ok = IterateWeakCaches(rt, [&] (JS::detail::WeakCacheBase* cache) {
if (!cache->needsSweep())
return true;
return tasks.emplaceBack(rt, *cache);
});
@ -6009,7 +6012,6 @@ GCRuntime::canChangeActiveContext(JSContext* cx)
// scheduling.
return cx->heapState == JS::HeapState::Idle
&& !cx->suppressGC
&& cx->allowGCBarriers
&& !cx->inUnsafeRegion
&& !cx->generationalDisabled
&& !cx->compactingDisabledCount
@ -7494,25 +7496,6 @@ JS::AutoAssertNoGC::~AutoAssertNoGC()
cx_->inUnsafeRegion--;
}
JS::AutoAssertOnBarrier::AutoAssertOnBarrier(JSContext* cx)
: context(cx),
prev(cx->allowGCBarriers)
{
context->allowGCBarriers = false;
}
JS::AutoAssertOnBarrier::~AutoAssertOnBarrier()
{
MOZ_ASSERT(!context->allowGCBarriers);
context->allowGCBarriers = prev;
}
JS_FRIEND_API(bool)
js::gc::BarriersAreAllowedOnCurrentThread()
{
return TlsContext.get()->allowGCBarriers;
}
#ifdef DEBUG
JS::AutoAssertNoAlloc::AutoAssertNoAlloc(JSContext* cx)
: gc(nullptr)

Просмотреть файл

@ -3554,6 +3554,12 @@ JSObject::uninlinedIsProxy() const
return is<ProxyObject>();
}
bool
JSObject::uninlinedNonProxyIsExtensible() const
{
return nonProxyIsExtensible();
}
void
JSObject::dump(FILE* fp) const
{

Просмотреть файл

@ -504,6 +504,7 @@ class JSObject : public js::gc::Cell
// places that want it (JITs and the like), and it'd be a pain to mark them
// all as friends.
inline bool nonProxyIsExtensible() const;
bool uninlinedNonProxyIsExtensible() const;
public:
/*

Просмотреть файл

@ -599,6 +599,10 @@ class InnerViewTable
void sweep();
void sweepAfterMinorGC();
bool needsSweep() const {
return map.needsSweep();
}
bool needsSweepAfterMinorGC() const {
return !nurseryKeys.empty() || !nurseryKeysValid;
}

Просмотреть файл

@ -2757,7 +2757,7 @@ END_CASE(JSOP_CHECKTHIS)
CASE(JSOP_CHECKTHISREINIT)
{
if (!REGS.sp[-1].isMagic(JS_UNINITIALIZED_LEXICAL)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_REINIT_THIS);
MOZ_ALWAYS_FALSE(ThrowInitializedThis(cx, REGS.fp()));
goto error;
}
}
@ -4226,24 +4226,10 @@ END_CASE(JSOP_NEWTARGET)
CASE(JSOP_SUPERFUN)
{
ReservedRooted<JSObject*> superEnvFunc(&rootObject0, &GetSuperEnvFunction(cx, REGS));
MOZ_ASSERT(superEnvFunc->as<JSFunction>().isClassConstructor());
MOZ_ASSERT(superEnvFunc->as<JSFunction>().nonLazyScript()->isDerivedClassConstructor());
ReservedRooted<JSObject*> superFun(&rootObject1);
if (!GetPrototype(cx, superEnvFunc, &superFun))
goto error;
ReservedRooted<Value> superFunVal(&rootValue0, UndefinedValue());
superFun = SuperFunOperation(cx, superEnvFunc);
if (!superFun)
superFunVal = NullValue();
else if (!superFun->isConstructor())
superFunVal = ObjectValue(*superFun);
if (superFunVal.isObjectOrNull()) {
ReportIsNotFunction(cx, superFunVal, JSDVG_IGNORE_STACK, CONSTRUCT);
goto error;
}
PUSH_OBJECT(*superFun);
}
@ -5241,3 +5227,35 @@ js::HomeObjectSuperBase(JSContext* cx, HandleObject homeObj)
return superBase;
}
JSObject*
js::SuperFunOperation(JSContext* cx, HandleObject callee)
{
MOZ_ASSERT(callee->as<JSFunction>().isClassConstructor());
MOZ_ASSERT(callee->as<JSFunction>().nonLazyScript()->isDerivedClassConstructor());
RootedObject superFun(cx);
if (!GetPrototype(cx, callee, &superFun))
return nullptr;
RootedValue superFunVal(cx, UndefinedValue());
if (!superFun)
superFunVal = NullValue();
else if (!superFun->isConstructor())
superFunVal = ObjectValue(*superFun);
if (superFunVal.isObjectOrNull()) {
ReportIsNotFunction(cx, superFunVal, JSDVG_IGNORE_STACK, CONSTRUCT);
return nullptr;
}
return superFun;
}
bool
js::ThrowInitializedThis(JSContext* cx, AbstractFramePtr frame)
{
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_REINIT_THIS);
return false;
}

Просмотреть файл

@ -571,6 +571,9 @@ ThrowCheckIsCallable(JSContext* cx, CheckIsCallableKind kind);
bool
ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame);
bool
ThrowInitializedThis(JSContext* cx, AbstractFramePtr frame);
bool
DefaultClassConstructor(JSContext* cx, unsigned argc, Value* vp);
@ -592,6 +595,9 @@ MakeDefaultConstructor(JSContext* cx, HandleScript script, jsbytecode* pc, Handl
JSObject*
HomeObjectSuperBase(JSContext* cx, HandleObject homeObj);
JSObject*
SuperFunOperation(JSContext* cx, HandleObject callee);
} /* namespace js */
#endif /* vm_Interpreter_h */

Просмотреть файл

@ -420,7 +420,7 @@ NativeObject::copy(JSContext* cx, gc::AllocKind kind, gc::InitialHeap heap,
return obj;
}
inline void
MOZ_ALWAYS_INLINE void
NativeObject::setSlotWithType(JSContext* cx, Shape* shape,
const Value& value, bool overwriting)
{
@ -739,8 +739,9 @@ LookupOwnPropertyInline(JSContext* cx,
}
}
// Check for a native property.
if (Shape* shape = obj->lookup(cx, id)) {
// Check for a native property. Call Shape::search directly (instead of
// NativeObject::lookup) because it's inlined.
if (Shape* shape = obj->lastProperty()->search(cx, id)) {
propp.setNativeProperty(shape);
*donep = true;
return true;

Просмотреть файл

@ -795,15 +795,16 @@ class NativeObject : public ShapedObject
void freeSlot(JSContext* cx, uint32_t slot);
private:
static Shape* getChildProperty(JSContext* cx, HandleNativeObject obj,
HandleShape parent, MutableHandle<StackShape> child);
static MOZ_ALWAYS_INLINE Shape* getChildProperty(JSContext* cx, HandleNativeObject obj,
HandleShape parent,
MutableHandle<StackShape> child);
public:
/* Add a property whose id is not yet in this scope. */
static Shape* addProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
JSGetterOp getter, JSSetterOp setter,
uint32_t slot, unsigned attrs, unsigned flags,
bool allowDictionary = true);
static MOZ_ALWAYS_INLINE Shape* addProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
JSGetterOp getter, JSSetterOp setter,
uint32_t slot, unsigned attrs, unsigned flags,
bool allowDictionary = true);
/* Add a data property whose id is not yet in this scope. */
static Shape* addDataProperty(JSContext* cx, HandleNativeObject obj,
@ -901,36 +902,36 @@ class NativeObject : public ShapedObject
return getSlotAddressUnchecked(slot);
}
HeapSlot& getSlotRef(uint32_t slot) {
MOZ_ALWAYS_INLINE HeapSlot& getSlotRef(uint32_t slot) {
MOZ_ASSERT(slotInRange(slot));
return *getSlotAddress(slot);
}
const HeapSlot& getSlotRef(uint32_t slot) const {
MOZ_ALWAYS_INLINE const HeapSlot& getSlotRef(uint32_t slot) const {
MOZ_ASSERT(slotInRange(slot));
return *getSlotAddress(slot);
}
// Check requirements on values stored to this object.
inline void checkStoredValue(const Value& v) {
MOZ_ALWAYS_INLINE void checkStoredValue(const Value& v) {
MOZ_ASSERT(IsObjectValueInCompartment(v, compartment()));
MOZ_ASSERT(AtomIsMarked(zoneFromAnyThread(), v));
}
void setSlot(uint32_t slot, const Value& value) {
MOZ_ALWAYS_INLINE void setSlot(uint32_t slot, const Value& value) {
MOZ_ASSERT(slotInRange(slot));
checkStoredValue(value);
getSlotRef(slot).set(this, HeapSlot::Slot, slot, value);
}
void initSlot(uint32_t slot, const Value& value) {
MOZ_ALWAYS_INLINE void initSlot(uint32_t slot, const Value& value) {
MOZ_ASSERT(getSlot(slot).isUndefined());
MOZ_ASSERT(slotInRange(slot));
checkStoredValue(value);
initSlotUnchecked(slot, value);
}
void initSlotUnchecked(uint32_t slot, const Value& value) {
MOZ_ALWAYS_INLINE void initSlotUnchecked(uint32_t slot, const Value& value) {
getSlotAddressUnchecked(slot)->init(this, HeapSlot::Slot, slot, value);
}
@ -964,30 +965,30 @@ class NativeObject : public ShapedObject
static bool rollbackProperties(JSContext* cx, HandleNativeObject obj,
uint32_t slotSpan);
inline void setSlotWithType(JSContext* cx, Shape* shape,
const Value& value, bool overwriting = true);
MOZ_ALWAYS_INLINE void setSlotWithType(JSContext* cx, Shape* shape,
const Value& value, bool overwriting = true);
inline const Value& getReservedSlot(uint32_t index) const {
MOZ_ALWAYS_INLINE const Value& getReservedSlot(uint32_t index) const {
MOZ_ASSERT(index < JSSLOT_FREE(getClass()));
return getSlot(index);
}
const HeapSlot& getReservedSlotRef(uint32_t index) const {
MOZ_ALWAYS_INLINE const HeapSlot& getReservedSlotRef(uint32_t index) const {
MOZ_ASSERT(index < JSSLOT_FREE(getClass()));
return getSlotRef(index);
}
HeapSlot& getReservedSlotRef(uint32_t index) {
MOZ_ALWAYS_INLINE HeapSlot& getReservedSlotRef(uint32_t index) {
MOZ_ASSERT(index < JSSLOT_FREE(getClass()));
return getSlotRef(index);
}
void initReservedSlot(uint32_t index, const Value& v) {
MOZ_ALWAYS_INLINE void initReservedSlot(uint32_t index, const Value& v) {
MOZ_ASSERT(index < JSSLOT_FREE(getClass()));
initSlot(index, v);
}
void setReservedSlot(uint32_t index, const Value& v) {
MOZ_ALWAYS_INLINE void setReservedSlot(uint32_t index, const Value& v) {
MOZ_ASSERT(index < JSSLOT_FREE(getClass()));
setSlot(index, v);
}

Просмотреть файл

@ -1907,8 +1907,8 @@ ObjectGroupCompartment::checkNewTableAfterMovingGC(NewTable* table)
if (!table || !table->initialized())
return;
for (NewTable::Enum e(*table); !e.empty(); e.popFront()) {
NewEntry entry = e.front();
for (auto r = table->all(); !r.empty(); r.popFront()) {
NewEntry entry = r.front();
CheckGCThingAfterMovingGC(entry.group.unbarrieredGet());
TaggedProto proto = entry.group.unbarrieredGet()->proto();
if (proto.isObject())
@ -1921,7 +1921,7 @@ ObjectGroupCompartment::checkNewTableAfterMovingGC(NewTable* table)
NewEntry::Lookup lookup(clasp, proto, entry.associated);
auto ptr = table->lookup(lookup);
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &e.front());
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
}
}

Просмотреть файл

@ -390,7 +390,7 @@ class ObjectGroup : public gc::TenuredCell
inline HeapTypeSet* getProperty(JSContext* cx, JSObject* obj, jsid id);
/* Get a property only if it already exists. */
inline HeapTypeSet* maybeGetProperty(jsid id);
MOZ_ALWAYS_INLINE HeapTypeSet* maybeGetProperty(jsid id);
/*
* Iterate through the group's properties. getPropertyCount overapproximates

Просмотреть файл

@ -333,6 +333,30 @@ Shape::searchNoHashify(Shape* start, jsid id)
return start->searchLinear(id);
}
/* static */ MOZ_ALWAYS_INLINE Shape*
NativeObject::addProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
GetterOp getter, SetterOp setter, uint32_t slot, unsigned attrs,
unsigned flags, bool allowDictionary)
{
MOZ_ASSERT(!JSID_IS_VOID(id));
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
MOZ_ASSERT(obj->uninlinedNonProxyIsExtensible());
MOZ_ASSERT(!obj->containsPure(id));
AutoKeepShapeTables keep(cx);
ShapeTable::Entry* entry = nullptr;
if (obj->inDictionaryMode()) {
ShapeTable* table = obj->lastProperty()->ensureTableForDictionary(cx, keep);
if (!table)
return nullptr;
entry = &table->search<MaybeAdding::Adding>(id, keep);
}
return addPropertyInternal(cx, obj, id, getter, setter, slot, attrs, flags, entry,
allowDictionary, keep);
}
} /* namespace js */
#endif /* vm_Shape_inl_h */

Просмотреть файл

@ -290,7 +290,7 @@ Shape::replaceLastProperty(JSContext* cx, StackBaseShape& base,
* which must be lastProperty() if inDictionaryMode(), else parent must be
* one of lastProperty() or lastProperty()->parent.
*/
/* static */ Shape*
/* static */ MOZ_ALWAYS_INLINE Shape*
NativeObject::getChildProperty(JSContext* cx,
HandleNativeObject obj, HandleShape parent,
MutableHandle<StackShape> child)
@ -418,30 +418,6 @@ js::NativeObject::toDictionaryMode(JSContext* cx, HandleNativeObject obj)
return true;
}
/* static */ Shape*
NativeObject::addProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
GetterOp getter, SetterOp setter, uint32_t slot, unsigned attrs,
unsigned flags, bool allowDictionary)
{
MOZ_ASSERT(!JSID_IS_VOID(id));
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
MOZ_ASSERT(obj->nonProxyIsExtensible());
MOZ_ASSERT(!obj->containsPure(id));
AutoKeepShapeTables keep(cx);
ShapeTable::Entry* entry = nullptr;
if (obj->inDictionaryMode()) {
ShapeTable* table = obj->lastProperty()->ensureTableForDictionary(cx, keep);
if (!table)
return nullptr;
entry = &table->search<MaybeAdding::Adding>(id, keep);
}
return addPropertyInternal(cx, obj, id, getter, setter, slot, attrs, flags, entry,
allowDictionary, keep);
}
static bool
ShouldConvertToDictionary(NativeObject* obj)
{
@ -1288,12 +1264,12 @@ Zone::checkBaseShapeTableAfterMovingGC()
if (!baseShapes().initialized())
return;
for (BaseShapeSet::Enum e(baseShapes()); !e.empty(); e.popFront()) {
UnownedBaseShape* base = e.front().unbarrieredGet();
for (auto r = baseShapes().all(); !r.empty(); r.popFront()) {
UnownedBaseShape* base = r.front().unbarrieredGet();
CheckGCThingAfterMovingGC(base);
BaseShapeSet::Ptr ptr = baseShapes().lookup(base);
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &e.front());
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
}
}
@ -1349,8 +1325,8 @@ Zone::checkInitialShapesTableAfterMovingGC()
* initialShapes that points into the nursery, and that the hash table
* entries are discoverable.
*/
for (InitialShapeSet::Enum e(initialShapes()); !e.empty(); e.popFront()) {
InitialShapeEntry entry = e.front();
for (auto r = initialShapes().all(); !r.empty(); r.popFront()) {
InitialShapeEntry entry = r.front();
JSProtoKey protoKey = entry.proto.key();
TaggedProto proto = entry.proto.proto().unbarrieredGet();
Shape* shape = entry.shape.unbarrieredGet();
@ -1365,7 +1341,7 @@ Zone::checkInitialShapesTableAfterMovingGC()
shape->numFixedSlots(),
shape->getObjectFlags());
InitialShapeSet::Ptr ptr = initialShapes().lookup(lookup);
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &e.front());
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
}
}

Просмотреть файл

@ -405,11 +405,10 @@ PropertyHasBeenMarkedNonConstant(JSObject* obj, jsid id)
}
MOZ_ALWAYS_INLINE bool
HasTypePropertyId(JSObject* obj, jsid id, TypeSet::Type type)
HasTrackedPropertyType(JSObject* obj, jsid id, TypeSet::Type type)
{
id = IdToTypeId(id);
if (!TrackPropertyTypes(obj, id))
return true;
MOZ_ASSERT(id == IdToTypeId(id));
MOZ_ASSERT(TrackPropertyTypes(obj, id));
if (HeapTypeSet* types = obj->group()->maybeGetProperty(id)) {
if (!types->hasType(type))
@ -423,6 +422,16 @@ HasTypePropertyId(JSObject* obj, jsid id, TypeSet::Type type)
return false;
}
MOZ_ALWAYS_INLINE bool
HasTypePropertyId(JSObject* obj, jsid id, TypeSet::Type type)
{
id = IdToTypeId(id);
if (!TrackPropertyTypes(obj, id))
return true;
return HasTrackedPropertyType(obj, id, type);
}
MOZ_ALWAYS_INLINE bool
HasTypePropertyId(JSObject* obj, jsid id, const Value& value)
{
@ -433,20 +442,18 @@ void AddTypePropertyId(JSContext* cx, ObjectGroup* group, JSObject* obj, jsid id
void AddTypePropertyId(JSContext* cx, ObjectGroup* group, JSObject* obj, jsid id, const Value& value);
/* Add a possible type for a property of obj. */
inline void
MOZ_ALWAYS_INLINE void
AddTypePropertyId(JSContext* cx, JSObject* obj, jsid id, TypeSet::Type type)
{
id = IdToTypeId(id);
if (TrackPropertyTypes(obj, id))
if (TrackPropertyTypes(obj, id) && !HasTrackedPropertyType(obj, id, type))
AddTypePropertyId(cx, obj->group(), obj, id, type);
}
inline void
MOZ_ALWAYS_INLINE void
AddTypePropertyId(JSContext* cx, JSObject* obj, jsid id, const Value& value)
{
id = IdToTypeId(id);
if (TrackPropertyTypes(obj, id))
AddTypePropertyId(cx, obj->group(), obj, id, value);
return AddTypePropertyId(cx, obj, id, TypeSet::GetValueType(value));
}
inline void
@ -830,7 +837,7 @@ struct TypeHashSet
// Lookup an entry in a hash set, return nullptr if it does not exist.
template <class T, class U, class KEY>
static inline U*
static MOZ_ALWAYS_INLINE U*
Lookup(U** values, unsigned count, T key)
{
if (count == 0)
@ -1126,7 +1133,7 @@ ObjectGroup::getProperty(JSContext* cx, JSObject* obj, jsid id)
return &base->types;
}
inline HeapTypeSet*
MOZ_ALWAYS_INLINE HeapTypeSet*
ObjectGroup::maybeGetProperty(jsid id)
{
MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));

Просмотреть файл

@ -786,7 +786,6 @@ nsIPresShell::nsIPresShell()
, mIsDestroying(false)
, mIsReflowing(false)
, mPaintingSuppressed(false)
, mIsThemeSupportDisabled(false)
, mIsActive(false)
, mFrozen(false)
, mIsFirstPaint(false)
@ -853,7 +852,6 @@ PresShell::PresShell()
mLastOSWake = mLoadBegin = TimeStamp::Now();
mSelectionFlags = nsISelectionDisplay::DISPLAY_TEXT | nsISelectionDisplay::DISPLAY_IMAGES;
mIsThemeSupportDisabled = false;
mIsActive = true;
// FIXME/bug 735029: find a better solution to this problem
mIsFirstPaint = true;

Просмотреть файл

@ -954,20 +954,6 @@ public:
*/
virtual void UnsuppressPainting() = 0;
/**
* Called to disable nsITheme support in a specific presshell.
*/
void DisableThemeSupport()
{
// Doesn't have to be dynamic. Just set the bool.
mIsThemeSupportDisabled = true;
}
/**
* Indicates whether theme support is enabled.
*/
bool IsThemeSupportEnabled() const { return !mIsThemeSupportDisabled; }
/**
* Get the set of agent style sheets for this presentation
*/
@ -1862,9 +1848,6 @@ protected:
// For all documents we initially lock down painting.
bool mPaintingSuppressed : 1;
// Whether or not form controls should use nsITheme in this shell.
bool mIsThemeSupportDisabled : 1;
bool mIsActive : 1;
bool mFrozen : 1;
bool mIsFirstPaint : 1;

Просмотреть файл

@ -1108,6 +1108,7 @@ inDOMUtils::SetContentState(nsIDOMElement* aElement,
NS_IMETHODIMP
inDOMUtils::RemoveContentState(nsIDOMElement* aElement,
EventStates::InternalType aState,
bool aClearActiveDocument,
bool* aRetVal)
{
NS_ENSURE_ARG_POINTER(aElement);
@ -1117,6 +1118,15 @@ inDOMUtils::RemoveContentState(nsIDOMElement* aElement,
NS_ENSURE_TRUE(esm, NS_ERROR_INVALID_ARG);
*aRetVal = esm->SetContentState(nullptr, EventStates(aState));
if (aClearActiveDocument && EventStates(aState) == NS_EVENT_STATE_ACTIVE) {
EventStateManager* activeESM = static_cast<EventStateManager*>(
EventStateManager::GetActiveEventStateManager());
if (activeESM == esm) {
EventStateManager::ClearGlobalActiveContent(nullptr);
}
}
return NS_OK;
}

Просмотреть файл

@ -152,7 +152,7 @@ interface inIDOMUtils : nsISupports
in boolean aShowingAnonymousContent);
nsIDOMNodeList getChildrenForNode(in nsIDOMNode aNode,
in boolean aShowingAnonymousContent);
// XBL utilities
nsIArray getBindingURLs(in nsIDOMElement aElement);
@ -164,11 +164,15 @@ interface inIDOMUtils : nsISupports
* that for the remove case we simply pass in nullptr for the element.
* Use them accordingly.
*
* When removing the active state, you may optionally also clear the active
* document as well by setting aClearActiveDocument
*
* @return Returns true if the state was set successfully. See more details
* in EventStateManager.h SetContentState.
*/
bool setContentState(in nsIDOMElement aElement, in unsigned long long aState);
bool removeContentState(in nsIDOMElement aElement, in unsigned long long aState);
bool removeContentState(in nsIDOMElement aElement, in unsigned long long aState,
[optional] in bool aClearActiveDocument);
nsIDOMFontFaceList getUsedFontFaces(in nsIDOMRange aRange);

Просмотреть файл

@ -1,5 +1,4 @@
<!DOCTYPE html>
<meta http-equiv="msthemecompatible" content="no">
<div style="width: 200px; height: 200px; overflow: scroll;">
<div style="width: 200px; height: 200px; overflow: scroll; -moz-appearance:none">
<div style="width: 100000px; height: 1000000px"></div>
</div>

Просмотреть файл

@ -1,6 +1,5 @@
<!DOCTYPE html>
<meta http-equiv="msthemecompatible" content="no">
<div style="width: 200px; height: 200px; overflow: scroll;">
<div style="width: 200px; height: 200px; overflow: scroll;; -moz-appearance:none">
<div style="width: 3725px; height: 3725px"></div>
</div>
<!--

Просмотреть файл

@ -80,7 +80,7 @@ ListInterfaceAddresses(int aFd, const char* aInterface, AddrMapType& aAddrMap)
switch(family=ifreq.ifr_addr.sa_family) {
case AF_INET:
case AF_INET6:
getnameinfo(&ifreq.ifr_addr, sizeof(ifreq.ifr_addr), host, sizeof(host), 0, 0, NI_NUMERICHOST);
getnameinfo(&ifreq.ifr_addr, sizeof(ifreq.ifr_addr), host, sizeof(host), nullptr, 0, NI_NUMERICHOST);
break;
case AF_UNSPEC:
return NS_OK;

Просмотреть файл

@ -186,7 +186,7 @@ class Continuation {
}
Continuation() {
// empty constructor needed for nsTArray
value = 0L;
value = nullptr;
length = 0;
needsPercentDecoding = false;
wasQuotedString = false;
@ -971,7 +971,7 @@ nsMIMEHeaderParamImpl::DecodeParameter(const nsACString& aParamValue,
// static
char *DecodeQ(const char *in, uint32_t length)
{
char *out, *dest = 0;
char *out, *dest = nullptr;
out = dest = (char *)PR_Calloc(length + 1, sizeof(char));
if (dest == nullptr)
@ -1186,7 +1186,7 @@ nsresult DecodeRFC2047Str(const char *aHeader, const char *aDefaultCharset,
// safe because we don't use a raw *char any more.
aResult.SetCapacity(3 * strlen(aHeader));
while ((p = PL_strstr(begin, "=?")) != 0) {
while ((p = PL_strstr(begin, "=?")) != nullptr) {
if (isLastEncodedWord) {
// See if it's all whitespace.
for (q = begin; q < p; ++q) {
@ -1214,7 +1214,7 @@ nsresult DecodeRFC2047Str(const char *aHeader, const char *aDefaultCharset,
// Get charset info
charsetStart = p;
charsetEnd = 0;
charsetEnd = nullptr;
for (q = p; *q != '?'; q++) {
if (*q <= ' ' || PL_strchr(especials, *q)) {
goto badsyntax;

Просмотреть файл

@ -1337,7 +1337,7 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
getter_Copies(sval));
if (NS_SUCCEEDED(rv)) {
if (sval.IsEmpty())
mDefaultSocketType.Adopt(0);
mDefaultSocketType.Adopt(nullptr);
else {
// verify that this socket type is actually valid
nsCOMPtr<nsISocketProviderService> sps(
@ -1899,13 +1899,13 @@ PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLangua
count_n = 0;
p2 = q_Accept;
for (token = nsCRT::strtok(o_Accept, ",", &p);
token != (char *) 0;
token != nullptr;
token = nsCRT::strtok(p, ",", &p))
{
token = net_FindCharNotInSet(token, HTTP_LWS);
char* trim;
trim = net_FindCharInSet(token, ";" HTTP_LWS);
if (trim != (char*)0) // remove "; q=..." if present
if (trim != nullptr) // remove "; q=..." if present
*trim = '\0';
if (*token != '\0') {

Просмотреть файл

@ -196,7 +196,7 @@ public:
void* operator()(void* anObject) override {
nsCString *string = (nsCString*)anObject;
delete string;
return 0;
return nullptr;
}
};

Просмотреть файл

@ -215,9 +215,9 @@ void nsNotifyAddrListener::checkLink(void)
// Walk through the linked list, maintaining head pointer so we can free
// list later
for (ifa = list; ifa != NULL; ifa = ifa->ifa_next) {
for (ifa = list; ifa != nullptr; ifa = ifa->ifa_next) {
int family;
if (ifa->ifa_addr == NULL)
if (ifa->ifa_addr == nullptr)
continue;
family = ifa->ifa_addr->sa_family;

Просмотреть файл

@ -202,6 +202,12 @@ macosx64/opt:
- macosx64-tests-talos
- macosx64-tests-debug
macosx64-devedition/opt:
build-platform: macosx64-devedition/opt
test-sets:
- macosx64-tests-talos
- macosx64-tests-debug
##
# Android platforms (matching /android.*/)

Просмотреть файл

@ -28,6 +28,7 @@ BUILDER_NAME_PREFIX = {
'linux64-jsdcov': 'Ubuntu Code Coverage VM 12.04 x64',
'linux64-stylo': 'Ubuntu VM 12.04 x64',
'macosx64': 'Rev7 MacOSX Yosemite 10.10.5',
'macosx64-devedition': 'Rev7 MacOSX Yosemite 10.10.5 DevEdition',
'android-4.3-arm7-api-15': 'Android 4.3 armv7 API 15+',
'android-4.2-x86': 'Android 4.2 x86 Emulator',
'android-4.3-arm7-api-15-gradle': 'Android 4.3 armv7 API 15+',
@ -46,7 +47,7 @@ def test_packages_url(taskdesc):
build_platform = taskdesc['attributes']['build_platform']
build_type = taskdesc['attributes']['build_type']
if build_platform == 'macosx64' and build_type == 'opt':
if build_platform.startswith('macosx64') and build_type == 'opt':
target = 'firefox-{}.en-US.{}'.format(get_firefox_version(), 'mac')
else:
target = 'target'

Просмотреть файл

@ -56658,6 +56658,11 @@
{}
]
],
"html/semantics/forms/the-label-element/iframe-label-attributes.html": [
[
{}
]
],
"html/semantics/forms/the-legend-element/.gitkeep": [
[
{}
@ -189030,12 +189035,16 @@
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
"html/semantics/forms/the-label-element/iframe-label-attributes.html": [
"5110391fe9ee5f04c2175bdaa1f38eeba0c40803",
"support"
],
"html/semantics/forms/the-label-element/label-attributes.html": [
"bb00ee78b9fa2343d85dcaa13376a832d376617a",
"4ce7bb05fecd15b76e40959bb9ab1e0b0adcd8da",
"testharness"
],
"html/semantics/forms/the-label-element/labelable-elements.html": [
"421328f898fb2487152f6fd8df315fc22ddea61a",
"80275984254360d8b713b5b330c18ae34138b670",
"testharness"
],
"html/semantics/forms/the-label-element/proxy-click-to-associated-element.html": [

Просмотреть файл

@ -1060,9 +1060,6 @@
[HTMLInputElement interface: attribute valueHigh]
expected: FAIL
[HTMLInputElement interface: attribute labels]
expected: FAIL
[HTMLInputElement interface: document.createElement("input") must inherit property "dirName" with the proper type (6)]
expected: FAIL
@ -1078,9 +1075,6 @@
[HTMLButtonElement interface: attribute menu]
expected: FAIL
[HTMLButtonElement interface: attribute labels]
expected: FAIL
[HTMLButtonElement interface: document.createElement("button") must inherit property "menu" with the proper type (11)]
expected: FAIL
@ -1090,15 +1084,9 @@
[HTMLSelectElement interface: attribute autocomplete]
expected: FAIL
[HTMLSelectElement interface: attribute labels]
expected: FAIL
[HTMLSelectElement interface: document.createElement("select") must inherit property "autocomplete" with the proper type (0)]
expected: FAIL
[HTMLSelectElement interface: document.createElement("select") must inherit property "labels" with the proper type (26)]
expected: FAIL
[HTMLTextAreaElement interface: attribute autocomplete]
expected: FAIL
@ -1108,9 +1096,6 @@
[HTMLTextAreaElement interface: attribute inputMode]
expected: FAIL
[HTMLTextAreaElement interface: attribute labels]
expected: FAIL
[HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "autocomplete" with the proper type (0)]
expected: FAIL
@ -1120,9 +1105,6 @@
[HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "inputMode" with the proper type (6)]
expected: FAIL
[HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "labels" with the proper type (25)]
expected: FAIL
[HTMLKeygenElement interface: existence and properties of interface object]
expected: FAIL
@ -1228,24 +1210,6 @@
[HTMLKeygenElement interface: document.createElement("keygen") must inherit property "labels" with the proper type (13)]
expected: FAIL
[HTMLOutputElement interface: attribute labels]
expected: FAIL
[HTMLOutputElement interface: document.createElement("output") must inherit property "labels" with the proper type (12)]
expected: FAIL
[HTMLProgressElement interface: attribute labels]
expected: FAIL
[HTMLProgressElement interface: document.createElement("progress") must inherit property "labels" with the proper type (3)]
expected: FAIL
[HTMLMeterElement interface: attribute labels]
expected: FAIL
[HTMLMeterElement interface: document.createElement("meter") must inherit property "labels" with the proper type (6)]
expected: FAIL
[HTMLMenuItemElement interface: attribute default]
expected: FAIL
@ -2755,75 +2719,6 @@
[HTMLMediaElement interface: new Audio() must inherit property "videoTracks" with the proper type (39)]
expected: FAIL
[HTMLInputElement interface: document.createElement("input") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("text") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("hidden") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("search") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("tel") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("url") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("email") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("password") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("date") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("month") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("week") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("time") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("datetime-local") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("number") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("range") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("color") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("checkbox") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("radio") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("file") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("submit") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("image") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("reset") must inherit property "labels" with the proper type (46)]
expected: FAIL
[HTMLInputElement interface: createInput("button") must inherit property "labels" with the proper type (46)]
expected: FAIL
[CanvasRenderingContext2D interface: operation getTransform()]
expected: FAIL
@ -3379,9 +3274,6 @@
[Document interface: document.implementation.createDocument(null, "", null) must inherit property "onmousewheel" with the proper type (126)]
expected: FAIL
[HTMLButtonElement interface: document.createElement("button") must inherit property "labels" with the proper type (17)]
expected: FAIL
[HTMLScriptElement interface: attribute noModule]
expected: FAIL

Просмотреть файл

@ -1,17 +0,0 @@
[label-attributes.html]
type: testharness
[A non-control follows by a control with same ID.]
expected: FAIL
[A form control has multiple labels.]
expected: FAIL
[A form control has no label 1.]
expected: FAIL
[A form control has no label 2.]
expected: FAIL
[A form control has an implicit label.]
expected: FAIL

Просмотреть файл

@ -1,32 +1,6 @@
[labelable-elements.html]
type: testharness
[Check if the output element can access 'labels']
expected: FAIL
[Check if the progress element can access 'labels']
expected: FAIL
[Check if the select element can access 'labels']
expected: FAIL
[Check if the textarea element can access 'labels']
expected: FAIL
[Check if the button element can access 'labels']
expected: FAIL
[Check if the hidden input element can access 'labels']
expected: FAIL
[Check if the input element in radio state can access 'labels']
expected: FAIL
[Check if the meter element can access 'labels']
expected: FAIL
[Check if the hidden input element has null 'labels']
expected: FAIL
[Check if the keygen element is not a labelable element]
expected: FAIL
[Check if the keygen element can access 'labels']
expected: FAIL

Просмотреть файл

@ -1,5 +0,0 @@
[button_labels.html]
type: testharness
[Forms]
expected: FAIL

Просмотреть файл

@ -1,5 +0,0 @@
[input_labels.html]
type: testharness
[Forms]
expected: FAIL

Просмотреть файл

@ -0,0 +1,8 @@
<html>
<body>
<label>
<div id="div1"></div>
</label>
<label for="test13"></label>
</body>
</html>

Просмотреть файл

@ -32,10 +32,53 @@
<label id="lbl5" for="test7"></label>
<input id="test7">
<label id="lbl7">
<label id="lbl8">
<div id="div1">
<input id="test8">
</div>
</label>
</label>
<div id="div2"></div>
<label id="lbl9">
<label id="lbl10" for="test10">
<div id="div3">
<input id="test9">
</div>
</label>
</label>
<div id="div4"><input id="test10"></div>
<label id="lbl11">
<object id="obj">
<input id="test11">
<input id="test12">
</object>
</label>
<label id="lbl12" for="test12"><div id="div5"></div></label>
<label id="lbl13">
<p id="p1">
<input id="test13">
</p>
</label>
<div id="div6">
<div id="div7">
<label id="lbl14">
<label id="lbl15" for="test15">
<input id="test14">
</label>
</label>
</div>
</div>
<input id="test15">
</form>
<label id="lbl6" for="test7"></label>
<div id="content" style="display: none">
<script>
//control attribute
@ -57,6 +100,7 @@
}, "A label element not in a document can not label any element in the document.");
test(function () {
var labels = document.getElementById("test3").labels;
assert_equals(document.getElementById("lbl1").control, document.getElementById("test3"),
"The first labelable descendant of a label element should be its labeled control.");
@ -64,6 +108,10 @@
document.getElementById("lbl1").insertBefore(input, document.getElementById("test2"));
assert_equals(document.getElementById("lbl1").control, input,
"The first labelable descendant of a label element in tree order should be its labeled control.");
assert_equals(input.labels.length, 1,
"The form control has an ancestor with no explicit associated label, and is the first labelable descendant.");
assert_equals(labels.length, 0,
"The number of labels should be 0 if it's not the first labelable descendant of a label element.");
input.remove();
}, "The labeled control for a label element that has no 'for' attribute is the first labelable element which is a descendant of that label element.");
@ -100,6 +148,168 @@
newLabel.remove();
}, "A form control has multiple labels.");
test(function () {
var labels = document.getElementById("test8").labels;
assert_true(labels instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
assert_equals(labels.length, 2,
"The form control has two ancestors with no explicit associated label, and is the first labelable descendant.");
assert_array_equals(labels, [document.getElementById("lbl7"), document.getElementById("lbl8")],
"The labels for a form control should be returned in tree order.");
document.getElementById('div2').insertBefore(document.getElementById('div1'), document.getElementById('div2').firstChild);
assert_equals(labels.length, 0,
"The number of labels should be 0 after the labelable element is moved to outside of nested associated labels.");
}, "A labelable element is moved to outside of nested associated labels.");
test(function () {
var labels1 = document.getElementById("test9").labels;
var labels2 = document.getElementById("test10").labels;
assert_true(labels1 instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
assert_true(labels2 instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
assert_equals(labels1.length, 1,
"The form control has an ancestor with no explicit associated label, and is the first labelable descendant.");
assert_equals(labels2.length, 1,
"The number of labels associated with a form control should be the number of label elements for which it is a labeled control.");
assert_array_equals(labels1, [document.getElementById("lbl9")],
"The labels for a form control should be returned in tree order.");
assert_array_equals(labels2, [document.getElementById("lbl10")],
"The labels for a form control should be returned in tree order.");
document.getElementById('div3').insertBefore(document.getElementById('div4'), document.getElementById('div3').firstChild);
assert_equals(labels1.length, 0,
"The number of labels should be 0 if it's not the first labelable descendant of a label element.");
assert_equals(labels2.length, 2,
"The form control has an ancestor with an explicit associated label, and is the first labelable descendant.");
}, "A labelable element is moved to inside of nested associated labels.");
test(function () {
var labels1 = document.getElementById("test11").labels;
var labels2 = document.getElementById("test12").labels;
assert_true(labels1 instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
assert_true(labels2 instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
assert_equals(labels1.length, 1,
"The form control has an ancestor with no explicit associated label, and it is the first labelable descendant.");
assert_equals(labels2.length, 1,
"The number of labels should be 1 since there is a label with a 'for' attribute associated with this labelable element.");
assert_array_equals(labels1, [document.getElementById("lbl11")],
"The labels for a form control should be returned in tree order.");
assert_array_equals(labels2, [document.getElementById("lbl12")],
"The labels for a form control should be returned in tree order.");
document.getElementById('div5').appendChild(document.getElementById('obj'));
assert_equals(labels1.length, 0,
"The number of labels should be 0 after the labelable element is moved to outside of associated label.");
assert_equals(labels2.length, 1,
"The number of labels should be 1 after the labelable element is moved to outside of associated label.");
}, "A labelable element which is a descendant of non-labelable element is moved to outside of associated label.");
async_test(function () {
var labels = document.getElementById("test13").labels;
assert_true(labels instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
assert_equals(labels.length, 1,
"The form control has an ancestor with no explicit associated label, and is the first labelable descendant.");
assert_array_equals(labels, [document.getElementById("lbl13")],
"The labels for a form control should be returned in tree order.");
let iframe = document.createElement('iframe');
iframe.onload = this.step_func_done(() => {
iframe.contentWindow.document.getElementById("div1").appendChild(document.getElementById("p1"));
assert_equals(labels.length, 2,
"The number of labels should be 2 after the labelable element is moved to iframe.");
});
iframe.setAttribute('src', 'http://web-platform.test:8000/html/semantics/forms/the-label-element/iframe-label-attributes.html');
document.body.appendChild(iframe);
}, "A labelable element is moved to iframe.");
test(function () {
var labels1 = document.getElementById("test14").labels;
var labels2 = document.getElementById("test15").labels;
assert_true(labels1 instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
assert_equals(labels1.length, 1,
"The form control has an ancestor with no explicit associated label, and is the first labelable descendant.");
assert_equals(labels2.length, 1,
"The number of labels associated with a form control should be the number of label elements for which it is a labeled control.");
assert_array_equals(labels1, [document.getElementById("lbl14")],
"The labels for a form control should be returned in tree order.");
document.getElementById('div6').removeChild(document.getElementById('div7'));
assert_equals(labels1.length, 0,
"The number of labels should be 0 after the labelable element is removed.");
assert_equals(labels2.length, 0,
"The number of labels should be 0 since there is no label with a 'for' attribute associated with this labelable element.");
}, "A div element which contains labelable element is removed.");
test(function () {
// <label><input id="test16"><label for="test16"></label></label>
var label1 = document.createElement('label');
label1.innerHTML = "<input id='test16'>";
var label2 = document.createElement('label');
label2.htmlFor = "test16";
label1.appendChild(label2);
var input = label1.firstChild;
var labels = input.labels;
assert_equals(labels.length, 2,
"The number of labels associated with a form control should be the number of label elements for which it is a labeled control.");
assert_true(labels instanceof NodeList,
"A form control's 'labels' property should be an instance of a NodeList.");
assert_equals(label1.control, input, "The first labelable descendant of a label element should be its labeled control.");
assert_equals(label2.control, input, "The labeled cotrol should be associated with the control whose ID is equal to the value of the 'for' attribute.");
}, "A labelable element not in a document can label element in the same tree.");
test(function () {
var isShadowDOMV0;
if ("createShadowRoot" in document.getElementById('content')) {
isShadowDOMV0 = true;
}
var root1;
if (isShadowDOMV0) {
root1 = document.getElementById('content').createShadowRoot();
} else {
root1 = document.getElementById('content').attachShadow({mode: 'open'});
}
assert_true(root1 instanceof DocumentFragment,
"ShadowRoot should be an instance of DocumentFragment.");
// <label><input id="shadow1"/></label><div id="div1"></div>
var label1 = document.createElement('label');
var input1 = document.createElement('input');
input1.setAttribute("id", "shadow1");
label1.appendChild(input1);
root1.appendChild(label1);
var div1 = document.createElement('div');
label1.appendChild(div1);
// <label for="shadow2"></label><input id="shadow2"/>
var root2;
if (isShadowDOMV0) {
root2 = div1.createShadowRoot();
} else {
root2 = div1.attachShadow({mode: 'open'});
}
assert_true(root2 instanceof DocumentFragment,
"ShadowRoot should be an instance of DocumentFragment.");
var label2 = document.createElement('label');
label2.setAttribute("for", "shadow2");
var input2 = document.createElement('input');
input2.setAttribute("id", "shadow2");
root2.appendChild(label2);
root2.appendChild(input2);
assert_equals(root1.getElementById("shadow1").labels.length, 1,
"The form control has an ancestor with no explicit associated label, and it is the first labelable descendant.");
assert_equals(root2.getElementById("shadow2").labels.length, 1,
"The number of labels should be 1 since there is a label with a 'for' attribute associated with this labelable element.");
}, "A labelable element inside the shadow DOM.");
test(function () {
var labels = document.getElementById("test3").labels;
assert_true(labels instanceof NodeList, "A form control's 'labels' property should be an instance of a NodeList.");

Просмотреть файл

@ -104,6 +104,7 @@ test(function() {
hiddenInput.type = "hidden";
assert_equals(labels.length, 0, "Retained .labels NodeList should be empty after input type changed to hidden");
assert_equals(hiddenInput.labels, null, ".labels NodeList should be null after input type changed to hidden");
hiddenInput.type = "checkbox";
assert_true(labels === hiddenInput.labels, ".labels property must return the [SameObject] after input type is toggled back from 'hidden'");

Просмотреть файл

@ -190,6 +190,7 @@ var listener = {
onWindowLoaded() {
let browser = this.win.document.createElementNS(XUL_NS, "browser");
browser.setAttribute("type", "content");
browser.setAttribute("disableglobalhistory", "true");
let remoteBrowser = Services.appinfo.browserTabsRemoteAutostart;
browser.setAttribute("remote", remoteBrowser);

Просмотреть файл

@ -259,7 +259,12 @@ this.SelectContentHelper.prototype = {
case "Forms:DismissedDropDown":
let selectedOption = this.element.item(this.element.selectedIndex);
if (this.initialSelection != selectedOption) {
if (this.initialSelection === selectedOption) {
// Clear active document
DOMUtils.removeContentState(this.element,
kStateActive,
/* aClearActiveDocument */ true);
} else {
let win = this.element.ownerGlobal;
// For ordering of events, we're using non-e10s as our guide here,
// since the spec isn't exactly clear. In non-e10s, we fire:
@ -270,8 +275,12 @@ this.SelectContentHelper.prototype = {
if (!this.closedWithEnter) {
this.dispatchMouseEvent(win, selectedOption, "mousedown");
this.dispatchMouseEvent(win, selectedOption, "mouseup");
DOMUtils.removeContentState(this.element, kStateActive);
}
// Clear active document no matter user selects
// via keyboard or mouse
DOMUtils.removeContentState(this.element,
kStateActive,
/* aClearActiveDocument */ true);
let inputEvent = new win.UIEvent("input", {
bubbles: true,

Просмотреть файл

@ -3574,12 +3574,6 @@ bool
nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame,
uint8_t aWidgetType)
{
// We don't have CSS set up to render non-native scrollbars on Mac OS X so we
// render natively even if native theme support is disabled.
if (aWidgetType != NS_THEME_SCROLLBAR &&
aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
return false;
// if this is a dropdown button in a combobox the answer is always no
if (aWidgetType == NS_THEME_MENULIST_BUTTON) {
nsIFrame* parentFrame = aFrame->GetParent();

Просмотреть файл

@ -2441,9 +2441,6 @@ nsNativeThemeWin::ThemeSupportsWidget(nsPresContext* aPresContext,
// XXXdwh We can go even further and call the API to ask if support exists for
// specific widgets.
if (aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
return false;
if (aWidgetType == NS_THEME_FOCUS_OUTLINE) {
return true;
}