Merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Razvan Maries 2018-12-12 18:32:14 +02:00
Родитель b3b5a48999 25784a5a17
Коммит cef33be47c
126 изменённых файлов: 2659 добавлений и 865 удалений

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

@ -2553,6 +2553,56 @@ int32_t nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
return child1index < aOffset2 ? -1 : 1;
}
// static
nsINode*
nsContentUtils::GetCommonAncestorUnderInteractiveContent(nsINode* aNode1,
nsINode* aNode2)
{
if (!aNode1 || !aNode2) {
return nullptr;
}
if (aNode1 == aNode2) {
return aNode1;
}
// Build the chain of parents
AutoTArray<nsINode*, 30> parents1;
do {
parents1.AppendElement(aNode1);
if (aNode1->IsElement() &&
aNode1->AsElement()->IsInteractiveHTMLContent(true)) {
break;
}
aNode1 = aNode1->GetFlattenedTreeParentNode();
} while (aNode1);
AutoTArray<nsINode*, 30> parents2;
do {
parents2.AppendElement(aNode2);
if (aNode2->IsElement() &&
aNode2->AsElement()->IsInteractiveHTMLContent(true)) {
break;
}
aNode2 = aNode2->GetFlattenedTreeParentNode();
} while (aNode2);
// Find where the parent chain differs
uint32_t pos1 = parents1.Length();
uint32_t pos2 = parents2.Length();
nsINode* parent = nullptr;
for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
nsINode* child1 = parents1.ElementAt(--pos1);
nsINode* child2 = parents2.ElementAt(--pos2);
if (child1 != child2) {
break;
}
parent = child1;
}
return parent;
}
/* static */
int32_t nsContentUtils::ComparePoints(const RawRangeBoundary& aFirst,
const RawRangeBoundary& aSecond,

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

@ -439,6 +439,15 @@ class nsContentUtils {
static Element* GetCommonFlattenedTreeAncestorForStyle(Element* aElement1,
Element* aElement2);
/**
* Returns the common ancestor under interactive content, if any.
* If neither one has interactive content as ancestor, common ancestor will be
* returned. If only one has interactive content as ancestor, null will be
* returned. If the nodes are the same, that node is returned.
*/
static nsINode* GetCommonAncestorUnderInteractiveContent(nsINode* aNode1,
nsINode* aNode2);
/**
* Returns true if aNode1 is before aNode2 in the same connected
* tree.

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

@ -162,6 +162,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Event)
default:
break;
}
if (WidgetMouseEvent* mouseEvent = tmp->mEvent->AsMouseEvent()) {
mouseEvent->mClickTarget = nullptr;
}
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExplicitOriginalTarget);
@ -194,6 +198,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event)
default:
break;
}
if (WidgetMouseEvent* mouseEvent = tmp->mEvent->AsMouseEvent()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mClickTarget");
cb.NoteXPCOMChild(mouseEvent->mClickTarget);
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExplicitOriginalTarget)

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

@ -347,11 +347,9 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(EventStateManager)
NS_IMPL_CYCLE_COLLECTION(
EventStateManager, mCurrentTargetContent, mGestureDownContent,
mGestureDownFrameOwner, mLastLeftMouseDownContent,
mLastLeftMouseDownContentParent, mLastMiddleMouseDownContent,
mLastMiddleMouseDownContentParent, mLastRightMouseDownContent,
mLastRightMouseDownContentParent, mActiveContent, mHoverContent,
mURLTargetContent, mMouseEnterLeaveHelper, mPointersEnterLeaveHelper,
mDocument, mIMEContentObserver, mAccessKeys)
mLastMiddleMouseDownContent, mLastRightMouseDownContent, mActiveContent,
mHoverContent, mURLTargetContent, mMouseEnterLeaveHelper,
mPointersEnterLeaveHelper, mDocument, mIMEContentObserver, mAccessKeys)
void EventStateManager::ReleaseCurrentIMEContentObserver() {
if (mIMEContentObserver) {
@ -4594,16 +4592,13 @@ nsresult EventStateManager::SetClickCount(WidgetMouseEvent* aEvent,
nsEventStatus* aStatus,
nsIContent* aOverrideClickTarget) {
nsCOMPtr<nsIContent> mouseContent = aOverrideClickTarget;
nsIContent* mouseContentParent = nullptr;
if (!mouseContent && mCurrentTarget) {
mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(mouseContent));
}
if (mouseContent) {
if (mouseContent->IsText()) {
mouseContent = mouseContent->GetFlattenedTreeParent();
}
if (mouseContent && mouseContent->IsRootOfNativeAnonymousSubtree()) {
mouseContentParent = mouseContent->GetParent();
if (mouseContent && mouseContent->IsText()) {
nsINode* parent = mouseContent->GetFlattenedTreeParentNode();
if (parent && parent->IsContent()) {
mouseContent = parent->AsContent();
}
}
@ -4611,54 +4606,51 @@ nsresult EventStateManager::SetClickCount(WidgetMouseEvent* aEvent,
case WidgetMouseEvent::eLeftButton:
if (aEvent->mMessage == eMouseDown) {
mLastLeftMouseDownContent = mouseContent;
mLastLeftMouseDownContentParent = mouseContentParent;
} else if (aEvent->mMessage == eMouseUp) {
if (mLastLeftMouseDownContent == mouseContent ||
mLastLeftMouseDownContentParent == mouseContent ||
mLastLeftMouseDownContent == mouseContentParent) {
aEvent->mClickTarget =
nsContentUtils::GetCommonAncestorUnderInteractiveContent(
mouseContent, mLastLeftMouseDownContent);
if (aEvent->mClickTarget) {
aEvent->mClickCount = mLClickCount;
mLClickCount = 0;
} else {
aEvent->mClickCount = 0;
}
mLastLeftMouseDownContent = nullptr;
mLastLeftMouseDownContentParent = nullptr;
}
break;
case WidgetMouseEvent::eMiddleButton:
if (aEvent->mMessage == eMouseDown) {
mLastMiddleMouseDownContent = mouseContent;
mLastMiddleMouseDownContentParent = mouseContentParent;
} else if (aEvent->mMessage == eMouseUp) {
if (mLastMiddleMouseDownContent == mouseContent ||
mLastMiddleMouseDownContentParent == mouseContent ||
mLastMiddleMouseDownContent == mouseContentParent) {
aEvent->mClickTarget =
nsContentUtils::GetCommonAncestorUnderInteractiveContent(
mouseContent, mLastMiddleMouseDownContent);
if (aEvent->mClickTarget) {
aEvent->mClickCount = mMClickCount;
mMClickCount = 0;
} else {
aEvent->mClickCount = 0;
}
mLastMiddleMouseDownContent = nullptr;
mLastMiddleMouseDownContentParent = nullptr;
}
break;
case WidgetMouseEvent::eRightButton:
if (aEvent->mMessage == eMouseDown) {
mLastRightMouseDownContent = mouseContent;
mLastRightMouseDownContentParent = mouseContentParent;
} else if (aEvent->mMessage == eMouseUp) {
if (mLastRightMouseDownContent == mouseContent ||
mLastRightMouseDownContentParent == mouseContent ||
mLastRightMouseDownContent == mouseContentParent) {
aEvent->mClickTarget =
nsContentUtils::GetCommonAncestorUnderInteractiveContent(
mouseContent, mLastRightMouseDownContent);
if (aEvent->mClickTarget) {
aEvent->mClickCount = mRClickCount;
mRClickCount = 0;
} else {
aEvent->mClickCount = 0;
}
mLastRightMouseDownContent = nullptr;
mLastRightMouseDownContentParent = nullptr;
}
break;
}
@ -4679,7 +4671,7 @@ bool EventStateManager::EventCausesClickEvents(
}
// If mouse is still over same element, clickcount will be > 1.
// If it has moved it will be zero, so no click.
if (!aMouseEvent.mClickCount) {
if (!aMouseEvent.mClickCount || !aMouseEvent.mClickTarget) {
return false;
}
// Check that the window isn't disabled before firing a click
@ -4716,6 +4708,10 @@ nsresult EventStateManager::InitAndDispatchClickEvent(
targetFrame = aOverrideClickTarget->GetPrimaryFrame();
}
if (!target->IsInComposedDoc()) {
return NS_OK;
}
// Use local event status for each click event dispatching since it'll be
// cleared by EventStateManager::PreHandleEvent(). Therefore, dispatching
// an event means that previous event status will be ignored.
@ -4756,25 +4752,16 @@ nsresult EventStateManager::PostHandleMouseUp(
return NS_OK;
}
nsCOMPtr<nsIContent> mouseUpContent = GetEventTargetContent(aMouseUpEvent);
// Click events apply to *elements* not nodes. At this point the target
// content may have been reset to some non-element content, and so we need
// to walk up the closest ancestor element, just like we do in
// nsPresShell::HandleEvent.
while (mouseUpContent && !mouseUpContent->IsElement()) {
mouseUpContent = mouseUpContent->GetFlattenedTreeParent();
}
if (!mouseUpContent && !mCurrentTarget && !aOverrideClickTarget) {
return NS_OK;
}
nsCOMPtr<nsIContent> clickTarget =
do_QueryInterface(aMouseUpEvent->mClickTarget);
NS_ENSURE_STATE(clickTarget);
// Fire click events if the event target is still available.
// Note that do not include the eMouseUp event's status since we ignore it
// for compatibility with the other browsers.
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv = DispatchClickEvents(presShell, aMouseUpEvent, &status,
mouseUpContent, aOverrideClickTarget);
clickTarget, aOverrideClickTarget);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -4815,13 +4802,13 @@ nsresult EventStateManager::PostHandleMouseUp(
nsresult EventStateManager::DispatchClickEvents(
nsIPresShell* aPresShell, WidgetMouseEvent* aMouseUpEvent,
nsEventStatus* aStatus, nsIContent* aMouseUpContent,
nsEventStatus* aStatus, nsIContent* aClickTarget,
nsIContent* aOverrideClickTarget) {
MOZ_ASSERT(aPresShell);
MOZ_ASSERT(aMouseUpEvent);
MOZ_ASSERT(EventCausesClickEvents(*aMouseUpEvent));
MOZ_ASSERT(aStatus);
MOZ_ASSERT(aMouseUpContent || mCurrentTarget || aOverrideClickTarget);
MOZ_ASSERT(aClickTarget || aOverrideClickTarget);
bool notDispatchToContents =
(aMouseUpEvent->button == WidgetMouseEvent::eMiddleButton ||
@ -4829,20 +4816,19 @@ nsresult EventStateManager::DispatchClickEvents(
bool fireAuxClick = notDispatchToContents;
// HandleEvent clears out mCurrentTarget which we might need again
AutoWeakFrame currentTarget = mCurrentTarget;
AutoWeakFrame currentTarget = aClickTarget->GetPrimaryFrame();
nsresult rv = InitAndDispatchClickEvent(
aMouseUpEvent, aStatus, eMouseClick, aPresShell, aMouseUpContent,
aMouseUpEvent, aStatus, eMouseClick, aPresShell, aClickTarget,
currentTarget, notDispatchToContents, aOverrideClickTarget);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Fire double click event if click count is 2.
if (aMouseUpEvent->mClickCount == 2 && aMouseUpContent &&
aMouseUpContent->IsInComposedDoc()) {
if (aMouseUpEvent->mClickCount == 2 && aClickTarget &&
aClickTarget->IsInComposedDoc()) {
rv = InitAndDispatchClickEvent(aMouseUpEvent, aStatus, eMouseDoubleClick,
aPresShell, aMouseUpContent, currentTarget,
aPresShell, aClickTarget, currentTarget,
notDispatchToContents, aOverrideClickTarget);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
@ -4850,9 +4836,9 @@ nsresult EventStateManager::DispatchClickEvents(
}
// Fire auxclick even if necessary.
if (fireAuxClick && aMouseUpContent && aMouseUpContent->IsInComposedDoc()) {
if (fireAuxClick && aClickTarget && aClickTarget->IsInComposedDoc()) {
rv = InitAndDispatchClickEvent(aMouseUpEvent, aStatus, eMouseAuxClick,
aPresShell, aMouseUpContent, currentTarget,
aPresShell, aClickTarget, currentTarget,
false, aOverrideClickTarget);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to dispatch eMouseAuxClick");
}

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

@ -1210,11 +1210,8 @@ class EventStateManager : public nsSupportsWeakReference, public nsIObserver {
uint16_t mGestureDownButtons;
nsCOMPtr<nsIContent> mLastLeftMouseDownContent;
nsCOMPtr<nsIContent> mLastLeftMouseDownContentParent;
nsCOMPtr<nsIContent> mLastMiddleMouseDownContent;
nsCOMPtr<nsIContent> mLastMiddleMouseDownContentParent;
nsCOMPtr<nsIContent> mLastRightMouseDownContent;
nsCOMPtr<nsIContent> mLastRightMouseDownContentParent;
nsCOMPtr<nsIContent> mActiveContent;
nsCOMPtr<nsIContent> mHoverContent;

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

@ -58,7 +58,7 @@ function runTest() {
is(downCount, 3, "Wrong mousedown event count!");
is(upCount, 3, "Wrong mouseup event count!");
is(clickCount, 2, "Wrong click event count!");
is(clickCount, 3, "Wrong click event count!");
SimpleTest.finish();
}

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

@ -22,8 +22,27 @@ function runTests()
synthesizeMouse(document.getElementById("display"), 5, 5, { clickCount: 2 });
}
window.onmousedown = function(event) {
is(event.explicitOriginalTarget.nodeType, Node.TEXT_NODE,
"explicitOriginalTarget is a text node");
is(event.explicitOriginalTarget, document.getElementById("display").firstChild,
"explicitOriginalTarget should point to the child node of the click target");
}
window.onmouseup = function(event) {
is(event.explicitOriginalTarget.nodeType, Node.TEXT_NODE,
"explicitOriginalTarget is a text node");
is(event.explicitOriginalTarget, document.getElementById("display").firstChild,
"explicitOriginalTarget should point to the child node of the click target");
}
// The old versions of Gecko had explicitOriginalTarget pointing to a Text node
// when handling *click events, newer versions target Elements.
window.ondblclick = function(event) {
is(event.explicitOriginalTarget.nodeType, Node.TEXT_NODE, "explicitOriginalTarget is a text node");
is(event.explicitOriginalTarget.nodeType, Node.ELEMENT_NODE,
"explicitOriginalTarget is an element node");
is(event.explicitOriginalTarget, document.getElementById("display"),
"explicitOriginalTarget should point to the click target");
SimpleTest.finish();
}

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

@ -171,11 +171,14 @@ void HTMLButtonElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
bool outerActivateEvent = ((mouseEvent && mouseEvent->IsLeftClickEvent()) ||
(aVisitor.mEvent->mMessage == eLegacyDOMActivate &&
!mInInternalActivate));
!mInInternalActivate &&
aVisitor.mEvent->mOriginalTarget == this));
if (outerActivateEvent) {
aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT;
if (mType == NS_FORM_BUTTON_SUBMIT && mForm) {
if (mType == NS_FORM_BUTTON_SUBMIT && mForm &&
!aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented) {
aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented = true;
aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK;
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the

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

@ -132,11 +132,14 @@ namespace dom {
#define NS_ORIGINAL_CHECKED_VALUE (1 << 10)
#define NS_NO_CONTENT_DISPATCH (1 << 11)
#define NS_ORIGINAL_INDETERMINATE_VALUE (1 << 12)
#define NS_CONTROL_TYPE(bits) \
((bits) & ~(NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | \
NS_NO_CONTENT_DISPATCH | NS_ORIGINAL_INDETERMINATE_VALUE))
#define NS_PRE_HANDLE_BLUR_EVENT (1 << 13)
#define NS_PRE_HANDLE_INPUT_EVENT (1 << 14)
#define NS_IN_SUBMIT_CLICK (1 << 15)
#define NS_CONTROL_TYPE(bits) \
((bits) & ~(NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | \
NS_NO_CONTENT_DISPATCH | NS_ORIGINAL_INDETERMINATE_VALUE | \
NS_PRE_HANDLE_BLUR_EVENT | NS_PRE_HANDLE_INPUT_EVENT | \
NS_IN_SUBMIT_CLICK))
// whether textfields should be selected once focused:
// -1: no, 1: yes, 0: uninitialized
@ -3180,7 +3183,10 @@ void HTMLInputElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_IMAGE:
if (mForm) {
if (mForm && !aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented) {
// Make sure other submit elements don't try to trigger submission.
aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented = true;
aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK;
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the
@ -3736,17 +3742,15 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
}
}
if (outerActivateEvent) {
if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) && mForm) {
switch (oldType) {
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_IMAGE:
if (mForm) {
// tell the form that we are about to exit a click handler
// so the form knows not to defer subsequent submissions
// the pending ones that were created during the handler
// will be flushed or forgoten.
mForm->OnSubmitClickEnd();
}
// tell the form that we are about to exit a click handler
// so the form knows not to defer subsequent submissions
// the pending ones that were created during the handler
// will be flushed or forgoten.
mForm->OnSubmitClickEnd();
break;
default:
break;
@ -4112,7 +4116,8 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
if (outerActivateEvent) {
if (mForm && (oldType == NS_FORM_INPUT_SUBMIT ||
oldType == NS_FORM_INPUT_IMAGE)) {
if (mType != NS_FORM_INPUT_SUBMIT && mType != NS_FORM_INPUT_IMAGE) {
if (mType != NS_FORM_INPUT_SUBMIT && mType != NS_FORM_INPUT_IMAGE &&
aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) {
// If the type has changed to a non-submit type, then we want to
// flush the stored submission if there is one (as if the submit()
// was allowed to succeed)
@ -4152,7 +4157,7 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
break;
} // switch
} // click or outer activate event
} else if (outerActivateEvent &&
} else if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) &&
(oldType == NS_FORM_INPUT_SUBMIT ||
oldType == NS_FORM_INPUT_IMAGE) &&
mForm) {

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

@ -417,6 +417,7 @@ support-files =
[test_bug982039.html]
[test_bug1003539.html]
[test_bug1045270.html]
[test_bug1089326.html]
[test_bug1146116.html]
[test_bug1264157.html]
[test_bug1287321.html]

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

@ -0,0 +1,108 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1089326
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1089326</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1089326 **/
function test() {
var b = document.getElementById("button");
var b_rect = b.getBoundingClientRect();
var a = document.getElementById("anchor");
var a_rect = a.getBoundingClientRect();
is(document.elementFromPoint(b_rect.x + 1, b_rect.y + 1), b,
"Should find button when doing hit test on top of it.");
is(document.elementFromPoint(a_rect.x + 1, a_rect.y + 1), a,
"Should find anchor when doing hit test on top of it.");
var expectedTarget;
var clickCount = 0;
var container = document.getElementById("interactiveContentContainer");
container.addEventListener("click", function(event) {
is(event.target, expectedTarget, "Got expected click event target.");
++clickCount;
}, true);
var i1 = document.getElementById("interactiveContent1");
var s11 = document.getElementById("s11");
var s12 = document.getElementById("s12");
var i2 = document.getElementById("interactiveContent2");
var s21 = document.getElementById("s21");
expectedTarget = i1;
synthesizeMouseAtCenter(s11, { type: "mousedown" });
synthesizeMouseAtCenter(s12, { type: "mouseup" });
is(clickCount, 1, "Should have got a click event.");
expectedTarget = null;
synthesizeMouseAtCenter(s11, { type: "mousedown" });
synthesizeMouseAtCenter(s21, { type: "mouseup" });
is(clickCount, 1, "Should not have got a click event.");
expectedTarget = null;
synthesizeMouseAtCenter(s21, { type: "mousedown" });
synthesizeMouseAtCenter(s11, { type: "mouseup" });
is(clickCount, 1, "Should not have got a click event.");
var span1 = document.getElementById("span1");
var span2 = document.getElementById("span2");
expectedTarget = container;
synthesizeMouseAtCenter(span1, { type: "mousedown" });
synthesizeMouseAtCenter(span2, { type: "mouseup" });
is(clickCount, 2, "Should not have got a click event.");
button.addEventListener("click", function(event) {
is(event.target, expectedTarget, "Got expected click event target.");
++clickCount;
}, true);
expectedTarget = a;
synthesizeMouseAtCenter(a, { type: "mousedown" });
synthesizeMouseAtCenter(a, { type: "mouseup" });
is(clickCount, 3, "Should have got a click event.");
expectedTarget = a;
synthesizeMouseAtCenter(b, { type: "mousedown" });
synthesizeMouseAtCenter(b, { type: "mouseup" });
is(clickCount, 4, "Should have got a click event.");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(test);
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1089326">Mozilla Bug 1089326</a>
<p id="display"></p>
<button id="button">button <a id="anchor" href="#">anchor</a>button</button>
<div id="interactiveContentContainer">
<a id="interactiveContent1" href="#">foo <span id="s11">s11</span><span id="s12">s12</span> bar</a>
<a id="interactiveContent2" href="#">foo <span id="s21">s21</span><span id="s22">s22</span> bar</a>
<div>
<span>
<span id="span1">span1</span>
</span>
</div>
<div>
<span>
<span id="span2">span2</span>
</span>
</div>
</div>
</body>
</html>

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

@ -60,9 +60,16 @@ function InitDetectorTests()
function SetDetectorPref(aPrefValue)
{
var fallback = "";
if (aPrefValue == "ja_parallel_state_machine") {
fallback = "Shift_JIS";
} else if (aPrefValue == "ruprob" || aPrefValue == "ukprob") {
fallback = "windows-1251";
}
var prefService = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);
prefService.setStringPref("intl.charset.detector", aPrefValue);
prefService.setStringPref("intl.charset.fallback.override", fallback);
gCurrentDetector = aPrefValue;
}

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

@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=811363
<script class="testbody" type="text/javascript">
/** Test for Bug 811363 **/
CharsetDetectionTests("bug811363-invalid-1.text",
"windows-1252",
"Shift_JIS",
new Array("ja_parallel_state_machine"));
</script>
</pre>

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

@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=811363
<script class="testbody" type="text/javascript">
/** Test for Bug 811363 **/
CharsetDetectionTests("bug811363-invalid-5.text",
"windows-1252",
"Shift_JIS",
new Array("ja_parallel_state_machine"));
</script>
</pre>

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

@ -1738,7 +1738,8 @@ bool WebRenderCommandBuilder::PushImage(
nsDisplayItem* aItem, ImageContainer* aContainer,
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc, const LayoutDeviceRect& aRect) {
const StackingContextHelper& aSc, const LayoutDeviceRect& aRect,
const LayoutDeviceRect& aClip) {
mozilla::wr::ImageRendering rendering = wr::ToImageRendering(
nsLayoutUtils::GetSamplingFilterForFrame(aItem->Frame()));
gfx::IntSize size;
@ -1755,7 +1756,8 @@ bool WebRenderCommandBuilder::PushImage(
}
auto r = wr::ToRoundedLayoutRect(aRect);
aBuilder.PushImage(r, r, !aItem->BackfaceIsHidden(), rendering, key.value());
auto c = wr::ToRoundedLayoutRect(aClip);
aBuilder.PushImage(r, c, !aItem->BackfaceIsHidden(), rendering, key.value());
return true;
}

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

@ -77,7 +77,7 @@ class WebRenderCommandBuilder {
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
const LayoutDeviceRect& aRect);
const LayoutDeviceRect& aRect, const LayoutDeviceRect& aClip);
Maybe<wr::WrImageMask> BuildWrMaskImage(
nsDisplayItem* aItem, wr::DisplayListBuilder& aBuilder,

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

@ -459,7 +459,47 @@ void CodeGeneratorARM64::modICommon(MMod* mir, Register lhs, Register rhs,
MOZ_CRASH("CodeGeneratorARM64::modICommon");
}
void CodeGenerator::visitModI(LModI* ins) { MOZ_CRASH("visitModI"); }
void CodeGenerator::visitModI(LModI* ins) {
if (gen->compilingWasm()) {
MOZ_CRASH("visitModI while compilingWasm");
}
MMod* mir = ins->mir();
ARMRegister lhs = toWRegister(ins->lhs());
ARMRegister rhs = toWRegister(ins->rhs());
ARMRegister output = toWRegister(ins->output());
Label done;
if (mir->canBeDivideByZero() && !mir->isTruncated()) {
// Non-truncated division by zero produces a non-integer.
masm.Cmp(rhs, Operand(0));
bailoutIf(Assembler::Equal, ins->snapshot());
} else if (mir->canBeDivideByZero()) {
// Truncated division by zero yields integer zero.
masm.Mov(output, rhs);
masm.Cbz(rhs, &done);
}
// Signed division.
masm.Sdiv(output, lhs, rhs);
// Compute the remainder: output = lhs - (output * rhs).
masm.Msub(output, output, rhs, lhs);
if (mir->canBeNegativeDividend() && !mir->isTruncated()) {
// If output == 0 and lhs < 0, then the result should be double -0.0.
// Note that this guard handles lhs == INT_MIN and rhs == -1:
// output = INT_MIN - (INT_MIN / -1) * -1
// = INT_MIN - INT_MIN
// = 0
masm.Cbnz(output, &done);
bailoutCmp32(Assembler::LessThan, lhs, Imm32(0), ins->snapshot());
}
if (done.used()) {
masm.bind(&done);
}
}
void CodeGenerator::visitModPowTwoI(LModPowTwoI* ins) {
Register lhs = ToRegister(ins->getOperand(0));
@ -502,7 +542,97 @@ void CodeGenerator::visitModPowTwoI(LModPowTwoI* ins) {
}
void CodeGenerator::visitModMaskI(LModMaskI* ins) {
MOZ_CRASH("CodeGenerator::visitModMaskI");
MMod* mir = ins->mir();
int32_t shift = ins->shift();
const Register src = ToRegister(ins->getOperand(0));
const Register dest = ToRegister(ins->getDef(0));
const Register hold = ToRegister(ins->getTemp(0));
const Register remain = ToRegister(ins->getTemp(1));
const ARMRegister src32 = ARMRegister(src, 32);
const ARMRegister dest32 = ARMRegister(dest, 32);
const ARMRegister remain32 = ARMRegister(remain, 32);
vixl::UseScratchRegisterScope temps(&masm.asVIXL());
const ARMRegister scratch32 = temps.AcquireW();
const Register scratch = scratch32.asUnsized();
// We wish to compute x % (1<<y) - 1 for a known constant, y.
//
// 1. Let b = (1<<y) and C = (1<<y)-1, then think of the 32 bit dividend as
// a number in base b, namely c_0*1 + c_1*b + c_2*b^2 ... c_n*b^n
//
// 2. Since both addition and multiplication commute with modulus:
// x % C == (c_0 + c_1*b + ... + c_n*b^n) % C ==
// (c_0 % C) + (c_1%C) * (b % C) + (c_2 % C) * (b^2 % C)...
//
// 3. Since b == C + 1, b % C == 1, and b^n % C == 1 the whole thing
// simplifies to: c_0 + c_1 + c_2 ... c_n % C
//
// Each c_n can easily be computed by a shift/bitextract, and the modulus
// can be maintained by simply subtracting by C whenever the number gets
// over C.
int32_t mask = (1 << shift) - 1;
Label loop;
// Register 'hold' holds -1 if the value was negative, 1 otherwise.
// The remain reg holds the remaining bits that have not been processed.
// The scratch reg serves as a temporary location to store extracted bits.
// The dest reg is the accumulator, becoming final result.
//
// Move the whole value into the remain.
masm.Mov(remain32, src32);
// Zero out the dest.
masm.Mov(dest32, wzr);
// Set the hold appropriately.
{
Label negative;
masm.branch32(Assembler::Signed, remain, Imm32(0), &negative);
masm.move32(Imm32(1), hold);
masm.jump(&loop);
masm.bind(&negative);
masm.move32(Imm32(-1), hold);
masm.neg32(remain);
}
// Begin the main loop.
masm.bind(&loop);
{
// Extract the bottom bits into scratch.
masm.And(scratch32, remain32, Operand(mask));
// Add those bits to the accumulator.
masm.Add(dest32, dest32, scratch32);
// Do a trial subtraction. This functions as a cmp but remembers the result.
masm.Subs(scratch32, dest32, Operand(mask));
// If (sum - C) > 0, store sum - C back into sum, thus performing a modulus.
{
Label sumSigned;
masm.branch32(Assembler::Signed, scratch, scratch, &sumSigned);
masm.Mov(dest32, scratch32);
masm.bind(&sumSigned);
}
// Get rid of the bits that we extracted before.
masm.Lsr(remain32, remain32, shift);
// If the shift produced zero, finish, otherwise, continue in the loop.
masm.branchTest32(Assembler::NonZero, remain, remain, &loop);
}
// Check the hold to see if we need to negate the result.
{
Label done;
// If the hold was non-zero, negate the result to match JS expectations.
masm.branchTest32(Assembler::NotSigned, hold, hold, &done);
if (mir->canBeNegativeDividend() && !mir->isTruncated()) {
// Bail in case of negative zero hold.
bailoutTest32(Assembler::Zero, hold, hold, ins->snapshot());
}
masm.neg32(dest);
masm.bind(&done);
}
}
void CodeGenerator::visitBitNotI(LBitNotI* ins) {
@ -1144,7 +1274,41 @@ void CodeGenerator::visitWasmStackArg(LWasmStackArg* ins) {
void CodeGenerator::visitUDiv(LUDiv* ins) { MOZ_CRASH("visitUDiv"); }
void CodeGenerator::visitUMod(LUMod* ins) { MOZ_CRASH("visitUMod"); }
void CodeGenerator::visitUMod(LUMod* ins) {
MMod* mir = ins->mir();
ARMRegister lhs = toWRegister(ins->lhs());
ARMRegister rhs = toWRegister(ins->rhs());
ARMRegister output = toWRegister(ins->output());
Label done;
if (mir->canBeDivideByZero() && !mir->isTruncated()) {
// Non-truncated division by zero produces a non-integer.
masm.Cmp(rhs, Operand(0));
bailoutIf(Assembler::Equal, ins->snapshot());
} else if (mir->canBeDivideByZero()) {
// Truncated division by zero yields integer zero.
masm.Mov(output, rhs);
masm.Cbz(rhs, &done);
}
// Unsigned division.
masm.Udiv(output, lhs, rhs);
// Compute the remainder: output = lhs - (output * rhs).
masm.Msub(output, output, rhs, lhs);
if (!mir->isTruncated()) {
// Bail if the output would be negative.
//
// LUMod inputs may be Uint32, so care is taken to ensure the result
// is not unexpectedly signed.
bailoutCmp32(Assembler::LessThan, output, Imm32(0), ins->snapshot());
}
if (done.used()) {
masm.bind(&done);
}
}
void CodeGenerator::visitEffectiveAddress(LEffectiveAddress* ins) {
const MEffectiveAddress* mir = ins->mir();
@ -1241,10 +1405,6 @@ void CodeGenerator::visitBitOpI64(LBitOpI64*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitShiftI64(LShiftI64*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitSoftDivI(LSoftDivI*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitSoftModI(LSoftModI*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitWasmLoad(LWasmLoad*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitCopySignD(LCopySignD*) { MOZ_CRASH("NYI"); }
@ -1271,8 +1431,6 @@ void CodeGenerator::visitWasmStoreI64(LWasmStoreI64*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitMemoryBarrier(LMemoryBarrier*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitSoftUDivOrMod(LSoftUDivOrMod*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitWasmAddOffset(LWasmAddOffset*) { MOZ_CRASH("NYI"); }
void CodeGenerator::visitWasmSelectI64(LWasmSelectI64*) { MOZ_CRASH("NYI"); }

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

@ -80,36 +80,6 @@ class LDivI : public LBinaryMath<1> {
MDiv* mir() const { return mir_->toDiv(); }
};
// LSoftDivI is a software divide for ARM cores that don't support a hardware
// divide instruction.
//
// It is implemented as a proper C function so it trashes r0, r1, r2 and r3.
// The call also trashes lr, and has the ability to trash ip. The function also
// takes two arguments (dividend in r0, divisor in r1). The LInstruction gets
// encoded such that the divisor and dividend are passed in their apropriate
// registers and end their life at the start of the instruction by the use of
// useFixedAtStart. The result is returned in r0 and the other three registers
// that can be trashed are marked as temps. For the time being, the link
// register is not marked as trashed because we never allocate to the link
// register. The FP registers are not trashed.
class LSoftDivI : public LBinaryMath<3> {
public:
LIR_HEADER(SoftDivI);
LSoftDivI(const LAllocation& lhs, const LAllocation& rhs,
const LDefinition& temp1, const LDefinition& temp2,
const LDefinition& temp3)
: LBinaryMath(classOpcode) {
setOperand(0, lhs);
setOperand(1, rhs);
setTemp(0, temp1);
setTemp(1, temp2);
setTemp(2, temp3);
}
MDiv* mir() const { return mir_->toDiv(); }
};
class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {
const int32_t shift_;
@ -145,27 +115,6 @@ class LModI : public LBinaryMath<1> {
MMod* mir() const { return mir_->toMod(); }
};
class LSoftModI : public LBinaryMath<4> {
public:
LIR_HEADER(SoftModI);
LSoftModI(const LAllocation& lhs, const LAllocation& rhs,
const LDefinition& temp1, const LDefinition& temp2,
const LDefinition& temp3, const LDefinition& callTemp)
: LBinaryMath(classOpcode) {
setOperand(0, lhs);
setOperand(1, rhs);
setTemp(0, temp1);
setTemp(1, temp2);
setTemp(2, temp3);
setTemp(3, callTemp);
}
const LDefinition* callTemp() { return getTemp(3); }
MMod* mir() const { return mir_->toMod(); }
};
class LModPowTwoI : public LInstructionHelper<1, 1, 0> {
const int32_t shift_;
@ -181,16 +130,18 @@ class LModPowTwoI : public LInstructionHelper<1, 1, 0> {
MMod* mir() const { return mir_->toMod(); }
};
class LModMaskI : public LInstructionHelper<1, 1, 1> {
class LModMaskI : public LInstructionHelper<1, 1, 2> {
const int32_t shift_;
public:
LIR_HEADER(ModMaskI);
LModMaskI(const LAllocation& lhs, const LDefinition& temp1, int32_t shift)
LModMaskI(const LAllocation& lhs, const LDefinition& temp1,
const LDefinition& temp2, int32_t shift)
: LInstructionHelper(classOpcode), shift_(shift) {
setOperand(0, lhs);
setTemp(0, temp1);
setTemp(1, temp2);
}
int32_t shift() const { return shift_; }
@ -262,26 +213,13 @@ class LUMod : public LBinaryMath<0> {
public:
LIR_HEADER(UMod);
MMod* mir() { return mir_->toMod(); }
};
// This class performs a simple x86 'div', yielding either a quotient or
// remainder depending on whether this instruction is defined to output eax
// (quotient) or edx (remainder).
class LSoftUDivOrMod : public LBinaryMath<3> {
public:
LIR_HEADER(SoftUDivOrMod);
LSoftUDivOrMod(const LAllocation& lhs, const LAllocation& rhs,
const LDefinition& temp1, const LDefinition& temp2,
const LDefinition& temp3)
LUMod(const LAllocation& lhs, const LAllocation& rhs)
: LBinaryMath(classOpcode) {
setOperand(0, lhs);
setOperand(1, rhs);
setTemp(0, temp1);
setTemp(1, temp2);
setTemp(2, temp3);
}
MMod* mir() { return mir_->toMod(); }
};
} // namespace jit

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

@ -222,7 +222,41 @@ void LIRGeneratorARM64::lowerMulI(MMul* mul, MDefinition* lhs,
lowerForALU(lir, mul, lhs, rhs);
}
void LIRGeneratorARM64::lowerModI(MMod* mod) { MOZ_CRASH("lowerModI"); }
void LIRGeneratorARM64::lowerModI(MMod* mod) {
if (mod->isUnsigned()) {
lowerUMod(mod);
return;
}
if (mod->rhs()->isConstant()) {
int32_t rhs = mod->rhs()->toConstant()->toInt32();
int32_t shift = FloorLog2(rhs);
if (rhs > 0 && 1 << shift == rhs) {
LModPowTwoI* lir = new(alloc()) LModPowTwoI(useRegister(mod->lhs()), shift);
if (mod->fallible()) {
assignSnapshot(lir, Bailout_DoubleOutput);
}
define(lir, mod);
return;
} else if (shift < 31 && (1 << (shift + 1)) - 1 == rhs) {
LModMaskI* lir = new(alloc()) LModMaskI(useRegister(mod->lhs()),
temp(),
temp(),
shift + 1);
if (mod->fallible()) {
assignSnapshot(lir, Bailout_DoubleOutput);
}
define(lir, mod);
}
}
LModI* lir = new(alloc()) LModI(useRegister(mod->lhs()),
useRegister(mod->rhs()), temp());
if (mod->fallible()) {
assignSnapshot(lir, Bailout_DoubleOutput);
}
define(lir, mod);
}
void LIRGeneratorARM64::lowerDivI64(MDiv* div) { MOZ_CRASH("NYI"); }
@ -279,7 +313,14 @@ void LIRGenerator::visitWasmSelect(MWasmSelect* ins) {
void LIRGeneratorARM64::lowerUDiv(MDiv* div) { MOZ_CRASH("lowerUDiv"); }
void LIRGeneratorARM64::lowerUMod(MMod* mod) { MOZ_CRASH("lowerUMod"); }
void LIRGeneratorARM64::lowerUMod(MMod* mod) {
LUMod* lir = new(alloc()) LUMod(useRegister(mod->getOperand(0)),
useRegister(mod->getOperand(1)));
if (mod->fallible()) {
assignSnapshot(lir, Bailout_DoubleOutput);
}
define(lir, mod);
}
void LIRGenerator::visitWasmUnsignedToDouble(MWasmUnsignedToDouble* ins) {
MOZ_CRASH("visitWasmUnsignedToDouble");

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

@ -96,8 +96,10 @@ void nsHTMLButtonControlFrame::BuildDisplayList(
nsDisplayListCollection set(aBuilder);
// Do not allow the child subtree to receive events.
if (!isForEventDelivery || aBuilder->HitTestIsForVisibility()) {
// Do not allow the child subtree to receive events,
// except in case of <button>.
if (!isForEventDelivery || mContent->IsHTMLElement(nsGkAtoms::button) ||
aBuilder->HitTestIsForVisibility()) {
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (ShouldClipPaintingToBorderBox()) {

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

@ -53,8 +53,9 @@ class TextDrawTarget : public DrawTarget {
wr::IpcResourceUpdateQueue& aResources,
const layers::StackingContextHelper& aSc,
layers::WebRenderLayerManager* aManager,
nsDisplayItem* aItem, nsRect& aBounds)
: mBuilder(aBuilder) {
nsDisplayItem* aItem, nsRect& aBounds,
bool aCallerDoesSaveRestore = false)
: mCallerDoesSaveRestore(aCallerDoesSaveRestore), mBuilder(aBuilder) {
Reinitialize(aResources, aSc, aManager, aItem, aBounds);
}
@ -62,7 +63,7 @@ class TextDrawTarget : public DrawTarget {
TextDrawTarget(const TextDrawTarget& src) = delete;
TextDrawTarget& operator=(const TextDrawTarget&) = delete;
~TextDrawTarget() {}
~TextDrawTarget() { MOZ_ASSERT(mFinished); }
void Reinitialize(wr::IpcResourceUpdateQueue& aResources,
const layers::StackingContextHelper& aSc,
@ -93,12 +94,26 @@ class TextDrawTarget : public DrawTarget {
mBackfaceVisible = !aItem->BackfaceIsHidden();
mBuilder.Save();
if (!mCallerDoesSaveRestore) {
mBuilder.Save();
}
}
void FoundUnsupportedFeature() { mHasUnsupportedFeatures = true; }
bool CheckHasUnsupportedFeatures() {
MOZ_ASSERT(mCallerDoesSaveRestore);
#ifdef DEBUG
MOZ_ASSERT(!mFinished);
mFinished = true;
#endif
return mHasUnsupportedFeatures;
}
bool Finish() {
MOZ_ASSERT(!mCallerDoesSaveRestore);
#ifdef DEBUG
mFinished = true;
#endif
if (mHasUnsupportedFeatures) {
mBuilder.Restore();
return false;
@ -336,6 +351,12 @@ class TextDrawTarget : public DrawTarget {
// * Text stroke
bool mHasUnsupportedFeatures = false;
// The caller promises to call Save/Restore on the builder as needed.
bool mCallerDoesSaveRestore = false;
#ifdef DEBUG
bool mFinished = false;
#endif
// Whether PopAllShadows needs to be called
bool mHasShadows = false;

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

@ -8,6 +8,7 @@
#include "nsImageFrame.h"
#include "TextDrawTarget.h"
#include "gfx2DGlue.h"
#include "gfxContext.h"
#include "gfxUtils.h"
@ -1316,6 +1317,21 @@ class nsDisplayAltFeedback final : public nsDisplayItem {
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
}
bool CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override {
uint32_t flags = imgIContainer::FLAG_ASYNC_NOTIFY;
nsImageFrame* f = static_cast<nsImageFrame*>(mFrame);
ImgDrawResult result = f->DisplayAltFeedbackWithoutLayer(
this, aBuilder, aResources, aSc, aManager, aDisplayListBuilder,
ToReferenceFrame(), flags);
return result == ImgDrawResult::SUCCESS;
}
NS_DISPLAY_DECL_NAME("AltFeedback", TYPE_ALT_FEEDBACK)
};
@ -1473,6 +1489,226 @@ ImgDrawResult nsImageFrame::DisplayAltFeedback(gfxContext& aRenderingContext,
return result;
}
ImgDrawResult nsImageFrame::DisplayAltFeedbackWithoutLayer(
nsDisplayItem* aItem, mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder, nsPoint aPt, uint32_t aFlags) {
// We should definitely have a gIconLoad here.
MOZ_ASSERT(gIconLoad, "How did we succeed in Init then?");
// Whether we draw the broken or loading icon.
bool isLoading = IMAGE_OK(GetContent()->AsElement()->State(), true);
// Calculate the inner area
nsRect inner = GetInnerArea() + aPt;
// Display a recessed one pixel border
nscoord borderEdgeWidth =
nsPresContext::CSSPixelsToAppUnits(ALT_BORDER_WIDTH);
// if inner area is empty, then make it big enough for at least the icon
if (inner.IsEmpty()) {
inner.SizeTo(2 * (nsPresContext::CSSPixelsToAppUnits(
ICON_SIZE + ICON_PADDING + ALT_BORDER_WIDTH)),
2 * (nsPresContext::CSSPixelsToAppUnits(
ICON_SIZE + ICON_PADDING + ALT_BORDER_WIDTH)));
}
// Make sure we have enough room to actually render the border within
// our frame bounds
if ((inner.width < 2 * borderEdgeWidth) ||
(inner.height < 2 * borderEdgeWidth)) {
return ImgDrawResult::SUCCESS;
}
// If the TextDrawTarget requires fallback we need to rollback everything we
// may have added to the display list, but we don't find that out until the
// end.
bool textDrawResult = true;
class AutoSaveRestore {
public:
explicit AutoSaveRestore(mozilla::wr::DisplayListBuilder& aBuilder,
bool& aTextDrawResult)
: mBuilder(aBuilder), mTextDrawResult(aTextDrawResult) {
mBuilder.Save();
}
~AutoSaveRestore() {
// If we have to use fallback for the text restore the builder and remove
// anything else we added to the display list, we need to use fallback.
if (mTextDrawResult) {
mBuilder.ClearSave();
} else {
mBuilder.Restore();
}
}
private:
mozilla::wr::DisplayListBuilder& mBuilder;
bool& mTextDrawResult;
};
AutoSaveRestore autoSaveRestore(aBuilder, textDrawResult);
// Paint the border
if (!isLoading || gIconLoad->mPrefShowLoadingPlaceholder) {
nsRecessedBorder recessedBorder(borderEdgeWidth, PresContext());
// Assert that we're not drawing a border-image here; if we were, we
// couldn't ignore the ImgDrawResult that PaintBorderWithStyleBorder
// returns.
MOZ_ASSERT(recessedBorder.mBorderImageSource.GetType() ==
eStyleImageType_Null);
nsRect rect = nsRect(aPt, GetSize());
Unused << nsCSSRendering::CreateWebRenderCommandsForBorderWithStyleBorder(
aItem, this, rect, aBuilder, aResources, aSc, aManager,
aDisplayListBuilder, recessedBorder);
}
// Adjust the inner rect to account for the one pixel recessed border,
// and a six pixel padding on each edge
inner.Deflate(
nsPresContext::CSSPixelsToAppUnits(ICON_PADDING + ALT_BORDER_WIDTH),
nsPresContext::CSSPixelsToAppUnits(ICON_PADDING + ALT_BORDER_WIDTH));
if (inner.IsEmpty()) {
return ImgDrawResult::SUCCESS;
}
// Clip to this rect so we don't render outside the inner rect
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
inner, PresContext()->AppUnitsPerDevPixel());
auto wrBounds = wr::ToRoundedLayoutRect(bounds);
// Draw image
ImgDrawResult result = ImgDrawResult::NOT_READY;
// Check if we should display image placeholders
if (!ShouldShowBrokenImageIcon() || !gIconLoad->mPrefShowPlaceholders ||
(isLoading && !gIconLoad->mPrefShowLoadingPlaceholder)) {
result = ImgDrawResult::SUCCESS;
} else {
nscoord size = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE);
imgIRequest* request = isLoading ? nsImageFrame::gIconLoad->mLoadingImage
: nsImageFrame::gIconLoad->mBrokenImage;
// If we weren't previously displaying an icon, register ourselves
// as an observer for load and animation updates and flag that we're
// doing so now.
if (request && !mDisplayingIcon) {
gIconLoad->AddIconObserver(this);
mDisplayingIcon = true;
}
WritingMode wm = GetWritingMode();
bool flushRight =
(!wm.IsVertical() && !wm.IsBidiLTR()) || wm.IsVerticalRL();
// If the icon in question is loaded, draw it.
uint32_t imageStatus = 0;
if (request) request->GetImageStatus(&imageStatus);
if (imageStatus & imgIRequest::STATUS_LOAD_COMPLETE &&
!(imageStatus & imgIRequest::STATUS_ERROR)) {
nsCOMPtr<imgIContainer> imgCon;
request->GetImage(getter_AddRefs(imgCon));
MOZ_ASSERT(imgCon, "Load complete, but no image container?");
nsRect dest(flushRight ? inner.XMost() - size : inner.x, inner.y, size,
size);
const int32_t factor = PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect(
LayoutDeviceRect::FromAppUnits(dest, factor));
Maybe<SVGImageContext> svgContext;
IntSize decodeSize =
nsLayoutUtils::ComputeImageContainerDrawingParameters(
imgCon, this, destRect, aSc, aFlags, svgContext);
RefPtr<ImageContainer> container;
result = imgCon->GetImageContainerAtSize(
aManager, decodeSize, svgContext, aFlags, getter_AddRefs(container));
if (container) {
bool wrResult = aManager->CommandBuilder().PushImage(
aItem, container, aBuilder, aResources, aSc, destRect, bounds);
result &= wrResult ? ImgDrawResult::SUCCESS : ImgDrawResult::NOT_READY;
} else {
// We don't use &= here because we want the result to be NOT_READY so
// the next block executes.
result = ImgDrawResult::NOT_READY;
}
}
// If we could not draw the icon, just draw some graffiti in the mean time.
if (result == ImgDrawResult::NOT_READY) {
auto color = wr::ColorF{1.0f, 0.0f, 0.0f, 1.0f};
bool isBackfaceVisible = !aItem->BackfaceIsHidden();
nscoord iconXPos = flushRight ? inner.XMost() - size : inner.x;
// stroked rect:
nsRect rect(iconXPos, inner.y, size, size);
auto devPxRect = LayoutDeviceRect::FromAppUnits(
rect, PresContext()->AppUnitsPerDevPixel());
auto dest = wr::ToRoundedLayoutRect(devPxRect);
auto borderWidths = wr::ToBorderWidths(1.0, 1.0, 1.0, 1.0);
wr::BorderSide side = {color, wr::BorderStyle::Solid};
wr::BorderSide sides[4] = {side, side, side, side};
Range<const wr::BorderSide> sidesRange(sides, 4);
aBuilder.PushBorder(dest, wrBounds, isBackfaceVisible, borderWidths,
sidesRange, wr::EmptyBorderRadius());
// filled circle in bottom right quadrant of stroked rect:
nscoord twoPX = nsPresContext::CSSPixelsToAppUnits(2);
rect = nsRect(iconXPos + size / 2, inner.y + size / 2, size / 2 - twoPX,
size / 2 - twoPX);
devPxRect = LayoutDeviceRect::FromAppUnits(
rect, PresContext()->AppUnitsPerDevPixel());
dest = wr::ToRoundedLayoutRect(devPxRect);
AutoTArray<wr::ComplexClipRegion, 1> clips;
clips.AppendElement(wr::SimpleRadii(dest, dest.size.width / 2));
auto clipId = aBuilder.DefineClip(Nothing(), dest, &clips, nullptr);
aBuilder.PushClip(clipId);
aBuilder.PushRect(dest, wrBounds, isBackfaceVisible, color);
aBuilder.PopClip();
}
// Reduce the inner rect by the width of the icon, and leave an
// additional ICON_PADDING pixels for padding
int32_t paddedIconSize =
nsPresContext::CSSPixelsToAppUnits(ICON_SIZE + ICON_PADDING);
if (wm.IsVertical()) {
inner.y += paddedIconSize;
inner.height -= paddedIconSize;
} else {
if (!flushRight) {
inner.x += paddedIconSize;
}
inner.width -= paddedIconSize;
}
}
// Draw text
if (!inner.IsEmpty()) {
RefPtr<TextDrawTarget> textDrawer =
new TextDrawTarget(aBuilder, aResources, aSc, aManager, aItem, inner,
/* aCallerDoesSaveRestore = */ true);
RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
nsAutoString altText;
nsCSSFrameConstructor::GetAlternateTextFor(
mContent->AsElement(), mContent->NodeInfo()->NameAtom(), altText);
DisplayAltText(PresContext(), *captureCtx.get(), altText, inner);
textDrawer->TerminateShadows();
textDrawResult = !textDrawer->CheckHasUnsupportedFeatures();
}
// Purposely ignore local DrawResult because we handled it not being success
// already.
return textDrawResult ? ImgDrawResult::SUCCESS : ImgDrawResult::NOT_READY;
}
#ifdef DEBUG
static void PaintDebugImageMap(nsIFrame* aFrame, DrawTarget* aDrawTarget,
const nsRect& aDirtyRect, nsPoint aPt) {
@ -1716,7 +1952,7 @@ bool nsDisplayImage::CreateWebRenderCommands(
// help us. Hence we can ignore the return value from PushImage.
if (container) {
aManager->CommandBuilder().PushImage(this, container, aBuilder, aResources,
aSc, destRect);
aSc, destRect, destRect);
}
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, drawResult);

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

@ -150,6 +150,13 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
const nsRect& aDirtyRect, nsPoint aPt,
uint32_t aFlags);
ImgDrawResult DisplayAltFeedbackWithoutLayer(
nsDisplayItem* aItem, mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder, nsPoint aPt, uint32_t aFlags);
nsRect GetInnerArea() const;
/**

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

@ -1340,7 +1340,7 @@ bool nsPluginFrame::CreateWebRenderCommands(
// help us. Hence we can ignore the return value from PushImage.
LayoutDeviceRect dest(r.x, r.y, size.width, size.height);
aManager->CommandBuilder().PushImage(aItem, container, aBuilder, aResources,
aSc, dest);
aSc, dest, dest);
return true;
}

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

@ -499,7 +499,7 @@ class nsDisplayVideo : public nsDisplayItem {
LayoutDeviceRect rect(destGFXRect.x, destGFXRect.y, destGFXRect.width,
destGFXRect.height);
aManager->CommandBuilder().PushImage(this, container, aBuilder, aResources,
aSc, rect);
aSc, rect, rect);
return true;
}

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

@ -670,12 +670,28 @@ ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorder(
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
const nsStyleBorder* styleBorder = aForFrame->Style()->StyleBorder();
return nsCSSRendering::CreateWebRenderCommandsForBorderWithStyleBorder(
aItem, aForFrame, aBorderArea, aBuilder, aResources, aSc, aManager,
aDisplayListBuilder, *styleBorder);
}
ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorderWithStyleBorder(
nsDisplayItem* aItem, nsIFrame* aForFrame, const nsRect& aBorderArea,
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder,
const nsStyleBorder& aStyleBorder) {
// First try to draw a normal border
{
bool borderIsEmpty = false;
Maybe<nsCSSBorderRenderer> br = nsCSSRendering::CreateBorderRenderer(
aForFrame->PresContext(), nullptr, aForFrame, nsRect(), aBorderArea,
aForFrame->Style(), &borderIsEmpty, aForFrame->GetSkipSides());
Maybe<nsCSSBorderRenderer> br =
nsCSSRendering::CreateBorderRendererWithStyleBorder(
aForFrame->PresContext(), nullptr, aForFrame, nsRect(), aBorderArea,
aStyleBorder, aForFrame->Style(), &borderIsEmpty,
aForFrame->GetSkipSides());
if (borderIsEmpty) {
return ImgDrawResult::SUCCESS;
}
@ -687,8 +703,7 @@ ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorder(
}
// Next try to draw an image border
const nsStyleBorder* styleBorder = aForFrame->Style()->StyleBorder();
const nsStyleImage* image = &styleBorder->mBorderImageSource;
const nsStyleImage* image = &aStyleBorder.mBorderImageSource;
// Filter out unsupported image/border types
if (!image) {
@ -704,10 +719,10 @@ ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorder(
return ImgDrawResult::NOT_SUPPORTED;
}
if (styleBorder->mBorderImageRepeatH == StyleBorderImageRepeat::Round ||
styleBorder->mBorderImageRepeatH == StyleBorderImageRepeat::Space ||
styleBorder->mBorderImageRepeatV == StyleBorderImageRepeat::Round ||
styleBorder->mBorderImageRepeatV == StyleBorderImageRepeat::Space) {
if (aStyleBorder.mBorderImageRepeatH == StyleBorderImageRepeat::Round ||
aStyleBorder.mBorderImageRepeatH == StyleBorderImageRepeat::Space ||
aStyleBorder.mBorderImageRepeatV == StyleBorderImageRepeat::Round ||
aStyleBorder.mBorderImageRepeatV == StyleBorderImageRepeat::Space) {
return ImgDrawResult::NOT_SUPPORTED;
}
@ -719,7 +734,7 @@ ImgDrawResult nsCSSRendering::CreateWebRenderCommandsForBorder(
image::ImgDrawResult result;
Maybe<nsCSSBorderImageRenderer> bir =
nsCSSBorderImageRenderer::CreateBorderImageRenderer(
aForFrame->PresContext(), aForFrame, aBorderArea, *styleBorder,
aForFrame->PresContext(), aForFrame, aBorderArea, aStyleBorder,
aItem->GetPaintRect(), aForFrame->GetSkipSides(), flags, &result);
if (!bir) {

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

@ -205,6 +205,15 @@ struct nsCSSRendering {
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder);
static ImgDrawResult CreateWebRenderCommandsForBorderWithStyleBorder(
nsDisplayItem* aItem, nsIFrame* aForFrame, const nsRect& aBorderArea,
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder,
const nsStyleBorder& aStyleBorder);
/**
* Render the outline for an element using css rendering rules
* for borders.

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

@ -141,6 +141,7 @@ nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
mBomState(eBomState::BOM_SNIFFING_NOT_STARTED),
mCharsetSource(kCharsetUninitialized),
mEncoding(WINDOWS_1252_ENCODING),
mFeedChardetIfEncoding(nullptr),
mReparseForbidden(false),
mLastBuffer(nullptr), // Will be filled when starting
mExecutor(aExecutor),
@ -165,7 +166,6 @@ nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
mEventTarget(nsHtml5Module::GetStreamParserThread()->SerialEventTarget()),
mExecutorFlusher(new nsHtml5ExecutorFlusher(aExecutor)),
mLoadFlusher(new nsHtml5LoadFlusher(aExecutor)),
mFeedChardet(false),
mInitialEncodingWasFromParentFrame(false),
mHasHadErrors(false),
mDecodingLocalFileAsUTF8(false),
@ -198,16 +198,16 @@ nsHtml5StreamParser::nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor,
// We recognize one of the three magic strings for the following languages.
if (detectorName.EqualsLiteral("ruprob")) {
mChardet = new nsRUProbDetector();
mFeedChardetIfEncoding = WINDOWS_1251_ENCODING;
} else if (detectorName.EqualsLiteral("ukprob")) {
mChardet = new nsUKProbDetector();
mFeedChardetIfEncoding = WINDOWS_1251_ENCODING;
} else if (detectorName.EqualsLiteral("ja_parallel_state_machine")) {
mChardet = new nsJAPSMDetector();
} else {
mChardet = nullptr;
mFeedChardetIfEncoding = SHIFT_JIS_ENCODING;
}
if (mChardet) {
(void)mChardet->Init(this);
mFeedChardet = true;
}
}
@ -248,7 +248,7 @@ NS_IMETHODIMP
nsHtml5StreamParser::Notify(const char* aCharset, nsDetectionConfident aConf) {
NS_ASSERTION(IsParserThread(), "Wrong thread!");
if (aConf == eBestAnswer || aConf == eSureAnswer) {
mFeedChardet = false; // just in case
mFeedChardetIfEncoding = nullptr; // just in case
auto encoding =
Encoding::ForLabelNoReplacement(nsDependentCString(aCharset));
if (!encoding) {
@ -339,7 +339,7 @@ nsresult nsHtml5StreamParser::SetupDecodingFromBom(
mDecodingLocalFileAsUTF8 = false;
mUnicodeDecoder = mEncoding->NewDecoderWithoutBOMHandling();
mCharsetSource = kCharsetFromByteOrderMark;
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource);
mSniffingBuffer = nullptr;
mMetaScanner = nullptr;
@ -397,7 +397,7 @@ void nsHtml5StreamParser::SniffBOMlessUTF16BasicLatin(
}
mCharsetSource = kCharsetFromIrreversibleAutoDetection;
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource);
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
mTreeBuilder->MaybeComplainAboutCharset("EncBomlessUtf16", true, 0);
}
@ -533,7 +533,7 @@ nsresult nsHtml5StreamParser::FinalizeSniffing(Span<const uint8_t> aFromSegment,
// meta scan failed.
if (mCharsetSource >= kCharsetFromHintPrevDoc) {
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
return SetupDecodingAndWriteSniffingBufferAndCurrentSegment(aFromSegment);
}
// Check for BOMless UTF-16 with Basic
@ -541,16 +541,18 @@ nsresult nsHtml5StreamParser::FinalizeSniffing(Span<const uint8_t> aFromSegment,
SniffBOMlessUTF16BasicLatin(aFromSegment.To(aCountToSniffingLimit));
// the charset may have been set now
// maybe try chardet now;
if (mFeedChardet && !mDecodingLocalFileAsUTF8) {
if ((mFeedChardetIfEncoding == mEncoding) && !mDecodingLocalFileAsUTF8) {
bool dontFeed;
nsresult rv;
if (mSniffingBuffer) {
rv = mChardet->DoIt((const char*)mSniffingBuffer.get(), mSniffingLength,
&dontFeed);
mFeedChardet = !dontFeed;
if (dontFeed) {
mFeedChardetIfEncoding = nullptr;
}
NS_ENSURE_SUCCESS(rv, rv);
}
if (mFeedChardet && !aFromSegment.IsEmpty()) {
if ((mFeedChardetIfEncoding == mEncoding) && !aFromSegment.IsEmpty()) {
rv = mChardet->DoIt(
(const char*)aFromSegment.Elements(),
// Avoid buffer boundary-dependent behavior when
@ -561,14 +563,16 @@ nsresult nsHtml5StreamParser::FinalizeSniffing(Span<const uint8_t> aFromSegment,
// once or twice. :-(
mReparseForbidden ? aCountToSniffingLimit : aFromSegment.Length(),
&dontFeed);
mFeedChardet = !dontFeed;
if (dontFeed) {
mFeedChardetIfEncoding = nullptr;
}
NS_ENSURE_SUCCESS(rv, rv);
}
if (mFeedChardet && (aEof || mReparseForbidden)) {
if ((mFeedChardetIfEncoding == mEncoding) && (aEof || mReparseForbidden)) {
// mReparseForbidden is checked so that we get to use the sniffing
// buffer with the best guess so far if we aren't allowed to guess
// better later.
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
rv = mChardet->Done();
NS_ENSURE_SUCCESS(rv, rv);
}
@ -581,7 +585,7 @@ nsresult nsHtml5StreamParser::FinalizeSniffing(Span<const uint8_t> aFromSegment,
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource);
} else if (mMode == LOAD_AS_DATA && mCharsetSource == kCharsetFromFallback) {
NS_ASSERTION(mReparseForbidden, "Reparse should be forbidden for XHR");
NS_ASSERTION(!mFeedChardet, "Should not feed chardet for XHR");
NS_ASSERTION(!mFeedChardetIfEncoding, "Should not feed chardet for XHR");
NS_ASSERTION(mEncoding == UTF_8_ENCODING, "XHR should default to UTF-8");
// Now mark charset source as non-weak to signal that we have a decision
mCharsetSource = kCharsetFromDocTypeDefault;
@ -668,7 +672,7 @@ nsresult nsHtml5StreamParser::SniffStreamBytes(
// earlier call to SetDocumentCharset(), since we didn't find a BOM and
// overwrite mEncoding. (Note that if the user has overridden the charset,
// we don't come here but check <meta> for XSS-dangerous charsets first.)
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource);
return SetupDecodingAndWriteSniffingBufferAndCurrentSegment(aFromSegment);
}
@ -707,7 +711,7 @@ nsresult nsHtml5StreamParser::SniffStreamBytes(
}
mEncoding = WrapNotNull(encoding);
mCharsetSource = kCharsetFromMetaPrescan;
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource);
return SetupDecodingAndWriteSniffingBufferAndCurrentSegment(
aFromSegment);
@ -744,7 +748,7 @@ nsresult nsHtml5StreamParser::SniffStreamBytes(
}
mEncoding = WrapNotNull(encoding);
mCharsetSource = kCharsetFromMetaPrescan;
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource);
return SetupDecodingAndWriteSniffingBufferAndCurrentSegment(aFromSegment);
}
@ -841,7 +845,7 @@ void nsHtml5StreamParser::CommitLocalFileToUTF8()
{
MOZ_ASSERT(mDecodingLocalFileAsUTF8);
mDecodingLocalFileAsUTF8 = false;
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
mEncoding = UTF_8_ENCODING;
mCharsetSource = kCharsetFromFileURLGuess;
mTreeBuilder->SetDocumentCharset(mEncoding, mCharsetSource);
@ -987,7 +991,7 @@ nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest,
// This is the old Gecko behavior but the HTML5 spec disagrees.
// Don't reparse on POST.
mReparseForbidden = true;
mFeedChardet = false; // can't restart anyway
mFeedChardetIfEncoding = nullptr; // can't restart anyway
}
}
@ -1019,7 +1023,7 @@ nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest,
}
if (mCharsetSource >= kCharsetFromAutoDetection) {
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
}
nsCOMPtr<nsIWyciwygChannel> wyciwygChannel(do_QueryInterface(mRequest));
@ -1033,7 +1037,7 @@ nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest,
// a browsing context. In the latter case, there's no need to remove the
// BOM manually here, because the UTF-8 decoder removes it.
mReparseForbidden = true;
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
// Instantiate the converter here to avoid BOM sniffing.
mDecodingLocalFileAsUTF8 = false;
@ -1073,7 +1077,7 @@ void nsHtml5StreamParser::DoStopRequest() {
return;
}
}
if (mFeedChardet && !mDecodingLocalFileAsUTF8) {
if ((mFeedChardetIfEncoding == mEncoding) && !mDecodingLocalFileAsUTF8) {
mChardet->Done();
}
@ -1231,10 +1235,12 @@ void nsHtml5StreamParser::DoDataAvailable(Span<const uint8_t> aBuffer) {
nsresult rv;
if (HasDecoder()) {
if (mFeedChardet && !mDecodingLocalFileAsUTF8) {
if ((mFeedChardetIfEncoding == mEncoding) && !mDecodingLocalFileAsUTF8) {
bool dontFeed;
mChardet->DoIt((const char*)aBuffer.Elements(), aBuffer.Length(), &dontFeed);
mFeedChardet = !dontFeed;
if (dontFeed) {
mFeedChardetIfEncoding = nullptr;
}
}
rv = WriteStreamBytes(aBuffer);
} else {
@ -1393,7 +1399,7 @@ const Encoding* nsHtml5StreamParser::PreferredForInternalEncodingDecl(
}
}
mCharsetSource = kCharsetFromMetaTag; // become confident
mFeedChardet = false; // don't feed chardet when confident
mFeedChardetIfEncoding = nullptr; // don't feed chardet when confident
return nullptr;
}
@ -1432,7 +1438,7 @@ bool nsHtml5StreamParser::internalEncodingDeclaration(nsHtml5String aEncoding) {
// Avoid having the chardet ask for another restart after this restart
// request.
mFeedChardet = false;
mFeedChardetIfEncoding = nullptr;
mTreeBuilder->NeedsCharsetSwitchTo(WrapNotNull(encoding), kCharsetFromMetaTag,
mTokenizer->getLineNumber());
FlushTreeOpsAndDisarmTimer();

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

@ -412,6 +412,11 @@ class nsHtml5StreamParser final : public nsICharsetDetectionObserver {
*/
NotNull<const Encoding*> mEncoding;
/**
* The character encoding that is the base expectation for detection.
*/
const Encoding* mFeedChardetIfEncoding;
/**
* Whether reparse is forbidden
*/
@ -530,11 +535,6 @@ class nsHtml5StreamParser final : public nsICharsetDetectionObserver {
*/
nsCOMPtr<nsICharsetDetector> mChardet;
/**
* If false, don't push data to chardet.
*/
bool mFeedChardet;
/**
* Whether the initial charset source was kCharsetFromParentFrame
*/

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

@ -1035,9 +1035,7 @@ element.getContainer = function(el) {
return element.findClosest(el, "datalist,select") || el;
}
// Child nodes of button will not be part of the element tree for
// elementsFromPoint until bug 1089326 is fixed.
return element.findClosest(el, "button") || el;
return el;
};
/**

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

@ -1,4 +1,2 @@
[ecdh_keys.https.any.html]
expected: TIMEOUT
[ecdh_keys.https.any.worker.html]

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

@ -4865,11 +4865,3 @@
[Derived key of type name: AES-CTR length: 128 using empty derivedKey, normal salt, SHA-256, with empty info with missing deriveKey usage]
expected: FAIL
[hkdf.https.any.worker.html?2001-3000]
[hkdf.https.any.worker.html?3001-last]
[hkdf.https.any.worker.html?1001-2000]
[hkdf.https.any.worker.html?1-1000]

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

@ -6,7 +6,5 @@
expected: FAIL
[Test that the child iframe navigation is not allowed]
expected:
if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): NOTRUN
FAIL
expected: FAIL

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

@ -1,2 +0,0 @@
[adopted-callback.html]
expected: ERROR

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

@ -1,5 +1,4 @@
[parser-uses-registry-of-owner-document.html]
expected: ERROR
[HTML parser must use the registry of window.document in a document created by document.implementation.createHTMLDocument()]
expected: FAIL

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

@ -1,7 +0,0 @@
[Attr.html]
[value on Attr must not enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL
[value on Attr must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL

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

@ -1,91 +0,0 @@
[CSSStyleDeclaration.html]
[A dashed property (border-width) on CSSStyleDeclaration must enqueue an attributeChanged reaction when it adds the observed style attribute]
expected: FAIL
[cssText on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it mutates the style attribute but the style attribute is not observed]
expected: FAIL
[setProperty on CSSStyleDeclaration must enqueue an attributeChanged reaction when it mutates the observed style attribute]
expected: FAIL
[A webkit prefixed dashed property (-webkit-filter) on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it mutates the style attribute but the style attribute is not observed]
expected: FAIL
[cssFloat on CSSStyleDeclaration must enqueue an attributeChanged reaction when it adds the observed style attribute]
expected: FAIL
[cssText on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed]
expected: FAIL
[A camel case attribute (borderWidth) on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it mutates the style attribute but the style attribute is not observed]
expected: FAIL
[cssFloat on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed]
expected: FAIL
[A webkit prefixed dashed property (-webkit-filter) on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed]
expected: FAIL
[setProperty on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed]
expected: FAIL
[setProperty on CSSStyleDeclaration must enqueue an attributeChanged reaction when it makes a property important but the style attribute is not observed]
expected: FAIL
[setProperty on CSSStyleDeclaration must enqueue an attributeChanged reaction when it makes a property important and the style attribute is observed]
expected: FAIL
[A webkit prefixed dashed property (-webkit-filter) on CSSStyleDeclaration must enqueue an attributeChanged reaction when it adds the observed style attribute]
expected: FAIL
[A webkit prefixed dashed property (-webkit-filter) on CSSStyleDeclaration must enqueue an attributeChanged reaction when it mutates the observed style attribute]
expected: FAIL
[A dashed property (border-width) on CSSStyleDeclaration must enqueue an attributeChanged reaction when it mutates the observed style attribute]
expected: FAIL
[A camel case attribute (borderWidth) on CSSStyleDeclaration must enqueue an attributeChanged reaction when it adds the observed style attribute]
expected: FAIL
[setProperty on CSSStyleDeclaration must enqueue an attributeChanged reaction when it adds the observed style attribute]
expected: FAIL
[A webkit prefixed camel case attribute (webkitFilter) on CSSStyleDeclaration must enqueue an attributeChanged reaction when it adds the observed style attribute]
expected: FAIL
[A webkit prefixed camel case attribute (webkitFilter) on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it mutates the style attribute but the style attribute is not observed]
expected: FAIL
[removeProperty on CSSStyleDeclaration must enqueue an attributeChanged reaction when it removes a property from the observed style attribute]
expected: FAIL
[cssText on CSSStyleDeclaration must enqueue an attributeChanged reaction when it mutates the observed style attribute]
expected: FAIL
[A camel case attribute (borderWidth) on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed]
expected: FAIL
[A dashed property (border-width) on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed]
expected: FAIL
[A webkit prefixed camel case attribute (webkitFilter) on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed]
expected: FAIL
[A webkit prefixed camel case attribute (webkitFilter) on CSSStyleDeclaration must enqueue an attributeChanged reaction when it mutates the observed style attribute]
expected: FAIL
[setProperty on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it mutates the style attribute but the style attribute is not observed]
expected: FAIL
[cssText on CSSStyleDeclaration must enqueue an attributeChanged reaction when it adds the observed style attribute]
expected: FAIL
[removeProperty on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it removes a property from the style attribute but the style attribute is not observed]
expected: FAIL
[A camel case attribute (borderWidth) on CSSStyleDeclaration must enqueue an attributeChanged reaction when it mutates the observed style attribute]
expected: FAIL
[A dashed property (border-width) on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it mutates the style attribute but the style attribute is not observed]
expected: FAIL

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

@ -1,22 +0,0 @@
[ChildNode.html]
[before on ChildNode must enqueue a connected reaction]
expected: FAIL
[replaceWith on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[before on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[after on ChildNode must enqueue a connected reaction]
expected: FAIL
[remove on ChildNode must enqueue a disconnected reaction]
expected: FAIL
[replaceWith on ChildNode must enqueue a connected reaction]
expected: FAIL
[after on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL

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

@ -1,25 +0,0 @@
[DOMStringMap.html]
[deleter on DOMStringMap must enqueue an attributeChanged reaction when removing an observed data attribute]
expected: FAIL
[deleter on DOMStringMap must not enqueue an attributeChanged reaction when removing an unobserved data attribute]
expected: FAIL
[setter on DOMStringMap must not enqueue an attributeChanged reaction when mutating the value of an unobserved data attribute]
expected: FAIL
[setter on DOMStringMap must enqueue an attributeChanged reaction when adding an observed data attribute]
expected: FAIL
[setter on DOMStringMap must not enqueue an attributeChanged reaction when adding an unobserved data attribute]
expected: FAIL
[setter on DOMStringMap must enqueue an attributeChanged reaction when mutating the value of an observed data attribute to the same value]
expected: FAIL
[deleter on DOMStringMap must not enqueue an attributeChanged reaction when it does not remove a data attribute]
expected: FAIL
[setter on DOMStringMap must enqueue an attributeChanged reaction when mutating the value of an observed data attribute]
expected: FAIL

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

@ -1,58 +0,0 @@
[DOMTokenList.html]
[add on DOMTokenList must not enqueue an attributeChanged reaction when adding an unobserved attribute]
expected: FAIL
[replace on DOMTokenList must not enqueue an attributeChanged reaction when the token to replace does not exist in the attribute]
expected: FAIL
[replace on DOMTokenList must not enqueue an attributeChanged reaction when replacing a value in an unobserved attribute]
expected: FAIL
[toggle on DOMTokenList must enqueue an attributeChanged reaction when removing a value from an attribute]
expected: FAIL
[add on DOMTokenList must not enqueue an attributeChanged reaction when adding a value to an unobserved attribute]
expected: FAIL
[add on DOMTokenList must enqueue exactly one attributeChanged reaction when adding multiple values to an attribute]
expected: FAIL
[remove on DOMTokenList must enqueue an attributeChanged reaction when removing a value from an attribute]
expected: FAIL
[the stringifier of DOMTokenList must not enqueue an attributeChanged reaction when adding an unobserved attribute]
expected: FAIL
[the stringifier of DOMTokenList must enqueue an attributeChanged reaction when the setter is called with the original value of the attribute]
expected: FAIL
[toggle on DOMTokenList must enqueue an attributeChanged reaction when adding a value to an attribute]
expected: FAIL
[the stringifier of DOMTokenList must enqueue an attributeChanged reaction when adding an observed attribute]
expected: FAIL
[add on DOMTokenList must enqueue an attributeChanged reaction when adding a value to an existing attribute]
expected: FAIL
[remove on DOMTokenList must enqueue an attributeChanged reaction even when removing a non-existent value from an attribute]
expected: FAIL
[remove on DOMTokenList must not enqueue an attributeChanged reaction when removing a value from an unobserved attribute]
expected: FAIL
[remove on DOMTokenList must enqueue exactly one attributeChanged reaction when removing multiple values to an attribute]
expected: FAIL
[the stringifier of DOMTokenList must enqueue an attributeChanged reaction when mutating the value of an observed attribute]
expected: FAIL
[replace on DOMTokenList must enqueue an attributeChanged reaction when replacing a value in an attribute]
expected: FAIL
[add on DOMTokenList must enqueue an attributeChanged reaction when adding an attribute]
expected: FAIL
[the stringifier of DOMTokenList must not enqueue an attributeChanged reaction when mutating the value of an unobserved attribute]
expected: FAIL

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

@ -14,126 +14,3 @@
[undefined must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[className on Element must enqueue an attributeChanged reaction when adding class content attribute]
expected: FAIL
[id on Element must enqueue an attributeChanged reaction when adding id content attribute]
expected: FAIL
[removeAttributeNS on Element must not enqueue an attributeChanged reaction when removing an unobserved attribute]
expected: FAIL
[setAttributeNode on Element must not enqueue an attributeChanged reaction when adding an unobserved attribute]
expected: FAIL
[slot on Element must enqueue an attributeChanged reaction when adding slot content attribute]
expected: FAIL
[insertAdjacentHTML on Element must enqueue a attributeChanged reaction for a newly constructed custom element]
expected: FAIL
[removeAttribute on Element must enqueue an attributeChanged reaction when removing an existing attribute]
expected: FAIL
[setAttributeNodeNS on Element must not enqueue an attributeChanged reaction when adding an unobserved attribute]
expected: FAIL
[removeAttribute on Element must not enqueue an attributeChanged reaction when removing an existing unobserved attribute]
expected: FAIL
[id on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[insertAdjacentHTML on Element must enqueue a connected reaction for a newly constructed custom element]
expected: FAIL
[removeAttributeNode on Element must not enqueue an attributeChanged reaction when removing an unobserved attribute]
expected: FAIL
[removeAttributeNode on Element must enqueue an attributeChanged reaction when removing an existing attribute]
expected: FAIL
[slot on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[outerHTML on Element must enqueue a attributeChanged reaction for a newly constructed custom element]
expected: FAIL
[innerHTML on Element must enqueue a disconnected reaction]
expected: FAIL
[setAttributeNS on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[setAttribute on Element must not enqueue an attributeChanged reaction when adding an unobserved attribute]
expected: FAIL
[outerHTML on Element must enqueue a disconnected reaction]
expected: FAIL
[removeAttributeNode on Element must not enqueue an attributeChanged reaction when removing an existing unobserved attribute]
expected: FAIL
[outerHTML on Element must enqueue a connected reaction for a newly constructed custom element]
expected: FAIL
[innerHTML on Element must enqueue a attributeChanged reaction for a newly constructed custom element]
expected: FAIL
[setAttribute on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[setAttributeNode on Element must enqueue an attributeChanged reaction when adding an attribute]
expected: FAIL
[setAttributeNodeNS on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[insertAdjacentElement on Element must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[removeAttribute on Element must not enqueue an attributeChanged reaction when removing an unobserved attribute]
expected: FAIL
[setAttributeNodeNS on Element must enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL
[className on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[removeAttributeNS on Element must enqueue an attributeChanged reaction when removing an existing attribute]
expected: FAIL
[innerHTML on Element must enqueue a connected reaction for a newly constructed custom element]
expected: FAIL
[setAttributeNodeNS on Element must enqueue an attributeChanged reaction when adding an attribute]
expected: FAIL
[removeAttributeNS on Element must not enqueue an attributeChanged reaction when removing an existing unobserved attribute]
expected: FAIL
[insertAdjacentElement on Element must enqueue a connected reaction]
expected: FAIL
[setAttributeNode on Element must enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL
[setAttribute on Element must enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL
[setAttributeNS on Element must enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL
[setAttribute on Element must enqueue an attributeChanged reaction when adding an attribute]
expected: FAIL
[setAttributeNode on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[setAttributeNS on Element must not enqueue an attributeChanged reaction when adding an unobserved attribute]
expected: FAIL
[setAttributeNS on Element must enqueue an attributeChanged reaction when adding an attribute]
expected: FAIL

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

@ -1,7 +0,0 @@
[ElementContentEditable.html]
[contentEditable on ElementContentEditable must enqueue an attributeChanged reaction when adding contenteditable content attribute]
expected: FAIL
[contentEditable on ElementContentEditable must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL

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

@ -17,45 +17,3 @@
[formNoValidate on HTMLButtonElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[formMethod on HTMLButtonElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[formMethod on HTMLButtonElement must enqueue an attributeChanged reaction when adding a new attribute]
expected: FAIL
[formEnctype on HTMLButtonElement must enqueue an attributeChanged reaction when adding a new attribute]
expected: FAIL
[formAction on HTMLButtonElement must enqueue an attributeChanged reaction when adding a new attribute]
expected: FAIL
[value on HTMLButtonElement must enqueue an attributeChanged reaction when adding value content attribute]
expected: FAIL
[type on HTMLButtonElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[formTarget on HTMLButtonElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[formTarget on HTMLButtonElement must enqueue an attributeChanged reaction when adding a new attribute]
expected: FAIL
[formAction on HTMLButtonElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[name on HTMLButtonElement must enqueue an attributeChanged reaction when adding name content attribute]
expected: FAIL
[value on HTMLButtonElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[formEnctype on HTMLButtonElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[name on HTMLButtonElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[type on HTMLButtonElement must enqueue an attributeChanged reaction when adding a new attribute]
expected: FAIL

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

@ -17,54 +17,3 @@
[contextMenu on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[hidden on HTMLElement must enqueue an attributeChanged reaction when adding hidden content attribute]
expected: FAIL
[hidden on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[tabIndex on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[draggable on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[accessKey on HTMLElement must enqueue an attributeChanged reaction when adding accesskey content attribute]
expected: FAIL
[spellcheck on HTMLElement must enqueue an attributeChanged reaction when adding spellcheck content attribute]
expected: FAIL
[lang on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[accessKey on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[draggable on HTMLElement must enqueue an attributeChanged reaction when adding draggable content attribute]
expected: FAIL
[innerText on HTMLElement must enqueue a disconnected reaction]
expected: FAIL
[title on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[spellcheck on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[lang on HTMLElement must enqueue an attributeChanged reaction when adding lang content attribute]
expected: FAIL
[dir on HTMLElement must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[title on HTMLElement must enqueue an attributeChanged reaction when adding title content attribute]
expected: FAIL
[tabIndex on HTMLElement must enqueue an attributeChanged reaction when adding tabindex content attribute]
expected: FAIL
[dir on HTMLElement must enqueue an attributeChanged reaction when adding dir content attribute]
expected: FAIL

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

@ -1,43 +0,0 @@
[NamedNodeMap.html]
[removeNamedItem on NamedNodeMap must not enqueue an attributeChanged reaction when removing an existing unobserved attribute]
expected: FAIL
[removeNamedItemNS on NamedNodeMap must enqueue an attributeChanged reaction when removing an existing attribute]
expected: FAIL
[setNamedItemNS on NamedNodeMap must enqueue an attributeChanged reaction when adding an attribute]
expected: FAIL
[removeNamedItem on NamedNodeMap must enqueue an attributeChanged reaction when removing an existing attribute]
expected: FAIL
[setNamedItemNS on NamedNodeMap must enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL
[removeNamedItemNS on NamedNodeMap must not enqueue an attributeChanged reaction when removing an unobserved attribute]
expected: FAIL
[setNamedItem on NamedNodeMap must enqueue an attributeChanged reaction when adding an attribute]
expected: FAIL
[setNamedItem on NamedNodeMap must not enqueue an attributeChanged reaction when adding an unobserved attribute]
expected: FAIL
[removeNamedItem on NamedNodeMap must not enqueue an attributeChanged reaction when removing an unobserved attribute]
expected: FAIL
[setNamedItemNS on NamedNodeMap must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[setNamedItem on NamedNodeMap must enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL
[removeNamedItemNS on NamedNodeMap must not enqueue an attributeChanged reaction when removing an existing unobserved attribute]
expected: FAIL
[setNamedItemNS on NamedNodeMap must not enqueue an attributeChanged reaction when adding an unobserved attribute]
expected: FAIL
[setNamedItem on NamedNodeMap must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL

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

@ -1,43 +0,0 @@
[Node.html]
[removeChild on ChildNode must enqueue a disconnected reaction]
expected: FAIL
[cloneNode on Node must enqueue an attributeChanged reaction when cloning an element with an observed attribute]
expected: FAIL
[replaceChild on ChildNode must enqueue a connected reaction]
expected: FAIL
[nodeValue on Node must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[cloneNode on Node must not enqueue an attributeChanged reaction when cloning an element with an unobserved attribute]
expected: FAIL
[cloneNode on Node must enqueue an attributeChanged reaction when cloning an element only for observed attributes]
expected: FAIL
[appendChild on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[insertBefore on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[insertBefore on ChildNode must enqueue a connected reaction]
expected: FAIL
[appendChild on ChildNode must enqueue a connected reaction]
expected: FAIL
[textContent on Node must not enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL
[textContent on Node must enqueue an attributeChanged reaction when replacing an existing attribute]
expected: FAIL
[replaceChild on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[nodeValue on Node must not enqueue an attributeChanged reaction when replacing an existing unobserved attribute]
expected: FAIL

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

@ -1,13 +0,0 @@
[ParentNode.html]
[prepend on ParentNode must enqueue a connected reaction]
expected: FAIL
[prepend on ParentNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[append on ParentNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[append on ParentNode must enqueue a connected reaction]
expected: FAIL

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

@ -1,31 +0,0 @@
[Range.html]
[cloneContents on Range must enqueue an attributeChanged reaction when cloning an element only for observed attributes]
expected: FAIL
[cloneContents on Range must not enqueue an attributeChanged reaction when cloning an element with an unobserved attribute]
expected: FAIL
[deleteContents on Range must enqueue a disconnected reaction]
expected: FAIL
[extractContents on Range must enqueue a disconnected reaction]
expected: FAIL
[insertNode on Range must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[cloneContents on Range must enqueue an attributeChanged reaction when cloning an element with an observed attribute]
expected: FAIL
[surroundContents on Range must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document]
expected: FAIL
[surroundContents on Range must enqueue a connected reaction]
expected: FAIL
[insertNode on Range must enqueue a connected reaction]
expected: FAIL
[createContextualFragment on Range must construct a custom element]
expected: FAIL

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

@ -1,4 +0,0 @@
[Selection.html]
[deleteFromDocument on Selection must enqueue a disconnected reaction]
expected: FAIL

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

@ -0,0 +1,30 @@
[eucjp-decode-x-euc-jp.html?3001-4000]
[eucjp-decode-x-euc-jp.html?2001-3000]
[eucjp-decode-x-euc-jp.html?13001-last]
[eucjp-decode-x-euc-jp.html?10001-11000]
[x-euc-jp decoding]
expected: FAIL
[eucjp-decode-x-euc-jp.html?1001-2000]
[eucjp-decode-x-euc-jp.html?7001-8000]
[eucjp-decode-x-euc-jp.html?12001-13000]
[eucjp-decode-x-euc-jp.html?6001-7000]
[eucjp-decode-x-euc-jp.html?9001-10000]
[eucjp-decode-x-euc-jp.html?11001-12000]
[eucjp-decode-x-euc-jp.html?8001-9000]
[eucjp-decode-x-euc-jp.html?5001-6000]
[eucjp-decode-x-euc-jp.html?1-1000]
[eucjp-decode-x-euc-jp.html?4001-5000]

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

@ -0,0 +1,18 @@
[sjis-encode-form-shift-jis.html?2001-3000]
[sjis-encode-form-shift-jis.html?1-1000]
[sjis-encode-form-shift-jis.html?3001-4000]
[sjis-encode-form-shift-jis.html?5001-6000]
[shift-jis encoding (form)]
expected: FAIL
[sjis-encode-form-shift-jis.html?4001-5000]
[sjis-encode-form-shift-jis.html?6001-7000]
[sjis-encode-form-shift-jis.html?1001-2000]
[sjis-encode-form-shift-jis.html?7001-last]

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

@ -0,0 +1,4 @@
[event-timing-bufferbeforeonload.html]
[Event Timing: click, onload.]
expected: FAIL

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

@ -0,0 +1,4 @@
[event-timing-crossiframe.html]
[Event Timing: entries should only be observable by its own frame.]
expected: FAIL

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

@ -0,0 +1,5 @@
[event-timing-observethenonload.html]
expected: TIMEOUT
[Event Timing: click, observer, onload, click.]
expected: TIMEOUT

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

@ -0,0 +1,5 @@
[event-timing-onloadthenobserve-firstInput.html]
expected: TIMEOUT
[Event Timing: check firstInput after onload, observer, click, click.]
expected: TIMEOUT

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

@ -0,0 +1,5 @@
[event-timing-onloadthenobserve.html]
expected: TIMEOUT
[Event Timing: onload, click, observer, click.]
expected: TIMEOUT

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

@ -0,0 +1,4 @@
[event-timing-only-observe-firstInput.html]
[Event Timing: check firstInput for a PerformanceObserver observing only firstInput.]
expected: FAIL

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

@ -0,0 +1,5 @@
[event-timing-retrievability.html]
expected: ERROR
[Event Timing: make sure event-timing entries are retrievable by existing perf APIs.]
expected: TIMEOUT

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

@ -0,0 +1,5 @@
[event-timing-timingconditions.html]
expected: TIMEOUT
[Event Timing only times certain types of trusted event.]
expected: TIMEOUT

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

@ -1,5 +1,7 @@
[no_window_open_when_term_nesting_level_nonzero.window.html]
expected: ERROR
expected:
if not debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): TIMEOUT
ERROR
[no popups from synchronously reachable window]
expected: FAIL

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

@ -404,13 +404,3 @@
[<meta>: "-0"]
expected: FAIL
[parsing.html?21-30]
[parsing.html?1-10]
[parsing.html?41-50]
[parsing.html?121-130]
[parsing.html?51-60]

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

@ -20,3 +20,6 @@
[Test that decodingInfo returns a valid MediaCapabilitiesDecodingInfo objects with encrypted media]
expected: FAIL
[Test that random key systems are reported as non supported.]
expected: FAIL

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

@ -1,2 +1,2 @@
local: a6a52f144b7e00102574a5fe2b53feaa0d653264
upstream: 7268cc55c89de22afe2823f20aa05b8cab6a66bd
local: 3df33cfe93b1d11a21ac3aacc1e63cae6f44609a
upstream: 25f3222fcba6e642e2edfe4bb29a5793c8109dfc

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

@ -14,3 +14,4 @@
[embed]
expected:
if not e10s: FAIL

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

@ -1,8 +1,2 @@
[idlharness.https.any.serviceworker.html]
expected: TIMEOUT
[idlharness.any.worker.html]
[idlharness.any.sharedworker.html]
[idlharness.any.html]

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

@ -1,2 +1,5 @@
[pointerevent_setpointercapture_inactive_button_mouse.html]
expected: TIMEOUT
[setPointerCapture + inactive button state]
expected: FAIL

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

@ -5,7 +5,3 @@
[WindowOrWorkerGlobalScope interface: self must inherit property "isSecureContext" with the proper type]
expected: FAIL
[idlharness.any.worker.html]
[idlharness.any.sharedworker.html]

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

@ -1,4 +1,3 @@
[unregister-then-register.https.html]
disabled:
if os == "android": https://bugzilla.mozilla.org/show_bug.cgi?id=1499972

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

@ -0,0 +1,19 @@
[shape-inside-valid.svg]
[e.style['shape-inside'\] = "url(\\"https://example.com/\\")" should set the property value]
expected: FAIL
[e.style['shape-inside'\] = "auto" should set the property value]
expected: FAIL
[e.style['shape-inside'\] = "circle(10px at 20px -30px) url(\\"https://example.com/\\") ellipse(10px 20px at -30px 40px)" should set the property value]
expected: FAIL
[e.style['shape-inside'\] = "ellipse(10px 20px at -30px 40px)" should set the property value]
expected: FAIL
[e.style['shape-inside'\] = "circle(10px at 20px -30px)" should set the property value]
expected: FAIL
[e.style['shape-inside'\] = "polygon(10px 20px, -30px 40px, 50px 60px)" should set the property value]
expected: FAIL

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

@ -0,0 +1,19 @@
[shape-subtract-valid.svg]
[e.style['shape-subtract'\] = "circle(10px at 20px -30px)" should set the property value]
expected: FAIL
[e.style['shape-subtract'\] = "polygon(10px 20px, -30px 40px, 50px 60px)" should set the property value]
expected: FAIL
[e.style['shape-subtract'\] = "auto" should set the property value]
expected: FAIL
[e.style['shape-subtract'\] = "circle(10px at 20px -30px) url(\\"https://example.com/\\") ellipse(10px 20px at -30px 40px)" should set the property value]
expected: FAIL
[e.style['shape-subtract'\] = "ellipse(10px 20px at -30px 40px)" should set the property value]
expected: FAIL
[e.style['shape-subtract'\] = "url(\\"https://example.com/\\")" should set the property value]
expected: FAIL

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

@ -0,0 +1,22 @@
[text-decoration-fill-valid.svg]
[e.style['text-decoration-fill'\] = "none" should set the property value]
expected: FAIL
[e.style['text-decoration-fill'\] = "url(\\"https://example.com/\\") none" should set the property value]
expected: FAIL
[e.style['text-decoration-fill'\] = "context-stroke" should set the property value]
expected: FAIL
[e.style['text-decoration-fill'\] = "url(\\"https://example.com/\\")" should set the property value]
expected: FAIL
[e.style['text-decoration-fill'\] = "url(\\"https://example.com/\\") rgb(12, 34, 56)" should set the property value]
expected: FAIL
[e.style['text-decoration-fill'\] = "context-fill" should set the property value]
expected: FAIL
[e.style['text-decoration-fill'\] = "rgb(12, 34, 56)" should set the property value]
expected: FAIL

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

@ -0,0 +1,22 @@
[text-decoration-stroke-valid.svg]
[e.style['text-decoration-stroke'\] = "rgb(12, 34, 56)" should set the property value]
expected: FAIL
[e.style['text-decoration-stroke'\] = "context-fill" should set the property value]
expected: FAIL
[e.style['text-decoration-stroke'\] = "url(\\"https://example.com/\\") none" should set the property value]
expected: FAIL
[e.style['text-decoration-stroke'\] = "none" should set the property value]
expected: FAIL
[e.style['text-decoration-stroke'\] = "context-stroke" should set the property value]
expected: FAIL
[e.style['text-decoration-stroke'\] = "url(\\"https://example.com/\\") rgb(12, 34, 56)" should set the property value]
expected: FAIL
[e.style['text-decoration-stroke'\] = "url(\\"https://example.com/\\")" should set the property value]
expected: FAIL

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

@ -1,8 +1,2 @@
[idlharness.https.any.serviceworker.html]
expected: TIMEOUT
[idlharness.any.sharedworker.html]
[idlharness.any.html]
[idlharness.any.worker.html]

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

@ -0,0 +1,79 @@
[set.py]
[test_invalid_parameters[parameters0\]]
expected: FAIL
[test_invalid_parameters[parameters1\]]
expected: FAIL
[test_invalid_parameters[parameters2\]]
expected: FAIL
[test_invalid_parameters[parameters3\]]
expected: FAIL
[test_invalid_parameters[parameters4\]]
expected: FAIL
[test_invalid_parameters[parameters5\]]
expected: FAIL
[test_invalid_parameters[parameters6\]]
expected: FAIL
[test_invalid_parameters[parameters7\]]
expected: FAIL
[test_non_secure_context[granted\]]
expected: FAIL
[test_non_secure_context[denied\]]
expected: FAIL
[test_non_secure_context[prompt\]]
expected: FAIL
[test_set_to_state[realmSetting0-granted\]]
expected: FAIL
[test_set_to_state[realmSetting0-denied\]]
expected: FAIL
[test_set_to_state[realmSetting0-prompt\]]
expected: FAIL
[test_set_to_state[realmSetting1-granted\]]
expected: FAIL
[test_set_to_state[realmSetting1-denied\]]
expected: FAIL
[test_set_to_state[realmSetting1-prompt\]]
expected: FAIL
[test_set_to_state[realmSetting2-granted\]]
expected: FAIL
[test_set_to_state[realmSetting2-denied\]]
expected: FAIL
[test_set_to_state[realmSetting2-prompt\]]
expected: FAIL
[test_set_to_state_cross_realm[realmSetting0-granted\]]
expected: FAIL
[test_set_to_state_cross_realm[realmSetting0-denied\]]
expected: FAIL
[test_set_to_state_cross_realm[realmSetting0-prompt\]]
expected: FAIL
[test_set_to_state_cross_realm[realmSetting1-granted\]]
expected: FAIL
[test_set_to_state_cross_realm[realmSetting1-denied\]]
expected: FAIL
[test_set_to_state_cross_realm[realmSetting1-prompt\]]
expected: FAIL

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

@ -686,3 +686,72 @@
[XR must be primary interface of navigator.xr]
expected: FAIL
[XRViewerPose interface object length]
expected: FAIL
[XR interface: calling supportsSession(XRSessionCreationOptions) on navigator.xr with too few arguments must throw TypeError]
expected: FAIL
[XRFrame interface: operation getInputPose(XRInputSource, XRFrameOfReference)]
expected: FAIL
[XR interface: operation requestSession(XRSessionCreationOptions)]
expected: FAIL
[XRViewerPose interface: attribute poseMatrix]
expected: FAIL
[XRViewerPose interface object name]
expected: FAIL
[XR interface: navigator.xr must inherit property "requestSession(XRSessionCreationOptions)" with the proper type]
expected: FAIL
[XRFrame interface: operation getViewerPose(XRFrameOfReference)]
expected: FAIL
[XRView interface: attribute viewMatrix]
expected: FAIL
[XRViewerPose interface: existence and properties of interface prototype object]
expected: FAIL
[XR interface: calling requestSession(XRSessionCreationOptions) on navigator.xr with too few arguments must throw TypeError]
expected: FAIL
[XRViewerPose interface: attribute views]
expected: FAIL
[XRViewerPose interface: existence and properties of interface object]
expected: FAIL
[XR interface: navigator.xr must inherit property "supportsSession(XRSessionCreationOptions)" with the proper type]
expected: FAIL
[WebGLRenderingContext interface: operation makeXRCompatible()]
expected: FAIL
[XRViewerPose interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL
[XRViewerPose interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
[XRSession interface: attribute oninputsourceschange]
expected: FAIL
[XR interface: operation supportsSession(XRSessionCreationOptions)]
expected: FAIL
[XR interface: navigator.xr must inherit property "supportsSessionMode(XRSessionMode)" with the proper type]
expected: FAIL
[XR interface: operation supportsSessionMode(XRSessionMode)]
expected: FAIL
[XRSession interface: attribute mode]
expected: FAIL
[XR interface: calling supportsSessionMode(XRSessionMode) on navigator.xr with too few arguments must throw TypeError]
expected: FAIL

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

@ -61,7 +61,7 @@ tasks:
owner: ${event.pusher.email}
source: ${event.repository.url}
payload:
image: harjgam/web-platform-tests:0.22
image: hexcles/web-platform-tests:0.23
maxRunTime: 7200
artifacts:
public/results:
@ -125,7 +125,7 @@ tasks:
owner: ${event.pull_request.user.login}@users.noreply.github.com
source: ${event.repository.url}
payload:
image: harjgam/web-platform-tests:0.22
image: hexcles/web-platform-tests:0.23
maxRunTime: 7200
artifacts:
public/results:

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

@ -8,7 +8,7 @@
<meta name="help" content="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/custom-elements-helpers.js"></script>
<script src="./resources/custom-elements-helpers.js"></script>
</head>
<body>
<div id="log"></div>

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

@ -8,7 +8,7 @@
<meta name="help" content="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/custom-elements-helpers.js"></script>
<script src="./resources/custom-elements-helpers.js"></script>
</head>
<body>
<div id="log"></div>

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

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: buffer long-latency events before onload</title>
<button id='button' onclick='clickDelay()'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-support.js></script>
<img src=resources/slow-image.py>
<script>
let clickTimeMin;
let processingStartMin;
let onloadStart;
let firstClickStart = 0;
let firstClickEnd = 0;
function clickDelay() {
const onclickStart = performance.now();
if (firstClickStart === 0)
firstClickStart = onclickStart;
while(performance.now() < onclickStart + 60) {}
if (firstClickEnd === 0)
firstClickEnd = performance.now();
}
function validateEntries() {
const entries = performance.getEntriesByName('click', 'event');
const entriesBeforeOnload = entries.filter(
e => e.startTime < onloadStart);
assert_equals(entriesBeforeOnload.length, 1,
"Long latency events before onload should be buffered.");
const entry = entriesBeforeOnload[0];
verifyClickEvent(entry, true);
assert_greater_than_equal(entry.startTime, clickTimeMin,
"The entry's start time should be later than clickTimeMin.");
assert_greater_than_equal(entry.processingStart, processingStartMin,
"The entry should be processed later than processingStartMin.");
assert_less_than_equal(entry.processingStart, firstClickStart,
"The processingStart must be before firstClickStart.")
assert_greater_than_equal(entry.processingEnd, firstClickEnd,
"The processingEnd must be after firstClickEnd.");
const entriesAfterOnload = entries.filter(
e => e.startTime >= onloadStart);
assert_equals(entriesAfterOnload.length, 0,
"Events after onload shouldn't be buffered.");
}
/* Timeline:
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 - buffered)
Onload Event Fires
Begin Busy Loop
Click 2 arrives
End Busy Loop
(Dispatch and Process Click 2 - not buffered)
*/
async_test(function(t) {
clickTimeMin = performance.now();
clickAndBlockMain('button');
// Event handlers will be dispatched asynchronously, so this will be called
// before processing begins.
processingStartMin = performance.now();
on_event(window, 'load', e => {
onloadStart = performance.now();
clickAndBlockMain('button').then(wait).then(
t.step_func_done(validateEntries));
});
}, "Event Timing: click, onload.");
</script>
</html>

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

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Event Timing: entries should be observable by its own frame.</title>
</head>
<body>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-support.js></script>
<img src=./resources/slow-image.py>
<iframe src=resources/event-timing-crossiframe-childframe.html></iframe>
<script>
let clickTimeMin;
let processingStartMin;
let onloadStart;
function validateEntries() {
const entries = performance.getEntriesByName('click', 'event');
assert_equals(entries.length, 1,
"Observer of main frames should only capture main-frame event-timing entries."
);
const entry = entries[0];
verifyClickEvent(entry, true);
assert_greater_than(entry.processingStart, processingStartMin,
"The entry's processing start should be later than processingStartMin.");
assert_greater_than(onloadStart, entry.processingStart,
"onload should occur later than the entry's procesisng start.");
assert_greater_than(entry.startTime, clickTimeMin,
"The entry's start time should be later than clickTimeMin.");
assert_greater_than(onloadStart, entry.startTime,
"onload should occur later than the entry's start time.");
}
function validateChildFrameEntries(childFrameData) {
assert_equals(childFrameData.bufferedEntries.length, 1,
"Event Timing of child frames should only capture child-frame event-timing entries."
);
const entry = entries[0];
verifyClickEvent(entry);
assert_greater_than(entry.processingStart, childFrameData.processingStartMin,
"The entry's processing start should be later than the child frame's processingStartMin.");
assert_greater_than(childFrameData.onloadStart, entry.processingStart,
"Child frame's onload should occur later than the entry's processing \
start.");
assert_greater_than(entry.startTime, childFrameData.clickTimeMin,
"The entry's start time should be later than the child frame's \
clickTimeMin.");
assert_greater_than(childFrameData.onloadStart, entry.startTime,
"Child frame's onload should be later than the entry's start time.");
assert_array_equals(childFrameData.observedEntries,
childFrameData.bufferedEntries,
"The child frame's observed entries should be buffered as well.");
}
async_test(function(t) {
clickTimeMin = performance.now();
clickAndBlockMain('button');
processingStartMin = performance.now();
const childFrameEntriesPromise = new Promise((resolve, reject) => {
window.addEventListener("message", (event) => {
resolve(event.data);
}, false);
});
on_event(window, 'load', e => {
onloadStart = performance.now();
childFrameEntriesPromise.then((entries) => {
t.step(() => {
validateChildFrameEntries(entries);
validateEntries();
});
t.done();
});
});
}, "Event Timing: entries should only be observable by its own frame.");
</script>
</body>
</html>

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

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Event Timing: entries should be observable by its own frame.
</title>
<script src=./resources/event-timing-support.js></script>
</head>
<body>
<h2>Description:</h2>
<p>
<div>
The goal of this manual test is to verify that observers that have
registered "event" entry type can observe the long-latency input events,
and verify the same behavior within iframe and in cross-frame scenario.
</div>
</p>
<h2>Manual test steps:</h2>
<p>
<div>
Step 1: Click the "make busy" button to make main-thread busy for 2 seconds.</span>
</div>
<div>
Step 2: do several clicks on "click while busy" while busy to generate long-latency inputs.
</div>
<div>
Step 3: observe in the "timeline" section that the long-latency clicks are captured by the observer.
</div>
<div>
Step 4: do step 1 to step 3 for the iframe. Observe that the observers only observe input events within its frame.
</div>
</p>
<div>
<h2>Actions:</h2>
<button id='busy_button' onclick='onMakeBusy()'>make busy</button>
<button id='click_input_button' onclick='1'> click while busy </button>
</div>
<h2>iframe:</h2>
<div>
<iframe name='childframe' width="100%" height="30%" src=./resources/event-timing-observer-manual-childframe.html></iframe>
</div>
<h2>Timeline:</h2>
<p id='timeline'></p>
</body>
<script>
function log(message) {
const timestamp = performance.now();
const elem = document.createElement('div');
elem.innerHTML = `${timestamp.toFixed(1)}: ${message}`;
const timeline = document.getElementById('timeline');
timeline.appendChild(elem);
}
function onMakeBusy() {
log("busy start");
step_timeout(()=>{
mainThreadBusy(2000);
log("busy end");
}, 0);
}
document.body.onload = () => {
new PerformanceObserver((entryList) => {
entryList.getEntries().forEach(e => {
log(`entry observed: ${JSON.stringify(e)}`);
});
}).observe({ entryTypes: ['event'] });
log("observer registered");
};
window.onmessage = (msg) => {
log("received msg: " + msg.data);
if (msg.data === 'CHILD_FRAME_IS_READY') {
// TODO(crbug/831729): automate clicks on iframe when testdriver support
// clicking in iframe.
}
};
</script>
</html>

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

@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: Performance observers can observe long-latency events
</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-support.js></script>
<img src=resources/slow-image.py>
<script>
let timeBeforeFirstClick;
let timeAfterFirstClick;
let timeAfterSecondClick;
let onloadStart;
let observedEntries = [];
function verifyBuffer(bufferedEntries) {
assert_equals(bufferedEntries.length, 1,
"Only events before onload should be buffered.");
const entry = bufferedEntries[0];
assert_greater_than(onloadStart, entry.startTime,
"Onload should be later than entry's start time.");
assert_greater_than(entry.processingStart, timeBeforeFirstClick,
"The entry's processing start should be after timeBeforeFirstClick");
assert_less_than(entry.processingStart, timeAfterFirstClick,
"The entry's processing start should be before timeAfterFirstClick.");
verifyClickEvent(entry, true);
}
function verifyObserverEntries(observedEntries) {
const entriesAfterFirstClick = observedEntries.filter(
e => e.startTime > timeAfterFirstClick);
assert_equals(entriesAfterFirstClick.length, 1,
'There should be one event after timeAfterFirstClick.');
const entry1 = entriesAfterFirstClick[0];
verifyClickEvent(entry1);
assert_greater_than(entry1.processingStart, timeAfterFirstClick,
"entry1's processing start should be after timeAfterFirstClick");
assert_less_than(entry1.processingStart, timeAfterSecondClick,
"entry1's processing start should be before timeAfterSecondClick.");
assert_greater_than(entry1.startTime, onloadStart,
"entry1's start time should be later than onloadStart.");
const entriesBeforeFirstClick =
observedEntries.filter(e => e.startTime < timeAfterFirstClick);
assert_equals(entriesBeforeFirstClick.length, 1,
'There should be one event before timeAfterFirstClick.'
);
const entry2 = entriesBeforeFirstClick[0];
verifyClickEvent(entry2);
assert_greater_than(entry2.processingStart, timeBeforeFirstClick,
"entry2's processing start should be after timeBeforeFirstClick");
assert_less_than(entry2.processingStart, timeAfterFirstClick,
"entry2's processing start should be berfore timeAfterFirstClick.");
assert_greater_than(timeAfterFirstClick, entry2.startTime,
"timeAfterFirstClick should be later than entry2's start time.");
}
/* Timeline:
Observer starts
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 (buffered, observed))
Onload Event Fires
Begin Busy Loop
Click 2 arrives
End Busy Loop
(Dispatch and Process Click 2 (buffered, observed))
observer callback start
*/
async_test(function(t) {
const observerPromise = new Promise((resolve, reject) => {
new PerformanceObserver(function(entryList) {
observedEntries = observedEntries.concat(entryList.getEntries());
if (observedEntries.length < 2) return;
resolve(observedEntries);
}).observe({ entryTypes: ['event'] });
});
timeBeforeFirstClick = performance.now();
clickAndBlockMain('button').then( () => {
timeAfterFirstClick = performance.now();
});
on_event(window, 'load', function(e) {
onloadStart = performance.now();
// After onload start and before registering observer.
const bufferPromise = clickAndBlockMain('button').then(wait);
Promise.all([observerPromise, bufferPromise]).then((results) => {
timeAfterSecondClick = performance.now();
t.step(verifyObserverEntries.bind(null, results[0]));
t.step(verifyBuffer.bind(null, performance.getEntriesByName('click', 'event')));
t.done();
});
});
}, "Event Timing: click, observer, onload, click.");
</script>
</html>

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

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: buffer long-latency events before onload</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-support.js></script>
<script>
/* Timeline:
Onload
PerformanceObserver is registered
Click 1
Click 2
PerformanceObserver should observe only one firstInput entry.
(Dispatch and Process Click 2 - not buffered)
*/
async_test(function(t) {
let numFirstInputObserved = 0;
let numEventsObserved = 0;
new PerformanceObserver(t.step_func((entryList, obs) => {
const observedEntries = entryList.getEntries();
numEventsObserved += observedEntries.filter(entry =>
entry.entryType == 'event').length;
numFirstInputObserved += observedEntries.filter(entry =>
entry.entryType == 'firstInput').length;
if (numEventsObserved >= 2) {
assert_equals(performance.getEntriesByType('event').length, 0,
"There should be no buffered event entries.");
assert_equals(performance.getEntriesByType('firstInput').length, 0,
"There should be no buffered firstInput entries.");
// There should be 2 event entries and one firstInput entry.
assert_equals(numEventsObserved, 2,
"There should be 2 observed event entries.");
assert_equals(numFirstInputObserved, 1,
"There should be only 1 observed firstInput entry.");
t.done();
}
})).observe({ entryTypes: ['event', 'firstInput'] });
on_event(window, 'load', () => {
clickAndBlockMain('button').then(wait).then(() => {
clickAndBlockMain('button').then(wait);
});
});
},
"Event Timing: check firstInput after onload, observer, click, click."
);
</script>
</html>

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

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: long-latency events after onload and before observer
registration are lost
</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-support.js></script>
<script>
let callbackTime;
let observerStart;
let processingStartMin;
function verifyBufferAndObserverEntries(observedEntries) {
// Verify buffer entries
const bufferedEntries = performance.getEntriesByName('click', 'event');
const bufferedEntriesBeforeObserver = bufferedEntries.filter(e => e.startTime <
observerStart);
assert_equals(bufferedEntries.length, 0,
"Long latency events after onload should not be buffered."
);
// Verify observer entries
assert_equals(observedEntries.length, 1, "Long latency task after observer start should be observed.");
const entry = observedEntries[0];
verifyClickEvent(entry);
assert_greater_than(entry.processingStart, processingStartMin,
"The entry's processing start should be later than processingStartMin.");
assert_greater_than(callbackTime, entry.processingStart,
"The callback time should be later than the entry's processing start.");
assert_greater_than(entry.startTime, observerStart,
"The entry's start time should be later than observer start.");
assert_greater_than(callbackTime, entry.startTime,
"The callback time should be later than entry's start time.");
}
function startObserver(t) {
new PerformanceObserver(t.step_func_done((entryList, obs) => {
callbackTime = performance.now();
const observedEntries = entryList.getEntries();
verifyBufferAndObserverEntries(observedEntries);
})).observe({ entryTypes: ['event'] });
observerStart = performance.now();
}
/* Timeline:
Onload Event fires
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 (not buffered, not observed))
Observer start
Begin Busy Loop
Click 2 arrives
End Busy Loop
(Dispatch and Process Click 2 (not buffered, observed))
*/
async_test(function(t) {
on_event(window, 'load', () => {
clickAndBlockMain('button').then(() => {
startObserver(t);
clickAndBlockMain('button').then(wait);
processingStartMin = performance.now();
});
});
},
"Event Timing: onload, click, observer, click."
);
</script>
</html>

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

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: only observe the first input</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-support.js></script>
<script>
/* Test:
PerformanceObserver for firstInput is registered
Click 1
Click 2
Wait
Expected result:
PerformanceObserver should observe one and only one entry.
*/
async_test(function(t) {
let hasObservedFirstInput = false;
new PerformanceObserver(t.step_func((entryList) => {
assert_false(hasObservedFirstInput);
hasObservedFirstInput = true;
const observedEntries = entryList.getEntries();
assert_equals(observedEntries.length, 1);
assert_equals(observedEntries[0].entryType, 'firstInput');
assert_equals(observedEntries[0].name, 'click');
})).observe({ entryTypes: ['firstInput'] });
on_event(window, 'load', () => {
clickAndBlockMain('button').then(() => {
clickAndBlockMain('button').then(wait).then( () => {
// After some wait, the PerformanceObserver should have processed both clicks.
// One and only one firstInput entry should have been dispatched, so
// |hasObservedFirstInput| should be true.
t.step_timeout( () => {
assert_true(hasObservedFirstInput);
t.done();
}, 10);
});
});
});
},
"Event Timing: check firstInput for a PerformanceObserver observing only firstInput."
);
</script>
</html>

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

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8>
<title>Event Timing: make sure event-timing entries are retrievable by existing perf APIs.</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-support.js></script>
<img src=resources/slow-image.py>
<script>
function validateEntries() {
const entriesByName = performance.getEntriesByName('click', 'event');
const entriesByType = performance.getEntriesByType('event');
const allEntries = performance.getEntries();
assert_equals(entriesByName.length, 1, 'event-timing entry should be retrievable by getEntriesByName');
const e = entriesByName[0];
assert_true(entriesByType.includes(e), 'event-timing entry should be retrievable by getEntries');
assert_true(allEntries.includes(e), 'event-timing entry should be retrievable by getEntriesByType');
}
/* Timeline:
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 - buffered)
Onload Event Fires
Validate entries
*/
async_test(function(t) {
clickAndBlockMain('button');
on_event(window, 'load', e => {
validateEntries();
t.done();
});
}, "Event Timing: make sure event-timing entries are retrievable by existing perf APIs.");
</script>
</html>

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

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing only times certain types of trusted event.
</title>
<button id='button' onclick='mainThreadBusy(60)'
onfocus='mainThreadBusy(60)'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-support.js></script>
<script>
let trustedClickStart;
function trustedClickAndBlockMain(id) {
return new Promise((resolve, reject) => {
trustedClickStart = performance.now();
clickOnElement(id, resolve);
});
}
function untrustedClickAndBlockMain(id) {
const target = document.getElementById(id);
// Block mainthread in the callback, as dispatchEvent() is a sync call.
target.dispatchEvent(new MouseEvent('click'));
}
function trustedFocusAndBlockMain(id) {
const target = document.getElementById(id);
trustedFocusStart = performance.now();
// Block mainthread in the callback, as focus() is a sync call.
target.focus();
}
async_test(function(t) {
new PerformanceObserver(t.step_func_done(entryList => {
const observerCallbackTime = performance.now();
const entries = entryList.getEntries();
assert_equals(entries.length, 1,
"Should only observe one entry: " +
JSON.stringify(entries) + ".");
assert_equals(entries[0].name, 'click',
"The observed entry should be a click");
assert_less_than(entries[0].startTime, observerCallbackTime,
"The startTime should be before observerCallbackTime");
assert_greater_than(entries[0].startTime, trustedClickStart,
"The startTime should be after trustedClickStart");
})).observe({ entryTypes: ['event'] });
// Untrusted event of a type event timing cares about.
untrustedClickAndBlockMain('button');
// Trusted event of a type event timing doesn't cares about.
trustedFocusAndBlockMain('button');
// Trusted event of a type event timing cares about.
trustedClickAndBlockMain('button').then(wait);
}, "Event Timing only times certain types of trusted event.");
</script>
</html>

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

@ -0,0 +1,29 @@
<!DOCType html>
<html>
<script src=event-timing-support.js></script>
<button id='button_child_frame' onclick='2'>Generate a 'click' event</button>
<img src=slow-image.py>
<script>
const clickTimeMin = performance.now();
clickAndBlockMain('button_child_frame');
const processingStartMin = performance.now();
const observerPromise = new Promise((resolve, reject) => {
new PerformanceObserver((entryList) => {
resolve(entryList.getEntries());
}).observe({ entryTypes: ['event'] });
});
window.addEventListener('load', e => {
observerPromise.then((observedEntries) => {
const onloadStart = performance.now();
const bufferedEntries = performance.getEntriesByType('event');
top.postMessage({
"bufferedEntries" : bufferedEntries,
"observedEntries": observedEntries,
"clickTimeMin": clickTimeMin,
"processingStartMin" : processingStartMin,
"onloadStart" : onloadStart,
}, '*');
});
});
</script>
</html>

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

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
</head>
<script src=./event-timing-support.js></script>
<script>
function log(message) {
const timestamp = performance.now();
const elem = document.createElement('div');
elem.innerHTML = `${timestamp.toFixed(1)}: ${message}`;
const timeline = document.getElementById('timeline');
timeline.appendChild(elem);
}
function run() {
new PerformanceObserver((entryList) => {
entryList.getEntries().forEach(e => {
log(`entry observed: ${JSON.stringify(e)}`);
});
}).observe({ entryTypes: ['event'] });
log("observer registered");
top.postMessage('CHILD_FRAME_IS_READY', "*");
}
function onMakeBusy() {
log("busy start");
step_timeout(()=>{
mainThreadBusy(2000);
log("busy end");
}, 0);
}
</script>
<body onload='run()'>
<h3>Actions:</h3>
<p>
<button id='busy_button' onclick='onMakeBusy()'>Make busy</button>
<button id='click_input_button' onclick='1'> click while busy </button>
</p>
<h3>Timeline:</h3>
<p id='timeline'></p>
</body>
</html>

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

@ -0,0 +1,66 @@
// Clicks on the element with the given ID. It adds an event handler to the element
// which ensures that the events have a long duration and reported by EventTiming
// where appropriate. Calls |callback| during event handler.
function clickOnElement(id, callback) {
const element = document.getElementById(id);
const rect = element.getBoundingClientRect();
const xCenter = rect.x + rect.width / 2;
const yCenter = rect.y + rect.height / 2;
const leftButton = 0;
const clickHandler = () => {
mainThreadBusy(60);
if (callback)
callback();
element.removeEventListener("click", clickHandler);
};
element.addEventListener("click", clickHandler);
test_driver.click(element);
}
function mainThreadBusy(duration) {
const now = performance.now();
while (performance.now() < now + duration);
}
// This method should receive an entry of type 'event'. |is_first| is true only
// when the event also happens to correspond to the first event. In this case,
// the timings of the 'firstInput' entry should be equal to those of this entry.
function verifyClickEvent(entry, is_first=false) {
assert_true(entry.cancelable);
assert_equals(entry.name, 'click');
assert_equals(entry.entryType, 'event');
assert_greater_than(entry.duration, 50,
"The entry's duration should be greater than 50ms.");
assert_greater_than(entry.processingStart, entry.startTime,
"The entry's processingStart should be greater than startTime.");
assert_greater_than_equal(entry.processingEnd, entry.processingStart,
"The entry's processingEnd must be at least as large as processingStart.");
assert_greater_than_equal(entry.duration, entry.processingEnd - entry.startTime,
"The entry's duration must be at least as large as processingEnd - startTime.");
if (is_first) {
let firstInputs = performance.getEntriesByType('firstInput');
assert_equals(firstInputs.length, 1, 'There should be a single firstInput entry');
let firstInput = firstInputs[0];
assert_equals(firstInput.name, entry.name);
assert_equals(firstInput.entryType, 'firstInput');
assert_equals(firstInput.startTime, entry.startTime);
assert_equals(firstInput.duration, entry.duration);
assert_equals(firstInput.processingStart, entry.processingStart);
assert_equals(firstInput.processingEnd, entry.processingEnd);
assert_equals(firstInput.cancelable, entry.cancelable);
}
}
function wait() {
return new Promise((resolve, reject) => {
step_timeout(() => {
resolve();
}, 0);
});
}
function clickAndBlockMain(id) {
return new Promise((resolve, reject) => {
clickOnElement(id, resolve);
});
}

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

@ -0,0 +1,7 @@
import time
def main(request, response):
# Sleep for 500ms to delay onload.
time.sleep(0.5)
response.headers.set("Cache-Control", "no-cache, must-revalidate");
response.headers.set("Location", "data:image/gif;base64,R0lGODlhAQABAJAAAMjIyAAAACwAAAAAAQABAAACAgQBADs%3D");

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

@ -16,6 +16,13 @@ var btn = document.getElementById("btn"),
menu_btn = document.getElementById("menu_btn"),
t1 = async_test("The submit event must be fired when click a button in submit status"),
t2 = async_test("The reset event must be fired when click a button in reset status");
t3 = async_test("type=button shouldn't trigger submit or reset events");
t4 = async_test("Switching from type=button to type=submit should submit the form");
t5 = async_test("Switching from type=button to type=reset should reset the form");
t6 = async_test("Innermost button should submit its form");
t7 = async_test("Innermost button should reset its form");
t8 = async_test("Anchor inside a button should be prevent button activation");
t9 = async_test("input type=submit inside a button should be prevent button activation");
document.forms.fm1.onsubmit = t1.step_func(function (evt) {
evt.preventDefault();
@ -46,4 +53,114 @@ t2.step(function () {
btn.click();
});
t3.step(function () {
btn.type = "button";
assert_equals(btn.type, "button", "The button type should be 'button'.");
document.forms.fm1.onsubmit = t3.step_func(function (evt) {
assert_unreached("type=button shouldn't trigger submission.");
});
document.forms.fm1.onreset = t3.step_func(function (evt) {
assert_unreached("type=button shouldn't reset the form.");
});
btn.click();
t3.done();
});
t4.step(function () {
btn.type = "button";
btn.onclick = function() { btn.type = "submit"; }
document.forms.fm1.onsubmit = t4.step_func(function (evt) {
evt.preventDefault();
assert_equals(btn.type, "submit", "The button type should be 'submit'.");
t4.done();
});
btn.click();
});
t5.step(function () {
btn.type = "button";
btn.onclick = function() { btn.type = "reset"; }
document.forms.fm1.onreset = t5.step_func(function (evt) {
evt.preventDefault();
assert_equals(btn.type, "reset", "The button type should be 'reset'.");
t5.done();
});
btn.click();
});
t6.step(function () {
btn.type = "submit";
btn.innerHTML = "";
var fm2 = document.createElement("form");
var btn2 = document.createElement("button");
btn2.type = "submit";
fm2.appendChild(btn2);
btn.appendChild(fm2);
assert_true(document.forms.fm1.contains(fm2), "Should have nested forms");
function submitListener(evt) {
evt.preventDefault();
assert_equals(evt.target, fm2, "Innermost form should have got the submit event");
};
window.addEventListener("submit", submitListener, true);
btn2.click();
window.removeEventListener("submit", submitListener, true);
t6.done();
});
t7.step(function () {
btn.type = "reset";
btn.innerHTML = "";
var fm2 = document.createElement("form");
var btn2 = document.createElement("button");
btn2.type = "reset";
fm2.appendChild(btn2);
btn.appendChild(fm2);
assert_true(document.forms.fm1.contains(fm2), "Should have nested forms");
function resetListener(evt) {
evt.currentTarget.removeEventListener(evt.type, resetListener, true);
evt.preventDefault();
assert_equals(evt.target, fm2, "Innermost form should have got the reset event");
t7.done();
};
window.addEventListener("reset", resetListener, true);
btn2.click();
});
t8.step(function () {
btn.type = "submit";
btn.innerHTML = "";
var a = document.createElement("a");
a.href = "#";
btn.appendChild(a);
document.forms.fm1.onsubmit = t8.step_func(function (evt) {
assert_unreached("type=button shouldn't trigger submission.");
});
a.click();
t8.done();
});
t9.step(function () {
btn.type = "submit";
btn.innerHTML = "";
var fm2 = document.createElement("form");
var btn2 = document.createElement("input");
btn2.type = "submit";
fm2.appendChild(btn2);
btn.appendChild(fm2);
assert_true(document.forms.fm1.contains(fm2), "Should have nested forms");
function submitListener(evt) {
evt.preventDefault();
assert_equals(evt.target, fm2, "Innermost form should have got the submit event");
};
window.addEventListener("submit", submitListener, true);
btn2.click();
window.removeEventListener("submit", submitListener, true);
t9.done();
});
</script>

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

@ -68,6 +68,7 @@ enum PaymentShippingType {
dictionary PaymentOptions {
boolean requestPayerName = false;
boolean requestBillingAddress = false;
boolean requestPayerEmail = false;
boolean requestPayerPhone = false;
boolean requestShipping = false;

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

@ -5,7 +5,8 @@
[SecureContext, Exposed=Window] interface XR : EventTarget {
// Methods
Promise<XRDevice?> requestDevice();
Promise<void> supportsSessionMode(XRSessionMode mode);
Promise<XRSession> requestSession(optional XRSessionCreationOptions parameters);
// Events
attribute EventHandler ondevicechange;
@ -16,14 +17,14 @@ partial interface Navigator {
[SameObject] readonly attribute XR xr;
};
[SecureContext, Exposed=Window] interface XRDevice {
// Methods
Promise<void> supportsSession(optional XRSessionCreationOptions options);
Promise<XRSession> requestSession(optional XRSessionCreationOptions options);
enum XRSessionMode {
"inline",
"immersive-vr",
"immersive-ar"
};
dictionary XRSessionCreationOptions {
boolean immersive = false;
XRSessionMode mode = "inline";
XRPresentationContext outputContext;
};
@ -35,8 +36,7 @@ enum XREnvironmentBlendMode {
[SecureContext, Exposed=Window] interface XRSession : EventTarget {
// Attributes
readonly attribute XRDevice device;
readonly attribute boolean immersive;
readonly attribute XRSessionMode mode;
readonly attribute XRPresentationContext outputContext;
readonly attribute XREnvironmentBlendMode environmentBlendMode;
@ -60,6 +60,7 @@ enum XREnvironmentBlendMode {
attribute EventHandler onresetpose;
attribute EventHandler onend;
attribute EventHandler onselect;
attribute EventHandler oninputsourceschange;
attribute EventHandler onselectstart;
attribute EventHandler onselectend;
};
@ -68,10 +69,9 @@ callback XRFrameRequestCallback = void (DOMHighResTimeStamp time, XRFrame frame)
[SecureContext, Exposed=Window] interface XRFrame {
readonly attribute XRSession session;
readonly attribute FrozenArray<XRView> views;
XRDevicePose? getDevicePose(XRCoordinateSystem coordinateSystem);
XRInputPose? getInputPose(XRInputSource inputSource, XRCoordinateSystem coordinateSystem);
XRViewerPose? getViewerPose(XRFrameOfReference frameOfRef);
XRInputPose? getInputPose(XRInputSource inputSource, XRFrameOfReference frameOfRef);
};
[SecureContext, Exposed=Window] interface XRCoordinateSystem : EventTarget {
@ -108,6 +108,7 @@ enum XREye {
[SecureContext, Exposed=Window] interface XRView {
readonly attribute XREye eye;
readonly attribute Float32Array projectionMatrix;
readonly attribute Float32Array viewMatrix;
};
[SecureContext, Exposed=Window] interface XRViewport {
@ -117,10 +118,9 @@ enum XREye {
readonly attribute long height;
};
[SecureContext, Exposed=Window] interface XRDevicePose {
readonly attribute Float32Array poseModelMatrix;
Float32Array getViewMatrix(XRView view);
[SecureContext, Exposed=Window] interface XRViewerPose {
readonly attribute Float32Array poseMatrix;
readonly attribute FrozenArray<XRView> views;
};
enum XRHandedness {
@ -165,7 +165,6 @@ dictionary XRWebGLLayerInit {
boolean depth = true;
boolean stencil = false;
boolean alpha = true;
boolean multiview = false;
double framebufferScaleFactor = 1.0;
};
@ -180,7 +179,6 @@ interface XRWebGLLayer : XRLayer {
readonly attribute boolean depth;
readonly attribute boolean stencil;
readonly attribute boolean alpha;
readonly attribute boolean multiview;
readonly attribute WebGLFramebuffer framebuffer;
readonly attribute unsigned long framebufferWidth;
@ -195,11 +193,11 @@ interface XRWebGLLayer : XRLayer {
};
partial dictionary WebGLContextAttributes {
XRDevice compatibleXRDevice = null;
boolean xrCompatible = null;
};
partial interface mixin WebGLRenderingContextBase {
Promise<void> setCompatibleXRDevice(XRDevice device);
Promise<void> makeXRCompatible();
};
[SecureContext, Exposed=Window] interface XRPresentationContext {

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

@ -168,4 +168,38 @@ promise_test(t => {
});
}, "Test that decodingInfo returns a valid MediaCapabilitiesDecodingInfo objects with encrypted media");
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
keySystemConfiguration: {
keySystem: 'foobar',
videoRobustness: '',
}
}).then(ability => {
assert_false(ability.supported);
assert_false(ability.smooth);
assert_false(ability.powerEfficient);
assert_equals(ability.keySystemAccess, null);
});
}, "Test that random key systems are reported as non supported.");
// TODO(mlamouri): this test could be split in two tests for which codec support
// across browsers is widely compatible: one when all browsers wouldn't support
// and one where all browsers do support. The current approach is to check that
// the answer is consistent to the spec.
promise_test(t => {
return navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: minimalVideoConfiguration,
audio: minimalAudioConfiguration,
keySystemConfiguration: minimalKeySystemConfiguration,
}).then(ability => {
if (ability.supported)
assert_not_equals(ability.keySystemAccess, null);
else
assert_equals(ability.keySystemAccess, null);
});
}, "Test that keySystemAccess is only null when not supported if keySystemConfiguration was used.");
</script>

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

@ -0,0 +1,14 @@
import time
def main(request, response):
delay = float(request.GET.first("ms", 500)) / 1E3
count = int(request.GET.first("count", 50))
# Read request body
request.body
time.sleep(delay)
response.headers.set("Content-type", "text/plain")
response.write_status_headers()
time.sleep(delay);
for i in xrange(count):
response.writer.write_content("TEST_TRICKLE\n")
time.sleep(delay)

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

@ -0,0 +1,19 @@
import time
def main(request, response):
# no-cache itself to ensure the user agent finds a new version for each update.
headers = [('Cache-Control', 'no-cache, must-revalidate'),
('Pragma', 'no-cache')]
content_type = ''
extra_body = ''
content_type = 'application/javascript'
headers.append(('Content-Type', content_type))
extra_body = "self.onfetch = (event) => { event.respondWith(fetch(event.request)); };"
# Return a different script for each access. Use .time() and .clock() for
# best time resolution across different platforms.
return headers, '/* %s %s */ %s' % (time.time(), time.clock(), extra_body)

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

@ -0,0 +1,20 @@
<!DOCTYPE html>
<title>Update on navigation</title>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='resources/test-helpers.sub.js'></script>
<script>
promise_test(async (t) => {
var script = 'resources/update-fetch-worker.py';
var scope = 'resources/trickle.py?ms=1000&count=1';
const registration = await service_worker_unregister_and_register(t, script, scope);
t.add_cleanup(() => registration.unregister());
if (registration.installing)
await wait_for_state(t, registration.installing, 'activated');
const frame = await with_iframe(scope);
t.add_cleanup(() => frame.remove());
}, 'The active service worker in charge of a navigation load should not be terminated as part of updating the registration');
</script>

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

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:h="http://www.w3.org/1999/xhtml"
width="800px" height="800px">
<title>SVG Text: parsing inline-size with invalid values</title>
<metadata>
<h:link rel="help" href="https://svgwg.org/svg2-draft/text.html#InlineSizeProperty"/>
<h:link rel="help" href="https://drafts.csswg.org/css-logical/#dimension-properties"/>
<h:meta name="assert" content="inline-size supports only the grammar 'auto | length-percentage'"/>
</metadata>
<g id="target"></g>
<h:script src="/resources/testharness.js"/>
<h:script src="/resources/testharnessreport.js"/>
<h:script src="/css/support/parsing-testcommon.js"/>
<script><![CDATA[
test_invalid_value("inline-size", "none");
test_invalid_value("inline-size", "-10px");
test_invalid_value("inline-size", "20");
test_invalid_value("inline-size", "30deg");
test_invalid_value("inline-size", "40px 50%");
]]></script>
</svg>

После

Ширина:  |  Высота:  |  Размер: 974 B

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше