mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Merge inbound to central, a=merge
MozReview-Commit-ID: 4igUgM6r0wO
This commit is contained in:
commit
d509baac11
@ -1495,6 +1495,10 @@ a11y::ProxyEvent(ProxyAccessible* aTarget, uint32_t aEventType)
|
|||||||
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
|
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
|
||||||
g_object_notify((GObject*)wrapper, "accessible-value");
|
g_object_notify((GObject*)wrapper, "accessible-value");
|
||||||
break;
|
break;
|
||||||
|
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
|
||||||
|
case nsIAccessibleEvent::EVENT_SELECTION_WITHIN:
|
||||||
|
g_signal_emit_by_name(wrapper, "selection_changed");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1610,6 +1614,13 @@ MaiAtkObject::FireAtkShowHideEvent(AtkObject* aParent, bool aIsAdded,
|
|||||||
g_signal_emit_by_name(aParent, signal_name, indexInParent, this, nullptr);
|
g_signal_emit_by_name(aParent, signal_name, indexInParent, this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
a11y::ProxySelectionEvent(ProxyAccessible*, ProxyAccessible* aWidget, uint32_t)
|
||||||
|
{
|
||||||
|
MaiAtkObject* obj = MAI_ATK_OBJECT(GetWrapperFor(aWidget));
|
||||||
|
g_signal_emit_by_name(obj, "selection_changed");
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
AccessibleWrap::GetKeyBinding(Accessible* aAccessible, nsAString& aResult)
|
AccessibleWrap::GetKeyBinding(Accessible* aAccessible, nsAString& aResult)
|
||||||
|
@ -77,6 +77,8 @@ void ProxyTextChangeEvent(ProxyAccessible* aTarget, const nsString& aStr,
|
|||||||
bool aFromUser);
|
bool aFromUser);
|
||||||
void ProxyShowHideEvent(ProxyAccessible* aTarget, ProxyAccessible* aParent,
|
void ProxyShowHideEvent(ProxyAccessible* aTarget, ProxyAccessible* aParent,
|
||||||
bool aInsert, bool aFromUser);
|
bool aInsert, bool aFromUser);
|
||||||
|
void ProxySelectionEvent(ProxyAccessible* aTarget, ProxyAccessible* aWidget,
|
||||||
|
uint32_t aType);
|
||||||
} // namespace a11y
|
} // namespace a11y
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
@ -884,6 +884,15 @@ Accessible::HandleAccEvent(AccEvent* aEvent)
|
|||||||
event->IsFromUserInput());
|
event->IsFromUserInput());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case nsIAccessibleEvent::EVENT_SELECTION:
|
||||||
|
case nsIAccessibleEvent::EVENT_SELECTION_ADD:
|
||||||
|
case nsIAccessibleEvent::EVENT_SELECTION_REMOVE: {
|
||||||
|
AccSelChangeEvent* selEvent = downcast_accEvent(aEvent);
|
||||||
|
uint64_t widgetID = selEvent->Widget()->IsDoc() ? 0 :
|
||||||
|
reinterpret_cast<uintptr_t>(selEvent->Widget());
|
||||||
|
ipcDoc->SendSelectionEvent(id, widgetID, aEvent->GetEventType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ipcDoc->SendEvent(id, aEvent->GetEventType());
|
ipcDoc->SendEvent(id, aEvent->GetEventType());
|
||||||
}
|
}
|
||||||
|
@ -160,6 +160,25 @@ DocAccessible::GetAccessibleEvenIfNotInMapOrContainer(nsINode* aNode) const
|
|||||||
return acc ? acc : GetContainerAccessible(aNode);
|
return acc ? acc : GetContainerAccessible(aNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
DocAccessible::CreateSubtree(Accessible* aChild)
|
||||||
|
{
|
||||||
|
// If a focused node has been shown then it could mean its frame was recreated
|
||||||
|
// while the node stays focused and we need to fire focus event on
|
||||||
|
// the accessible we just created. If the queue contains a focus event for
|
||||||
|
// this node already then it will be suppressed by this one.
|
||||||
|
Accessible* focusedAcc = nullptr;
|
||||||
|
CacheChildrenInSubtree(aChild, &focusedAcc);
|
||||||
|
|
||||||
|
// XXX: do we really want to send focus to focused DOM node not taking into
|
||||||
|
// account active item?
|
||||||
|
if (focusedAcc) {
|
||||||
|
FocusMgr()->DispatchFocusEvent(this, focusedAcc);
|
||||||
|
SelectionMgr()->
|
||||||
|
SetControlSelectionListener(focusedAcc->GetNode()->AsElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace a11y
|
} // namespace a11y
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
@ -1762,7 +1762,6 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
|
|||||||
aContainer);
|
aContainer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t updateFlags = 0;
|
|
||||||
TreeMutation mt(aContainer);
|
TreeMutation mt(aContainer);
|
||||||
do {
|
do {
|
||||||
Accessible* parent = iter.Child()->Parent();
|
Accessible* parent = iter.Child()->Parent();
|
||||||
@ -1791,7 +1790,7 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
mt.AfterInsertion(iter.Child());
|
mt.AfterInsertion(iter.Child());
|
||||||
updateFlags |= UpdateTreeInternal(iter.Child(), true);
|
CreateSubtree(iter.Child());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1805,7 +1804,7 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
|
|||||||
aContainer);
|
aContainer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FireEventsOnInsertion(aContainer, updateFlags);
|
FireEventsOnInsertion(aContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1828,25 +1827,18 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, nsIContent* aNode)
|
|||||||
mt.AfterInsertion(child);
|
mt.AfterInsertion(child);
|
||||||
mt.Done();
|
mt.Done();
|
||||||
|
|
||||||
uint32_t flags = UpdateTreeInternal(child, true);
|
CreateSubtree(child);
|
||||||
FireEventsOnInsertion(aContainer, flags);
|
FireEventsOnInsertion(aContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DocAccessible::FireEventsOnInsertion(Accessible* aContainer,
|
DocAccessible::FireEventsOnInsertion(Accessible* aContainer)
|
||||||
uint32_t aUpdateFlags)
|
|
||||||
{
|
{
|
||||||
// Content insertion did not cause an accessible tree change.
|
|
||||||
if (aUpdateFlags == eNoAccessible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if change occurred inside an alert, and fire an EVENT_ALERT
|
// Check to see if change occurred inside an alert, and fire an EVENT_ALERT
|
||||||
// if it did.
|
// if it did.
|
||||||
if (!(aUpdateFlags & eAlertAccessible) &&
|
if (aContainer->IsAlert() || aContainer->IsInsideAlert()) {
|
||||||
(aContainer->IsAlert() || aContainer->IsInsideAlert())) {
|
|
||||||
Accessible* ancestor = aContainer;
|
Accessible* ancestor = aContainer;
|
||||||
do {
|
do {
|
||||||
if (ancestor->IsAlert()) {
|
if (ancestor->IsAlert()) {
|
||||||
@ -1880,72 +1872,23 @@ DocAccessible::UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNod
|
|||||||
TreeMutation mt(aContainer);
|
TreeMutation mt(aContainer);
|
||||||
if (child) {
|
if (child) {
|
||||||
mt.BeforeRemoval(child);
|
mt.BeforeRemoval(child);
|
||||||
UpdateTreeInternal(child, false);
|
MOZ_ASSERT(aContainer == child->Parent(), "Wrong parent");
|
||||||
|
aContainer->RemoveChild(child);
|
||||||
|
UncacheChildrenInSubtree(child);
|
||||||
|
mt.Done();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
TreeWalker walker(aContainer, aChildNode, TreeWalker::eWalkCache);
|
TreeWalker walker(aContainer, aChildNode, TreeWalker::eWalkCache);
|
||||||
Accessible* child = walker.Next();
|
while (Accessible* child = walker.Next()) {
|
||||||
if (child) {
|
mt.BeforeRemoval(child);
|
||||||
do {
|
MOZ_ASSERT(aContainer == child->Parent(), "Wrong parent");
|
||||||
mt.BeforeRemoval(child);
|
aContainer->RemoveChild(child);
|
||||||
UpdateTreeInternal(child, false);
|
UncacheChildrenInSubtree(child);
|
||||||
}
|
|
||||||
while ((child = walker.Next()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mt.Done();
|
mt.Done();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
|
||||||
DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert)
|
|
||||||
{
|
|
||||||
uint32_t updateFlags = eAccessible;
|
|
||||||
|
|
||||||
// If a focused node has been shown then it could mean its frame was recreated
|
|
||||||
// while the node stays focused and we need to fire focus event on
|
|
||||||
// the accessible we just created. If the queue contains a focus event for
|
|
||||||
// this node already then it will be suppressed by this one.
|
|
||||||
Accessible* focusedAcc = nullptr;
|
|
||||||
|
|
||||||
if (aIsInsert) {
|
|
||||||
// Create accessible tree for shown accessible.
|
|
||||||
CacheChildrenInSubtree(aChild, &focusedAcc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aIsInsert) {
|
|
||||||
roles::Role ariaRole = aChild->ARIARole();
|
|
||||||
if (ariaRole == roles::MENUPOPUP) {
|
|
||||||
// Fire EVENT_MENUPOPUP_START if ARIA menu appears.
|
|
||||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
|
|
||||||
|
|
||||||
} else if (ariaRole == roles::ALERT) {
|
|
||||||
// Fire EVENT_ALERT if ARIA alert appears.
|
|
||||||
updateFlags = eAlertAccessible;
|
|
||||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Update the tree for content removal.
|
|
||||||
// The accessible parent may differ from container accessible if
|
|
||||||
// the parent doesn't have own DOM node like list accessible for HTML
|
|
||||||
// selects.
|
|
||||||
Accessible* parent = aChild->Parent();
|
|
||||||
NS_ASSERTION(parent, "No accessible parent?!");
|
|
||||||
if (parent)
|
|
||||||
parent->RemoveChild(aChild);
|
|
||||||
|
|
||||||
UncacheChildrenInSubtree(aChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: do we really want to send focus to focused DOM node not taking into
|
|
||||||
// account active item?
|
|
||||||
if (focusedAcc) {
|
|
||||||
FocusMgr()->DispatchFocusEvent(this, focusedAcc);
|
|
||||||
SelectionMgr()->SetControlSelectionListener(focusedAcc->GetNode()->AsElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
return updateFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DocAccessible::RelocateARIAOwnedIfNeeded(nsIContent* aElement)
|
DocAccessible::RelocateARIAOwnedIfNeeded(nsIContent* aElement)
|
||||||
{
|
{
|
||||||
@ -2045,8 +1988,8 @@ DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
|
|||||||
insertIdx = child->IndexInParent() + 1;
|
insertIdx = child->IndexInParent() + 1;
|
||||||
arrayIdx++;
|
arrayIdx++;
|
||||||
|
|
||||||
uint32_t flags = UpdateTreeInternal(child, true);
|
CreateSubtree(child);
|
||||||
FireEventsOnInsertion(aOwner, flags);
|
FireEventsOnInsertion(aOwner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -2233,12 +2176,26 @@ DocAccessible::CacheChildrenInSubtree(Accessible* aRoot,
|
|||||||
mt.Done();
|
mt.Done();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire document load complete on ARIA documents.
|
// Fire events for ARIA elements.
|
||||||
// XXX: we should delay an event if the ARIA document has aria-busy.
|
if (!aRoot->HasARIARole()) {
|
||||||
if (aRoot->HasARIARole() && !aRoot->IsDoc()) {
|
return;
|
||||||
a11y::role role = aRoot->ARIARole();
|
}
|
||||||
if (role == roles::DIALOG || role == roles::DOCUMENT)
|
|
||||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
|
roles::Role role = aRoot->ARIARole();
|
||||||
|
if (role == roles::MENUPOPUP) {
|
||||||
|
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aRoot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == roles::ALERT) {
|
||||||
|
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aRoot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: we should delay document load complete event if the ARIA document
|
||||||
|
// has aria-busy.
|
||||||
|
if (!aRoot->IsDoc() && (role == roles::DIALOG || role == roles::DOCUMENT)) {
|
||||||
|
FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void FireDelayedEvent(AccEvent* aEvent);
|
void FireDelayedEvent(AccEvent* aEvent);
|
||||||
void FireDelayedEvent(uint32_t aEventType, Accessible* aTarget);
|
void FireDelayedEvent(uint32_t aEventType, Accessible* aTarget);
|
||||||
void FireEventsOnInsertion(Accessible* aContainer, uint32_t aUpdateFlags);
|
void FireEventsOnInsertion(Accessible* aContainer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fire value change event on the given accessible if applicable.
|
* Fire value change event on the given accessible if applicable.
|
||||||
@ -516,17 +516,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNode);
|
void UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNode);
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for UpdateTreeOn methods. Go down to DOM subtree and updates
|
|
||||||
* accessible tree. Return one of these flags.
|
|
||||||
*/
|
|
||||||
enum EUpdateTreeFlags {
|
|
||||||
eNoAccessible = 0,
|
|
||||||
eAccessible = 1,
|
|
||||||
eAlertAccessible = 2
|
|
||||||
};
|
|
||||||
uint32_t UpdateTreeInternal(Accessible* aChild, bool aIsInsert);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates all aria-owns connections and updates the tree accordingly.
|
* Validates all aria-owns connections and updates the tree accordingly.
|
||||||
*/
|
*/
|
||||||
@ -555,6 +544,7 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void CacheChildrenInSubtree(Accessible* aRoot,
|
void CacheChildrenInSubtree(Accessible* aRoot,
|
||||||
Accessible** aFocusedAcc = nullptr);
|
Accessible** aFocusedAcc = nullptr);
|
||||||
|
void CreateSubtree(Accessible* aRoot);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove accessibles in subtree from node to accessible map.
|
* Remove accessibles in subtree from node to accessible map.
|
||||||
|
@ -259,6 +259,31 @@ DocAccessibleParent::RecvTextChangeEvent(const uint64_t& aID,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID,
|
||||||
|
const uint64_t& aWidgetID,
|
||||||
|
const uint32_t& aType)
|
||||||
|
{
|
||||||
|
ProxyAccessible* target = GetAccessible(aID);
|
||||||
|
ProxyAccessible* widget = GetAccessible(aWidgetID);
|
||||||
|
if (!target || !widget) {
|
||||||
|
NS_ERROR("invalid id in selection event");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxySelectionEvent(target, widget, aType);
|
||||||
|
if (!nsCoreUtils::AccEventObserversExist()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
xpcAccessibleGeneric* xpcTarget = GetXPCAccessible(target);
|
||||||
|
xpcAccessibleDocument* xpcDoc = GetAccService()->GetXPCDocument(this);
|
||||||
|
RefPtr<xpcAccEvent> event = new xpcAccEvent(aType, xpcTarget, xpcDoc,
|
||||||
|
nullptr, false);
|
||||||
|
nsCoreUtils::DispatchAccEvent(Move(event));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DocAccessibleParent::RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID)
|
DocAccessibleParent::RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID)
|
||||||
{
|
{
|
||||||
|
@ -64,6 +64,10 @@ public:
|
|||||||
const bool& aIsInsert,
|
const bool& aIsInsert,
|
||||||
const bool& aFromUser) override;
|
const bool& aFromUser) override;
|
||||||
|
|
||||||
|
virtual bool RecvSelectionEvent(const uint64_t& aID,
|
||||||
|
const uint64_t& aWidgetID,
|
||||||
|
const uint32_t& aType) override;
|
||||||
|
|
||||||
virtual bool RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override;
|
virtual bool RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override;
|
||||||
void Unbind()
|
void Unbind()
|
||||||
{
|
{
|
||||||
|
@ -61,6 +61,7 @@ parent:
|
|||||||
async CaretMoveEvent(uint64_t aID, int32_t aOffset);
|
async CaretMoveEvent(uint64_t aID, int32_t aOffset);
|
||||||
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
|
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
|
||||||
bool aIsInsert, bool aFromUser);
|
bool aIsInsert, bool aFromUser);
|
||||||
|
async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the parent document to bind the existing document as a new child
|
* Tell the parent document to bind the existing document as a new child
|
||||||
|
@ -106,6 +106,11 @@ void
|
|||||||
ProxyShowHideEvent(ProxyAccessible*, ProxyAccessible*, bool, bool)
|
ProxyShowHideEvent(ProxyAccessible*, ProxyAccessible*, bool, bool)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ProxySelectionEvent(ProxyAccessible*, ProxyAccessible*, uint32_t)
|
||||||
|
{
|
||||||
|
}
|
||||||
} // namespace a11y
|
} // namespace a11y
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
@ -54,3 +54,8 @@ void
|
|||||||
a11y::ProxyShowHideEvent(ProxyAccessible*, ProxyAccessible*, bool, bool)
|
a11y::ProxyShowHideEvent(ProxyAccessible*, ProxyAccessible*, bool, bool)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
a11y::ProxySelectionEvent(ProxyAccessible*, ProxyAccessible*, uint32_t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -127,3 +127,10 @@ a11y::ProxyShowHideEvent(ProxyAccessible* aTarget, ProxyAccessible*, bool aInser
|
|||||||
AccessibleWrap* wrapper = WrapperFor(aTarget);
|
AccessibleWrap* wrapper = WrapperFor(aTarget);
|
||||||
AccessibleWrap::FireWinEvent(wrapper, event);
|
AccessibleWrap::FireWinEvent(wrapper, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
a11y::ProxySelectionEvent(ProxyAccessible* aTarget, ProxyAccessible*, uint32_t aType)
|
||||||
|
{
|
||||||
|
AccessibleWrap* wrapper = WrapperFor(aTarget);
|
||||||
|
AccessibleWrap::FireWinEvent(wrapper, aType);
|
||||||
|
}
|
||||||
|
@ -138,58 +138,11 @@ button.default.focused {
|
|||||||
/* Radio Buttons */
|
/* Radio Buttons */
|
||||||
.radioItem {
|
.radioItem {
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"] {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"] + label {
|
input[type="radio"] + label {
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
}
|
text-align: left;
|
||||||
|
|
||||||
input[type="radio"] + label::before {
|
|
||||||
background-color: #fff;
|
|
||||||
background-position: center;
|
|
||||||
border: 1px solid #b1b1b1;
|
|
||||||
border-radius: 50%;
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
height: 16px;
|
|
||||||
margin-right: 6px;
|
|
||||||
vertical-align: text-top;
|
|
||||||
width: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"]:hover + label::before,
|
|
||||||
.radioItem.hover input[type="radio"]:not(active) + label::before {
|
|
||||||
background-color: #fbfbfb;
|
|
||||||
border-color: #b1b1b1;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"]:hover:active + label::before,
|
|
||||||
.radioItem.pressed input[type="radio"]:not(active) + label::before {
|
|
||||||
background-color: #ebebeb;
|
|
||||||
border-color: #858585;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"]:checked + label::before {
|
|
||||||
background-color: #0996f8;
|
|
||||||
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iNCIgZmlsbD0iI2ZmZiIgLz4KPC9zdmc+Cg==);
|
|
||||||
border-color: #0670cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"]:checked:hover + label::before,
|
|
||||||
.radioItem.hover input[type="radio"]:checked:not(active) + label::before {
|
|
||||||
background-color: #0670cc;
|
|
||||||
border-color: #005bab;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"]:checked:hover:active + label::before,
|
|
||||||
.radioItem.pressed input[type="radio"]:checked:not(active) + label::before {
|
|
||||||
background-color: #005bab;
|
|
||||||
border-color: #004480;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.radioItem.disabled input[type="radio"] + label,
|
.radioItem.disabled input[type="radio"] + label,
|
||||||
@ -199,69 +152,14 @@ input[type="radio"]:checked:hover:active + label::before,
|
|||||||
opacity: .5;
|
opacity: .5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radioItem.focused input[type="radio"] + label::before {
|
|
||||||
border-color: #0996f8;
|
|
||||||
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.radioItem.focused input[type="radio"]:checked + label::before {
|
|
||||||
border-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checkboxes */
|
/* Checkboxes */
|
||||||
.checkboxItem {
|
.checkboxItem {
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"] {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] + label {
|
input[type="checkbox"] + label {
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
}
|
text-align: left;
|
||||||
|
|
||||||
input[type="checkbox"] + label::before {
|
|
||||||
background-color: #fff;
|
|
||||||
background-position: center;
|
|
||||||
border: 1px solid #b1b1b1;
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
height: 16px;
|
|
||||||
margin-right: 6px;
|
|
||||||
vertical-align: text-top;
|
|
||||||
width: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]:hover + label::before,
|
|
||||||
.checkboxItem.hover input[type="checkbox"]:not(active) + label::before {
|
|
||||||
background-color: #fbfbfb;
|
|
||||||
border-color: #b1b1b1;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]:hover:active + label::before,
|
|
||||||
.checkboxItem.pressed input[type="checkbox"]:not(active) + label::before {
|
|
||||||
background-color: #ebebeb;
|
|
||||||
border-color: #858585;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]:checked + label::before {
|
|
||||||
background-color: #0996f8;
|
|
||||||
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNNy43LDEyLjkgQzcuNCwxMy4zIDYuOCwxMy40IDYuNCwxMyBMMy4yLDkuOCBDMi44LDkuNCAyLjgsOC42IDMuMiw4LjIgQzMuNiw3LjggNC40LDcuOCA0LjgsOC4yIEw2LjksMTAuMyBMMTEuMSw0LjQgQzExLjUsMy45IDEyLjIsMy44IDEyLjcsNC4xIEMxMy4yLDQuNSAxMy4zLDUuMiAxMyw1LjcgTDcuNywxMi45IEw3LjcsMTIuOSBaIiBmaWxsPSIjZmZmIiAvPgo8L3N2Zz4K);
|
|
||||||
border-color: #0670cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]:checked:hover + label::before,
|
|
||||||
.checkboxItem.hover input[type="checkbox"]:checked:not(active) + label::before {
|
|
||||||
background-color: #0670cc;
|
|
||||||
border-color: #005bab;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="checkbox"]:checked:hover:active + label::before,
|
|
||||||
.checkboxItem.pressed input[type="checkbox"]:checked:not(active) + label::before {
|
|
||||||
background-color: #005bab;
|
|
||||||
border-color: #004480;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkboxItem.disabled input[type="checkbox"] + label,
|
.checkboxItem.disabled input[type="checkbox"] + label,
|
||||||
@ -271,15 +169,6 @@ input[type="checkbox"]:checked:hover:active + label::before,
|
|||||||
opacity: .5;
|
opacity: .5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkboxItem.focused input[type="checkbox"] + label::before {
|
|
||||||
border-color: #0996f8;
|
|
||||||
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkboxItem.focused input[type="checkbox"]:checked + label::before {
|
|
||||||
border-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expander Button */
|
/* Expander Button */
|
||||||
button.expander {
|
button.expander {
|
||||||
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==);
|
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==);
|
||||||
@ -465,7 +354,7 @@ textarea:focus:hover {
|
|||||||
|
|
||||||
.panel-formElements-item label {
|
.panel-formElements-item label {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-right: 6px;
|
margin: 0 6px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ if test -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
b2g-inbound|mozilla-inbound|fx-team)
|
mozilla-inbound|fx-team)
|
||||||
case "${master}" in
|
case "${master}" in
|
||||||
*use1.mozilla.com*)
|
*use1.mozilla.com*)
|
||||||
bucket=mozilla-releng-s3-cache-us-east-1-prod
|
bucket=mozilla-releng-s3-cache-us-east-1-prod
|
||||||
|
@ -96,6 +96,7 @@ public:
|
|||||||
, mIDType(eUnknown)
|
, mIDType(eUnknown)
|
||||||
, mOuterIDNumber(0)
|
, mOuterIDNumber(0)
|
||||||
, mInnerIDNumber(0)
|
, mInnerIDNumber(0)
|
||||||
|
, mStatus(eUnused)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
, mOwningThread(PR_GetCurrentThread())
|
, mOwningThread(PR_GetCurrentThread())
|
||||||
#endif
|
#endif
|
||||||
|
@ -1567,7 +1567,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
|
|||||||
|
|
||||||
if (!aString.empty()) {
|
if (!aString.empty()) {
|
||||||
aRequest->mScriptTextLength = aString.length();
|
aRequest->mScriptTextLength = aString.length();
|
||||||
aRequest->mScriptTextBuf = aString.extractRawBuffer();
|
aRequest->mScriptTextBuf = aString.extractOrCopyRawBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This assertion could fire errorously if we ran out of memory when
|
// This assertion could fire errorously if we ran out of memory when
|
||||||
|
@ -119,18 +119,7 @@ WebGLContext::GetChannelBits(const char* funcName, GLenum pname, GLint* const ou
|
|||||||
|
|
||||||
case LOCAL_GL_DEPTH_BITS:
|
case LOCAL_GL_DEPTH_BITS:
|
||||||
if (mOptions.depth) {
|
if (mOptions.depth) {
|
||||||
const auto& glFormats = gl->GetGLFormats();
|
*out_val = gl->Screen()->DepthBits();
|
||||||
|
|
||||||
GLenum depthFormat = glFormats.depth;
|
|
||||||
if (mOptions.stencil && glFormats.depthStencil) {
|
|
||||||
depthFormat = glFormats.depthStencil;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depthFormat == LOCAL_GL_DEPTH_COMPONENT16) {
|
|
||||||
*out_val = 16;
|
|
||||||
} else {
|
|
||||||
*out_val = 24;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
*out_val = 0;
|
*out_val = 0;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ NS_IMPL_RELEASE_INHERITED(CommandEvent, Event)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
CommandEvent::GetCommand(nsAString& aCommand)
|
CommandEvent::GetCommand(nsAString& aCommand)
|
||||||
{
|
{
|
||||||
nsIAtom* command = mEvent->AsCommandEvent()->command;
|
nsIAtom* command = mEvent->AsCommandEvent()->mCommand;
|
||||||
if (command) {
|
if (command) {
|
||||||
command->ToString(aCommand);
|
command->ToString(aCommand);
|
||||||
} else {
|
} else {
|
||||||
@ -53,7 +53,7 @@ CommandEvent::InitCommandEvent(const nsAString& aTypeArg,
|
|||||||
{
|
{
|
||||||
Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
|
||||||
|
|
||||||
mEvent->AsCommandEvent()->command = NS_Atomize(aCommand);
|
mEvent->AsCommandEvent()->mCommand = NS_Atomize(aCommand);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3831,6 +3831,8 @@ void HTMLMediaElement::CheckProgress(bool aHaveNewProgress)
|
|||||||
ChangeDelayLoadStatus(true);
|
ChangeDelayLoadStatus(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Download statistics may have been updated, force a recheck of the readyState.
|
||||||
|
UpdateReadyStateInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (now - mDataTime >= TimeDuration::FromMilliseconds(STALL_MS)) {
|
if (now - mDataTime >= TimeDuration::FromMilliseconds(STALL_MS)) {
|
||||||
|
@ -9,11 +9,14 @@
|
|||||||
#include "MediaData.h"
|
#include "MediaData.h"
|
||||||
#include "PDMFactory.h"
|
#include "PDMFactory.h"
|
||||||
#include "WebMDemuxer.h"
|
#include "WebMDemuxer.h"
|
||||||
#include "WebMSample.h"
|
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
#include "mozilla/dom/ContentChild.h"
|
#include "mozilla/dom/ContentChild.h"
|
||||||
|
|
||||||
|
#ifndef MOZ_WIDGET_ANDROID
|
||||||
|
#include "WebMSample.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
// Update this version number to force re-running the benchmark. Such as when
|
// Update this version number to force re-running the benchmark. Such as when
|
||||||
@ -30,6 +33,9 @@ VP9Benchmark::IsVP9DecodeFast()
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
bool hasPref = Preferences::HasUserValue(sBenchmarkFpsPref);
|
bool hasPref = Preferences::HasUserValue(sBenchmarkFpsPref);
|
||||||
uint32_t hadRecentUpdate = Preferences::GetUint(sBenchmarkFpsVersionCheck, 0U);
|
uint32_t hadRecentUpdate = Preferences::GetUint(sBenchmarkFpsVersionCheck, 0U);
|
||||||
|
|
||||||
@ -77,6 +83,7 @@ VP9Benchmark::IsVP9DecodeFast()
|
|||||||
Preferences::GetUint("media.benchmark.vp9.threshold", 150);
|
Preferences::GetUint("media.benchmark.vp9.threshold", 150);
|
||||||
|
|
||||||
return decodeFps >= threshold;
|
return decodeFps >= threshold;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Benchmark::Benchmark(MediaDataDemuxer* aDemuxer, const Parameters& aParameters)
|
Benchmark::Benchmark(MediaDataDemuxer* aDemuxer, const Parameters& aParameters)
|
||||||
|
@ -429,7 +429,7 @@ void MediaDecoderStateMachine::DiscardStreamData()
|
|||||||
|
|
||||||
const auto clockTime = GetClock();
|
const auto clockTime = GetClock();
|
||||||
while (true) {
|
while (true) {
|
||||||
const MediaData* a = AudioQueue().PeekFront();
|
RefPtr<MediaData> a = AudioQueue().PeekFront();
|
||||||
|
|
||||||
// If we discard audio samples fed to the stream immediately, we will
|
// If we discard audio samples fed to the stream immediately, we will
|
||||||
// keep decoding audio samples till the end and consume a lot of memory.
|
// keep decoding audio samples till the end and consume a lot of memory.
|
||||||
@ -1977,7 +1977,7 @@ MediaDecoderStateMachine::SeekCompleted()
|
|||||||
if (seekTime == Duration().ToMicroseconds()) {
|
if (seekTime == Duration().ToMicroseconds()) {
|
||||||
newCurrentTime = seekTime;
|
newCurrentTime = seekTime;
|
||||||
} else if (HasAudio()) {
|
} else if (HasAudio()) {
|
||||||
MediaData* audio = AudioQueue().PeekFront();
|
RefPtr<MediaData> audio = AudioQueue().PeekFront();
|
||||||
// Though we adjust the newCurrentTime in audio-based, and supplemented
|
// Though we adjust the newCurrentTime in audio-based, and supplemented
|
||||||
// by video. For better UX, should NOT bind the slide position to
|
// by video. For better UX, should NOT bind the slide position to
|
||||||
// the first audio data timestamp directly.
|
// the first audio data timestamp directly.
|
||||||
|
@ -65,12 +65,12 @@ public:
|
|||||||
return rv.forget();
|
return rv.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T* Peek() {
|
inline RefPtr<T> Peek() {
|
||||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||||
return static_cast<T*>(nsDeque::Peek());
|
return static_cast<T*>(nsDeque::Peek());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T* PeekFront() {
|
inline RefPtr<T> PeekFront() {
|
||||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||||
return static_cast<T*>(nsDeque::PeekFront());
|
return static_cast<T*>(nsDeque::PeekFront());
|
||||||
}
|
}
|
||||||
@ -109,8 +109,8 @@ public:
|
|||||||
if (GetSize() == 0) {
|
if (GetSize() == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
T* last = Peek();
|
T* last = static_cast<T*>(nsDeque::Peek());
|
||||||
T* first = PeekFront();
|
T* first = static_cast<T*>(nsDeque::PeekFront());
|
||||||
return last->GetEndTime() - first->mTime;
|
return last->GetEndTime() - first->mTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ DecodedAudioDataSink::PopFrames(uint32_t aFrames)
|
|||||||
return MakeUnique<Chunk>();
|
return MakeUnique<Chunk>();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioData* a = AudioQueue().PeekFront()->As<AudioData>();
|
RefPtr<AudioData> a = AudioQueue().PeekFront()->As<AudioData>();
|
||||||
|
|
||||||
// Ignore the element with 0 frames and try next.
|
// Ignore the element with 0 frames and try next.
|
||||||
if (a->mFrames == 0) {
|
if (a->mFrames == 0) {
|
||||||
|
@ -383,7 +383,7 @@ VideoSink::UpdateRenderedVideoFrames()
|
|||||||
RefPtr<MediaData> currentFrame = VideoQueue().PopFront();
|
RefPtr<MediaData> currentFrame = VideoQueue().PopFront();
|
||||||
int32_t framesRemoved = 0;
|
int32_t framesRemoved = 0;
|
||||||
while (VideoQueue().GetSize() > 0) {
|
while (VideoQueue().GetSize() > 0) {
|
||||||
MediaData* nextFrame = VideoQueue().PeekFront();
|
RefPtr<MediaData> nextFrame = VideoQueue().PeekFront();
|
||||||
if (nextFrame->mTime > clockTime) {
|
if (nextFrame->mTime > clockTime) {
|
||||||
remainingTime = nextFrame->mTime - clockTime;
|
remainingTime = nextFrame->mTime - clockTime;
|
||||||
break;
|
break;
|
||||||
|
@ -1358,7 +1358,7 @@ nsresult OggReader::SeekInBufferedRange(int64_t aTarget,
|
|||||||
} while (!eof &&
|
} while (!eof &&
|
||||||
mVideoQueue.GetSize() == 0);
|
mVideoQueue.GetSize() == 0);
|
||||||
|
|
||||||
VideoData* video = mVideoQueue.PeekFront();
|
RefPtr<VideoData> video = mVideoQueue.PeekFront();
|
||||||
if (video && !video->mKeyframe) {
|
if (video && !video->mKeyframe) {
|
||||||
// First decoded frame isn't a keyframe, seek back to previous keyframe,
|
// First decoded frame isn't a keyframe, seek back to previous keyframe,
|
||||||
// otherwise we'll get visual artifacts.
|
// otherwise we'll get visual artifacts.
|
||||||
@ -1490,7 +1490,7 @@ nsresult OggReader::SeekInternal(int64_t aTarget, int64_t aEndTime)
|
|||||||
// First, we must check to see if there's already a keyframe in the frames
|
// First, we must check to see if there's already a keyframe in the frames
|
||||||
// that we may have already decoded, and discard frames up to the
|
// that we may have already decoded, and discard frames up to the
|
||||||
// keyframe.
|
// keyframe.
|
||||||
VideoData* v;
|
RefPtr<VideoData> v;
|
||||||
while ((v = mVideoQueue.PeekFront()) && !v->mKeyframe) {
|
while ((v = mVideoQueue.PeekFront()) && !v->mKeyframe) {
|
||||||
RefPtr<VideoData> releaseMe = mVideoQueue.PopFront();
|
RefPtr<VideoData> releaseMe = mVideoQueue.PopFront();
|
||||||
}
|
}
|
||||||
@ -1959,7 +1959,7 @@ media::TimeIntervals OggReader::GetBuffered()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoData* OggReader::FindStartTime(int64_t& aOutStartTime)
|
void OggReader::FindStartTime(int64_t& aOutStartTime)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(OnTaskQueue());
|
MOZ_ASSERT(OnTaskQueue());
|
||||||
|
|
||||||
@ -1967,17 +1967,16 @@ VideoData* OggReader::FindStartTime(int64_t& aOutStartTime)
|
|||||||
// the duration.
|
// the duration.
|
||||||
int64_t videoStartTime = INT64_MAX;
|
int64_t videoStartTime = INT64_MAX;
|
||||||
int64_t audioStartTime = INT64_MAX;
|
int64_t audioStartTime = INT64_MAX;
|
||||||
VideoData* videoData = nullptr;
|
|
||||||
|
|
||||||
if (HasVideo()) {
|
if (HasVideo()) {
|
||||||
videoData = SyncDecodeToFirstVideoData();
|
RefPtr<VideoData> videoData = SyncDecodeToFirstVideoData();
|
||||||
if (videoData) {
|
if (videoData) {
|
||||||
videoStartTime = videoData->mTime;
|
videoStartTime = videoData->mTime;
|
||||||
LOG(LogLevel::Debug, ("OggReader::FindStartTime() video=%lld", videoStartTime));
|
LOG(LogLevel::Debug, ("OggReader::FindStartTime() video=%lld", videoStartTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (HasAudio()) {
|
if (HasAudio()) {
|
||||||
AudioData* audioData = SyncDecodeToFirstAudioData();
|
RefPtr<AudioData> audioData = SyncDecodeToFirstAudioData();
|
||||||
if (audioData) {
|
if (audioData) {
|
||||||
audioStartTime = audioData->mTime;
|
audioStartTime = audioData->mTime;
|
||||||
LOG(LogLevel::Debug, ("OggReader::FindStartTime() audio=%lld", audioStartTime));
|
LOG(LogLevel::Debug, ("OggReader::FindStartTime() audio=%lld", audioStartTime));
|
||||||
@ -1988,11 +1987,9 @@ VideoData* OggReader::FindStartTime(int64_t& aOutStartTime)
|
|||||||
if (startTime != INT64_MAX) {
|
if (startTime != INT64_MAX) {
|
||||||
aOutStartTime = startTime;
|
aOutStartTime = startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
return videoData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioData* OggReader::SyncDecodeToFirstAudioData()
|
RefPtr<AudioData> OggReader::SyncDecodeToFirstAudioData()
|
||||||
{
|
{
|
||||||
bool eof = false;
|
bool eof = false;
|
||||||
while (!eof && AudioQueue().GetSize() == 0) {
|
while (!eof && AudioQueue().GetSize() == 0) {
|
||||||
@ -2004,11 +2001,10 @@ AudioData* OggReader::SyncDecodeToFirstAudioData()
|
|||||||
if (eof) {
|
if (eof) {
|
||||||
AudioQueue().Finish();
|
AudioQueue().Finish();
|
||||||
}
|
}
|
||||||
AudioData* d = nullptr;
|
return AudioQueue().PeekFront();
|
||||||
return (d = AudioQueue().PeekFront()) ? d : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoData* OggReader::SyncDecodeToFirstVideoData()
|
RefPtr<VideoData> OggReader::SyncDecodeToFirstVideoData()
|
||||||
{
|
{
|
||||||
bool eof = false;
|
bool eof = false;
|
||||||
while (!eof && VideoQueue().GetSize() == 0) {
|
while (!eof && VideoQueue().GetSize() == 0) {
|
||||||
@ -2021,8 +2017,7 @@ VideoData* OggReader::SyncDecodeToFirstVideoData()
|
|||||||
if (eof) {
|
if (eof) {
|
||||||
VideoQueue().Finish();
|
VideoQueue().Finish();
|
||||||
}
|
}
|
||||||
VideoData* d = nullptr;
|
return VideoQueue().PeekFront();
|
||||||
return (d = VideoQueue().PeekFront()) ? d : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OggCodecStore::OggCodecStore()
|
OggCodecStore::OggCodecStore()
|
||||||
|
@ -77,9 +77,9 @@ private:
|
|||||||
// Stores the presentation time of the first frame we'd be able to play if
|
// Stores the presentation time of the first frame we'd be able to play if
|
||||||
// we started playback at the current position. Returns the first video
|
// we started playback at the current position. Returns the first video
|
||||||
// frame, if we have video.
|
// frame, if we have video.
|
||||||
VideoData* FindStartTime(int64_t& aOutStartTime);
|
void FindStartTime(int64_t& aOutStartTime);
|
||||||
AudioData* SyncDecodeToFirstAudioData();
|
RefPtr<AudioData> SyncDecodeToFirstAudioData();
|
||||||
VideoData* SyncDecodeToFirstVideoData();
|
RefPtr<VideoData> SyncDecodeToFirstVideoData();
|
||||||
|
|
||||||
// This monitor should be taken when reading or writing to mIsChained.
|
// This monitor should be taken when reading or writing to mIsChained.
|
||||||
ReentrantMonitor mMonitor;
|
ReentrantMonitor mMonitor;
|
||||||
|
@ -1036,6 +1036,9 @@ AudioContext::StartRendering(ErrorResult& aRv)
|
|||||||
|
|
||||||
mIsStarted = true;
|
mIsStarted = true;
|
||||||
RefPtr<Promise> promise = Promise::Create(parentObject, aRv);
|
RefPtr<Promise> promise = Promise::Create(parentObject, aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
mDestination->StartRendering(promise);
|
mDestination->StartRendering(promise);
|
||||||
|
|
||||||
OnStateChanged(nullptr, AudioContextState::Running);
|
OnStateChanged(nullptr, AudioContextState::Running);
|
||||||
@ -1043,6 +1046,13 @@ AudioContext::StartRendering(ErrorResult& aRv)
|
|||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
AudioContext::Length()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mIsOffline);
|
||||||
|
return mDestination->Length();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioContext::Mute() const
|
AudioContext::Mute() const
|
||||||
{
|
{
|
||||||
|
@ -266,6 +266,7 @@ public:
|
|||||||
// OfflineAudioContext methods
|
// OfflineAudioContext methods
|
||||||
already_AddRefed<Promise> StartRendering(ErrorResult& aRv);
|
already_AddRefed<Promise> StartRendering(ErrorResult& aRv);
|
||||||
IMPL_EVENT_HANDLER(complete)
|
IMPL_EVENT_HANDLER(complete)
|
||||||
|
unsigned long Length();
|
||||||
|
|
||||||
bool IsOffline() const { return mIsOffline; }
|
bool IsOffline() const { return mIsOffline; }
|
||||||
|
|
||||||
|
@ -86,6 +86,12 @@ public:
|
|||||||
void InputMuted(bool aInputMuted);
|
void InputMuted(bool aInputMuted);
|
||||||
void ResolvePromise(AudioBuffer* aRenderedBuffer);
|
void ResolvePromise(AudioBuffer* aRenderedBuffer);
|
||||||
|
|
||||||
|
unsigned long Length()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mIsOffline);
|
||||||
|
return mFramesToProduce;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~AudioDestinationNode();
|
virtual ~AudioDestinationNode();
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ SimpleTest.waitForExplicitFinish();
|
|||||||
addLoadEvent(function() {
|
addLoadEvent(function() {
|
||||||
var ctx = new OfflineAudioContext(2, 100, 22050);
|
var ctx = new OfflineAudioContext(2, 100, 22050);
|
||||||
ok(ctx instanceof EventTarget, "OfflineAudioContexts must be EventTargets");
|
ok(ctx instanceof EventTarget, "OfflineAudioContexts must be EventTargets");
|
||||||
|
is(ctx.length, 100, "OfflineAudioContext.length is equal to the value passed to the ctor.");
|
||||||
|
|
||||||
var buf = ctx.createBuffer(2, 100, ctx.sampleRate);
|
var buf = ctx.createBuffer(2, 100, ctx.sampleRate);
|
||||||
for (var i = 0; i < 2; ++i) {
|
for (var i = 0; i < 2; ++i) {
|
||||||
|
@ -525,6 +525,10 @@ Promise::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
|||||||
already_AddRefed<Promise>
|
already_AddRefed<Promise>
|
||||||
Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
|
Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
|
if (!aGlobal) {
|
||||||
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
RefPtr<Promise> p = new Promise(aGlobal);
|
RefPtr<Promise> p = new Promise(aGlobal);
|
||||||
p->CreateWrapper(nullptr, aRv);
|
p->CreateWrapper(nullptr, aRv);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
@ -859,6 +863,10 @@ already_AddRefed<Promise>
|
|||||||
Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
|
Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
|
||||||
JS::Handle<JSObject*> aDesiredProto)
|
JS::Handle<JSObject*> aDesiredProto)
|
||||||
{
|
{
|
||||||
|
if (!aGlobal) {
|
||||||
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
RefPtr<Promise> p = new Promise(aGlobal);
|
RefPtr<Promise> p = new Promise(aGlobal);
|
||||||
p->CreateWrapper(aDesiredProto, aRv);
|
p->CreateWrapper(aDesiredProto, aRv);
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
|
@ -19,5 +19,6 @@ interface OfflineAudioContext : AudioContext {
|
|||||||
Promise<AudioBuffer> startRendering();
|
Promise<AudioBuffer> startRendering();
|
||||||
|
|
||||||
attribute EventHandler oncomplete;
|
attribute EventHandler oncomplete;
|
||||||
|
readonly attribute unsigned long length;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -416,7 +416,8 @@ DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
|||||||
Float aSigma,
|
Float aSigma,
|
||||||
CompositionOp aOperator)
|
CompositionOp aOperator)
|
||||||
{
|
{
|
||||||
if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA)) {
|
if (!(aSurface->GetType() == SurfaceType::SKIA || aSurface->GetType() == SurfaceType::DATA) ||
|
||||||
|
aSurface->GetSize().IsEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +138,7 @@ enum class LogReason : int {
|
|||||||
TextureAliveAfterShutdown,
|
TextureAliveAfterShutdown,
|
||||||
InvalidContext,
|
InvalidContext,
|
||||||
InvalidCommandList,
|
InvalidCommandList,
|
||||||
|
AsyncTransactionTimeout,
|
||||||
// End
|
// End
|
||||||
MustBeLessThanThis = 101,
|
MustBeLessThanThis = 101,
|
||||||
};
|
};
|
||||||
|
@ -1045,8 +1045,6 @@ GLContext::InitWithPrefixImpl(const char* prefix, bool trygl)
|
|||||||
mCaps.alpha = false;
|
mCaps.alpha = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateGLFormats(mCaps);
|
|
||||||
|
|
||||||
mTexGarbageBin = new TextureGarbageBin(this);
|
mTexGarbageBin = new TextureGarbageBin(this);
|
||||||
|
|
||||||
MOZ_ASSERT(IsCurrent());
|
MOZ_ASSERT(IsCurrent());
|
||||||
@ -2868,8 +2866,6 @@ GLContext::InitOffscreen(const gfx::IntSize& size, const SurfaceCaps& caps)
|
|||||||
mCaps = mScreen->mCaps;
|
mCaps = mScreen->mCaps;
|
||||||
MOZ_ASSERT(!mCaps.any);
|
MOZ_ASSERT(!mCaps.any);
|
||||||
|
|
||||||
UpdateGLFormats(mCaps);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3412,7 +3412,6 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
SurfaceCaps mCaps;
|
SurfaceCaps mCaps;
|
||||||
nsAutoPtr<GLFormats> mGLFormats;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const SurfaceCaps& Caps() const {
|
const SurfaceCaps& Caps() const {
|
||||||
@ -3421,14 +3420,6 @@ public:
|
|||||||
|
|
||||||
// Only varies based on bpp16 and alpha.
|
// Only varies based on bpp16 and alpha.
|
||||||
GLFormats ChooseGLFormats(const SurfaceCaps& caps) const;
|
GLFormats ChooseGLFormats(const SurfaceCaps& caps) const;
|
||||||
void UpdateGLFormats(const SurfaceCaps& caps) {
|
|
||||||
mGLFormats = new GLFormats(ChooseGLFormats(caps));
|
|
||||||
}
|
|
||||||
|
|
||||||
const GLFormats& GetGLFormats() const {
|
|
||||||
MOZ_ASSERT(mGLFormats);
|
|
||||||
return *mGLFormats;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsFramebufferComplete(GLuint fb, GLenum* status = nullptr);
|
bool IsFramebufferComplete(GLuint fb, GLenum* status = nullptr);
|
||||||
|
|
||||||
|
@ -694,6 +694,17 @@ GLScreenBuffer::IsReadFramebufferDefault() const
|
|||||||
return SharedSurf()->mAttachType == AttachmentType::Screen;
|
return SharedSurf()->mAttachType == AttachmentType::Screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
GLScreenBuffer::DepthBits() const
|
||||||
|
{
|
||||||
|
const GLFormats& formats = mFactory->mFormats;
|
||||||
|
|
||||||
|
if (formats.depth == LOCAL_GL_DEPTH_COMPONENT16)
|
||||||
|
return 16;
|
||||||
|
|
||||||
|
return 24;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Utils
|
// Utils
|
||||||
|
|
||||||
|
@ -211,6 +211,8 @@ public:
|
|||||||
return mDraw->mSamples;
|
return mDraw->mSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t DepthBits() const;
|
||||||
|
|
||||||
void DeletingFB(GLuint fb);
|
void DeletingFB(GLuint fb);
|
||||||
|
|
||||||
const gfx::IntSize& Size() const {
|
const gfx::IntSize& Size() const {
|
||||||
|
@ -898,7 +898,7 @@ struct ParamTraits<mozilla::StereoMode>
|
|||||||
: public ContiguousEnumSerializer<
|
: public ContiguousEnumSerializer<
|
||||||
mozilla::StereoMode,
|
mozilla::StereoMode,
|
||||||
mozilla::StereoMode::MONO,
|
mozilla::StereoMode::MONO,
|
||||||
mozilla::StereoMode::TOP_BOTTOM>
|
mozilla::StereoMode::MAX>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -99,7 +99,8 @@ enum class StereoMode {
|
|||||||
LEFT_RIGHT,
|
LEFT_RIGHT,
|
||||||
RIGHT_LEFT,
|
RIGHT_LEFT,
|
||||||
BOTTOM_TOP,
|
BOTTOM_TOP,
|
||||||
TOP_BOTTOM
|
TOP_BOTTOM,
|
||||||
|
MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -34,6 +34,10 @@ AsyncTransactionWaiter::WaitComplete()
|
|||||||
if (mWaitCount > 0) {
|
if (mWaitCount > 0) {
|
||||||
printf_stderr("Timeout of waiting transaction complete.");
|
printf_stderr("Timeout of waiting transaction complete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count == maxCount) {
|
||||||
|
gfxDevCrash(LogReason::AsyncTransactionTimeout) << "Bug 1244883: AsyncTransactionWaiter timed out.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Atomic<uint64_t> AsyncTransactionTracker::sSerialCounter(0);
|
Atomic<uint64_t> AsyncTransactionTracker::sSerialCounter(0);
|
||||||
|
@ -1799,7 +1799,7 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
|
|||||||
// get a crash on Intel 8.5.10.[18xx-1994] drivers.
|
// get a crash on Intel 8.5.10.[18xx-1994] drivers.
|
||||||
// We can work around this issue by doing UpdateSubresource.
|
// We can work around this issue by doing UpdateSubresource.
|
||||||
if (!TryCreateTexture2D(device, &desc, nullptr, texture)) {
|
if (!TryCreateTexture2D(device, &desc, nullptr, texture)) {
|
||||||
gfxCriticalError() << "DoesD3D11TextureSharingWork_TryCreateTextureFailure";
|
gfxCriticalNote << "DoesD3D11TextureSharingWork_TryCreateTextureFailure";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1236,7 +1236,7 @@ DecodeExportName(JSContext* cx, Decoder& d, CStringSet* dupSet)
|
|||||||
if (!fieldBytes.append(0))
|
if (!fieldBytes.append(0))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
UniqueChars fieldName((char*)fieldBytes.extractRawBuffer());
|
UniqueChars fieldName((char*)fieldBytes.extractOrCopyRawBuffer());
|
||||||
if (!fieldName)
|
if (!fieldName)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -1446,6 +1446,58 @@ js::RegExpGetSubstitution(JSContext* cx, HandleLinearString matched, HandleLinea
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
js::GetFirstDollarIndex(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
MOZ_ASSERT(args.length() == 1);
|
||||||
|
RootedString str(cx, args[0].toString());
|
||||||
|
|
||||||
|
int32_t index = -1;
|
||||||
|
if (!GetFirstDollarIndexRaw(cx, str, &index))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
args.rval().setInt32(index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TextChar>
|
||||||
|
static MOZ_ALWAYS_INLINE int
|
||||||
|
GetFirstDollarIndexImpl(const TextChar* text, uint32_t textLen)
|
||||||
|
{
|
||||||
|
const TextChar* end = text + textLen;
|
||||||
|
for (const TextChar* c = text; c != end; ++c) {
|
||||||
|
if (*c == '$')
|
||||||
|
return c - text;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
js::GetFirstDollarIndexRawFlat(JSLinearString* text)
|
||||||
|
{
|
||||||
|
uint32_t len = text->length();
|
||||||
|
// Should be handled in different path.
|
||||||
|
MOZ_ASSERT(len != 0);
|
||||||
|
|
||||||
|
JS::AutoCheckCannotGC nogc;
|
||||||
|
if (text->hasLatin1Chars())
|
||||||
|
return GetFirstDollarIndexImpl(text->latin1Chars(nogc), len);
|
||||||
|
|
||||||
|
return GetFirstDollarIndexImpl(text->twoByteChars(nogc), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
js::GetFirstDollarIndexRaw(JSContext* cx, HandleString str, int32_t* index)
|
||||||
|
{
|
||||||
|
JSLinearString* text = str->ensureLinear(cx);
|
||||||
|
if (!text)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*index = GetFirstDollarIndexRawFlat(text);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
js::RegExpPrototypeOptimizable(JSContext* cx, unsigned argc, Value* vp)
|
js::RegExpPrototypeOptimizable(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
@ -130,6 +130,15 @@ RegExpGetSubstitution(JSContext* cx, HandleLinearString matched, HandleLinearStr
|
|||||||
size_t position, HandleObject capturesObj, HandleLinearString replacement,
|
size_t position, HandleObject capturesObj, HandleLinearString replacement,
|
||||||
size_t firstDollarIndex, MutableHandleValue rval);
|
size_t firstDollarIndex, MutableHandleValue rval);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
GetFirstDollarIndex(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
GetFirstDollarIndexRaw(JSContext* cx, HandleString str, int32_t* index);
|
||||||
|
|
||||||
|
extern int32_t
|
||||||
|
GetFirstDollarIndexRawFlat(JSLinearString* text);
|
||||||
|
|
||||||
// RegExp ClassSpec members used in RegExpObject.cpp.
|
// RegExp ClassSpec members used in RegExpObject.cpp.
|
||||||
extern bool
|
extern bool
|
||||||
regexp_construct(JSContext* cx, unsigned argc, Value* vp);
|
regexp_construct(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
@ -190,7 +190,7 @@ function RegExpReplace(string, replaceValue) {
|
|||||||
// A single character string may contain "$", but that cannot be a
|
// A single character string may contain "$", but that cannot be a
|
||||||
// substitution.
|
// substitution.
|
||||||
if (replaceValue.length > 1)
|
if (replaceValue.length > 1)
|
||||||
firstDollarIndex = callFunction(std_String_indexOf, replaceValue, "$");
|
firstDollarIndex = GetFirstDollarIndex(replaceValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 7.
|
// Step 7.
|
||||||
|
@ -644,8 +644,10 @@ ArrayMetaTypeDescr::create(JSContext* cx,
|
|||||||
if (!CreateTraceList(cx, obj))
|
if (!CreateTraceList(cx, obj))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (!cx->zone()->typeDescrObjects.put(obj))
|
if (!cx->zone()->typeDescrObjects.put(obj)) {
|
||||||
|
ReportOutOfMemory(cx);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -691,12 +693,16 @@ ArrayMetaTypeDescr::construct(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
|
|
||||||
// Construct a canonical string `new ArrayType(<elementType>, N)`:
|
// Construct a canonical string `new ArrayType(<elementType>, N)`:
|
||||||
StringBuffer contents(cx);
|
StringBuffer contents(cx);
|
||||||
contents.append("new ArrayType(");
|
if (!contents.append("new ArrayType("))
|
||||||
contents.append(&elementType->stringRepr());
|
return false;
|
||||||
contents.append(", ");
|
if (!contents.append(&elementType->stringRepr()))
|
||||||
|
return false;
|
||||||
|
if (!contents.append(", "))
|
||||||
|
return false;
|
||||||
if (!NumberValueToStringBuffer(cx, NumberValue(length), contents))
|
if (!NumberValueToStringBuffer(cx, NumberValue(length), contents))
|
||||||
return false;
|
return false;
|
||||||
contents.append(")");
|
if (!contents.append(")"))
|
||||||
|
return false;
|
||||||
RootedAtom stringRepr(cx, contents.finishAtom());
|
RootedAtom stringRepr(cx, contents.finishAtom());
|
||||||
if (!stringRepr)
|
if (!stringRepr)
|
||||||
return false;
|
return false;
|
||||||
@ -799,10 +805,8 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
if (!userFieldTypes)
|
if (!userFieldTypes)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (!stringBuffer.append("new StructType({")) {
|
if (!stringBuffer.append("new StructType({"))
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
RootedValue fieldTypeVal(cx);
|
RootedValue fieldTypeVal(cx);
|
||||||
RootedId id(cx);
|
RootedId id(cx);
|
||||||
@ -830,14 +834,10 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
|
|
||||||
// Collect field name and type object
|
// Collect field name and type object
|
||||||
RootedValue fieldName(cx, IdToValue(id));
|
RootedValue fieldName(cx, IdToValue(id));
|
||||||
if (!fieldNames.append(fieldName)) {
|
if (!fieldNames.append(fieldName))
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
if (!fieldTypeObjs.append(ObjectValue(*fieldType)))
|
||||||
if (!fieldTypeObjs.append(ObjectValue(*fieldType))) {
|
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
// userFieldTypes[id] = typeObj
|
// userFieldTypes[id] = typeObj
|
||||||
if (!DefineProperty(cx, userFieldTypes, id, fieldTypeObjs[i], nullptr, nullptr,
|
if (!DefineProperty(cx, userFieldTypes, id, fieldTypeObjs[i], nullptr, nullptr,
|
||||||
@ -847,22 +847,14 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Append "f:Type" to the string repr
|
// Append "f:Type" to the string repr
|
||||||
if (i > 0 && !stringBuffer.append(", ")) {
|
if (i > 0 && !stringBuffer.append(", "))
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
if (!stringBuffer.append(JSID_TO_ATOM(id)))
|
||||||
if (!stringBuffer.append(JSID_TO_ATOM(id))) {
|
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
if (!stringBuffer.append(": "))
|
||||||
if (!stringBuffer.append(": ")) {
|
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
if (!stringBuffer.append(&fieldType->stringRepr()))
|
||||||
if (!stringBuffer.append(&fieldType->stringRepr())) {
|
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
// Offset of this field is the current total size adjusted for
|
// Offset of this field is the current total size adjusted for
|
||||||
// the field's alignment.
|
// the field's alignment.
|
||||||
@ -873,10 +865,8 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(offset.value() >= 0);
|
MOZ_ASSERT(offset.value() >= 0);
|
||||||
if (!fieldOffsets.append(Int32Value(offset.value()))) {
|
if (!fieldOffsets.append(Int32Value(offset.value())))
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
// userFieldOffsets[id] = offset
|
// userFieldOffsets[id] = offset
|
||||||
RootedValue offsetValue(cx, Int32Value(offset.value()));
|
RootedValue offsetValue(cx, Int32Value(offset.value()));
|
||||||
@ -903,10 +893,9 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Complete string representation.
|
// Complete string representation.
|
||||||
if (!stringBuffer.append("})")) {
|
if (!stringBuffer.append("})"))
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
RootedAtom stringRepr(cx, stringBuffer.finishAtom());
|
RootedAtom stringRepr(cx, stringBuffer.finishAtom());
|
||||||
if (!stringRepr)
|
if (!stringRepr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -1003,6 +992,7 @@ StructMetaTypeDescr::create(JSContext* cx,
|
|||||||
if (!cx->zone()->typeDescrObjects.put(descr) ||
|
if (!cx->zone()->typeDescrObjects.put(descr) ||
|
||||||
!cx->zone()->typeDescrObjects.put(fieldTypeVec))
|
!cx->zone()->typeDescrObjects.put(fieldTypeVec))
|
||||||
{
|
{
|
||||||
|
ReportOutOfMemory(cx);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1172,8 +1162,10 @@ DefineSimpleTypeDescr(JSContext* cx,
|
|||||||
if (!CreateTraceList(cx, descr))
|
if (!CreateTraceList(cx, descr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!cx->zone()->typeDescrObjects.put(descr))
|
if (!cx->zone()->typeDescrObjects.put(descr)) {
|
||||||
|
ReportOutOfMemory(cx);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
14
js/src/jit-test/tests/TypedObject/bug1265690.js
Normal file
14
js/src/jit-test/tests/TypedObject/bug1265690.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
if (!('oomTest' in this) || !this.hasOwnProperty("TypedObject"))
|
||||||
|
quit();
|
||||||
|
lfCodeBuffer = `
|
||||||
|
ArrayType = TypedObject.ArrayType;
|
||||||
|
var StructType = TypedObject.StructType;
|
||||||
|
float32 = TypedObject.float32;
|
||||||
|
Point = new ArrayType(float32, 3);
|
||||||
|
var Line = new StructType({ Point });
|
||||||
|
new ArrayType(Line, 3);
|
||||||
|
`;
|
||||||
|
loadFile(lfCodeBuffer);
|
||||||
|
function loadFile(lfVarx) {
|
||||||
|
oomTest(function() { eval(lfVarx) });
|
||||||
|
}
|
@ -12,5 +12,6 @@ evalcx(`
|
|||||||
}\
|
}\
|
||||||
');
|
');
|
||||||
oomTest(() => eval('Array(..."")'));
|
oomTest(() => eval('Array(..."")'));
|
||||||
Intl.NumberFormat.prototype.format(0);
|
if ('Intl' in this)
|
||||||
|
Intl.NumberFormat.prototype.format(0);
|
||||||
`, newGlobal());
|
`, newGlobal());
|
||||||
|
28
js/src/jit-test/tests/auto-regress/bug1266579.js
Normal file
28
js/src/jit-test/tests/auto-regress/bug1266579.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
function test1() {
|
||||||
|
do {
|
||||||
|
"8pan08pa8pan08pa".split("");
|
||||||
|
} while (!inIon());
|
||||||
|
}
|
||||||
|
|
||||||
|
function test2() {
|
||||||
|
do {
|
||||||
|
"abababababababababababababababab".split("a");
|
||||||
|
} while (!inIon());
|
||||||
|
}
|
||||||
|
|
||||||
|
function test3() {
|
||||||
|
do {
|
||||||
|
"abcabcabcabcabcabcabcabcabcabcabcabcabcabcabc".split("ab");
|
||||||
|
} while (!inIon());
|
||||||
|
}
|
||||||
|
|
||||||
|
function test4() {
|
||||||
|
do {
|
||||||
|
"".split("");
|
||||||
|
} while (!inIon());
|
||||||
|
}
|
||||||
|
|
||||||
|
test1();
|
||||||
|
test2();
|
||||||
|
test3();
|
||||||
|
test4();
|
@ -1402,7 +1402,9 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
|
|||||||
RootedObject obj(cx, &lhs.toObject());
|
RootedObject obj(cx, &lhs.toObject());
|
||||||
|
|
||||||
// Check for ArgumentsObj[int] accesses
|
// Check for ArgumentsObj[int] accesses
|
||||||
if (obj->is<ArgumentsObject>() && rhs.isInt32()) {
|
if (obj->is<ArgumentsObject>() && rhs.isInt32() &&
|
||||||
|
!obj->as<ArgumentsObject>().hasOverriddenElement())
|
||||||
|
{
|
||||||
ICGetElem_Arguments::Which which = ICGetElem_Arguments::Mapped;
|
ICGetElem_Arguments::Which which = ICGetElem_Arguments::Mapped;
|
||||||
if (obj->is<UnmappedArgumentsObject>())
|
if (obj->is<UnmappedArgumentsObject>())
|
||||||
which = ICGetElem_Arguments::Unmapped;
|
which = ICGetElem_Arguments::Unmapped;
|
||||||
@ -2272,10 +2274,11 @@ ICGetElem_Arguments::Compiler::generateStubCode(MacroAssembler& masm)
|
|||||||
// Get initial ArgsObj length value.
|
// Get initial ArgsObj length value.
|
||||||
masm.unboxInt32(Address(objReg, ArgumentsObject::getInitialLengthSlotOffset()), scratchReg);
|
masm.unboxInt32(Address(objReg, ArgumentsObject::getInitialLengthSlotOffset()), scratchReg);
|
||||||
|
|
||||||
// Test if length has been overridden.
|
// Test if length or any element have been overridden.
|
||||||
masm.branchTest32(Assembler::NonZero,
|
masm.branchTest32(Assembler::NonZero,
|
||||||
scratchReg,
|
scratchReg,
|
||||||
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT),
|
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT |
|
||||||
|
ArgumentsObject::ELEMENT_OVERRIDDEN_BIT),
|
||||||
&failure);
|
&failure);
|
||||||
|
|
||||||
// Length has not been overridden, ensure that R1 is an integer and is <= length.
|
// Length has not been overridden, ensure that R1 is an integer and is <= length.
|
||||||
|
@ -2213,6 +2213,63 @@ CodeGenerator::visitOutOfLineRegExpInstanceOptimizable(OutOfLineRegExpInstanceOp
|
|||||||
masm.jump(ool->rejoin());
|
masm.jump(ool->rejoin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FindFirstDollarIndex(MacroAssembler& masm, Register str, Register len, Register chars,
|
||||||
|
Register temp, Register output, bool isLatin1)
|
||||||
|
{
|
||||||
|
masm.loadStringChars(str, chars);
|
||||||
|
|
||||||
|
masm.move32(Imm32(0), output);
|
||||||
|
|
||||||
|
Label start, done;
|
||||||
|
masm.bind(&start);
|
||||||
|
if (isLatin1)
|
||||||
|
masm.load8ZeroExtend(BaseIndex(chars, output, TimesOne), temp);
|
||||||
|
else
|
||||||
|
masm.load16ZeroExtend(BaseIndex(chars, output, TimesTwo), temp);
|
||||||
|
|
||||||
|
masm.branch32(Assembler::Equal, temp, Imm32('$'), &done);
|
||||||
|
|
||||||
|
masm.add32(Imm32(1), output);
|
||||||
|
masm.branch32(Assembler::NotEqual, output, len, &start);
|
||||||
|
|
||||||
|
masm.move32(Imm32(-1), output);
|
||||||
|
|
||||||
|
masm.bind(&done);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef bool (*GetFirstDollarIndexRawFn)(JSContext*, HandleString, int32_t*);
|
||||||
|
static const VMFunction GetFirstDollarIndexRawInfo = FunctionInfo<GetFirstDollarIndexRawFn>(GetFirstDollarIndexRaw);
|
||||||
|
|
||||||
|
void
|
||||||
|
CodeGenerator::visitGetFirstDollarIndex(LGetFirstDollarIndex* ins)
|
||||||
|
{
|
||||||
|
Register str = ToRegister(ins->str());
|
||||||
|
Register output = ToRegister(ins->output());
|
||||||
|
Register temp0 = ToRegister(ins->temp0());
|
||||||
|
Register temp1 = ToRegister(ins->temp1());
|
||||||
|
Register len = ToRegister(ins->temp2());
|
||||||
|
|
||||||
|
OutOfLineCode* ool = oolCallVM(GetFirstDollarIndexRawInfo, ins, ArgList(str),
|
||||||
|
StoreRegisterTo(output));
|
||||||
|
|
||||||
|
masm.branchIfRope(str, ool->entry());
|
||||||
|
masm.loadStringLength(str, len);
|
||||||
|
|
||||||
|
Label isLatin1, done;
|
||||||
|
masm.branchLatin1String(str, &isLatin1);
|
||||||
|
{
|
||||||
|
FindFirstDollarIndex(masm, str, len, temp0, temp1, output, /* isLatin1 = */ false);
|
||||||
|
}
|
||||||
|
masm.jump(&done);
|
||||||
|
{
|
||||||
|
masm.bind(&isLatin1);
|
||||||
|
FindFirstDollarIndex(masm, str, len, temp0, temp1, output, /* isLatin1 = */ true);
|
||||||
|
}
|
||||||
|
masm.bind(&done);
|
||||||
|
masm.bind(ool->rejoin());
|
||||||
|
}
|
||||||
|
|
||||||
typedef JSString* (*StringReplaceFn)(JSContext*, HandleString, HandleString, HandleString);
|
typedef JSString* (*StringReplaceFn)(JSContext*, HandleString, HandleString, HandleString);
|
||||||
static const VMFunction StringFlatReplaceInfo = FunctionInfo<StringReplaceFn>(js::str_flat_replace_string);
|
static const VMFunction StringFlatReplaceInfo = FunctionInfo<StringReplaceFn>(js::str_flat_replace_string);
|
||||||
static const VMFunction StringReplaceInfo = FunctionInfo<StringReplaceFn>(StringReplace);
|
static const VMFunction StringReplaceInfo = FunctionInfo<StringReplaceFn>(StringReplace);
|
||||||
|
@ -122,6 +122,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||||||
void visitOutOfLineRegExpPrototypeOptimizable(OutOfLineRegExpPrototypeOptimizable* ool);
|
void visitOutOfLineRegExpPrototypeOptimizable(OutOfLineRegExpPrototypeOptimizable* ool);
|
||||||
void visitRegExpInstanceOptimizable(LRegExpInstanceOptimizable* lir);
|
void visitRegExpInstanceOptimizable(LRegExpInstanceOptimizable* lir);
|
||||||
void visitOutOfLineRegExpInstanceOptimizable(OutOfLineRegExpInstanceOptimizable* ool);
|
void visitOutOfLineRegExpInstanceOptimizable(OutOfLineRegExpInstanceOptimizable* ool);
|
||||||
|
void visitGetFirstDollarIndex(LGetFirstDollarIndex* lir);
|
||||||
void visitStringReplace(LStringReplace* lir);
|
void visitStringReplace(LStringReplace* lir);
|
||||||
void emitSharedStub(ICStub::Kind kind, LInstruction* lir);
|
void emitSharedStub(ICStub::Kind kind, LInstruction* lir);
|
||||||
void visitBinarySharedStub(LBinarySharedStub* lir);
|
void visitBinarySharedStub(LBinarySharedStub* lir);
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
_(IsRegExpObject) \
|
_(IsRegExpObject) \
|
||||||
_(RegExpPrototypeOptimizable) \
|
_(RegExpPrototypeOptimizable) \
|
||||||
_(RegExpInstanceOptimizable) \
|
_(RegExpInstanceOptimizable) \
|
||||||
|
_(GetFirstDollarIndex) \
|
||||||
\
|
\
|
||||||
_(String) \
|
_(String) \
|
||||||
_(StringCharCodeAt) \
|
_(StringCharCodeAt) \
|
||||||
|
@ -842,6 +842,7 @@ class IonBuilder
|
|||||||
InliningStatus inlineIsRegExpObject(CallInfo& callInfo);
|
InliningStatus inlineIsRegExpObject(CallInfo& callInfo);
|
||||||
InliningStatus inlineRegExpPrototypeOptimizable(CallInfo& callInfo);
|
InliningStatus inlineRegExpPrototypeOptimizable(CallInfo& callInfo);
|
||||||
InliningStatus inlineRegExpInstanceOptimizable(CallInfo& callInfo);
|
InliningStatus inlineRegExpInstanceOptimizable(CallInfo& callInfo);
|
||||||
|
InliningStatus inlineGetFirstDollarIndex(CallInfo& callInfo);
|
||||||
|
|
||||||
// Object natives and intrinsics.
|
// Object natives and intrinsics.
|
||||||
InliningStatus inlineObjectCreate(CallInfo& callInfo);
|
InliningStatus inlineObjectCreate(CallInfo& callInfo);
|
||||||
|
@ -542,6 +542,9 @@ IsOptimizableArgumentsObjectForGetElem(JSObject* obj, Value idval)
|
|||||||
if (argsObj.isAnyElementDeleted())
|
if (argsObj.isAnyElementDeleted())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (argsObj.hasOverriddenElement())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!idval.isInt32())
|
if (!idval.isInt32())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -4211,9 +4214,12 @@ GetPropertyIC::tryAttachArgumentsElement(JSContext* cx, HandleScript outerScript
|
|||||||
|
|
||||||
masm.branchTestObjClass(Assembler::NotEqual, object(), tmpReg, obj->getClass(), &failures);
|
masm.branchTestObjClass(Assembler::NotEqual, object(), tmpReg, obj->getClass(), &failures);
|
||||||
|
|
||||||
// Get initial ArgsObj length value, test if length has been overridden.
|
// Get initial ArgsObj length value, test if length or any element have
|
||||||
|
// been overridden.
|
||||||
masm.unboxInt32(Address(object(), ArgumentsObject::getInitialLengthSlotOffset()), tmpReg);
|
masm.unboxInt32(Address(object(), ArgumentsObject::getInitialLengthSlotOffset()), tmpReg);
|
||||||
masm.branchTest32(Assembler::NonZero, tmpReg, Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT),
|
masm.branchTest32(Assembler::NonZero, tmpReg,
|
||||||
|
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT |
|
||||||
|
ArgumentsObject::ELEMENT_OVERRIDDEN_BIT),
|
||||||
&failures);
|
&failures);
|
||||||
masm.rshiftPtr(Imm32(ArgumentsObject::PACKED_BITS_COUNT), tmpReg);
|
masm.rshiftPtr(Imm32(ArgumentsObject::PACKED_BITS_COUNT), tmpReg);
|
||||||
|
|
||||||
|
@ -2315,6 +2315,17 @@ LIRGenerator::visitRegExpInstanceOptimizable(MRegExpInstanceOptimizable* ins)
|
|||||||
define(lir, ins);
|
define(lir, ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LIRGenerator::visitGetFirstDollarIndex(MGetFirstDollarIndex* ins)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(ins->str()->type() == MIRType_String);
|
||||||
|
MOZ_ASSERT(ins->type() == MIRType_Int32);
|
||||||
|
LGetFirstDollarIndex* lir = new(alloc()) LGetFirstDollarIndex(useRegister(ins->str()),
|
||||||
|
temp(), temp(), temp());
|
||||||
|
define(lir, ins);
|
||||||
|
assignSafepoint(lir, ins);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LIRGenerator::visitStringReplace(MStringReplace* ins)
|
LIRGenerator::visitStringReplace(MStringReplace* ins)
|
||||||
{
|
{
|
||||||
|
@ -168,6 +168,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||||||
void visitRegExpTester(MRegExpTester* ins);
|
void visitRegExpTester(MRegExpTester* ins);
|
||||||
void visitRegExpPrototypeOptimizable(MRegExpPrototypeOptimizable* ins);
|
void visitRegExpPrototypeOptimizable(MRegExpPrototypeOptimizable* ins);
|
||||||
void visitRegExpInstanceOptimizable(MRegExpInstanceOptimizable* ins);
|
void visitRegExpInstanceOptimizable(MRegExpInstanceOptimizable* ins);
|
||||||
|
void visitGetFirstDollarIndex(MGetFirstDollarIndex* ins);
|
||||||
void visitStringReplace(MStringReplace* ins);
|
void visitStringReplace(MStringReplace* ins);
|
||||||
void visitBinarySharedStub(MBinarySharedStub* ins);
|
void visitBinarySharedStub(MBinarySharedStub* ins);
|
||||||
void visitUnarySharedStub(MUnarySharedStub* ins);
|
void visitUnarySharedStub(MUnarySharedStub* ins);
|
||||||
|
@ -188,6 +188,8 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
|||||||
return inlineRegExpPrototypeOptimizable(callInfo);
|
return inlineRegExpPrototypeOptimizable(callInfo);
|
||||||
case InlinableNative::RegExpInstanceOptimizable:
|
case InlinableNative::RegExpInstanceOptimizable:
|
||||||
return inlineRegExpInstanceOptimizable(callInfo);
|
return inlineRegExpInstanceOptimizable(callInfo);
|
||||||
|
case InlinableNative::GetFirstDollarIndex:
|
||||||
|
return inlineGetFirstDollarIndex(callInfo);
|
||||||
|
|
||||||
// String natives.
|
// String natives.
|
||||||
case InlinableNative::String:
|
case InlinableNative::String:
|
||||||
@ -1447,18 +1449,16 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
|
|||||||
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles)
|
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
|
if (!jsop_newarray(templateObject, initLength))
|
||||||
current->add(templateConst);
|
return InliningStatus_Error;
|
||||||
|
|
||||||
MNewArray* ins = MNewArray::New(alloc(), constraints(), initLength, templateConst,
|
MDefinition* array = current->peek(-1);
|
||||||
templateObject->group()->initialHeap(constraints()), pc);
|
|
||||||
|
|
||||||
current->add(ins);
|
|
||||||
current->push(ins);
|
|
||||||
|
|
||||||
if (!initLength) {
|
if (!initLength) {
|
||||||
if (!resumeAfter(ins))
|
if (!array->isResumePoint()) {
|
||||||
return InliningStatus_Error;
|
if (!resumeAfter(array->toNewArray()))
|
||||||
|
return InliningStatus_Error;
|
||||||
|
}
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1471,11 +1471,11 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
|
|||||||
MConstant* value = arrayValues[i];
|
MConstant* value = arrayValues[i];
|
||||||
current->add(value);
|
current->add(value);
|
||||||
|
|
||||||
if (!initializeArrayElement(ins, i, value, unboxedType, /* addResumePoint = */ false))
|
if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
|
||||||
return InliningStatus_Error;
|
return InliningStatus_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
MInstruction* setLength = setInitializedLength(ins, unboxedType, initLength);
|
MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
|
||||||
if (!resumeAfter(setLength))
|
if (!resumeAfter(setLength))
|
||||||
return InliningStatus_Error;
|
return InliningStatus_Error;
|
||||||
|
|
||||||
@ -1954,6 +1954,31 @@ IonBuilder::inlineRegExpInstanceOptimizable(CallInfo& callInfo)
|
|||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IonBuilder::InliningStatus
|
||||||
|
IonBuilder::inlineGetFirstDollarIndex(CallInfo& callInfo)
|
||||||
|
{
|
||||||
|
if (callInfo.argc() != 1 || callInfo.constructing()) {
|
||||||
|
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
|
||||||
|
return InliningStatus_NotInlined;
|
||||||
|
}
|
||||||
|
|
||||||
|
MDefinition* strArg = callInfo.getArg(0);
|
||||||
|
|
||||||
|
if (strArg->type() != MIRType_String)
|
||||||
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
|
if (getInlineReturnType() != MIRType_Int32)
|
||||||
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
|
callInfo.setImplicitlyUsedUnchecked();
|
||||||
|
|
||||||
|
MInstruction* ins = MGetFirstDollarIndex::New(alloc(), strArg);
|
||||||
|
current->add(ins);
|
||||||
|
current->push(ins);
|
||||||
|
|
||||||
|
return InliningStatus_Inlined;
|
||||||
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineStringReplaceString(CallInfo& callInfo)
|
IonBuilder::inlineStringReplaceString(CallInfo& callInfo)
|
||||||
{
|
{
|
||||||
|
@ -5290,6 +5290,18 @@ MArrayJoin::foldsTo(TempAllocator& alloc)
|
|||||||
return substr;
|
return substr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MDefinition*
|
||||||
|
MGetFirstDollarIndex::foldsTo(TempAllocator& alloc)
|
||||||
|
{
|
||||||
|
MDefinition* strArg = str();
|
||||||
|
if (!strArg->isConstant())
|
||||||
|
return this;
|
||||||
|
|
||||||
|
JSAtom* atom = &strArg->toConstant()->toString()->asAtom();
|
||||||
|
int32_t index = GetFirstDollarIndexRawFlat(atom);
|
||||||
|
return MConstant::New(alloc, Int32Value(index));
|
||||||
|
}
|
||||||
|
|
||||||
MConvertUnboxedObjectToNative*
|
MConvertUnboxedObjectToNative*
|
||||||
MConvertUnboxedObjectToNative::New(TempAllocator& alloc, MDefinition* obj, ObjectGroup* group)
|
MConvertUnboxedObjectToNative::New(TempAllocator& alloc, MDefinition* obj, ObjectGroup* group)
|
||||||
{
|
{
|
||||||
|
@ -8099,6 +8099,33 @@ class MRegExpInstanceOptimizable
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MGetFirstDollarIndex
|
||||||
|
: public MUnaryInstruction,
|
||||||
|
public StringPolicy<0>::Data
|
||||||
|
{
|
||||||
|
explicit MGetFirstDollarIndex(MDefinition* str)
|
||||||
|
: MUnaryInstruction(str)
|
||||||
|
{
|
||||||
|
setResultType(MIRType_Int32);
|
||||||
|
setMovable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
INSTRUCTION_HEADER(GetFirstDollarIndex)
|
||||||
|
|
||||||
|
static MGetFirstDollarIndex* New(TempAllocator& alloc, MDefinition* str) {
|
||||||
|
return new(alloc) MGetFirstDollarIndex(str);
|
||||||
|
}
|
||||||
|
MDefinition* str() const {
|
||||||
|
return getOperand(0);
|
||||||
|
}
|
||||||
|
AliasSet getAliasSet() const override {
|
||||||
|
return AliasSet::None();
|
||||||
|
}
|
||||||
|
|
||||||
|
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||||
|
};
|
||||||
|
|
||||||
class MStringReplace
|
class MStringReplace
|
||||||
: public MTernaryInstruction,
|
: public MTernaryInstruction,
|
||||||
public Mix3Policy<StringPolicy<0>, StringPolicy<1>, StringPolicy<2> >::Data
|
public Mix3Policy<StringPolicy<0>, StringPolicy<1>, StringPolicy<2> >::Data
|
||||||
|
@ -151,6 +151,7 @@ namespace jit {
|
|||||||
_(RegExpTester) \
|
_(RegExpTester) \
|
||||||
_(RegExpPrototypeOptimizable) \
|
_(RegExpPrototypeOptimizable) \
|
||||||
_(RegExpInstanceOptimizable) \
|
_(RegExpInstanceOptimizable) \
|
||||||
|
_(GetFirstDollarIndex) \
|
||||||
_(StringReplace) \
|
_(StringReplace) \
|
||||||
_(Lambda) \
|
_(Lambda) \
|
||||||
_(LambdaArrow) \
|
_(LambdaArrow) \
|
||||||
|
@ -4439,6 +4439,32 @@ class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LIR_HEADER(GetFirstDollarIndex);
|
||||||
|
explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0,
|
||||||
|
const LDefinition& temp1, const LDefinition& temp2) {
|
||||||
|
setOperand(0, str);
|
||||||
|
setTemp(0, temp0);
|
||||||
|
setTemp(1, temp1);
|
||||||
|
setTemp(2, temp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LAllocation* str() {
|
||||||
|
return getOperand(0);
|
||||||
|
}
|
||||||
|
const LDefinition* temp0() {
|
||||||
|
return getTemp(0);
|
||||||
|
}
|
||||||
|
const LDefinition* temp1() {
|
||||||
|
return getTemp(1);
|
||||||
|
}
|
||||||
|
const LDefinition* temp2() {
|
||||||
|
return getTemp(2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LStringReplace: public LCallInstructionHelper<1, 3, 0>
|
class LStringReplace: public LCallInstructionHelper<1, 3, 0>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -211,6 +211,7 @@
|
|||||||
_(RegExpTester) \
|
_(RegExpTester) \
|
||||||
_(RegExpPrototypeOptimizable) \
|
_(RegExpPrototypeOptimizable) \
|
||||||
_(RegExpInstanceOptimizable) \
|
_(RegExpInstanceOptimizable) \
|
||||||
|
_(GetFirstDollarIndex) \
|
||||||
_(StringReplace) \
|
_(StringReplace) \
|
||||||
_(Substr) \
|
_(Substr) \
|
||||||
_(BinarySharedStub) \
|
_(BinarySharedStub) \
|
||||||
|
@ -1028,49 +1028,49 @@ JS::CreateError(JSContext* cx, JSExnType type, HandleObject stack, HandleString
|
|||||||
const char*
|
const char*
|
||||||
js::ValueToSourceForError(JSContext* cx, HandleValue val, JSAutoByteString& bytes)
|
js::ValueToSourceForError(JSContext* cx, HandleValue val, JSAutoByteString& bytes)
|
||||||
{
|
{
|
||||||
if (val.isUndefined()) {
|
if (val.isUndefined())
|
||||||
return "undefined";
|
return "undefined";
|
||||||
}
|
|
||||||
if (val.isNull()) {
|
if (val.isNull())
|
||||||
return "null";
|
return "null";
|
||||||
}
|
|
||||||
|
AutoClearPendingException acpe(cx);
|
||||||
|
|
||||||
RootedString str(cx, JS_ValueToSource(cx, val));
|
RootedString str(cx, JS_ValueToSource(cx, val));
|
||||||
if (!str) {
|
if (!str)
|
||||||
JS_ClearPendingException(cx);
|
|
||||||
return "<<error converting value to string>>";
|
return "<<error converting value to string>>";
|
||||||
}
|
|
||||||
|
|
||||||
StringBuffer sb(cx);
|
StringBuffer sb(cx);
|
||||||
if (val.isObject()) {
|
if (val.isObject()) {
|
||||||
RootedObject valObj(cx, val.toObjectOrNull());
|
RootedObject valObj(cx, val.toObjectOrNull());
|
||||||
ESClassValue cls;
|
ESClassValue cls;
|
||||||
if (!GetBuiltinClass(cx, valObj, &cls)) {
|
if (!GetBuiltinClass(cx, valObj, &cls))
|
||||||
JS_ClearPendingException(cx);
|
|
||||||
return "<<error determining class of value>>";
|
return "<<error determining class of value>>";
|
||||||
}
|
const char* s;
|
||||||
if (cls == ESClass_Array) {
|
if (cls == ESClass_Array)
|
||||||
sb.append("the array ");
|
s = "the array ";
|
||||||
} else if (cls == ESClass_ArrayBuffer) {
|
else if (cls == ESClass_ArrayBuffer)
|
||||||
sb.append("the array buffer ");
|
s = "the array buffer ";
|
||||||
} else if (JS_IsArrayBufferViewObject(valObj)) {
|
else if (JS_IsArrayBufferViewObject(valObj))
|
||||||
sb.append("the typed array ");
|
s = "the typed array ";
|
||||||
} else {
|
else
|
||||||
sb.append("the object ");
|
s = "the object ";
|
||||||
}
|
if (!sb.append(s, strlen(s)))
|
||||||
|
return "<<error converting value to string>>";
|
||||||
} else if (val.isNumber()) {
|
} else if (val.isNumber()) {
|
||||||
sb.append("the number ");
|
if (!sb.append("the number "))
|
||||||
|
return "<<error converting value to string>>";
|
||||||
} else if (val.isString()) {
|
} else if (val.isString()) {
|
||||||
sb.append("the string ");
|
if (!sb.append("the string "))
|
||||||
|
return "<<error converting value to string>>";
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(val.isBoolean() || val.isSymbol());
|
MOZ_ASSERT(val.isBoolean() || val.isSymbol());
|
||||||
return bytes.encodeLatin1(cx, str);
|
return bytes.encodeLatin1(cx, str);
|
||||||
}
|
}
|
||||||
sb.append(str);
|
if (!sb.append(str))
|
||||||
str = sb.finishString();
|
return "<<error converting value to string>>";
|
||||||
if (!str) {
|
str = sb.finishString();
|
||||||
JS_ClearPendingException(cx);
|
if (!str)
|
||||||
return "<<error converting value to string>>";
|
return "<<error converting value to string>>";
|
||||||
}
|
|
||||||
return bytes.encodeLatin1(cx, str);
|
return bytes.encodeLatin1(cx, str);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/Casting.h"
|
#include "mozilla/Casting.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
|
||||||
@ -1295,21 +1296,27 @@ GetErrorMessage(void* userRef, const unsigned errorNumber);
|
|||||||
*/
|
*/
|
||||||
class MOZ_STACK_CLASS AutoStableStringChars
|
class MOZ_STACK_CLASS AutoStableStringChars
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* When copying string char, use this many bytes of inline storage. This is
|
||||||
|
* chosen to allow the inline string types to be copied without allocating.
|
||||||
|
* This is asserted in AutoStableStringChars::allocOwnChars.
|
||||||
|
*/
|
||||||
|
static const size_t InlineCapacity = 24;
|
||||||
|
|
||||||
/* Ensure the string is kept alive while we're using its chars. */
|
/* Ensure the string is kept alive while we're using its chars. */
|
||||||
JS::RootedString s_;
|
JS::RootedString s_;
|
||||||
union {
|
union {
|
||||||
const char16_t* twoByteChars_;
|
const char16_t* twoByteChars_;
|
||||||
const JS::Latin1Char* latin1Chars_;
|
const JS::Latin1Char* latin1Chars_;
|
||||||
};
|
};
|
||||||
|
mozilla::Maybe<Vector<uint8_t, InlineCapacity>> ownChars_;
|
||||||
enum State { Uninitialized, Latin1, TwoByte };
|
enum State { Uninitialized, Latin1, TwoByte };
|
||||||
State state_;
|
State state_;
|
||||||
bool ownsChars_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AutoStableStringChars(JSContext* cx)
|
explicit AutoStableStringChars(JSContext* cx)
|
||||||
: s_(cx), state_(Uninitialized), ownsChars_(false)
|
: s_(cx), state_(Uninitialized)
|
||||||
{}
|
{}
|
||||||
~AutoStableStringChars();
|
|
||||||
|
|
||||||
MOZ_WARN_UNUSED_RESULT
|
MOZ_WARN_UNUSED_RESULT
|
||||||
bool init(JSContext* cx, JSString* s);
|
bool init(JSContext* cx, JSString* s);
|
||||||
@ -1335,16 +1342,16 @@ class MOZ_STACK_CLASS AutoStableStringChars
|
|||||||
mozilla::Range<const char16_t> twoByteRange() const {
|
mozilla::Range<const char16_t> twoByteRange() const {
|
||||||
MOZ_ASSERT(state_ == TwoByte);
|
MOZ_ASSERT(state_ == TwoByte);
|
||||||
return mozilla::Range<const char16_t>(twoByteChars_,
|
return mozilla::Range<const char16_t>(twoByteChars_,
|
||||||
GetStringLength(s_));
|
GetStringLength(s_));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we own the chars, transfer ownership to the caller. */
|
/* If we own the chars, transfer ownership to the caller. */
|
||||||
bool maybeGiveOwnershipToCaller() {
|
bool maybeGiveOwnershipToCaller() {
|
||||||
MOZ_ASSERT(state_ != Uninitialized);
|
MOZ_ASSERT(state_ != Uninitialized);
|
||||||
if (!ownsChars_)
|
if (!ownChars_.isSome() || !ownChars_->extractRawBuffer())
|
||||||
return false;
|
return false;
|
||||||
state_ = Uninitialized;
|
state_ = Uninitialized;
|
||||||
ownsChars_ = false;
|
ownChars_.reset();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1353,8 +1360,9 @@ class MOZ_STACK_CLASS AutoStableStringChars
|
|||||||
void operator=(const AutoStableStringChars& other) = delete;
|
void operator=(const AutoStableStringChars& other) = delete;
|
||||||
|
|
||||||
bool baseIsInline(JS::Handle<JSLinearString*> linearString);
|
bool baseIsInline(JS::Handle<JSLinearString*> linearString);
|
||||||
bool copyLatin1Chars(JSContext*, JS::Handle<JSLinearString*> linearString);
|
template <typename T> T* allocOwnChars(JSContext* cx, size_t count);
|
||||||
bool copyTwoByteChars(JSContext*, JS::Handle<JSLinearString*> linearString);
|
bool copyLatin1Chars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
|
||||||
|
bool copyTwoByteChars(JSContext* cx, JS::Handle<JSLinearString*> linearString);
|
||||||
bool copyAndInflateLatin1Chars(JSContext*, JS::Handle<JSLinearString*> linearString);
|
bool copyAndInflateLatin1Chars(JSContext*, JS::Handle<JSLinearString*> linearString);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,8 +193,16 @@ class ZoneCellIterImpl
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ZoneCellIterImpl(JS::Zone* zone, AllocKind kind) {
|
ZoneCellIterImpl(JS::Zone* zone, AllocKind kind) {
|
||||||
|
JSRuntime* rt = zone->runtimeFromAnyThread();
|
||||||
MOZ_ASSERT(zone);
|
MOZ_ASSERT(zone);
|
||||||
MOZ_ASSERT(zone->runtimeFromAnyThread()->gc.nursery.isEmpty());
|
MOZ_ASSERT(rt->gc.nursery.isEmpty());
|
||||||
|
|
||||||
|
// We have a single-threaded runtime, so there's no need to protect
|
||||||
|
// against other threads iterating or allocating. However, we do have
|
||||||
|
// background finalization; we may have to wait for this to finish if
|
||||||
|
// it's currently active.
|
||||||
|
if (IsBackgroundFinalized(kind) && zone->arenas.needBackgroundFinalizeWait(kind))
|
||||||
|
rt->gc.waitBackgroundSweepEnd();
|
||||||
|
|
||||||
arenaIter.init(zone, kind);
|
arenaIter.init(zone, kind);
|
||||||
if (!arenaIter.done())
|
if (!arenaIter.done())
|
||||||
@ -248,13 +256,6 @@ class ZoneCellIter
|
|||||||
// that allows us to iterate.
|
// that allows us to iterate.
|
||||||
JSRuntime* rt = zone->runtimeFromMainThread();
|
JSRuntime* rt = zone->runtimeFromMainThread();
|
||||||
if (!rt->isHeapBusy()) {
|
if (!rt->isHeapBusy()) {
|
||||||
// We have a single-threaded runtime, so there's no need to protect
|
|
||||||
// against other threads iterating or allocating. However, we do
|
|
||||||
// have background finalization; we have to wait for this to finish
|
|
||||||
// if it's currently active.
|
|
||||||
if (IsBackgroundFinalized(kind) && zone->arenas.needBackgroundFinalizeWait(kind))
|
|
||||||
rt->gc.waitBackgroundSweepEnd();
|
|
||||||
|
|
||||||
// Evict the nursery before iterating so we can see all things.
|
// Evict the nursery before iterating so we can see all things.
|
||||||
rt->gc.evictNursery();
|
rt->gc.evictNursery();
|
||||||
|
|
||||||
|
@ -1672,15 +1672,15 @@ js::GetPCCountScriptCount(JSContext* cx)
|
|||||||
|
|
||||||
enum MaybeComma {NO_COMMA, COMMA};
|
enum MaybeComma {NO_COMMA, COMMA};
|
||||||
|
|
||||||
static void
|
static MOZ_WARN_UNUSED_RESULT bool
|
||||||
AppendJSONProperty(StringBuffer& buf, const char* name, MaybeComma comma = COMMA)
|
AppendJSONProperty(StringBuffer& buf, const char* name, MaybeComma comma = COMMA)
|
||||||
{
|
{
|
||||||
if (comma)
|
if (comma && !buf.append(','))
|
||||||
buf.append(',');
|
return false;
|
||||||
|
|
||||||
buf.append('\"');
|
return buf.append('\"') &&
|
||||||
buf.append(name, strlen(name));
|
buf.append(name, strlen(name)) &&
|
||||||
buf.append("\":", 2);
|
buf.append("\":", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(JSString*)
|
JS_FRIEND_API(JSString*)
|
||||||
@ -1703,24 +1703,30 @@ js::GetPCCountScriptSummary(JSContext* cx, size_t index)
|
|||||||
*/
|
*/
|
||||||
StringBuffer buf(cx);
|
StringBuffer buf(cx);
|
||||||
|
|
||||||
buf.append('{');
|
if (!buf.append('{'))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
AppendJSONProperty(buf, "file", NO_COMMA);
|
if (!AppendJSONProperty(buf, "file", NO_COMMA))
|
||||||
|
return nullptr;
|
||||||
JSString* str = JS_NewStringCopyZ(cx, script->filename());
|
JSString* str = JS_NewStringCopyZ(cx, script->filename());
|
||||||
if (!str || !(str = StringToSource(cx, str)))
|
if (!str || !(str = StringToSource(cx, str)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
buf.append(str);
|
if (!buf.append(str))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
AppendJSONProperty(buf, "line");
|
if (!AppendJSONProperty(buf, "line"))
|
||||||
|
return nullptr;
|
||||||
NumberValueToStringBuffer(cx, Int32Value(script->lineno()), buf);
|
NumberValueToStringBuffer(cx, Int32Value(script->lineno()), buf);
|
||||||
|
|
||||||
if (script->functionNonDelazifying()) {
|
if (script->functionNonDelazifying()) {
|
||||||
JSAtom* atom = script->functionNonDelazifying()->displayAtom();
|
JSAtom* atom = script->functionNonDelazifying()->displayAtom();
|
||||||
if (atom) {
|
if (atom) {
|
||||||
AppendJSONProperty(buf, "name");
|
if (!AppendJSONProperty(buf, "name"))
|
||||||
|
return nullptr;
|
||||||
if (!(str = StringToSource(cx, atom)))
|
if (!(str = StringToSource(cx, atom)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
buf.append(str);
|
if (!buf.append(str))
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1734,11 +1740,15 @@ js::GetPCCountScriptSummary(JSContext* cx, size_t index)
|
|||||||
total += counts->numExec();
|
total += counts->numExec();
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendJSONProperty(buf, "totals");
|
if (!AppendJSONProperty(buf, "totals"))
|
||||||
buf.append('{');
|
return nullptr;
|
||||||
|
if (!buf.append('{'))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
AppendJSONProperty(buf, PCCounts::numExecName, NO_COMMA);
|
if (!AppendJSONProperty(buf, PCCounts::numExecName, NO_COMMA))
|
||||||
NumberValueToStringBuffer(cx, DoubleValue(total), buf);
|
return nullptr;
|
||||||
|
if (!NumberValueToStringBuffer(cx, DoubleValue(total), buf))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
uint64_t ionActivity = 0;
|
uint64_t ionActivity = 0;
|
||||||
jit::IonScriptCounts* ionCounts = sac.getIonCounts();
|
jit::IonScriptCounts* ionCounts = sac.getIonCounts();
|
||||||
@ -1748,15 +1758,18 @@ js::GetPCCountScriptSummary(JSContext* cx, size_t index)
|
|||||||
ionCounts = ionCounts->previous();
|
ionCounts = ionCounts->previous();
|
||||||
}
|
}
|
||||||
if (ionActivity) {
|
if (ionActivity) {
|
||||||
AppendJSONProperty(buf, "ion", COMMA);
|
if (!AppendJSONProperty(buf, "ion", COMMA))
|
||||||
NumberValueToStringBuffer(cx, DoubleValue(ionActivity), buf);
|
return nullptr;
|
||||||
|
if (!NumberValueToStringBuffer(cx, DoubleValue(ionActivity), buf))
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append('}');
|
if (!buf.append('}'))
|
||||||
buf.append('}');
|
|
||||||
|
|
||||||
if (cx->isExceptionPending())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
if (!buf.append('}'))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
MOZ_ASSERT(!cx->isExceptionPending());
|
||||||
|
|
||||||
return buf.finishString();
|
return buf.finishString();
|
||||||
}
|
}
|
||||||
@ -1766,20 +1779,27 @@ GetPCCountJSON(JSContext* cx, const ScriptAndCounts& sac, StringBuffer& buf)
|
|||||||
{
|
{
|
||||||
RootedScript script(cx, sac.script);
|
RootedScript script(cx, sac.script);
|
||||||
|
|
||||||
buf.append('{');
|
if (!buf.append('{'))
|
||||||
AppendJSONProperty(buf, "text", NO_COMMA);
|
return false;
|
||||||
|
if (!AppendJSONProperty(buf, "text", NO_COMMA))
|
||||||
|
return false;
|
||||||
|
|
||||||
JSString* str = JS_DecompileScript(cx, script, nullptr, 0);
|
JSString* str = JS_DecompileScript(cx, script, nullptr, 0);
|
||||||
if (!str || !(str = StringToSource(cx, str)))
|
if (!str || !(str = StringToSource(cx, str)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
buf.append(str);
|
if (!buf.append(str))
|
||||||
|
return false;
|
||||||
|
|
||||||
AppendJSONProperty(buf, "line");
|
if (!AppendJSONProperty(buf, "line"))
|
||||||
NumberValueToStringBuffer(cx, Int32Value(script->lineno()), buf);
|
return false;
|
||||||
|
if (!NumberValueToStringBuffer(cx, Int32Value(script->lineno()), buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
AppendJSONProperty(buf, "opcodes");
|
if (!AppendJSONProperty(buf, "opcodes"))
|
||||||
buf.append('[');
|
return false;
|
||||||
|
if (!buf.append('['))
|
||||||
|
return false;
|
||||||
bool comma = false;
|
bool comma = false;
|
||||||
|
|
||||||
SrcNoteLineScanner scanner(script->notes(), script->lineno());
|
SrcNoteLineScanner scanner(script->notes(), script->lineno());
|
||||||
@ -1796,26 +1816,35 @@ GetPCCountJSON(JSContext* cx, const ScriptAndCounts& sac, StringBuffer& buf)
|
|||||||
if (counts)
|
if (counts)
|
||||||
hits = counts->numExec();
|
hits = counts->numExec();
|
||||||
|
|
||||||
if (comma)
|
if (comma && !buf.append(','))
|
||||||
buf.append(',');
|
return false;
|
||||||
comma = true;
|
comma = true;
|
||||||
|
|
||||||
buf.append('{');
|
if (!buf.append('{'))
|
||||||
|
return false;
|
||||||
|
|
||||||
AppendJSONProperty(buf, "id", NO_COMMA);
|
if (!AppendJSONProperty(buf, "id", NO_COMMA))
|
||||||
NumberValueToStringBuffer(cx, Int32Value(offset), buf);
|
return false;
|
||||||
|
if (!NumberValueToStringBuffer(cx, Int32Value(offset), buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
scanner.advanceTo(offset);
|
scanner.advanceTo(offset);
|
||||||
|
|
||||||
AppendJSONProperty(buf, "line");
|
if (!AppendJSONProperty(buf, "line"))
|
||||||
NumberValueToStringBuffer(cx, Int32Value(scanner.getLine()), buf);
|
return false;
|
||||||
|
if (!NumberValueToStringBuffer(cx, Int32Value(scanner.getLine()), buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
{
|
{
|
||||||
const char* name = CodeName[op];
|
const char* name = CodeName[op];
|
||||||
AppendJSONProperty(buf, "name");
|
if (!AppendJSONProperty(buf, "name"))
|
||||||
buf.append('\"');
|
return false;
|
||||||
buf.append(name, strlen(name));
|
if (!buf.append('\"'))
|
||||||
buf.append('\"');
|
return false;
|
||||||
|
if (!buf.append(name, strlen(name)))
|
||||||
|
return false;
|
||||||
|
if (!buf.append('\"'))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -1827,24 +1856,32 @@ GetPCCountJSON(JSContext* cx, const ScriptAndCounts& sac, StringBuffer& buf)
|
|||||||
char* text;
|
char* text;
|
||||||
if (!ed.getOutput(&text))
|
if (!ed.getOutput(&text))
|
||||||
return false;
|
return false;
|
||||||
AppendJSONProperty(buf, "text");
|
|
||||||
JSString* str = JS_NewStringCopyZ(cx, text);
|
JSString* str = JS_NewStringCopyZ(cx, text);
|
||||||
js_free(text);
|
js_free(text);
|
||||||
|
if (!AppendJSONProperty(buf, "text"))
|
||||||
|
return false;
|
||||||
if (!str || !(str = StringToSource(cx, str)))
|
if (!str || !(str = StringToSource(cx, str)))
|
||||||
return false;
|
return false;
|
||||||
buf.append(str);
|
if (!buf.append(str))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendJSONProperty(buf, "counts");
|
if (!AppendJSONProperty(buf, "counts"))
|
||||||
buf.append('{');
|
return false;
|
||||||
|
if (!buf.append('{'))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (hits > 0) {
|
if (hits > 0) {
|
||||||
AppendJSONProperty(buf, PCCounts::numExecName, NO_COMMA);
|
if (!AppendJSONProperty(buf, PCCounts::numExecName, NO_COMMA))
|
||||||
NumberValueToStringBuffer(cx, DoubleValue(hits), buf);
|
return false;
|
||||||
|
if (!NumberValueToStringBuffer(cx, DoubleValue(hits), buf))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append('}');
|
if (!buf.append('}'))
|
||||||
buf.append('}');
|
return false;
|
||||||
|
if (!buf.append('}'))
|
||||||
|
return false;
|
||||||
|
|
||||||
// If the current instruction has thrown,
|
// If the current instruction has thrown,
|
||||||
// then decrement the hit counts with the number of throws.
|
// then decrement the hit counts with the number of throws.
|
||||||
@ -1853,57 +1890,79 @@ GetPCCountJSON(JSContext* cx, const ScriptAndCounts& sac, StringBuffer& buf)
|
|||||||
hits -= counts->numExec();
|
hits -= counts->numExec();
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append(']');
|
if (!buf.append(']'))
|
||||||
|
return false;
|
||||||
|
|
||||||
jit::IonScriptCounts* ionCounts = sac.getIonCounts();
|
jit::IonScriptCounts* ionCounts = sac.getIonCounts();
|
||||||
if (ionCounts) {
|
if (ionCounts) {
|
||||||
AppendJSONProperty(buf, "ion");
|
if (!AppendJSONProperty(buf, "ion"))
|
||||||
buf.append('[');
|
return false;
|
||||||
|
if (!buf.append('['))
|
||||||
|
return false;
|
||||||
bool comma = false;
|
bool comma = false;
|
||||||
while (ionCounts) {
|
while (ionCounts) {
|
||||||
if (comma)
|
if (comma && !buf.append(','))
|
||||||
buf.append(',');
|
return false;
|
||||||
comma = true;
|
comma = true;
|
||||||
|
|
||||||
buf.append('[');
|
if (!buf.append('['))
|
||||||
|
return false;
|
||||||
for (size_t i = 0; i < ionCounts->numBlocks(); i++) {
|
for (size_t i = 0; i < ionCounts->numBlocks(); i++) {
|
||||||
if (i)
|
if (i && !buf.append(','))
|
||||||
buf.append(',');
|
return false;
|
||||||
const jit::IonBlockCounts& block = ionCounts->block(i);
|
const jit::IonBlockCounts& block = ionCounts->block(i);
|
||||||
|
|
||||||
buf.append('{');
|
if (!buf.append('{'))
|
||||||
AppendJSONProperty(buf, "id", NO_COMMA);
|
return false;
|
||||||
NumberValueToStringBuffer(cx, Int32Value(block.id()), buf);
|
if (!AppendJSONProperty(buf, "id", NO_COMMA))
|
||||||
AppendJSONProperty(buf, "offset");
|
return false;
|
||||||
NumberValueToStringBuffer(cx, Int32Value(block.offset()), buf);
|
if (!NumberValueToStringBuffer(cx, Int32Value(block.id()), buf))
|
||||||
AppendJSONProperty(buf, "successors");
|
return false;
|
||||||
buf.append('[');
|
if (!AppendJSONProperty(buf, "offset"))
|
||||||
|
return false;
|
||||||
|
if (!NumberValueToStringBuffer(cx, Int32Value(block.offset()), buf))
|
||||||
|
return false;
|
||||||
|
if (!AppendJSONProperty(buf, "successors"))
|
||||||
|
return false;
|
||||||
|
if (!buf.append('['))
|
||||||
|
return false;
|
||||||
for (size_t j = 0; j < block.numSuccessors(); j++) {
|
for (size_t j = 0; j < block.numSuccessors(); j++) {
|
||||||
if (j)
|
if (j && !buf.append(','))
|
||||||
buf.append(',');
|
return false;
|
||||||
NumberValueToStringBuffer(cx, Int32Value(block.successor(j)), buf);
|
if (!NumberValueToStringBuffer(cx, Int32Value(block.successor(j)), buf))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
buf.append(']');
|
if (!buf.append(']'))
|
||||||
AppendJSONProperty(buf, "hits");
|
return false;
|
||||||
NumberValueToStringBuffer(cx, DoubleValue(block.hitCount()), buf);
|
if (!AppendJSONProperty(buf, "hits"))
|
||||||
|
return false;
|
||||||
|
if (!NumberValueToStringBuffer(cx, DoubleValue(block.hitCount()), buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
AppendJSONProperty(buf, "code");
|
if (!AppendJSONProperty(buf, "code"))
|
||||||
|
return false;
|
||||||
JSString* str = JS_NewStringCopyZ(cx, block.code());
|
JSString* str = JS_NewStringCopyZ(cx, block.code());
|
||||||
if (!str || !(str = StringToSource(cx, str)))
|
if (!str || !(str = StringToSource(cx, str)))
|
||||||
return false;
|
return false;
|
||||||
buf.append(str);
|
if (!buf.append(str))
|
||||||
buf.append('}');
|
return false;
|
||||||
|
if (!buf.append('}'))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
buf.append(']');
|
if (!buf.append(']'))
|
||||||
|
return false;
|
||||||
|
|
||||||
ionCounts = ionCounts->previous();
|
ionCounts = ionCounts->previous();
|
||||||
}
|
}
|
||||||
buf.append(']');
|
if (!buf.append(']'))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append('}');
|
if (!buf.append('}'))
|
||||||
|
return false;
|
||||||
|
|
||||||
return !cx->isExceptionPending();
|
MOZ_ASSERT(!cx->isExceptionPending());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(JSString*)
|
JS_FRIEND_API(JSString*)
|
||||||
|
33
js/src/tests/ecma_6/Function/arguments-extra-property.js
Normal file
33
js/src/tests/ecma_6/Function/arguments-extra-property.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
var BUGNUMBER = 1263811;
|
||||||
|
var summary = "GetElem for modified arguments shouldn't be optimized to get original argument.";
|
||||||
|
|
||||||
|
print(BUGNUMBER + ": " + summary);
|
||||||
|
|
||||||
|
function testModifyFirst() {
|
||||||
|
function f() {
|
||||||
|
Object.defineProperty(arguments, 1, { value: 30 });
|
||||||
|
assertEq(arguments[1], 30);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 10; i++)
|
||||||
|
f(10, 20);
|
||||||
|
}
|
||||||
|
testModifyFirst();
|
||||||
|
|
||||||
|
function testModifyLater() {
|
||||||
|
function f() {
|
||||||
|
var ans = 20;
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
if (i == 5) {
|
||||||
|
Object.defineProperty(arguments, 1, { value: 30 });
|
||||||
|
ans = 30;
|
||||||
|
}
|
||||||
|
assertEq(arguments[1], ans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 10; i++)
|
||||||
|
f(10, 20);
|
||||||
|
}
|
||||||
|
testModifyLater();
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(true, true);
|
@ -127,7 +127,11 @@ class ArgumentsObject : public NativeObject
|
|||||||
public:
|
public:
|
||||||
static const uint32_t LENGTH_OVERRIDDEN_BIT = 0x1;
|
static const uint32_t LENGTH_OVERRIDDEN_BIT = 0x1;
|
||||||
static const uint32_t ITERATOR_OVERRIDDEN_BIT = 0x2;
|
static const uint32_t ITERATOR_OVERRIDDEN_BIT = 0x2;
|
||||||
static const uint32_t PACKED_BITS_COUNT = 2;
|
static const uint32_t ELEMENT_OVERRIDDEN_BIT = 0x4;
|
||||||
|
static const uint32_t PACKED_BITS_COUNT = 3;
|
||||||
|
|
||||||
|
static_assert(ARGS_LENGTH_MAX <= (UINT32_MAX >> PACKED_BITS_COUNT),
|
||||||
|
"Max arguments length must fit in available bits");
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template <typename CopyArgs>
|
template <typename CopyArgs>
|
||||||
@ -199,6 +203,18 @@ class ArgumentsObject : public NativeObject
|
|||||||
setFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(v));
|
setFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* True iff any element has been assigned or its attributes
|
||||||
|
* changed. */
|
||||||
|
bool hasOverriddenElement() const {
|
||||||
|
const Value& v = getFixedSlot(INITIAL_LENGTH_SLOT);
|
||||||
|
return v.toInt32() & ELEMENT_OVERRIDDEN_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void markElementOverridden() {
|
||||||
|
uint32_t v = getFixedSlot(INITIAL_LENGTH_SLOT).toInt32() | ELEMENT_OVERRIDDEN_BIT;
|
||||||
|
setFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(v));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Because the arguments object is a real object, its elements may be
|
* Because the arguments object is a real object, its elements may be
|
||||||
* deleted. This is implemented by setting a 'deleted' flag for the arg
|
* deleted. This is implemented by setting a 'deleted' flag for the arg
|
||||||
|
@ -1344,11 +1344,13 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||||||
// redefined, it will.
|
// redefined, it will.
|
||||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
||||||
obj->as<ArgumentsObject>().markLengthOverridden();
|
obj->as<ArgumentsObject>().markLengthOverridden();
|
||||||
}
|
} else if (JSID_IS_SYMBOL(id) && JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().iterator) {
|
||||||
if (JSID_IS_SYMBOL(id) && JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().iterator) {
|
|
||||||
// Do same thing as .length for [@@iterator].
|
// Do same thing as .length for [@@iterator].
|
||||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
||||||
obj->as<ArgumentsObject>().markIteratorOverridden();
|
obj->as<ArgumentsObject>().markIteratorOverridden();
|
||||||
|
} else if (JSID_IS_INT(id)) {
|
||||||
|
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
||||||
|
obj->as<ArgumentsObject>().markElementOverridden();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2568,6 +2568,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||||||
JS_FN("RegExpEscapeMetaChars", intrinsic_RegExpEscapeMetaChars, 1,0),
|
JS_FN("RegExpEscapeMetaChars", intrinsic_RegExpEscapeMetaChars, 1,0),
|
||||||
JS_FN("GetElemBaseForLambda", intrinsic_GetElemBaseForLambda, 1,0),
|
JS_FN("GetElemBaseForLambda", intrinsic_GetElemBaseForLambda, 1,0),
|
||||||
JS_FN("GetStringDataProperty", intrinsic_GetStringDataProperty, 2,0),
|
JS_FN("GetStringDataProperty", intrinsic_GetStringDataProperty, 2,0),
|
||||||
|
JS_INLINABLE_FN("GetFirstDollarIndex", GetFirstDollarIndex, 1,0,
|
||||||
|
GetFirstDollarIndex),
|
||||||
|
|
||||||
JS_FN("FlatStringMatch", FlatStringMatch, 2,0),
|
JS_FN("FlatStringMatch", FlatStringMatch, 2,0),
|
||||||
JS_FN("FlatStringSearch", FlatStringSearch, 2,0),
|
JS_FN("FlatStringSearch", FlatStringSearch, 2,0),
|
||||||
|
@ -874,17 +874,6 @@ StaticStrings::isStatic(JSAtom* atom)
|
|||||||
: isStatic(atom->twoByteChars(nogc), atom->length());
|
: isStatic(atom->twoByteChars(nogc), atom->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoStableStringChars::~AutoStableStringChars()
|
|
||||||
{
|
|
||||||
if (ownsChars_) {
|
|
||||||
MOZ_ASSERT(state_ == Latin1 || state_ == TwoByte);
|
|
||||||
if (state_ == Latin1)
|
|
||||||
js_free(const_cast<Latin1Char*>(latin1Chars_));
|
|
||||||
else
|
|
||||||
js_free(const_cast<char16_t*>(twoByteChars_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AutoStableStringChars::init(JSContext* cx, JSString* s)
|
AutoStableStringChars::init(JSContext* cx, JSString* s)
|
||||||
{
|
{
|
||||||
@ -944,10 +933,33 @@ bool AutoStableStringChars::baseIsInline(HandleLinearString linearString)
|
|||||||
return base->isInline();
|
return base->isInline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T*
|
||||||
|
AutoStableStringChars::allocOwnChars(JSContext* cx, size_t count)
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
InlineCapacity >= sizeof(JS::Latin1Char) * (JSFatInlineString::MAX_LENGTH_LATIN1 + 1) &&
|
||||||
|
InlineCapacity >= sizeof(char16_t) * (JSFatInlineString::MAX_LENGTH_TWO_BYTE + 1),
|
||||||
|
"InlineCapacity too small to hold fat inline strings");
|
||||||
|
|
||||||
|
static_assert((JSString::MAX_LENGTH & mozilla::tl::MulOverflowMask<sizeof(T)>::value) == 0,
|
||||||
|
"Size calculation can overflow");
|
||||||
|
MOZ_ASSERT(count <= JSString::MAX_LENGTH);
|
||||||
|
size_t size = sizeof(T) * count;
|
||||||
|
|
||||||
|
ownChars_.emplace(cx);
|
||||||
|
if (!ownChars_->resize(size)) {
|
||||||
|
ownChars_.reset();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<T*>(ownChars_->begin());
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AutoStableStringChars::copyAndInflateLatin1Chars(JSContext* cx, HandleLinearString linearString)
|
AutoStableStringChars::copyAndInflateLatin1Chars(JSContext* cx, HandleLinearString linearString)
|
||||||
{
|
{
|
||||||
char16_t* chars = cx->pod_malloc<char16_t>(linearString->length() + 1);
|
char16_t* chars = allocOwnChars<char16_t>(cx, linearString->length() + 1);
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -956,7 +968,6 @@ AutoStableStringChars::copyAndInflateLatin1Chars(JSContext* cx, HandleLinearStri
|
|||||||
chars[linearString->length()] = 0;
|
chars[linearString->length()] = 0;
|
||||||
|
|
||||||
state_ = TwoByte;
|
state_ = TwoByte;
|
||||||
ownsChars_ = true;
|
|
||||||
twoByteChars_ = chars;
|
twoByteChars_ = chars;
|
||||||
s_ = linearString;
|
s_ = linearString;
|
||||||
return true;
|
return true;
|
||||||
@ -966,7 +977,7 @@ bool
|
|||||||
AutoStableStringChars::copyLatin1Chars(JSContext* cx, HandleLinearString linearString)
|
AutoStableStringChars::copyLatin1Chars(JSContext* cx, HandleLinearString linearString)
|
||||||
{
|
{
|
||||||
size_t length = linearString->length();
|
size_t length = linearString->length();
|
||||||
JS::Latin1Char* chars = cx->pod_malloc<JS::Latin1Char>(length + 1);
|
JS::Latin1Char* chars = allocOwnChars<JS::Latin1Char>(cx, length + 1);
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -974,7 +985,6 @@ AutoStableStringChars::copyLatin1Chars(JSContext* cx, HandleLinearString linearS
|
|||||||
chars[length] = 0;
|
chars[length] = 0;
|
||||||
|
|
||||||
state_ = Latin1;
|
state_ = Latin1;
|
||||||
ownsChars_ = true;
|
|
||||||
latin1Chars_ = chars;
|
latin1Chars_ = chars;
|
||||||
s_ = linearString;
|
s_ = linearString;
|
||||||
return true;
|
return true;
|
||||||
@ -984,7 +994,7 @@ bool
|
|||||||
AutoStableStringChars::copyTwoByteChars(JSContext* cx, HandleLinearString linearString)
|
AutoStableStringChars::copyTwoByteChars(JSContext* cx, HandleLinearString linearString)
|
||||||
{
|
{
|
||||||
size_t length = linearString->length();
|
size_t length = linearString->length();
|
||||||
char16_t* chars = cx->pod_malloc<char16_t>(length + 1);
|
char16_t* chars = allocOwnChars<char16_t>(cx, length + 1);
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -992,7 +1002,6 @@ AutoStableStringChars::copyTwoByteChars(JSContext* cx, HandleLinearString linear
|
|||||||
chars[length] = 0;
|
chars[length] = 0;
|
||||||
|
|
||||||
state_ = TwoByte;
|
state_ = TwoByte;
|
||||||
ownsChars_ = true;
|
|
||||||
twoByteChars_ = chars;
|
twoByteChars_ = chars;
|
||||||
s_ = linearString;
|
s_ = linearString;
|
||||||
return true;
|
return true;
|
||||||
|
@ -21,7 +21,7 @@ ExtractWellSized(ExclusiveContext* cx, Buffer& cb)
|
|||||||
size_t capacity = cb.capacity();
|
size_t capacity = cb.capacity();
|
||||||
size_t length = cb.length();
|
size_t length = cb.length();
|
||||||
|
|
||||||
CharT* buf = cb.extractRawBuffer();
|
CharT* buf = cb.extractOrCopyRawBuffer();
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ class StringBuffer
|
|||||||
return cb.ref<TwoByteCharBuffer>();
|
return cb.ref<TwoByteCharBuffer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inflateChars();
|
MOZ_WARN_UNUSED_RESULT bool inflateChars();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StringBuffer(ExclusiveContext* cx)
|
explicit StringBuffer(ExclusiveContext* cx)
|
||||||
@ -85,25 +85,25 @@ class StringBuffer
|
|||||||
cb.construct<Latin1CharBuffer>(cx);
|
cb.construct<Latin1CharBuffer>(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool reserve(size_t len) {
|
MOZ_WARN_UNUSED_RESULT bool reserve(size_t len) {
|
||||||
if (len > reserved_)
|
if (len > reserved_)
|
||||||
reserved_ = len;
|
reserved_ = len;
|
||||||
return isLatin1() ? latin1Chars().reserve(len) : twoByteChars().reserve(len);
|
return isLatin1() ? latin1Chars().reserve(len) : twoByteChars().reserve(len);
|
||||||
}
|
}
|
||||||
inline bool resize(size_t len) {
|
MOZ_WARN_UNUSED_RESULT bool resize(size_t len) {
|
||||||
return isLatin1() ? latin1Chars().resize(len) : twoByteChars().resize(len);
|
return isLatin1() ? latin1Chars().resize(len) : twoByteChars().resize(len);
|
||||||
}
|
}
|
||||||
inline bool empty() const {
|
bool empty() const {
|
||||||
return isLatin1() ? latin1Chars().empty() : twoByteChars().empty();
|
return isLatin1() ? latin1Chars().empty() : twoByteChars().empty();
|
||||||
}
|
}
|
||||||
inline size_t length() const {
|
size_t length() const {
|
||||||
return isLatin1() ? latin1Chars().length() : twoByteChars().length();
|
return isLatin1() ? latin1Chars().length() : twoByteChars().length();
|
||||||
}
|
}
|
||||||
inline char16_t getChar(size_t idx) const {
|
char16_t getChar(size_t idx) const {
|
||||||
return isLatin1() ? latin1Chars()[idx] : twoByteChars()[idx];
|
return isLatin1() ? latin1Chars()[idx] : twoByteChars()[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool ensureTwoByteChars() {
|
MOZ_WARN_UNUSED_RESULT bool ensureTwoByteChars() {
|
||||||
if (isLatin1() && !inflateChars())
|
if (isLatin1() && !inflateChars())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ class StringBuffer
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool append(const char16_t c) {
|
MOZ_WARN_UNUSED_RESULT bool append(const char16_t c) {
|
||||||
if (isLatin1()) {
|
if (isLatin1()) {
|
||||||
if (c <= JSString::MAX_LATIN1_CHAR)
|
if (c <= JSString::MAX_LATIN1_CHAR)
|
||||||
return latin1Chars().append(Latin1Char(c));
|
return latin1Chars().append(Latin1Char(c));
|
||||||
@ -122,43 +122,44 @@ class StringBuffer
|
|||||||
}
|
}
|
||||||
return twoByteChars().append(c);
|
return twoByteChars().append(c);
|
||||||
}
|
}
|
||||||
inline bool append(Latin1Char c) {
|
MOZ_WARN_UNUSED_RESULT bool append(Latin1Char c) {
|
||||||
return isLatin1() ? latin1Chars().append(c) : twoByteChars().append(c);
|
return isLatin1() ? latin1Chars().append(c) : twoByteChars().append(c);
|
||||||
}
|
}
|
||||||
inline bool append(char c) {
|
MOZ_WARN_UNUSED_RESULT bool append(char c) {
|
||||||
return append(Latin1Char(c));
|
return append(Latin1Char(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool append(const char16_t* begin, const char16_t* end);
|
inline MOZ_WARN_UNUSED_RESULT bool append(const char16_t* begin, const char16_t* end);
|
||||||
inline bool append(const char16_t* chars, size_t len) {
|
|
||||||
|
MOZ_WARN_UNUSED_RESULT bool append(const char16_t* chars, size_t len) {
|
||||||
return append(chars, chars + len);
|
return append(chars, chars + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool append(const Latin1Char* begin, const Latin1Char* end) {
|
MOZ_WARN_UNUSED_RESULT bool append(const Latin1Char* begin, const Latin1Char* end) {
|
||||||
return isLatin1() ? latin1Chars().append(begin, end) : twoByteChars().append(begin, end);
|
return isLatin1() ? latin1Chars().append(begin, end) : twoByteChars().append(begin, end);
|
||||||
}
|
}
|
||||||
inline bool append(const Latin1Char* chars, size_t len) {
|
MOZ_WARN_UNUSED_RESULT bool append(const Latin1Char* chars, size_t len) {
|
||||||
return append(chars, chars + len);
|
return append(chars, chars + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool append(const JS::ConstCharPtr chars, size_t len) {
|
MOZ_WARN_UNUSED_RESULT bool append(const JS::ConstCharPtr chars, size_t len) {
|
||||||
return append(chars.get(), chars.get() + len);
|
return append(chars.get(), chars.get() + len);
|
||||||
}
|
}
|
||||||
inline bool appendN(Latin1Char c, size_t n) {
|
MOZ_WARN_UNUSED_RESULT bool appendN(Latin1Char c, size_t n) {
|
||||||
return isLatin1() ? latin1Chars().appendN(c, n) : twoByteChars().appendN(c, n);
|
return isLatin1() ? latin1Chars().appendN(c, n) : twoByteChars().appendN(c, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool append(JSString* str);
|
inline MOZ_WARN_UNUSED_RESULT bool append(JSString* str);
|
||||||
inline bool append(JSLinearString* str);
|
inline MOZ_WARN_UNUSED_RESULT bool append(JSLinearString* str);
|
||||||
inline bool appendSubstring(JSString* base, size_t off, size_t len);
|
inline MOZ_WARN_UNUSED_RESULT bool appendSubstring(JSString* base, size_t off, size_t len);
|
||||||
inline bool appendSubstring(JSLinearString* base, size_t off, size_t len);
|
inline MOZ_WARN_UNUSED_RESULT bool appendSubstring(JSLinearString* base, size_t off, size_t len);
|
||||||
|
|
||||||
inline bool append(const char* chars, size_t len) {
|
MOZ_WARN_UNUSED_RESULT bool append(const char* chars, size_t len) {
|
||||||
return append(reinterpret_cast<const Latin1Char*>(chars), len);
|
return append(reinterpret_cast<const Latin1Char*>(chars), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t ArrayLength>
|
template <size_t ArrayLength>
|
||||||
bool append(const char (&array)[ArrayLength]) {
|
MOZ_WARN_UNUSED_RESULT bool append(const char (&array)[ArrayLength]) {
|
||||||
return append(array, ArrayLength - 1); /* No trailing '\0'. */
|
return append(array, ArrayLength - 1); /* No trailing '\0'. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +742,7 @@ bool
|
|||||||
SCOutput::extractBuffer(uint64_t** datap, size_t* sizep)
|
SCOutput::extractBuffer(uint64_t** datap, size_t* sizep)
|
||||||
{
|
{
|
||||||
*sizep = buf.length() * sizeof(uint64_t);
|
*sizep = buf.length() * sizeof(uint64_t);
|
||||||
return (*datap = buf.extractRawBuffer()) != nullptr;
|
return (*datap = buf.extractOrCopyRawBuffer()) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
@ -2158,14 +2158,6 @@ static bool IsContentLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
|
|||||||
return nsLayoutUtils::CompareTreePosition(content1, content2, commonAncestor) <= 0;
|
return nsLayoutUtils::CompareTreePosition(content1, content2, commonAncestor) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsCSSOrderLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2, void*) {
|
|
||||||
nsIFrame* frame1 = aItem1->Frame();
|
|
||||||
nsIFrame* frame2 = aItem2->Frame();
|
|
||||||
int32_t order1 = frame1 ? frame1->StylePosition()->mOrder : 0;
|
|
||||||
int32_t order2 = frame2 ? frame2->StylePosition()->mOrder : 0;
|
|
||||||
return order1 <= order2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsZOrderLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
|
static bool IsZOrderLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
|
||||||
void* aClosure) {
|
void* aClosure) {
|
||||||
{
|
{
|
||||||
@ -2189,10 +2181,6 @@ void nsDisplayList::SortByContentOrder(nsIContent* aCommonAncestor) {
|
|||||||
Sort(IsContentLEQ, aCommonAncestor);
|
Sort(IsContentLEQ, aCommonAncestor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsDisplayList::SortByCSSOrder() {
|
|
||||||
Sort(IsCSSOrderLEQ, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsDisplayList::Sort(SortLEQ aCmp, void* aClosure) {
|
void nsDisplayList::Sort(SortLEQ aCmp, void* aClosure) {
|
||||||
::Sort(this, Count(), aCmp, aClosure);
|
::Sort(this, Count(), aCmp, aClosure);
|
||||||
}
|
}
|
||||||
|
@ -2017,13 +2017,6 @@ public:
|
|||||||
* ancestor of some elements, then we lose performance but not correctness
|
* ancestor of some elements, then we lose performance but not correctness
|
||||||
*/
|
*/
|
||||||
void SortByContentOrder(nsIContent* aCommonAncestor);
|
void SortByContentOrder(nsIContent* aCommonAncestor);
|
||||||
/**
|
|
||||||
* Stable sort this list by CSS 'order' property order.
|
|
||||||
* http://dev.w3.org/csswg/css-flexbox-1/#order-property
|
|
||||||
* (also applies to CSS Grid although it's in the Flexbox spec ATM)
|
|
||||||
* It is assumed that the list is already in document content order.
|
|
||||||
*/
|
|
||||||
void SortByCSSOrder();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic stable sort. Take care, because some of the items might be nsDisplayLists
|
* Generic stable sort. Take care, because some of the items might be nsDisplayLists
|
||||||
|
@ -112,7 +112,7 @@ struct nsGridContainerFrame::TrackSize
|
|||||||
eMaxContentMinSizing = 0x4,
|
eMaxContentMinSizing = 0x4,
|
||||||
eMinOrMaxContentMinSizing = eMinContentMinSizing | eMaxContentMinSizing,
|
eMinOrMaxContentMinSizing = eMinContentMinSizing | eMaxContentMinSizing,
|
||||||
eIntrinsicMinSizing = eMinOrMaxContentMinSizing | eAutoMinSizing,
|
eIntrinsicMinSizing = eMinOrMaxContentMinSizing | eAutoMinSizing,
|
||||||
eFlexMinSizing = 0x8,
|
eFlexMinSizing = 0x8, // not really used ATM due to a spec change
|
||||||
eAutoMaxSizing = 0x10,
|
eAutoMaxSizing = 0x10,
|
||||||
eMinContentMaxSizing = 0x20,
|
eMinContentMaxSizing = 0x20,
|
||||||
eMaxContentMaxSizing = 0x40,
|
eMaxContentMaxSizing = 0x40,
|
||||||
@ -167,6 +167,7 @@ nsGridContainerFrame::TrackSize::Initialize(nscoord aPercentageBasis,
|
|||||||
}
|
}
|
||||||
// http://dev.w3.org/csswg/css-grid/#algo-init
|
// http://dev.w3.org/csswg/css-grid/#algo-init
|
||||||
switch (minSizeUnit) {
|
switch (minSizeUnit) {
|
||||||
|
case eStyleUnit_FlexFraction:
|
||||||
case eStyleUnit_Auto:
|
case eStyleUnit_Auto:
|
||||||
mState = eAutoMinSizing;
|
mState = eAutoMinSizing;
|
||||||
break;
|
break;
|
||||||
@ -174,9 +175,6 @@ nsGridContainerFrame::TrackSize::Initialize(nscoord aPercentageBasis,
|
|||||||
mState = IsMinContent(aMinCoord) ? eMinContentMinSizing
|
mState = IsMinContent(aMinCoord) ? eMinContentMinSizing
|
||||||
: eMaxContentMinSizing;
|
: eMaxContentMinSizing;
|
||||||
break;
|
break;
|
||||||
case eStyleUnit_FlexFraction:
|
|
||||||
mState = eFlexMinSizing;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
mBase = nsRuleNode::ComputeCoordPercentCalc(aMinCoord, aPercentageBasis);
|
mBase = nsRuleNode::ComputeCoordPercentCalc(aMinCoord, aPercentageBasis);
|
||||||
}
|
}
|
||||||
@ -5215,15 +5213,6 @@ nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
// Our children are all grid-level boxes, which behave the same as
|
// Our children are all grid-level boxes, which behave the same as
|
||||||
// inline-blocks in painting, so their borders/backgrounds all go on
|
// inline-blocks in painting, so their borders/backgrounds all go on
|
||||||
// the BlockBorderBackgrounds list.
|
// the BlockBorderBackgrounds list.
|
||||||
// Also, we capture positioned descendants so we can sort them by
|
|
||||||
// CSS 'order'.
|
|
||||||
nsDisplayList positionedDescendants;
|
|
||||||
nsDisplayListSet childLists(aLists.BlockBorderBackgrounds(),
|
|
||||||
aLists.BlockBorderBackgrounds(),
|
|
||||||
aLists.Floats(),
|
|
||||||
aLists.Content(),
|
|
||||||
&positionedDescendants,
|
|
||||||
aLists.Outlines());
|
|
||||||
typedef GridItemCSSOrderIterator::OrderState OrderState;
|
typedef GridItemCSSOrderIterator::OrderState OrderState;
|
||||||
OrderState order = HasAnyStateBits(NS_STATE_GRID_NORMAL_FLOW_CHILDREN_IN_CSS_ORDER)
|
OrderState order = HasAnyStateBits(NS_STATE_GRID_NORMAL_FLOW_CHILDREN_IN_CSS_ORDER)
|
||||||
? OrderState::eKnownOrdered
|
? OrderState::eKnownOrdered
|
||||||
@ -5232,11 +5221,9 @@ nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
GridItemCSSOrderIterator::eIncludeAll, order);
|
GridItemCSSOrderIterator::eIncludeAll, order);
|
||||||
for (; !iter.AtEnd(); iter.Next()) {
|
for (; !iter.AtEnd(); iter.Next()) {
|
||||||
nsIFrame* child = *iter;
|
nsIFrame* child = *iter;
|
||||||
BuildDisplayListForChild(aBuilder, child, aDirtyRect, childLists,
|
BuildDisplayListForChild(aBuilder, child, aDirtyRect, aLists,
|
||||||
::GetDisplayFlagsForGridItem(child));
|
::GetDisplayFlagsForGridItem(child));
|
||||||
}
|
}
|
||||||
positionedDescendants.SortByCSSOrder();
|
|
||||||
aLists.PositionedDescendants()->AppendToTop(&positionedDescendants);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
-->
|
-->
|
||||||
<html><head>
|
<html><head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>CSS Grid Test: flex min-sizing</title>
|
<title>Reference: flex/auto min-sizing</title>
|
||||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151212">
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151212">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body,html { color:black; background:white; font-family:monospace; font-size:16px; padding:0; margin:0; }
|
body,html { color:black; background:white; font-family:monospace; font-size:16px; padding:0; margin:0; }
|
||||||
@ -42,9 +42,9 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
}
|
}
|
||||||
|
|
||||||
.g4 {
|
.g4 {
|
||||||
grid-template-columns: minmax(0,0)
|
grid-template-columns: minmax(2px,0)
|
||||||
minmax(0,0)
|
minmax(1px,0)
|
||||||
minmax(0,0)
|
minmax(1px,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,9 +56,9 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
}
|
}
|
||||||
|
|
||||||
.g6 {
|
.g6 {
|
||||||
grid-template-columns: minmax(0,0)
|
grid-template-columns: minmax(2px,0)
|
||||||
minmax(0,0)
|
minmax(1px,0)
|
||||||
minmax(0,0)
|
minmax(1px,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
-->
|
-->
|
||||||
<html><head>
|
<html><head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>CSS Grid Test: flex min-sizing</title>
|
<title>CSS Grid Test: flex/auto min-sizing</title>
|
||||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151212">
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151212">
|
||||||
<link rel="help" href="https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax">
|
<link rel="help" href="https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax">
|
||||||
<link rel="match" href="grid-flex-min-sizing-001-ref.html">
|
<link rel="match" href="grid-flex-min-sizing-001-ref.html">
|
||||||
@ -22,108 +22,113 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width:140px;
|
width:140px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE Due to a spec change, 'fr' min-sizing inside minmax() is now
|
||||||
|
* invalid, so they were replaced in this test with 'auto' instead (for now).
|
||||||
|
*/
|
||||||
|
|
||||||
.g1 {
|
.g1 {
|
||||||
grid-template-columns: minmax(1fr,min-content)
|
grid-template-columns: minmax(auto,min-content)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g2 {
|
.g2 {
|
||||||
grid-template-columns: minmax(1fr,max-content)
|
grid-template-columns: minmax(auto,max-content)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g3 {
|
.g3 {
|
||||||
grid-template-columns: minmax(1fr,auto)
|
grid-template-columns: minmax(auto,auto)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g4 {
|
.g4 {
|
||||||
grid-template-columns: minmax(1fr,0)
|
grid-template-columns: minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g5 {
|
.g5 {
|
||||||
grid-template-columns: minmax(20px,0)
|
grid-template-columns: minmax(20px,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g6 {
|
.g6 {
|
||||||
grid-template-columns: minmax(1fr,0)
|
grid-template-columns: minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g7 {
|
.g7 {
|
||||||
grid-template-columns: minmax(20px,1fr)
|
grid-template-columns: minmax(20px,1fr)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g8 {
|
.g8 {
|
||||||
grid-template-columns: minmax(1fr,1fr)
|
grid-template-columns: minmax(auto,1fr)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g9 {
|
.g9 {
|
||||||
grid-template-columns: 20px
|
grid-template-columns: 20px
|
||||||
30px
|
30px
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
10px;
|
10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gA {
|
.gA {
|
||||||
grid-template-columns: minmax(1fr,0)
|
grid-template-columns: minmax(auto,0)
|
||||||
minmax(min-content,40px)
|
minmax(min-content,40px)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gB {
|
.gB {
|
||||||
grid-template-columns: minmax(1fr,0)
|
grid-template-columns: minmax(auto,0)
|
||||||
minmax(auto,40px)
|
minmax(auto,40px)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gC {
|
.gC {
|
||||||
grid-template-columns: minmax(1fr,20px)
|
grid-template-columns: minmax(auto,20px)
|
||||||
minmax(auto,40px)
|
minmax(auto,40px)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gD {
|
.gD {
|
||||||
grid-template-columns: minmax(auto,20px)
|
grid-template-columns: minmax(auto,20px)
|
||||||
minmax(auto,40px)
|
minmax(auto,40px)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
min-content;
|
min-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gE {
|
.gE {
|
||||||
grid-template-columns: minmax(auto,20px)
|
grid-template-columns: minmax(auto,20px)
|
||||||
minmax(auto,40px)
|
minmax(auto,40px)
|
||||||
minmax(1fr,20px)
|
minmax(auto,20px)
|
||||||
auto;
|
auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gF {
|
.gF {
|
||||||
grid-template-columns: minmax(auto,20px)
|
grid-template-columns: minmax(auto,20px)
|
||||||
minmax(min-content,max-content)
|
minmax(min-content,max-content)
|
||||||
minmax(1fr,40px)
|
minmax(auto,40px)
|
||||||
auto;
|
auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
-->
|
-->
|
||||||
<html><head>
|
<html><head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>CSS Grid Test: flex min-sizing</title>
|
<title>Reference: flex/auto min-sizing</title>
|
||||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151212">
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151212">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body,html { color:black; background:white; font-family:monospace; font-size:16px; padding:0; margin:0; }
|
body,html { color:black; background:white; font-family:monospace; font-size:16px; padding:0; margin:0; }
|
||||||
@ -25,47 +25,45 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
}
|
}
|
||||||
|
|
||||||
.g1 {
|
.g1 {
|
||||||
grid-template-columns: minmax(min-content,min-content)
|
grid-template-columns: minmax(4px,0)
|
||||||
minmax(min-content,0)
|
minmax(0,0)
|
||||||
minmax(min-content,0)
|
minmax(0,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g2 {
|
.g2 {
|
||||||
grid-template-columns: minmax(min-content,max-content)
|
grid-template-columns: minmax(4px,0)
|
||||||
minmax(min-content,0)
|
0
|
||||||
minmax(min-content,0)
|
0
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g3 {
|
.g3 {
|
||||||
grid-template-columns: minmax(min-content,auto)
|
grid-template-columns: minmax(4px,0)
|
||||||
minmax(min-content,0)
|
0
|
||||||
minmax(min-content,0)
|
0
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g4 {
|
.g4 {
|
||||||
grid-template-columns: minmax(0,0)
|
grid-template-columns: minmax(2px,0)
|
||||||
minmax(0,0)
|
1px
|
||||||
minmax(0,0)
|
1px
|
||||||
1fr;
|
1fr;
|
||||||
min-width:24px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.g5 {
|
.g5 {
|
||||||
grid-template-columns: minmax(20px,0)
|
grid-template-columns: minmax(20px,0)
|
||||||
minmax(0,0)
|
minmax(0,0)
|
||||||
minmax(0,0)
|
minmax(0,0)
|
||||||
4px;
|
0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g6 {
|
.g6 {
|
||||||
grid-template-columns: minmax(0,0)
|
grid-template-columns: minmax(2px,0)
|
||||||
minmax(0,0)
|
minmax(1px,0)
|
||||||
minmax(0,0)
|
minmax(1px,0)
|
||||||
20px;
|
20px;
|
||||||
min-width:44px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.g7 {
|
.g7 {
|
||||||
@ -97,37 +95,37 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gB {
|
.gB {
|
||||||
grid-template-columns: minmax(min-content,0)
|
grid-template-columns: minmax(4px,0)
|
||||||
minmax(auto,40px)
|
0
|
||||||
minmax(0,0)
|
0
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gC {
|
.gC {
|
||||||
grid-template-columns: minmax(min-content,20px)
|
grid-template-columns: minmax(4px,0)
|
||||||
minmax(auto,40px)
|
0
|
||||||
minmax(0,0)
|
0
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gD {
|
.gD {
|
||||||
grid-template-columns: minmax(min-content,20px)
|
grid-template-columns: minmax(4px,0)
|
||||||
minmax(auto,40px)
|
0
|
||||||
minmax(0,0)
|
0
|
||||||
min-content;
|
0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gE {
|
.gE {
|
||||||
grid-template-columns: minmax(min-content,20px)
|
grid-template-columns: minmax(2px,0)
|
||||||
minmax(min-content,40px)
|
minmax(1px,0)
|
||||||
minmax(7px,20px)
|
minmax(1px,0)
|
||||||
auto;
|
0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gF {
|
.gF {
|
||||||
grid-template-columns: minmax(min-content,20px)
|
grid-template-columns: 22px
|
||||||
minmax(0,max-content)
|
1px
|
||||||
minmax(0,40px)
|
1px
|
||||||
auto;
|
auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
-->
|
-->
|
||||||
<html><head>
|
<html><head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>CSS Grid Test: flex min-sizing</title>
|
<title>CSS Grid Test: flex/auto min-sizing</title>
|
||||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151212">
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151212">
|
||||||
<link rel="help" href="https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax">
|
<link rel="help" href="https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax">
|
||||||
<link rel="match" href="grid-flex-min-sizing-002-ref.html">
|
<link rel="match" href="grid-flex-min-sizing-002-ref.html">
|
||||||
@ -26,108 +26,113 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE Due to a spec change, 'fr' min-sizing inside minmax() is now
|
||||||
|
* invalid, so they were replaced in this test with 'auto' instead (for now).
|
||||||
|
*/
|
||||||
|
|
||||||
.g1 {
|
.g1 {
|
||||||
grid-template-columns: minmax(1fr,min-content)
|
grid-template-columns: minmax(auto,min-content)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g2 {
|
.g2 {
|
||||||
grid-template-columns: minmax(1fr,max-content)
|
grid-template-columns: minmax(auto,max-content)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g3 {
|
.g3 {
|
||||||
grid-template-columns: minmax(1fr,auto)
|
grid-template-columns: minmax(auto,auto)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g4 {
|
.g4 {
|
||||||
grid-template-columns: minmax(1fr,0)
|
grid-template-columns: minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g5 {
|
.g5 {
|
||||||
grid-template-columns: minmax(20px,0)
|
grid-template-columns: minmax(20px,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g6 {
|
.g6 {
|
||||||
grid-template-columns: minmax(1fr,0)
|
grid-template-columns: minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g7 {
|
.g7 {
|
||||||
grid-template-columns: minmax(20px,1fr)
|
grid-template-columns: minmax(20px,1fr)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g8 {
|
.g8 {
|
||||||
grid-template-columns: minmax(1fr,1fr)
|
grid-template-columns: minmax(auto,1fr)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g9 {
|
.g9 {
|
||||||
grid-template-columns: 20px
|
grid-template-columns: 20px
|
||||||
30px
|
30px
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
10px;
|
10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gA {
|
.gA {
|
||||||
grid-template-columns: minmax(1fr,0)
|
grid-template-columns: minmax(auto,0)
|
||||||
minmax(min-content,40px)
|
minmax(min-content,40px)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gB {
|
.gB {
|
||||||
grid-template-columns: minmax(1fr,0)
|
grid-template-columns: minmax(auto,0)
|
||||||
minmax(auto,40px)
|
minmax(auto,40px)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gC {
|
.gC {
|
||||||
grid-template-columns: minmax(1fr,20px)
|
grid-template-columns: minmax(auto,20px)
|
||||||
minmax(auto,40px)
|
minmax(auto,40px)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
20px;
|
20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gD {
|
.gD {
|
||||||
grid-template-columns: minmax(auto,20px)
|
grid-template-columns: minmax(auto,20px)
|
||||||
minmax(auto,40px)
|
minmax(auto,40px)
|
||||||
minmax(1fr,0)
|
minmax(auto,0)
|
||||||
min-content;
|
min-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gE {
|
.gE {
|
||||||
grid-template-columns: minmax(auto,20px)
|
grid-template-columns: minmax(auto,20px)
|
||||||
minmax(auto,40px)
|
minmax(auto,40px)
|
||||||
minmax(1fr,20px)
|
minmax(auto,20px)
|
||||||
auto;
|
auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gF {
|
.gF {
|
||||||
grid-template-columns: minmax(auto,20px)
|
grid-template-columns: minmax(auto,20px)
|
||||||
minmax(min-content,max-content)
|
minmax(min-content,max-content)
|
||||||
minmax(1fr,40px)
|
minmax(auto,40px)
|
||||||
auto;
|
auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +22,9 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
|
|||||||
height: 25px;
|
height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.a { z-index:4; left:74px; right:5px; background:lime; }
|
.a { z-index:1; left:74px; right:5px; background:lime; }
|
||||||
.b { z-index:3; left:54px; right:5px; background:pink; }
|
.b { z-index:1; left:54px; right:5px; background:pink; }
|
||||||
.c { z-index:2; left:34px; right:5px; background:yellow; }
|
.c { z-index:1; left:34px; right:5px; background:yellow; }
|
||||||
.d { z-index:1; left:14px; right:5px; background:silver; }
|
.d { z-index:1; left:14px; right:5px; background:silver; }
|
||||||
.e { display:none; }
|
.e { display:none; }
|
||||||
|
|
||||||
@ -64,34 +64,34 @@ f { float:left; }
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div style="order:2">
|
<div>
|
||||||
<span class="abs a">a</span>
|
|
||||||
<span class="abs b">b</span>
|
|
||||||
</div>
|
|
||||||
<div style="order:1">
|
|
||||||
<span class="abs c">c</span>
|
<span class="abs c">c</span>
|
||||||
<span class="abs e">FAIL<x>x</x></span>
|
<span class="abs e">FAIL<x>x</x></span>
|
||||||
<span class="abs d">d<x>x</x></span>
|
<span class="abs d">d<x>x</x></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="abs a">a</span>
|
||||||
|
<span class="abs b">b</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div style="display:grid; order:2">
|
<div style="display:grid; order:2">
|
||||||
<div style="order:2">
|
<div style="display:grid;">
|
||||||
<span class="abs a">a</span>
|
<div>
|
||||||
</div>
|
|
||||||
<div style="order:1">
|
|
||||||
<span class="abs c">c</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="display:grid; order:1">
|
|
||||||
<div style="order:2">
|
|
||||||
<span class="abs b">b</span>
|
|
||||||
</div>
|
|
||||||
<div style="order:1">
|
|
||||||
<span class="abs e">FAIL<x>x</x></span>
|
<span class="abs e">FAIL<x>x</x></span>
|
||||||
<span class="abs d">d<x>x</x></span>
|
<span class="abs d">d<x>x</x></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="abs b">b</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="abs c">c</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="abs a">a</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -104,15 +104,15 @@ f { float:left; }
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div style="order:2">
|
<div>
|
||||||
<span class="abs a">a</span>
|
|
||||||
<span class="abs z1 b">b</span>
|
|
||||||
</div>
|
|
||||||
<div style="order:1">
|
|
||||||
<span class="abs z1 c">c</span>
|
<span class="abs z1 c">c</span>
|
||||||
<span class="abs e">FAIL<x>x</x></span>
|
<span class="abs e">FAIL<x>x</x></span>
|
||||||
<span class="abs d">d<x>x</x></span>
|
<span class="abs d">d<x>x</x></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="abs a">a</span>
|
||||||
|
<span class="abs z1 b">b</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
|
@ -33,7 +33,7 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 56px;
|
width: 56px;
|
||||||
}
|
}
|
||||||
.g2f .d1 {
|
.g2f .d1 {
|
||||||
width: 52px;
|
width: 69px;
|
||||||
}
|
}
|
||||||
.g3 .d1 {
|
.g3 .d1 {
|
||||||
width: 56px;
|
width: 56px;
|
||||||
@ -42,7 +42,7 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 96px;
|
width: 96px;
|
||||||
}
|
}
|
||||||
.g4f .d1 {
|
.g4f .d1 {
|
||||||
width: 92px;
|
width: 69px;
|
||||||
}
|
}
|
||||||
.g5 .d1 {
|
.g5 .d1 {
|
||||||
width: 96px;
|
width: 96px;
|
||||||
@ -51,7 +51,7 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 69px;
|
width: 69px;
|
||||||
}
|
}
|
||||||
.g6f .d1 {
|
.g6f .d1 {
|
||||||
width: 77px;
|
width: 69px;
|
||||||
}
|
}
|
||||||
.g7 .d1 {
|
.g7 .d1 {
|
||||||
width: 69px;
|
width: 69px;
|
||||||
|
@ -33,7 +33,7 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 56px;
|
width: 56px;
|
||||||
}
|
}
|
||||||
.g2f .d1 {
|
.g2f .d1 {
|
||||||
width: 56px;
|
width: 69px;
|
||||||
}
|
}
|
||||||
.g3 .d1 {
|
.g3 .d1 {
|
||||||
width: 56px;
|
width: 56px;
|
||||||
@ -90,7 +90,9 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 444px;
|
width: 444px;
|
||||||
}
|
}
|
||||||
.g2f .d2 {
|
.g2f .d2 {
|
||||||
width: 448px;
|
right: auto;
|
||||||
|
left: 69px;
|
||||||
|
width: 35px;
|
||||||
}
|
}
|
||||||
.g3 .d2 {
|
.g3 .d2 {
|
||||||
width: 444px;
|
width: 444px;
|
||||||
@ -99,7 +101,9 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 404px;
|
width: 404px;
|
||||||
}
|
}
|
||||||
.g4f .d2 {
|
.g4f .d2 {
|
||||||
width: 396px;
|
right: auto;
|
||||||
|
left: 69px;
|
||||||
|
width: 35px;
|
||||||
}
|
}
|
||||||
.g5 .d2 {
|
.g5 .d2 {
|
||||||
width: 404px;
|
width: 404px;
|
||||||
@ -108,7 +112,9 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 431px;
|
width: 431px;
|
||||||
}
|
}
|
||||||
.g6f .d2 {
|
.g6f .d2 {
|
||||||
width: 423px;
|
right: auto;
|
||||||
|
left: 69px;
|
||||||
|
width: 35px;
|
||||||
}
|
}
|
||||||
.g7 .d2 {
|
.g7 .d2 {
|
||||||
width: 431px;
|
width: 431px;
|
||||||
|
@ -33,7 +33,8 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 56px;
|
width: 56px;
|
||||||
}
|
}
|
||||||
.g2f .d1 {
|
.g2f .d1 {
|
||||||
width: 52px;
|
left: 28px;
|
||||||
|
width: 28px;
|
||||||
}
|
}
|
||||||
.g3 .d1 {
|
.g3 .d1 {
|
||||||
left: 41px;
|
left: 41px;
|
||||||
@ -44,8 +45,8 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 2px;
|
width: 2px;
|
||||||
}
|
}
|
||||||
.g4f .d1 {
|
.g4f .d1 {
|
||||||
left: 83px;
|
left: 28px;
|
||||||
width: 0px;
|
width: 28px;
|
||||||
}
|
}
|
||||||
.g5 .d1 {
|
.g5 .d1 {
|
||||||
left: 81px;
|
left: 81px;
|
||||||
@ -56,7 +57,7 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
width: 28px;
|
width: 28px;
|
||||||
}
|
}
|
||||||
.g6f .d1 {
|
.g6f .d1 {
|
||||||
left: 27px;
|
left: 28px;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
}
|
}
|
||||||
.g7 .d1 {
|
.g7 .d1 {
|
||||||
@ -104,7 +105,8 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
left: 2px;
|
left: 2px;
|
||||||
}
|
}
|
||||||
.g2f .d2 {
|
.g2f .d2 {
|
||||||
width: 104px;
|
width: 48px;
|
||||||
|
left: 56px;
|
||||||
}
|
}
|
||||||
.g3 .d2 {
|
.g3 .d2 {
|
||||||
width: 61px;
|
width: 61px;
|
||||||
@ -115,8 +117,8 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
left: 83px;
|
left: 83px;
|
||||||
}
|
}
|
||||||
.g4f .d2 {
|
.g4f .d2 {
|
||||||
width: 22px;
|
width: 48px;
|
||||||
left: 82px;
|
left: 56px;
|
||||||
}
|
}
|
||||||
.g5 .d2 {
|
.g5 .d2 {
|
||||||
width: 21px;
|
width: 21px;
|
||||||
@ -127,8 +129,8 @@ body,html { color:black; background:white; font-family:monospace; font-size:16px
|
|||||||
left: 56px;
|
left: 56px;
|
||||||
}
|
}
|
||||||
.g6f .d2 {
|
.g6f .d2 {
|
||||||
width: 49px;
|
width: 48px;
|
||||||
left: 55px;
|
left: 56px;
|
||||||
}
|
}
|
||||||
.g7 .d2 {
|
.g7 .d2 {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
|
@ -8735,6 +8735,10 @@ CSSParserImpl::ParseGridTrackSize(nsCSSValue& aValue,
|
|||||||
!func->Item(2).IsLengthPercentCalcUnit()) {
|
!func->Item(2).IsLengthPercentCalcUnit()) {
|
||||||
return CSSParseResult::Error;
|
return CSSParseResult::Error;
|
||||||
}
|
}
|
||||||
|
// Reject 'fr' min-sizing.
|
||||||
|
if (func->Item(1).GetUnit() == eCSSUnit_FlexFraction) {
|
||||||
|
return CSSParseResult::Error;
|
||||||
|
}
|
||||||
return CSSParseResult::Ok;
|
return CSSParseResult::Ok;
|
||||||
}
|
}
|
||||||
SkipUntil(')');
|
SkipUntil(')');
|
||||||
@ -10812,7 +10816,7 @@ CSSParserImpl::ParseWebkitTextStroke()
|
|||||||
eCSSProperty__webkit_text_stroke_color
|
eCSSProperty__webkit_text_stroke_color
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t numProps = ArrayLength(kWebkitTextStrokeIDs);
|
const size_t numProps = MOZ_ARRAY_LENGTH(kWebkitTextStrokeIDs);
|
||||||
nsCSSValue values[numProps];
|
nsCSSValue values[numProps];
|
||||||
|
|
||||||
int32_t found = ParseChoice(values, kWebkitTextStrokeIDs, numProps);
|
int32_t found = ParseChoice(values, kWebkitTextStrokeIDs, numProps);
|
||||||
|
@ -5996,7 +5996,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
|
|||||||
"[a] calc(1%) [b] repeat(auto-fit,[a b] minmax(1mm, 1%) [c]) [c]",
|
"[a] calc(1%) [b] repeat(auto-fit,[a b] minmax(1mm, 1%) [c]) [c]",
|
||||||
"repeat(auto-fill,minmax(1%,auto))",
|
"repeat(auto-fill,minmax(1%,auto))",
|
||||||
"repeat(auto-fill,minmax(1em,min-content)) minmax(min-content,0)",
|
"repeat(auto-fill,minmax(1em,min-content)) minmax(min-content,0)",
|
||||||
"repeat(auto-fill,minmax(1fr,1em)) [a] minmax(0, max-content)",
|
|
||||||
"repeat(auto-fill,minmax(max-content,1mm))",
|
"repeat(auto-fill,minmax(max-content,1mm))",
|
||||||
],
|
],
|
||||||
invalid_values: [
|
invalid_values: [
|
||||||
@ -6051,6 +6050,7 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
|
|||||||
"repeat(auto-fit,minmax(auto,auto))",
|
"repeat(auto-fit,minmax(auto,auto))",
|
||||||
"repeat(auto-fit,minmax(min-content,1fr))",
|
"repeat(auto-fit,minmax(min-content,1fr))",
|
||||||
"repeat(auto-fit,minmax(1fr,auto))",
|
"repeat(auto-fit,minmax(1fr,auto))",
|
||||||
|
"repeat(auto-fill,minmax(1fr,1em))",
|
||||||
"repeat(auto-fill, 10px) auto",
|
"repeat(auto-fill, 10px) auto",
|
||||||
"auto repeat(auto-fit, 10px)",
|
"auto repeat(auto-fit, 10px)",
|
||||||
"minmax(min-content,max-content) repeat(auto-fit, 0)",
|
"minmax(min-content,max-content) repeat(auto-fit, 0)",
|
||||||
|
@ -931,6 +931,11 @@ static int nr_ice_component_stun_server_cb(void *cb_arg,nr_stun_server_ctx *stun
|
|||||||
nr_transport_addr local_addr;
|
nr_transport_addr local_addr;
|
||||||
int r,_status;
|
int r,_status;
|
||||||
|
|
||||||
|
if(comp->state==NR_ICE_COMPONENT_FAILED) {
|
||||||
|
*error=400;
|
||||||
|
ABORT(R_REJECTED);
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the candidate pair that this maps to */
|
/* Find the candidate pair that this maps to */
|
||||||
if(r=nr_socket_getaddr(sock,&local_addr)) {
|
if(r=nr_socket_getaddr(sock,&local_addr)) {
|
||||||
*error=500;
|
*error=500;
|
||||||
|
@ -640,17 +640,35 @@ public:
|
|||||||
T popCopy();
|
T popCopy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfers ownership of the internal buffer used by this vector to the
|
* If elements are stored in-place, return nullptr and leave this vector
|
||||||
* caller. (It's the caller's responsibility to properly deallocate this
|
* unmodified.
|
||||||
* buffer, in accordance with this vector's AllocPolicy.) After this call,
|
*
|
||||||
* the vector is empty. Since the returned buffer may need to be allocated
|
* Otherwise return this vector's elements buffer, and clear this vector as if
|
||||||
* (if the elements are currently stored in-place), the call can fail,
|
* by clearAndFree(). The caller now owns the buffer and is responsible for
|
||||||
* returning nullptr.
|
* deallocating it consistent with this vector's AllocPolicy.
|
||||||
*
|
*
|
||||||
* N.B. Although a T*, only the range [0, length()) is constructed.
|
* N.B. Although a T*, only the range [0, length()) is constructed.
|
||||||
*/
|
*/
|
||||||
MOZ_WARN_UNUSED_RESULT T* extractRawBuffer();
|
MOZ_WARN_UNUSED_RESULT T* extractRawBuffer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If elements are stored in-place, allocate a new buffer, move this vector's
|
||||||
|
* elements into it, and return that buffer.
|
||||||
|
*
|
||||||
|
* Otherwise return this vector's elements buffer. The caller now owns the
|
||||||
|
* buffer and is responsible for deallocating it consistent with this vector's
|
||||||
|
* AllocPolicy.
|
||||||
|
*
|
||||||
|
* This vector is cleared, as if by clearAndFree(), when this method
|
||||||
|
* succeeds. This method fails and returns nullptr only if new elements buffer
|
||||||
|
* allocation fails.
|
||||||
|
*
|
||||||
|
* N.B. Only the range [0, length()) of the returned buffer is constructed.
|
||||||
|
* If any of these elements are uninitialized (as growByUninitialized
|
||||||
|
* enables), behavior is undefined.
|
||||||
|
*/
|
||||||
|
MOZ_WARN_UNUSED_RESULT T* extractOrCopyRawBuffer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfer ownership of an array of objects into the vector. The caller
|
* Transfer ownership of an array of objects into the vector. The caller
|
||||||
* must have allocated the array in accordance with this vector's
|
* must have allocated the array in accordance with this vector's
|
||||||
@ -1303,28 +1321,48 @@ template<typename T, size_t N, class AP>
|
|||||||
inline T*
|
inline T*
|
||||||
Vector<T, N, AP>::extractRawBuffer()
|
Vector<T, N, AP>::extractRawBuffer()
|
||||||
{
|
{
|
||||||
T* ret;
|
MOZ_REENTRANCY_GUARD_ET_AL;
|
||||||
|
|
||||||
if (usingInlineStorage()) {
|
if (usingInlineStorage()) {
|
||||||
ret = this->template pod_malloc<T>(mLength);
|
return nullptr;
|
||||||
if (!ret) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
Impl::copyConstruct(ret, beginNoCheck(), endNoCheck());
|
|
||||||
Impl::destroy(beginNoCheck(), endNoCheck());
|
|
||||||
/* mBegin, mCapacity are unchanged. */
|
|
||||||
mLength = 0;
|
|
||||||
} else {
|
|
||||||
ret = mBegin;
|
|
||||||
mBegin = static_cast<T*>(mStorage.addr());
|
|
||||||
mLength = 0;
|
|
||||||
mCapacity = kInlineCapacity;
|
|
||||||
#ifdef DEBUG
|
|
||||||
mReserved = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T* ret = mBegin;
|
||||||
|
mBegin = static_cast<T*>(mStorage.addr());
|
||||||
|
mLength = 0;
|
||||||
|
mCapacity = kInlineCapacity;
|
||||||
|
#ifdef DEBUG
|
||||||
|
mReserved = 0;
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, size_t N, class AP>
|
||||||
|
inline T*
|
||||||
|
Vector<T, N, AP>::extractOrCopyRawBuffer()
|
||||||
|
{
|
||||||
|
if (T* ret = extractRawBuffer()) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_REENTRANCY_GUARD_ET_AL;
|
||||||
|
|
||||||
|
T* copy = this->template pod_malloc<T>(mLength);
|
||||||
|
if (!copy) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl::moveConstruct(copy, beginNoCheck(), endNoCheck());
|
||||||
|
Impl::destroy(beginNoCheck(), endNoCheck());
|
||||||
|
mBegin = static_cast<T*>(mStorage.addr());
|
||||||
|
mLength = 0;
|
||||||
|
mCapacity = kInlineCapacity;
|
||||||
|
#ifdef DEBUG
|
||||||
|
mReserved = 0;
|
||||||
|
#endif
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, size_t N, class AP>
|
template<typename T, size_t N, class AP>
|
||||||
inline void
|
inline void
|
||||||
Vector<T, N, AP>::replaceRawBuffer(T* aP, size_t aLength)
|
Vector<T, N, AP>::replaceRawBuffer(T* aP, size_t aLength)
|
||||||
|
@ -20,6 +20,8 @@ struct mozilla::detail::VectorTesting
|
|||||||
static void testConstRange();
|
static void testConstRange();
|
||||||
static void testEmplaceBack();
|
static void testEmplaceBack();
|
||||||
static void testReverse();
|
static void testReverse();
|
||||||
|
static void testExtractRawBuffer();
|
||||||
|
static void testExtractOrCopyRawBuffer();
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -111,6 +113,13 @@ struct S
|
|||||||
|
|
||||||
static size_t constructCount;
|
static size_t constructCount;
|
||||||
static size_t moveCount;
|
static size_t moveCount;
|
||||||
|
static size_t destructCount;
|
||||||
|
|
||||||
|
static void resetCounts() {
|
||||||
|
constructCount = 0;
|
||||||
|
moveCount = 0;
|
||||||
|
destructCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
S(size_t j, size_t k)
|
S(size_t j, size_t k)
|
||||||
: j(j)
|
: j(j)
|
||||||
@ -123,27 +132,35 @@ struct S
|
|||||||
: j(rhs.j)
|
: j(rhs.j)
|
||||||
, k(Move(rhs.k))
|
, k(Move(rhs.k))
|
||||||
{
|
{
|
||||||
rhs.~S();
|
rhs.j = 0;
|
||||||
|
rhs.k.reset(0);
|
||||||
moveCount++;
|
moveCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~S() {
|
||||||
|
destructCount++;
|
||||||
|
}
|
||||||
|
|
||||||
S(const S&) = delete;
|
S(const S&) = delete;
|
||||||
S& operator=(const S&) = delete;
|
S& operator=(const S&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t S::constructCount = 0;
|
size_t S::constructCount = 0;
|
||||||
size_t S::moveCount = 0;
|
size_t S::moveCount = 0;
|
||||||
|
size_t S::destructCount = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mozilla::detail::VectorTesting::testEmplaceBack()
|
mozilla::detail::VectorTesting::testEmplaceBack()
|
||||||
{
|
{
|
||||||
|
S::resetCounts();
|
||||||
|
|
||||||
Vector<S> vec;
|
Vector<S> vec;
|
||||||
MOZ_RELEASE_ASSERT(vec.reserve(20));
|
MOZ_RELEASE_ASSERT(vec.reserve(20));
|
||||||
|
|
||||||
for (size_t i = 0; i < 10; i++) {
|
for (size_t i = 0; i < 10; i++) {
|
||||||
S s(i, i*i);
|
S s(i, i * i);
|
||||||
MOZ_RELEASE_ASSERT(vec.append(Move(s)));
|
MOZ_RELEASE_ASSERT(vec.append(Move(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +169,7 @@ mozilla::detail::VectorTesting::testEmplaceBack()
|
|||||||
MOZ_RELEASE_ASSERT(S::moveCount == 10);
|
MOZ_RELEASE_ASSERT(S::moveCount == 10);
|
||||||
|
|
||||||
for (size_t i = 10; i < 20; i++) {
|
for (size_t i = 10; i < 20; i++) {
|
||||||
MOZ_RELEASE_ASSERT(vec.emplaceBack(i, i*i));
|
MOZ_RELEASE_ASSERT(vec.emplaceBack(i, i * i));
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(vec.length() == 20);
|
MOZ_RELEASE_ASSERT(vec.length() == 20);
|
||||||
@ -161,7 +178,7 @@ mozilla::detail::VectorTesting::testEmplaceBack()
|
|||||||
|
|
||||||
for (size_t i = 0; i < 20; i++) {
|
for (size_t i = 0; i < 20; i++) {
|
||||||
MOZ_RELEASE_ASSERT(vec[i].j == i);
|
MOZ_RELEASE_ASSERT(vec[i].j == i);
|
||||||
MOZ_RELEASE_ASSERT(*vec[i].k == i*i);
|
MOZ_RELEASE_ASSERT(*vec[i].k == i * i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +239,113 @@ mozilla::detail::VectorTesting::testReverse()
|
|||||||
MOZ_RELEASE_ASSERT(*vec2[4] == 0);
|
MOZ_RELEASE_ASSERT(*vec2[4] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mozilla::detail::VectorTesting::testExtractRawBuffer()
|
||||||
|
{
|
||||||
|
S::resetCounts();
|
||||||
|
|
||||||
|
Vector<S, 5> vec;
|
||||||
|
MOZ_RELEASE_ASSERT(vec.reserve(5));
|
||||||
|
for (size_t i = 0; i < 5; i++) {
|
||||||
|
vec.infallibleEmplaceBack(i, i * i);
|
||||||
|
}
|
||||||
|
MOZ_RELEASE_ASSERT(vec.length() == 5);
|
||||||
|
MOZ_ASSERT(vec.reserved() == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::constructCount == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::moveCount == 0);
|
||||||
|
MOZ_RELEASE_ASSERT(S::destructCount == 0);
|
||||||
|
|
||||||
|
S* buf = vec.extractRawBuffer();
|
||||||
|
MOZ_RELEASE_ASSERT(!buf);
|
||||||
|
MOZ_RELEASE_ASSERT(vec.length() == 5);
|
||||||
|
MOZ_ASSERT(vec.reserved() == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::constructCount == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::moveCount == 0);
|
||||||
|
MOZ_RELEASE_ASSERT(S::destructCount == 0);
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(vec.reserve(10));
|
||||||
|
for (size_t i = 5; i < 10; i++) {
|
||||||
|
vec.infallibleEmplaceBack(i, i * i);
|
||||||
|
}
|
||||||
|
MOZ_RELEASE_ASSERT(vec.length() == 10);
|
||||||
|
MOZ_ASSERT(vec.reserved() == 10);
|
||||||
|
MOZ_RELEASE_ASSERT(S::constructCount == 10);
|
||||||
|
MOZ_RELEASE_ASSERT(S::moveCount == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::destructCount == 5);
|
||||||
|
|
||||||
|
buf = vec.extractRawBuffer();
|
||||||
|
MOZ_RELEASE_ASSERT(buf);
|
||||||
|
MOZ_RELEASE_ASSERT(vec.length() == 0);
|
||||||
|
MOZ_ASSERT(vec.reserved() == 0);
|
||||||
|
MOZ_RELEASE_ASSERT(S::constructCount == 10);
|
||||||
|
MOZ_RELEASE_ASSERT(S::moveCount == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::destructCount == 5);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 10; i++) {
|
||||||
|
MOZ_RELEASE_ASSERT(buf[i].j == i);
|
||||||
|
MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mozilla::detail::VectorTesting::testExtractOrCopyRawBuffer()
|
||||||
|
{
|
||||||
|
S::resetCounts();
|
||||||
|
|
||||||
|
Vector<S, 5> vec;
|
||||||
|
MOZ_RELEASE_ASSERT(vec.reserve(5));
|
||||||
|
for (size_t i = 0; i < 5; i++) {
|
||||||
|
vec.infallibleEmplaceBack(i, i * i);
|
||||||
|
}
|
||||||
|
MOZ_RELEASE_ASSERT(vec.length() == 5);
|
||||||
|
MOZ_ASSERT(vec.reserved() == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::constructCount == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::moveCount == 0);
|
||||||
|
MOZ_RELEASE_ASSERT(S::destructCount == 0);
|
||||||
|
|
||||||
|
S* buf = vec.extractOrCopyRawBuffer();
|
||||||
|
MOZ_RELEASE_ASSERT(buf);
|
||||||
|
MOZ_RELEASE_ASSERT(vec.length() == 0);
|
||||||
|
MOZ_ASSERT(vec.reserved() == 0);
|
||||||
|
MOZ_RELEASE_ASSERT(S::constructCount == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::moveCount == 5);
|
||||||
|
MOZ_RELEASE_ASSERT(S::destructCount == 5);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 5; i++) {
|
||||||
|
MOZ_RELEASE_ASSERT(buf[i].j == i);
|
||||||
|
MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
S::resetCounts();
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(vec.reserve(10));
|
||||||
|
for (size_t i = 0; i < 10; i++) {
|
||||||
|
vec.infallibleEmplaceBack(i, i * i);
|
||||||
|
}
|
||||||
|
MOZ_RELEASE_ASSERT(vec.length() == 10);
|
||||||
|
MOZ_ASSERT(vec.reserved() == 10);
|
||||||
|
MOZ_RELEASE_ASSERT(S::constructCount == 10);
|
||||||
|
MOZ_RELEASE_ASSERT(S::moveCount == 0);
|
||||||
|
MOZ_RELEASE_ASSERT(S::destructCount == 0);
|
||||||
|
|
||||||
|
buf = vec.extractOrCopyRawBuffer();
|
||||||
|
MOZ_RELEASE_ASSERT(buf);
|
||||||
|
MOZ_RELEASE_ASSERT(vec.length() == 0);
|
||||||
|
MOZ_ASSERT(vec.reserved() == 0);
|
||||||
|
MOZ_RELEASE_ASSERT(S::constructCount == 10);
|
||||||
|
MOZ_RELEASE_ASSERT(S::moveCount == 0);
|
||||||
|
MOZ_RELEASE_ASSERT(S::destructCount == 0);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 10; i++) {
|
||||||
|
MOZ_RELEASE_ASSERT(buf[i].j == i);
|
||||||
|
MOZ_RELEASE_ASSERT(*buf[i].k == i * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
@ -229,4 +353,6 @@ main()
|
|||||||
VectorTesting::testConstRange();
|
VectorTesting::testConstRange();
|
||||||
VectorTesting::testEmplaceBack();
|
VectorTesting::testEmplaceBack();
|
||||||
VectorTesting::testReverse();
|
VectorTesting::testReverse();
|
||||||
|
VectorTesting::testExtractRawBuffer();
|
||||||
|
VectorTesting::testExtractOrCopyRawBuffer();
|
||||||
}
|
}
|
||||||
|
@ -234,26 +234,21 @@ class GeckoInputConnection
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showSoftInput() {
|
private void showSoftInput() {
|
||||||
|
final View v = getView();
|
||||||
final InputMethodManager imm = getInputMethodManager();
|
final InputMethodManager imm = getInputMethodManager();
|
||||||
if (imm != null) {
|
if (v == null || imm == null) {
|
||||||
final View v = getView();
|
return;
|
||||||
|
|
||||||
if (v.hasFocus() && !imm.isActive(v)) {
|
|
||||||
// Workaround: The view has focus but it is not the active view for the input method. (Bug 1211848)
|
|
||||||
refocusAndShowSoftInput(imm, v);
|
|
||||||
} else {
|
|
||||||
imm.showSoftInput(v, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void refocusAndShowSoftInput(final InputMethodManager imm, final View v) {
|
v.post(new Runnable() {
|
||||||
ThreadUtils.postToUiThread(new Runnable() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
v.clearFocus();
|
if (v.hasFocus() && !imm.isActive(v)) {
|
||||||
v.requestFocus();
|
// Marshmallow workaround: The view has focus but it is not the active
|
||||||
|
// view for the input method. (Bug 1211848)
|
||||||
|
v.clearFocus();
|
||||||
|
v.requestFocus();
|
||||||
|
}
|
||||||
imm.showSoftInput(v, 0);
|
imm.showSoftInput(v, 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -472,18 +467,18 @@ class GeckoInputConnection
|
|||||||
return mEditableClient.setInputConnectionHandler(getBackgroundHandler());
|
return mEditableClient.setInputConnectionHandler(getBackgroundHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mIsVisible = false;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
||||||
if (mIMEState == IME_STATE_DISABLED) {
|
// Some keyboards require us to fill out outAttrs even if we return null.
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
|
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
|
||||||
outAttrs.imeOptions = EditorInfo.IME_ACTION_NONE;
|
outAttrs.imeOptions = EditorInfo.IME_ACTION_NONE;
|
||||||
outAttrs.actionLabel = null;
|
outAttrs.actionLabel = null;
|
||||||
|
|
||||||
|
if (mIMEState == IME_STATE_DISABLED) {
|
||||||
|
hideSoftInput();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (mIMEState == IME_STATE_PASSWORD ||
|
if (mIMEState == IME_STATE_PASSWORD ||
|
||||||
"password".equalsIgnoreCase(mIMETypeHint))
|
"password".equalsIgnoreCase(mIMETypeHint))
|
||||||
outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
|
outAttrs.inputType |= InputType.TYPE_TEXT_VARIATION_PASSWORD;
|
||||||
@ -587,12 +582,7 @@ class GeckoInputConnection
|
|||||||
outAttrs.initialSelStart = Selection.getSelectionStart(editable);
|
outAttrs.initialSelStart = Selection.getSelectionStart(editable);
|
||||||
outAttrs.initialSelEnd = Selection.getSelectionEnd(editable);
|
outAttrs.initialSelEnd = Selection.getSelectionEnd(editable);
|
||||||
|
|
||||||
if (mIsVisible) {
|
showSoftInput();
|
||||||
// The app has been brought to the foreground and the Soft Keyboard
|
|
||||||
// was previously visible, so request that it be shown again.
|
|
||||||
showSoftInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,16 +788,6 @@ class GeckoInputConnection
|
|||||||
return processKey(KeyEvent.ACTION_UP, keyCode, event);
|
return processKey(KeyEvent.ACTION_UP, keyCode, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onWindowVisibilityChanged (int visibility) {
|
|
||||||
if (visibility == View.VISIBLE) {
|
|
||||||
mIsVisible = true;
|
|
||||||
} else {
|
|
||||||
mIsVisible = false;
|
|
||||||
hideSoftInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a key that represents a given character.
|
* Get a key that represents a given character.
|
||||||
*/
|
*/
|
||||||
@ -936,11 +916,6 @@ class GeckoInputConnection
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
restartInput();
|
restartInput();
|
||||||
if (mIMEState == IME_STATE_DISABLED) {
|
|
||||||
hideSoftInput();
|
|
||||||
} else {
|
|
||||||
showSoftInput();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,24 +272,8 @@ public class GeckoView extends LayerView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int mLastVisibility = View.GONE;
|
|
||||||
|
|
||||||
/* package */ void setInputConnectionListener(final InputConnectionListener icl) {
|
/* package */ void setInputConnectionListener(final InputConnectionListener icl) {
|
||||||
mInputConnectionListener = icl;
|
mInputConnectionListener = icl;
|
||||||
if (mInputConnectionListener != null) {
|
|
||||||
mInputConnectionListener.onWindowVisibilityChanged(mLastVisibility);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onWindowVisibilityChanged (int visibility) {
|
|
||||||
mLastVisibility = visibility;
|
|
||||||
|
|
||||||
if (mInputConnectionListener != null) {
|
|
||||||
mInputConnectionListener.onWindowVisibilityChanged(visibility);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onWindowVisibilityChanged(visibility);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,6 +21,5 @@ interface InputConnectionListener
|
|||||||
boolean onKeyLongPress(int keyCode, KeyEvent event);
|
boolean onKeyLongPress(int keyCode, KeyEvent event);
|
||||||
boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event);
|
boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event);
|
||||||
boolean onKeyUp(int keyCode, KeyEvent event);
|
boolean onKeyUp(int keyCode, KeyEvent event);
|
||||||
void onWindowVisibilityChanged (int visibility);
|
|
||||||
boolean isIMEEnabled();
|
boolean isIMEEnabled();
|
||||||
}
|
}
|
||||||
|
@ -219,6 +219,14 @@ AssertNotAlreadyCached(const char* aPrefType,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
ReportToConsole(const char* aMessage, int aLine, bool aError)
|
||||||
|
{
|
||||||
|
nsPrintfCString message("** Preference parsing %s (line %d) = %s **\n",
|
||||||
|
(aError ? "error" : "warning"), aLine, aMessage);
|
||||||
|
nsPrefBranch::ReportToConsole(NS_ConvertUTF8toUTF16(message.get()));
|
||||||
|
}
|
||||||
|
|
||||||
// Although this is a member of Preferences, it measures sPreferences and
|
// Although this is a member of Preferences, it measures sPreferences and
|
||||||
// several other global structures.
|
// several other global structures.
|
||||||
/* static */ int64_t
|
/* static */ int64_t
|
||||||
@ -683,7 +691,7 @@ ReadExtensionPrefs(nsIFile *aFile)
|
|||||||
uint32_t read;
|
uint32_t read;
|
||||||
|
|
||||||
PrefParseState ps;
|
PrefParseState ps;
|
||||||
PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
|
PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
|
||||||
while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) {
|
while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) {
|
||||||
rv = stream->Read(buffer, 4096, &read);
|
rv = stream->Read(buffer, 4096, &read);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
@ -997,7 +1005,7 @@ static nsresult openPrefFile(nsIFile* aFile)
|
|||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
PrefParseState ps;
|
PrefParseState ps;
|
||||||
PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
|
PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
|
||||||
|
|
||||||
// Read is not guaranteed to return a buf the size of fileSize,
|
// Read is not guaranteed to return a buf the size of fileSize,
|
||||||
// but usually will.
|
// but usually will.
|
||||||
@ -1179,7 +1187,7 @@ static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
|
|||||||
NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
|
NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
PrefParseState ps;
|
PrefParseState ps;
|
||||||
PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
|
PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
|
||||||
PREF_ParseBuf(&ps, manifest, manifest.Length());
|
PREF_ParseBuf(&ps, manifest, manifest.Length());
|
||||||
PREF_FinalizeParseState(&ps);
|
PREF_FinalizeParseState(&ps);
|
||||||
|
|
||||||
|
@ -390,6 +390,17 @@ nsresult nsPrefBranch::CheckSanityOfStringLength(const char* aPrefName, const ui
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*static*/
|
||||||
|
void nsPrefBranch::ReportToConsole(const nsAString& aMessage)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsIConsoleService> console = do_GetService("@mozilla.org/consoleservice;1", &rv);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nsAutoString message(aMessage);
|
||||||
|
console->LogStringMessage(message.get());
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsPrefBranch::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
|
NS_IMETHODIMP nsPrefBranch::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
|
||||||
{
|
{
|
||||||
|
@ -196,6 +196,8 @@ public:
|
|||||||
|
|
||||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
||||||
|
|
||||||
|
static void ReportToConsole(const nsAString& aMessage);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~nsPrefBranch();
|
virtual ~nsPrefBranch();
|
||||||
|
|
||||||
|
@ -97,6 +97,20 @@ pref_GrowBuf(PrefParseState *ps)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report an error or a warning. If not specified, just dump to stderr.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pref_ReportParseProblem(PrefParseState& ps, const char* aMessage, int aLine, bool aError)
|
||||||
|
{
|
||||||
|
if (ps.reporter) {
|
||||||
|
ps.reporter(aMessage, aLine, aError);
|
||||||
|
} else {
|
||||||
|
printf_stderr("**** Preference parsing %s (line %d) = %s **\n",
|
||||||
|
(aError ? "error" : "warning"), aLine, aMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pref_DoCallback
|
* pref_DoCallback
|
||||||
*
|
*
|
||||||
@ -119,6 +133,7 @@ pref_DoCallback(PrefParseState *ps)
|
|||||||
break;
|
break;
|
||||||
case PrefType::Int:
|
case PrefType::Int:
|
||||||
if ((ps->vb[0] == '-' || ps->vb[0] == '+') && ps->vb[1] == '\0') {
|
if ((ps->vb[0] == '-' || ps->vb[0] == '+') && ps->vb[1] == '\0') {
|
||||||
|
pref_ReportParseProblem(*ps, "invalid integer value", 0, true);
|
||||||
NS_WARNING("malformed integer value");
|
NS_WARNING("malformed integer value");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -136,11 +151,13 @@ pref_DoCallback(PrefParseState *ps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PREF_InitParseState(PrefParseState *ps, PrefReader reader, void *closure)
|
PREF_InitParseState(PrefParseState *ps, PrefReader reader,
|
||||||
|
PrefParseErrorReporter reporter, void *closure)
|
||||||
{
|
{
|
||||||
memset(ps, 0, sizeof(*ps));
|
memset(ps, 0, sizeof(*ps));
|
||||||
ps->reader = reader;
|
ps->reader = reader;
|
||||||
ps->closure = closure;
|
ps->closure = closure;
|
||||||
|
ps->reporter = reporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -179,9 +196,16 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
char udigit;
|
char udigit;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
|
// The line number is currently only used for the error/warning reporting.
|
||||||
|
int lineNum = 0;
|
||||||
|
|
||||||
state = ps->state;
|
state = ps->state;
|
||||||
for (end = buf + bufLen; buf != end; ++buf) {
|
for (end = buf + bufLen; buf != end; ++buf) {
|
||||||
c = *buf;
|
c = *buf;
|
||||||
|
if (c == '\r' || c == '\n' || c == 0x1A) {
|
||||||
|
lineNum ++;
|
||||||
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
/* initial state */
|
/* initial state */
|
||||||
case PREF_PARSE_INIT:
|
case PREF_PARSE_INIT:
|
||||||
@ -228,6 +252,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
/* else wait for next char */
|
/* else wait for next char */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
pref_ReportParseProblem(*ps, "non-matching string", lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -263,6 +288,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||||
}
|
}
|
||||||
else if (!isspace(c)) {
|
else if (!isspace(c)) {
|
||||||
|
pref_ReportParseProblem(*ps, "need space, comment or quote", lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -279,6 +305,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||||
}
|
}
|
||||||
else if (!isspace(c)) {
|
else if (!isspace(c)) {
|
||||||
|
pref_ReportParseProblem(*ps, "need space, comment or comma", lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -315,6 +342,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||||
}
|
}
|
||||||
else if (!isspace(c)) {
|
else if (!isspace(c)) {
|
||||||
|
pref_ReportParseProblem(*ps, "need value, comment or space", lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -336,6 +364,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
else if (isspace(c))
|
else if (isspace(c))
|
||||||
state = PREF_PARSE_UNTIL_CLOSE_PAREN;
|
state = PREF_PARSE_UNTIL_CLOSE_PAREN;
|
||||||
else {
|
else {
|
||||||
|
pref_ReportParseProblem(*ps, "while parsing integer", lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -353,12 +382,13 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* pref file is malformed */
|
/* pref file is malformed */
|
||||||
|
pref_ReportParseProblem(*ps, "while parsing comment", lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PREF_PARSE_COMMENT_BLOCK:
|
case PREF_PARSE_COMMENT_BLOCK:
|
||||||
if (c == '*')
|
if (c == '*')
|
||||||
state = PREF_PARSE_COMMENT_BLOCK_MAYBE_END;
|
state = PREF_PARSE_COMMENT_BLOCK_MAYBE_END;
|
||||||
break;
|
break;
|
||||||
case PREF_PARSE_COMMENT_BLOCK_MAYBE_END:
|
case PREF_PARSE_COMMENT_BLOCK_MAYBE_END:
|
||||||
@ -401,6 +431,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
state = PREF_PARSE_HEX_ESCAPE;
|
state = PREF_PARSE_HEX_ESCAPE;
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
|
pref_ReportParseProblem(*ps, "preserving unexpected JS escape sequence",
|
||||||
|
lineNum, false);
|
||||||
NS_WARNING("preserving unexpected JS escape sequence");
|
NS_WARNING("preserving unexpected JS escape sequence");
|
||||||
/* Invalid escape sequence so we do have to write more than
|
/* Invalid escape sequence so we do have to write more than
|
||||||
* one character. Grow line buffer if necessary... */
|
* one character. Grow line buffer if necessary... */
|
||||||
@ -423,6 +455,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
udigit = (c - 'a') + 10;
|
udigit = (c - 'a') + 10;
|
||||||
else {
|
else {
|
||||||
/* bad escape sequence found, write out broken escape as-is */
|
/* bad escape sequence found, write out broken escape as-is */
|
||||||
|
pref_ReportParseProblem(*ps, "preserving invalid or incomplete hex escape",
|
||||||
|
lineNum, false);
|
||||||
NS_WARNING("preserving invalid or incomplete hex escape");
|
NS_WARNING("preserving invalid or incomplete hex escape");
|
||||||
*ps->lbcur++ = '\\'; /* original escape slash */
|
*ps->lbcur++ = '\\'; /* original escape slash */
|
||||||
if ((ps->lbcur + ps->esclen) >= ps->lbend && !pref_GrowBuf(ps))
|
if ((ps->lbcur + ps->esclen) >= ps->lbend && !pref_GrowBuf(ps))
|
||||||
@ -510,6 +544,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||||
}
|
}
|
||||||
else if (!isspace(c)) {
|
else if (!isspace(c)) {
|
||||||
|
pref_ReportParseProblem(*ps, "need space, comment or open parentheses",
|
||||||
|
lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -522,6 +558,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
ps->nextstate = state; /* return here when done with comment */
|
ps->nextstate = state; /* return here when done with comment */
|
||||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||||
} else if (!isspace(c)) {
|
} else if (!isspace(c)) {
|
||||||
|
pref_ReportParseProblem(*ps, "need space, comment or closing parentheses",
|
||||||
|
lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -540,6 +578,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
|
|||||||
state = PREF_PARSE_COMMENT_MAYBE_START;
|
state = PREF_PARSE_COMMENT_MAYBE_START;
|
||||||
}
|
}
|
||||||
else if (!isspace(c)) {
|
else if (!isspace(c)) {
|
||||||
|
pref_ReportParseProblem(*ps, "need space, comment or semicolon",
|
||||||
|
lineNum, true);
|
||||||
NS_WARNING("malformed pref file");
|
NS_WARNING("malformed pref file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -603,7 +643,7 @@ main(int argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PREF_InitParseState(&ps, pref_reader, nullptr);
|
PREF_InitParseState(&ps, pref_reader, nullptr, nullptr);
|
||||||
|
|
||||||
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
|
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
|
||||||
PREF_ParseBuf(&ps, buf, n);
|
PREF_ParseBuf(&ps, buf, n);
|
||||||
|
@ -36,9 +36,15 @@ typedef void (*PrefReader)(void *closure,
|
|||||||
bool defPref,
|
bool defPref,
|
||||||
bool stickyPref);
|
bool stickyPref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report any errors or warnings we encounter during parsing.
|
||||||
|
*/
|
||||||
|
typedef void (*PrefParseErrorReporter)(const char* message, int line, bool error);
|
||||||
|
|
||||||
/* structure fields are private */
|
/* structure fields are private */
|
||||||
typedef struct PrefParseState {
|
typedef struct PrefParseState {
|
||||||
PrefReader reader;
|
PrefReader reader;
|
||||||
|
PrefParseErrorReporter reporter;
|
||||||
void *closure;
|
void *closure;
|
||||||
int state; /* PREF_PARSE_... */
|
int state; /* PREF_PARSE_... */
|
||||||
int nextstate; /* sometimes used... */
|
int nextstate; /* sometimes used... */
|
||||||
@ -62,16 +68,20 @@ typedef struct PrefParseState {
|
|||||||
* PREF_InitParseState
|
* PREF_InitParseState
|
||||||
*
|
*
|
||||||
* Called to initialize a PrefParseState instance.
|
* Called to initialize a PrefParseState instance.
|
||||||
*
|
*
|
||||||
* @param ps
|
* @param ps
|
||||||
* PrefParseState instance.
|
* PrefParseState instance.
|
||||||
* @param reader
|
* @param reader
|
||||||
* PrefReader callback function, which will be called once for each
|
* PrefReader callback function, which will be called once for each
|
||||||
* preference name value pair extracted.
|
* preference name value pair extracted.
|
||||||
|
* @param reporter
|
||||||
|
* PrefParseErrorReporter callback function, which will be called if we
|
||||||
|
* encounter any errors (stop) or warnings (continue) during parsing.
|
||||||
* @param closure
|
* @param closure
|
||||||
* PrefReader closure.
|
* PrefReader closure.
|
||||||
*/
|
*/
|
||||||
void PREF_InitParseState(PrefParseState *ps, PrefReader reader, void *closure);
|
void PREF_InitParseState(PrefParseState *ps, PrefReader reader,
|
||||||
|
PrefParseErrorReporter reporter, void *closure);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PREF_FinalizeParseState
|
* PREF_FinalizeParseState
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user