diff --git a/browser/base/content/test/static/browser_parsable_css.js b/browser/base/content/test/static/browser_parsable_css.js index a45878fdbba3..931e2edabbf3 100644 --- a/browser/base/content/test/static/browser_parsable_css.js +++ b/browser/base/content/test/static/browser_parsable_css.js @@ -30,6 +30,9 @@ let whitelist = [ {sourceName: /\b(html|mathml|ua)\.css$/i, errorMessage: /Unknown property.*-moz-/i, isFromDevTools: false}, + {sourceName: /minimal-xul\.css$/i, + errorMessage: /Unknown property.*-moz-list-reversed/i, + isFromDevTools: false}, // Reserved to UA sheets unless layout.css.overflow-clip-box.enabled flipped to true. {sourceName: /(?:res|gre-resources)\/forms\.css$/i, errorMessage: /Unknown property.*overflow-clip-box/i, diff --git a/dom/websocket/WebSocket.cpp b/dom/websocket/WebSocket.cpp index d822d7a6f62c..dfcf18e65d68 100644 --- a/dom/websocket/WebSocket.cpp +++ b/dom/websocket/WebSocket.cpp @@ -10,6 +10,7 @@ #include "jsapi.h" #include "jsfriendapi.h" +#include "mozilla/Atomics.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/net/WebSocketChannel.h" #include "mozilla/dom/File.h" @@ -176,7 +177,7 @@ class WebSocketImpl final : public nsIInterfaceRequestor, bool mOnCloseScheduled; bool mFailed; - bool mDisconnectingOrDisconnected; + Atomic mDisconnectingOrDisconnected; // Set attributes of DOM 'onclose' message bool mCloseEventWasClean; @@ -231,9 +232,42 @@ class WebSocketImpl final : public nsIInterfaceRequestor, } }; -NS_IMPL_ISUPPORTS(WebSocketImpl, nsIInterfaceRequestor, nsIWebSocketListener, - nsIObserver, nsISupportsWeakReference, nsIRequest, - nsIEventTarget) +NS_IMPL_ADDREF(WebSocketImpl) +NS_IMPL_QUERY_INTERFACE(WebSocketImpl, nsIInterfaceRequestor, + nsIWebSocketListener, nsIObserver, + nsISupportsWeakReference, nsIRequest, nsIEventTarget) + +NS_IMETHODIMP_(MozExternalRefCountType) WebSocketImpl::Release(void) { + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); + + if (!mRefCnt.isThreadSafe) { + NS_ASSERT_OWNINGTHREAD(WebSocketImpl); + } + + nsrefcnt count = mRefCnt - 1; + // If WebSocketImpl::Disconnect is not called, the last release of + // WebSocketImpl should be on the right thread. + if (count == 0 && !IsTargetThread() && !mDisconnectingOrDisconnected) { + DebugOnly rv = Dispatch(NewNonOwningRunnableMethod( + "dom::WebSocketImpl::Release", this, &WebSocketImpl::Release)); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return count; + } + + count = --mRefCnt; + NS_LOG_RELEASE(this, count, "WebSocketImpl"); + + if (count == 0) { + if (!mRefCnt.isThreadSafe) { + NS_ASSERT_OWNINGTHREAD(WebSocketImpl); + } + + mRefCnt = 1; /* stabilize */ + delete (this); + return 0; + } + return count; +} class CallDispatchConnectionCloseEvents final : public CancelableRunnable { public: diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 413dcb09e121..f34ee7cf5baa 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -2153,13 +2153,14 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent, RuntimeService::GetDefaultJSSettings(mJSSettings); + mJSSettings.chrome.realmOptions.creationOptions().setClampAndJitterTime( + !UsesSystemPrincipal()); + mJSSettings.content.realmOptions.creationOptions().setClampAndJitterTime( + !UsesSystemPrincipal()); + if (mIsSecureContext) { mJSSettings.chrome.realmOptions.creationOptions().setSecureContext(true); - mJSSettings.chrome.realmOptions.creationOptions().setClampAndJitterTime( - false); mJSSettings.content.realmOptions.creationOptions().setSecureContext(true); - mJSSettings.content.realmOptions.creationOptions().setClampAndJitterTime( - false); } mIsInAutomation = xpc::IsInAutomation(); diff --git a/gfx/vr/gfxVR.h b/gfx/vr/gfxVR.h index 6a994056ca64..0e0008f51bde 100644 --- a/gfx/vr/gfxVR.h +++ b/gfx/vr/gfxVR.h @@ -56,6 +56,7 @@ enum class OpenVRControllerType : uint16_t { Vive, WMR, Knuckles, + Cosmos, NumOpenVRControllerTypes }; diff --git a/gfx/vr/service/OpenVRSession.cpp b/gfx/vr/service/OpenVRSession.cpp index 77a2f1ba231e..926e5d52fdab 100644 --- a/gfx/vr/service/OpenVRSession.cpp +++ b/gfx/vr/service/OpenVRSession.cpp @@ -25,6 +25,7 @@ #include "mozilla/dom/GamepadEventTypes.h" #include "mozilla/dom/GamepadBinding.h" +#include "binding/OpenVRCosmosBinding.h" #include "binding/OpenVRKnucklesBinding.h" #include "binding/OpenVRViveBinding.h" #if defined(XP_WIN) // Windows Mixed Reality is only available in Windows. @@ -100,6 +101,7 @@ class ControllerManifestFile { // We wanna keep these temporary files existing // until Firefox is closed instead of following OpenVRSession's lifetime. +StaticRefPtr sCosmosBindingFile; StaticRefPtr sKnucklesBindingFile; StaticRefPtr sViveBindingFile; #if defined(XP_WIN) @@ -324,6 +326,7 @@ bool OpenVRSession::SetupContollerActions() { nsCString viveManifest; nsCString WMRManifest; nsCString knucklesManifest; + nsCString cosmosManifest; // Getting / Generating manifest file paths. if (StaticPrefs::dom_vr_process_enabled()) { @@ -367,7 +370,6 @@ bool OpenVRSession::SetupContollerActions() { } } #endif - if (vrParent->GetOpenVRControllerManifestPath( OpenVRControllerType::Knuckles, &output)) { knucklesManifest = output; @@ -383,6 +385,21 @@ bool OpenVRSession::SetupContollerActions() { knucklesBindingFile.close(); } } + if (vrParent->GetOpenVRControllerManifestPath( + OpenVRControllerType::Cosmos, &output)) { + cosmosManifest = output; + } + if (!cosmosManifest.Length() || !FileIsExisting(cosmosManifest)) { + if (!GenerateTempFileName(cosmosManifest)) { + return false; + } + OpenVRCosmosBinding cosmosBinding; + std::ofstream cosmosBindingFile(cosmosManifest.BeginReading()); + if (cosmosBindingFile.is_open()) { + cosmosBindingFile << cosmosBinding.binding; + cosmosBindingFile.close(); + } + } } else { // Without using VR process if (!sControllerActionFile) { @@ -435,6 +452,26 @@ bool OpenVRSession::SetupContollerActions() { } knucklesManifest = sKnucklesBindingFile->GetFileName(); + if (!sCosmosBindingFile) { + sCosmosBindingFile = ControllerManifestFile::CreateManifest(); + NS_DispatchToMainThread(NS_NewRunnableFunction( + "ClearOnShutdown ControllerManifestFile", + []() { ClearOnShutdown(&sCosmosBindingFile); })); + } + if (!sCosmosBindingFile->IsExisting()) { + nsCString cosmosBindingPath; + if (!GenerateTempFileName(cosmosBindingPath)) { + return false; + } + sCosmosBindingFile->SetFileName(cosmosBindingPath.BeginReading()); + OpenVRCosmosBinding cosmosBinding; + std::ofstream cosmosBindingFile(sCosmosBindingFile->GetFileName()); + if (cosmosBindingFile.is_open()) { + cosmosBindingFile << cosmosBinding.binding; + cosmosBindingFile.close(); + } + } + cosmosManifest = sCosmosBindingFile->GetFileName(); #if defined(XP_WIN) if (!sWMRBindingFile) { sWMRBindingFile = ControllerManifestFile::CreateManifest(); @@ -508,6 +545,8 @@ bool OpenVRSession::SetupContollerActions() { "/actions/firefox/in/LHand_finger_ring_value", "vector1"); leftContollerInfo.mActionFingerPinky_Value = ControllerAction( "/actions/firefox/in/LHand_finger_pinky_value", "vector1"); + leftContollerInfo.mActionBumper_Pressed = + ControllerAction("/actions/firefox/in/LHand_bumper_pressed", "boolean"); ControllerInfo rightContollerInfo; rightContollerInfo.mActionPose = @@ -556,6 +595,8 @@ bool OpenVRSession::SetupContollerActions() { "/actions/firefox/in/RHand_finger_ring_value", "vector1"); rightContollerInfo.mActionFingerPinky_Value = ControllerAction( "/actions/firefox/in/RHand_finger_pinky_value", "vector1"); + rightContollerInfo.mActionBumper_Pressed = + ControllerAction("/actions/firefox/in/RHand_bumper_pressed", "boolean"); mControllerHand[OpenVRHand::Left] = leftContollerInfo; mControllerHand[OpenVRHand::Right] = rightContollerInfo; @@ -580,6 +621,10 @@ bool OpenVRSession::SetupContollerActions() { actionWriter.StringProperty("controller_type", "knuckles"); actionWriter.StringProperty("binding_url", knucklesManifest.BeginReading()); actionWriter.EndObject(); + actionWriter.StartObjectElement(); + actionWriter.StringProperty("controller_type", "vive_cosmos_controller"); + actionWriter.StringProperty("binding_url", cosmosManifest.BeginReading()); + actionWriter.EndObject(); #if defined(XP_WIN) actionWriter.StartObjectElement(); actionWriter.StringProperty("controller_type", "holographic_controller"); @@ -747,6 +792,13 @@ bool OpenVRSession::SetupContollerActions() { "type", controller.mActionFingerPinky_Value.type.BeginReading()); actionWriter.EndObject(); + actionWriter.StartObjectElement(); + actionWriter.StringProperty( + "name", controller.mActionBumper_Pressed.name.BeginReading()); + actionWriter.StringProperty( + "type", controller.mActionBumper_Pressed.type.BeginReading()); + actionWriter.EndObject(); + actionWriter.StartObjectElement(); actionWriter.StringProperty("name", controller.mActionHaptic.name.BeginReading()); @@ -772,7 +824,8 @@ bool OpenVRSession::SetupContollerActions() { if (StaticPrefs::dom_vr_process_enabled()) { NS_DispatchToMainThread(NS_NewRunnableFunction( "SendOpenVRControllerActionPathToParent", - [controllerAction, viveManifest, WMRManifest, knucklesManifest]() { + [controllerAction, viveManifest, WMRManifest, knucklesManifest, + cosmosManifest]() { VRParent* vrParent = VRProcessChild::GetVRParent(); Unused << vrParent->SendOpenVRControllerActionPathToParent( controllerAction); @@ -782,6 +835,8 @@ bool OpenVRSession::SetupContollerActions() { OpenVRControllerType::WMR, WMRManifest); Unused << vrParent->SendOpenVRControllerManifestPathToParent( OpenVRControllerType::Knuckles, knucklesManifest); + Unused << vrParent->SendOpenVRControllerManifestPathToParent( + OpenVRControllerType::Cosmos, cosmosManifest); })); } else { sControllerActionFile->SetFileName(controllerAction.BeginReading()); @@ -1136,6 +1191,9 @@ void OpenVRSession::EnumerateControllers(VRSystemState& aState) { mControllerHand[handIndex] .mActionFingerPinky_Value.name.BeginReading(), &mControllerHand[handIndex].mActionFingerPinky_Value.handle); + vr::VRInput()->GetActionHandle( + mControllerHand[handIndex].mActionBumper_Pressed.name.BeginReading(), + &mControllerHand[handIndex].mActionBumper_Pressed.handle); nsCString deviceId; GetControllerDeviceId(deviceType, originInfo.trackedDeviceIndex, @@ -1353,7 +1411,6 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { } else { controllerState.buttonPressed &= ~mask; } - if (mControllerHand[stateIndex].mActionTrackpad_Touched.handle && vr::VRInput()->GetDigitalActionData( mControllerHand[stateIndex].mActionTrackpad_Touched.handle, @@ -1396,7 +1453,6 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { } else { controllerState.buttonPressed &= ~mask; } - if (mControllerHand[stateIndex].mActionGrip_Touched.handle && vr::VRInput()->GetDigitalActionData( mControllerHand[stateIndex].mActionGrip_Touched.handle, @@ -1428,7 +1484,6 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { } else { controllerState.buttonPressed &= ~mask; } - if (mControllerHand[stateIndex].mActionMenu_Touched.handle && vr::VRInput()->GetDigitalActionData( mControllerHand[stateIndex].mActionMenu_Touched.handle, @@ -1460,7 +1515,6 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { } else { controllerState.buttonPressed &= ~mask; } - if (mControllerHand[stateIndex].mActionSystem_Touched.handle && vr::VRInput()->GetDigitalActionData( mControllerHand[stateIndex].mActionSystem_Touched.handle, @@ -1507,6 +1561,7 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { } ++buttonIdx; } + // Button 5: B if (mControllerHand[stateIndex].mActionB_Pressed.handle && vr::VRInput()->GetDigitalActionData( @@ -1522,7 +1577,6 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { } else { controllerState.buttonPressed &= ~mask; } - if (mControllerHand[stateIndex].mActionB_Touched.handle && vr::VRInput()->GetDigitalActionData( mControllerHand[stateIndex].mActionB_Touched.handle, &actionData, @@ -1538,6 +1592,7 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { } ++buttonIdx; } + // Axis 2 3: Thumbstick // Button 6: Thumbstick if (mControllerHand[stateIndex].mActionThumbstick_Analog.handle && @@ -1551,7 +1606,6 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { controllerState.axisValue[axisIdx] = analogData.y * yAxisInvert; ++axisIdx; } - if (mControllerHand[stateIndex].mActionThumbstick_Pressed.handle && vr::VRInput()->GetDigitalActionData( mControllerHand[stateIndex].mActionThumbstick_Pressed.handle, @@ -1559,13 +1613,13 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { vr::k_ulInvalidInputValueHandle) == vr::VRInputError_None && actionData.bActive) { bPressed = actionData.bState; + mask = (1ULL << buttonIdx); controllerState.triggerValue[buttonIdx] = bPressed ? 1.0 : 0.0f; if (bPressed) { controllerState.buttonPressed |= mask; } else { controllerState.buttonPressed &= ~mask; } - if (mControllerHand[stateIndex].mActionThumbstick_Touched.handle && vr::VRInput()->GetDigitalActionData( mControllerHand[stateIndex].mActionThumbstick_Touched.handle, @@ -1581,6 +1635,25 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { } ++buttonIdx; } + + // Button 7: Bumper (Cosmos only) + if (mControllerHand[stateIndex].mActionBumper_Pressed.handle && + vr::VRInput()->GetDigitalActionData( + mControllerHand[stateIndex].mActionBumper_Pressed.handle, &actionData, + sizeof(actionData), + vr::k_ulInvalidInputValueHandle) == vr::VRInputError_None && + actionData.bActive) { + bPressed = actionData.bState; + mask = (1ULL << buttonIdx); + controllerState.triggerValue[buttonIdx] = bPressed ? 1.0 : 0.0f; + if (bPressed) { + controllerState.buttonPressed |= mask; + } else { + controllerState.buttonPressed &= ~mask; + } + ++buttonIdx; + } + // Button 7: Finger index if (mControllerHand[stateIndex].mActionFingerIndex_Value.handle && vr::VRInput()->GetAnalogActionData( @@ -1591,6 +1664,7 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { UpdateTrigger(controllerState, buttonIdx, analogData.x, triggerThreshold); ++buttonIdx; } + // Button 8: Finger middle if (mControllerHand[stateIndex].mActionFingerMiddle_Value.handle && vr::VRInput()->GetAnalogActionData( @@ -1601,6 +1675,7 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { UpdateTrigger(controllerState, buttonIdx, analogData.x, triggerThreshold); ++buttonIdx; } + // Button 9: Finger ring if (mControllerHand[stateIndex].mActionFingerRing_Value.handle && vr::VRInput()->GetAnalogActionData( @@ -1611,6 +1686,7 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) { UpdateTrigger(controllerState, buttonIdx, analogData.x, triggerThreshold); ++buttonIdx; } + // Button 10: Finger pinky if (mControllerHand[stateIndex].mActionFingerPinky_Value.handle && vr::VRInput()->GetAnalogActionData( @@ -1905,6 +1981,9 @@ void OpenVRSession::GetControllerDeviceId( if (deviceId.Find("knuckles") != kNotFound) { aId.AssignLiteral("OpenVR Knuckles"); isFound = true; + } else if (deviceId.Find("vive_cosmos_controller") != kNotFound) { + aId.AssignLiteral("OpenVR Cosmos"); + isFound = true; } requiredBufferLen = mVRSystem->GetStringTrackedDeviceProperty( aDeviceIndex, ::vr::Prop_SerialNumber_String, charBuf, 128, &err); diff --git a/gfx/vr/service/OpenVRSession.h b/gfx/vr/service/OpenVRSession.h index 25d2c8864b55..5cc78fdac86f 100644 --- a/gfx/vr/service/OpenVRSession.h +++ b/gfx/vr/service/OpenVRSession.h @@ -62,20 +62,25 @@ struct ControllerInfo { ControllerAction mActionSystem_Pressed; ControllerAction mActionSystem_Touched; - // --- Knuckles + // --- Knuckles & Cosmos ControllerAction mActionA_Pressed; ControllerAction mActionA_Touched; ControllerAction mActionB_Pressed; ControllerAction mActionB_Touched; + // --- Knuckles, Cosmos, and WMR ControllerAction mActionThumbstick_Analog; ControllerAction mActionThumbstick_Pressed; ControllerAction mActionThumbstick_Touched; + // --- Knuckles ControllerAction mActionFingerIndex_Value; ControllerAction mActionFingerMiddle_Value; ControllerAction mActionFingerRing_Value; ControllerAction mActionFingerPinky_Value; + + // --- Cosmos + ControllerAction mActionBumper_Pressed; }; class OpenVRSession : public VRSession { diff --git a/gfx/vr/service/binding/OpenVRCosmosBinding.h b/gfx/vr/service/binding/OpenVRCosmosBinding.h new file mode 100644 index 000000000000..c87f79a01b86 --- /dev/null +++ b/gfx/vr/service/binding/OpenVRCosmosBinding.h @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GFX_VR_BLINDING_OPENVRCOSMOSBINDING_H +#define GFX_VR_BLINDING_OPENVRCOSMOSBINDING_H + +namespace mozilla { +namespace gfx { + +struct OpenVRCosmosBinding { + const char* binding = + // clang-format off + "{\n" + " \"version\" : \"0.1\", \n" + " \"controller_type\" : \"vive_cosmos_controller\", \n" + " \"description\" : \"Bindings for Firefox OpenVR for the Vive Cosmos controller\", \n" + " \"name\" : \"Firefox bindings for Vive Cosmos Controller\", \n" + " \"bindings\" : { \n" + " \"/actions/firefox\" : { \n" + " \"poses\" : [ \n" + " { \n" + " \"output\" : \"/actions/firefox/in/LHand_pose\", \n" + " \"path\" : \"/user/hand/left/pose/raw\" \n" + " },\n" + " { \n" + " \"output\" : \"/actions/firefox/in/RHand_pose\", \n" + " \"path\" : \"/user/hand/right/pose/raw\" \n" + " }\n" + " ],\n" + " \"haptics\" : [ \n" + " {\n" + " \"output\" : \"/actions/firefox/out/LHand_haptic\", \n" + " \"path\" : \"/user/hand/left/output/haptic\" \n" + " },\n" + " { \n" + " \"output\" : \"/actions/firefox/out/RHand_haptic\", \n" + " \"path\" : \"/user/hand/right/output/haptic\" \n" + " }\n" + " ],\n" + " \"sources\" : [ \n" + " {\n" + " \"inputs\" : { \n" + " \"pull\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_trigger_value\" \n" + " } \n" + " },\n" + " \"mode\" : \"trigger\", \n" + " \"path\" : \"/user/hand/left/input/trigger\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"pull\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_trigger_value\" \n" + " } \n" + " },\n" + " \"mode\" : \"trigger\", \n" + " \"path\" : \"/user/hand/right/input/trigger\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_grip_pressed\" \n" + " }, \n" + " \"touch\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_grip_touched\" \n" + " } \n" + " }, \n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/left/input/paddle_heavy\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_grip_pressed\" \n" + " }, \n" + " \"touch\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_grip_touched\" \n" + " } \n" + " }, \n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/right/input/paddle_heavy\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_system_pressed\" \n" + " }, \n" + " \"touch\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_system_touched\" \n" + " } \n" + " },\n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/left/input/system\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_system_pressed\" \n" + " }, \n" + " \"touch\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_system_touched\" \n" + " } \n" + " },\n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/right/input/system\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_a_pressed\" \n" + " } \n" + " },\n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/left/input/a\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_a_pressed\" \n" + " } \n" + " },\n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/right/input/a\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_b_pressed\" \n" + " } \n" + " },\n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/left/input/b\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_b_pressed\" \n" + " } \n" + " },\n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/right/input/b\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"position\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_thumbstick_analog\" \n" + " }, \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_thumbstick_pressed\" \n" + " }, \n" + " \"touch\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_thumbstick_touched\" \n" + " } \n" + " }, \n" + " \"mode\" : \"joystick\", \n" + " \"path\" : \"/user/hand/left/input/joystick\" \n" + " },\n" + " {\n" + " \"inputs\" : { \n" + " \"position\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_thumbstick_analog\" \n" + " }, \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_thumbstick_pressed\" \n" + " }, \n" + " \"touch\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_thumbstick_touched\" \n" + " } \n" + " }, \n" + " \"mode\" : \"joystick\", \n" + " \"path\" : \"/user/hand/right/input/joystick\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/LHand_bumper_pressed\" \n" + " } \n" + " },\n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/left/input/bumper\" \n" + " }, \n" + " {\n" + " \"inputs\" : { \n" + " \"click\" : { \n" + " \"output\" : \"/actions/firefox/in/RHand_bumper_pressed\" \n" + " } \n" + " },\n" + " \"mode\" : \"button\", \n" + " \"path\" : \"/user/hand/right/input/bumper\" \n" + " } \n" + " ]\n" + " }\n" + " }\n" + "}"; + // clang-format on +}; + +} // namespace gfx +} // namespace mozilla + +#endif // GFX_VR_BLINDING_OPENVRCOSMOSBINDING_H diff --git a/gfx/vr/service/binding/OpenVRKnucklesBinding.h b/gfx/vr/service/binding/OpenVRKnucklesBinding.h index 700e8615654d..91fd4e68e107 100644 --- a/gfx/vr/service/binding/OpenVRKnucklesBinding.h +++ b/gfx/vr/service/binding/OpenVRKnucklesBinding.h @@ -233,7 +233,7 @@ struct OpenVRKnucklesBinding { " \"mode\" : \"trigger\", \n" " \"path\" : \"/user/hand/right/input/finger/index\" \n" " }, \n" - " {\n" + " {\n" " \"inputs\" : { \n" " \"pull\" : { \n" " \"output\" : \"/actions/firefox/in/LHand_finger_middle_value\" \n" diff --git a/gfx/vr/service/binding/OpenVRWMRBinding.h b/gfx/vr/service/binding/OpenVRWMRBinding.h index 464e461f02cf..e5b986e681fd 100644 --- a/gfx/vr/service/binding/OpenVRWMRBinding.h +++ b/gfx/vr/service/binding/OpenVRWMRBinding.h @@ -11,7 +11,6 @@ namespace mozilla { namespace gfx { struct OpenVRWMRBinding { - // OpenVRWMRBinding(); const char* binding = // clang-format off "{\n" diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp index de83886f7efb..346f2834d643 100644 --- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -2260,6 +2260,12 @@ AttachDecision GetPropIRGenerator::tryAttachTypedElement( return AttachDecision::NoAction; } + // BigInt boxing not yet implemented. + if (obj->is() && + Scalar::isBigIntType(obj->as().type())) { + return AttachDecision::NoAction; + } + // Don't attach typed object stubs if the underlying storage could be // detached, as the stub will always bail out. if (IsPrimitiveArrayTypedObject(obj) && cx_->zone()->detachedTypedObjects) { @@ -3883,6 +3889,12 @@ AttachDecision SetPropIRGenerator::tryAttachSetTypedElement( return AttachDecision::NoAction; } + // bigIntArray[index] = rhsVal_ will throw as the RHS is a number. + if (obj->is() && + Scalar::isBigIntType(obj->as().type())) { + return AttachDecision::NoAction; + } + bool handleOutOfBounds = false; if (obj->is()) { handleOutOfBounds = (index >= obj->as().length()); diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp index 223b3e142442..9dfdac9279b6 100644 --- a/js/src/vm/BigIntType.cpp +++ b/js/src/vm/BigIntType.cpp @@ -1413,12 +1413,16 @@ bool BigInt::calculateMaximumDigitsRequired(JSContext* cx, uint8_t radix, size_t charcount, size_t* result) { MOZ_ASSERT(2 <= radix && radix <= 36); - size_t bitsPerChar = maxBitsPerCharTable[radix]; + uint8_t bitsPerChar = maxBitsPerCharTable[radix]; MOZ_ASSERT(charcount > 0); - MOZ_ASSERT(charcount <= std::numeric_limits::max() / bitsPerChar); - uint64_t n = - CeilDiv(charcount * bitsPerChar, DigitBits * bitsPerCharTableMultiplier); + MOZ_ASSERT(charcount <= std::numeric_limits::max() / bitsPerChar); + static_assert( + MaxDigitLength < std::numeric_limits::max(), + "can't safely cast calculateMaximumDigitsRequired result to size_t"); + + uint64_t n = CeilDiv(static_cast(charcount) * bitsPerChar, + DigitBits * bitsPerCharTableMultiplier); if (n > MaxDigitLength) { ReportOutOfMemory(cx); return false; diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index d32a970785e4..34f87515fe44 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -2431,7 +2431,7 @@ struct RestyleManager::TextPostTraversalState { ComputedStyle& ParentStyle() { if (!mParentContext) { mLazilyResolvedParentContext = - mParentRestyleState.StyleSet().ResolveServoStyle(mParentElement); + ServoStyleSet::ResolveServoStyle(mParentElement); mParentContext = mLazilyResolvedParentContext; } return *mParentContext; @@ -2668,8 +2668,7 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement, static_cast(Servo_TakeChangeHint(aElement, &wasRestyled)); RefPtr upToDateStyleIfRestyled = - wasRestyled ? aRestyleState.StyleSet().ResolveServoStyle(*aElement) - : nullptr; + wasRestyled ? ServoStyleSet::ResolveServoStyle(*aElement) : nullptr; // We should really fix the weird primary frame mapping for image maps // (bug 135040)... @@ -2767,8 +2766,7 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement, const bool isDisplayContents = !styleFrame && aElement->HasServoData() && Servo_Element_IsDisplayContents(aElement); if (isDisplayContents) { - oldOrDisplayContentsStyle = - aRestyleState.StyleSet().ResolveServoStyle(*aElement); + oldOrDisplayContentsStyle = ServoStyleSet::ResolveServoStyle(*aElement); } Maybe thisFrameRestyleState; diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 9ccb8be3f869..166cd1fa940f 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1761,7 +1761,7 @@ void nsCSSFrameConstructor::CreateGeneratedContentItem( // above. We need to grab style with animations from the pseudo element and // replace old one. mPresShell->StyleSet()->StyleNewSubtree(container); - pseudoStyle = styleSet->ResolveServoStyle(*container); + pseudoStyle = ServoStyleSet::ResolveServoStyle(*container); } uint32_t contentCount = pseudoStyle->StyleContent()->ContentCount(); @@ -2253,7 +2253,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame( } RefPtr computedStyle = - mPresShell->StyleSet()->ResolveServoStyle(*aDocElement); + ServoStyleSet::ResolveServoStyle(*aDocElement); const nsStyleDisplay* display = computedStyle->StyleDisplay(); @@ -3843,6 +3843,18 @@ static void SetFlagsOnSubtree(nsIContent* aNode, uintptr_t aFlagsToSet) { } } +static void GatherSubtreeElements(Element* aElement, + nsTArray& aElements) { + aElements.AppendElement(aElement); + StyleChildrenIterator iter(aElement); + for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) { + if (!c->IsElement()) { + continue; + } + GatherSubtreeElements(c->AsElement(), aElements); + } +} + nsresult nsCSSFrameConstructor::GetAnonymousContent( nsIContent* aParent, nsIFrame* aParentFrame, nsTArray& aContent) { @@ -3883,11 +3895,74 @@ nsresult nsCSSFrameConstructor::GetAnonymousContent( } } + // Some situations where we don't cache anonymous content styles: + // + // * when visibility is anything other than visible; we rely on visibility + // inheriting into anonymous content, but don't bother adding this state + // to the AnonymousContentKey, since it's not so common + // + // * when the medium is anything other than screen; some UA style sheet rules + // apply in e.g. print medium, and will give different results from the + // cached styles + bool allowStyleCaching = + StaticPrefs::layout_css_cached_scrollbar_styles_enabled() && + aParentFrame->StyleVisibility()->mVisible == NS_STYLE_VISIBILITY_VISIBLE && + mPresShell->GetPresContext()->Medium() == nsGkAtoms::screen; + + // Compute styles for the anonymous content tree. ServoStyleSet* styleSet = mPresShell->StyleSet(); - // Eagerly compute styles for the anonymous content tree. for (auto& info : aContent) { - if (info.mContent->IsElement()) { - styleSet->StyleNewSubtree(info.mContent->AsElement()); + Element* e = Element::FromNode(info.mContent); + if (!e) { + continue; + } + + if (info.mKey == AnonymousContentKey::None || !allowStyleCaching) { + // Most NAC subtrees do not use caching of computed styles. Just go + // ahead and eagerly style the subtree. + styleSet->StyleNewSubtree(e); + continue; + } + + // We have a NAC subtree for which we can use cached styles. + AutoTArray, 2> cachedStyles; + AutoTArray elements; + + GatherSubtreeElements(e, elements); + styleSet->GetCachedAnonymousContentStyles(info.mKey, cachedStyles); + + if (cachedStyles.IsEmpty()) { + // We haven't store cached styles for this kind of NAC subtree yet. + // Eagerly compute those styles, then cache them for later. + styleSet->StyleNewSubtree(e); + for (Element* e : elements) { + if (e->HasServoData()) { + cachedStyles.AppendElement(ServoStyleSet::ResolveServoStyle(*e)); + } else { + cachedStyles.AppendElement(nullptr); + } + } + styleSet->PutCachedAnonymousContentStyles(info.mKey, + std::move(cachedStyles)); + continue; + } + + // We previously stored cached styles for this kind of NAC subtree. + // Iterate over them and set them on the subtree's elements. + MOZ_ASSERT(cachedStyles.Length() == elements.Length(), + "should always produce the same size NAC subtree"); + for (size_t i = 0, len = cachedStyles.Length(); i != len; ++i) { + if (cachedStyles[i]) { +#ifdef DEBUG + // Assert that our cached style is the same as one we could compute. + RefPtr cs = styleSet->ResolveStyleLazily(*elements[i]); + MOZ_ASSERT( + cachedStyles[i]->EqualForCachedAnonymousContentStyle(*cs), + "cached anonymous content styles should be identical to those we " + "would compute normally"); +#endif + Servo_SetExplicitStyle(elements[i], cachedStyles[i]); + } } } @@ -4621,10 +4696,8 @@ void nsCSSFrameConstructor::InitAndRestoreFrame( already_AddRefed nsCSSFrameConstructor::ResolveComputedStyle( nsIContent* aContent) { - ServoStyleSet* styleSet = mPresShell->StyleSet(); - if (auto* element = Element::FromNode(aContent)) { - return styleSet->ResolveServoStyle(*element); + return ServoStyleSet::ResolveServoStyle(*element); } MOZ_ASSERT(aContent->IsText(), @@ -4646,7 +4719,7 @@ already_AddRefed nsCSSFrameConstructor::ResolveComputedStyle( // out. RefPtr parentStyle = Servo_Element_GetPrimaryComputedValues(parent).Consume(); - return styleSet->ResolveStyleForText(aContent, parentStyle); + return mPresShell->StyleSet()->ResolveStyleForText(aContent, parentStyle); } // MathML Mod - RBS diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 0c32ffd39c5d..595c259864f3 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -10044,12 +10044,12 @@ ComputedStyle* nsLayoutUtils::StyleForScrollbar(nsIFrame* aScrollbarPart) { // from the element directly. This can happen on viewport, because // the scrollbar of viewport may be shown when the root element has // > display: none; overflow: scroll; - nsPresContext* pc = aScrollbarPart->PresContext(); - MOZ_ASSERT(content == pc->Document()->GetRootElement(), - "Root element is the only case for this fallback " - "path to be triggered"); + MOZ_ASSERT( + content == aScrollbarPart->PresContext()->Document()->GetRootElement(), + "Root element is the only case for this fallback " + "path to be triggered"); RefPtr style = - pc->StyleSet()->ResolveServoStyle(*content->AsElement()); + ServoStyleSet::ResolveServoStyle(*content->AsElement()); // Dropping the strong reference is fine because the style should be // held strongly by the element. return style.get(); diff --git a/layout/generic/AnonymousContentKey.h b/layout/generic/AnonymousContentKey.h new file mode 100644 index 000000000000..ec3104f9ab8b --- /dev/null +++ b/layout/generic/AnonymousContentKey.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* values to identify particular subtrees of native anonymous content */ + +#ifndef mozilla_AnonymousContentKey_h +#define mozilla_AnonymousContentKey_h + +namespace mozilla { + +// clang-format off + +// We currently use cached anonymous content styles only for scrollbar parts, +// and we can fit the type of scrollbar part element along with its different +// options (such as orientation, and other attribute values that can affect +// styling) into a uint8_t. +// +// The lower three bits hold a Type_* value identifying the type of +// element, and the remaining bits store Flag_* values. +// +// A value of 0 is used to represent an anonymous content subtree that we don't +// cache styles for. +enum class AnonymousContentKey : uint8_t { + None = 0x00, + + // all + Type_ScrollCorner = 0x01, + Type_Resizer = 0x02, + Type_Scrollbar = 0x03, + Type_ScrollbarButton = 0x04, + Type_Slider = 0x05, + + // scrollbar, scrollbarbutton, slider + Flag_Vertical = 0x08, + + // resizer + Flag_Resizer_Right = 0x08, + Flag_Resizer_Bottom = 0x10, + Flag_Resizer_Flip = 0x20, + + // scrollbarbutton + Flag_ScrollbarButton_Down = 0x10, + Flag_ScrollbarButton_Bottom = 0x20, + Flag_ScrollbarButton_Decrement = 0x40, +}; + +// clang-format on + +MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(AnonymousContentKey) + +} // namespace mozilla + +#endif // mozilla_AnonymousContentKey_h diff --git a/layout/generic/moz.build b/layout/generic/moz.build index 80b0297b4ca7..5f655b62afa2 100644 --- a/layout/generic/moz.build +++ b/layout/generic/moz.build @@ -134,6 +134,7 @@ EXPORTS += [ EXPORTS.mozilla += [ '!FrameIdList.h', '!FrameTypeList.h', + 'AnonymousContentKey.h', 'AspectRatio.h', 'AutoCopyListener.h', 'ColumnUtils.h', diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 83f7fd799257..3a9cd3d465b2 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -9738,7 +9738,7 @@ ComputedStyle* nsFrame::DoGetParentComputedStyle( pseudo == PseudoStyleType::tableWrapper) { if (Servo_Element_IsDisplayContents(parentElement)) { RefPtr style = - PresShell()->StyleSet()->ResolveServoStyle(*parentElement); + ServoStyleSet::ResolveServoStyle(*parentElement); // NOTE(emilio): we return a weak reference because the element also // holds the style context alive. This is a bit silly (we could've // returned a weak ref directly), but it's probably not worth diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 03745486aa10..6435331159fb 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -286,7 +286,7 @@ void nsHTMLFramesetFrame::Init(nsIContent* aContent, nsContainerFrame* aParent, // // Maybe we should change that though. RefPtr kidStyle = - presShell->StyleSet()->ResolveServoStyle(*child->AsElement()); + ServoStyleSet::ResolveServoStyle(*child->AsElement()); nsIFrame* frame; if (child->IsHTMLElement(nsGkAtoms::frameset)) { frame = NS_NewHTMLFramesetFrame(presShell, kidStyle); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 339f63cac6ca..8e64dc65d64f 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -4756,6 +4756,51 @@ void ScrollFrameHelper::ReloadChildFrames() { } } +already_AddRefed ScrollFrameHelper::MakeScrollbar( + NodeInfo* aNodeInfo, bool aVertical, AnonymousContentKey& aKey) { + MOZ_ASSERT(aNodeInfo); + MOZ_ASSERT( + aNodeInfo->Equals(nsGkAtoms::scrollbar, nullptr, kNameSpaceID_XUL)); + + static constexpr nsLiteralString kOrientValues[2] = { + NS_LITERAL_STRING("horizontal"), + NS_LITERAL_STRING("vertical"), + }; + + aKey = AnonymousContentKey::Type_Scrollbar; + if (aVertical) { + aKey |= AnonymousContentKey::Flag_Vertical; + } + + RefPtr e; + NS_TrustedNewXULElement(getter_AddRefs(e), do_AddRef(aNodeInfo)); + +#ifdef DEBUG + // Scrollbars can get restyled by theme changes. Whether such a restyle + // will actually reconstruct them correctly if it involves a frame + // reconstruct... I don't know. :( + e->SetProperty(nsGkAtoms::restylableAnonymousNode, + reinterpret_cast(true)); +#endif // DEBUG + + e->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, kOrientValues[aVertical], + false); + e->SetAttr(kNameSpaceID_None, nsGkAtoms::clickthrough, + NS_LITERAL_STRING("always"), false); + + if (mIsRoot) { + e->SetProperty(nsGkAtoms::docLevelNativeAnonymousContent, + reinterpret_cast(true)); + e->SetAttr(kNameSpaceID_None, nsGkAtoms::root_, NS_LITERAL_STRING("true"), + false); + + // Don't bother making style caching take [root="true"] styles into account. + aKey = AnonymousContentKey::None; + } + + return e.forget(); +} + bool ScrollFrameHelper::IsForTextControlWithNoScrollbars() const { nsIFrame* parent = mOuter->GetParent(); // The anonymous
used by never gets scrollbars. @@ -4773,6 +4818,8 @@ bool ScrollFrameHelper::IsForTextControlWithNoScrollbars() const { nsresult ScrollFrameHelper::CreateAnonymousContent( nsTArray& aElements) { + typedef nsIAnonymousContentCreator::ContentInfo ContentInfo; + nsPresContext* presContext = mOuter->PresContext(); // Don't create scrollbars if we're an SVG document being used as an image, @@ -4833,62 +4880,28 @@ nsresult ScrollFrameHelper::CreateAnonymousContent( nsNodeInfoManager* nodeInfoManager = presContext->Document()->NodeInfoManager(); - RefPtr nodeInfo = nodeInfoManager->GetNodeInfo( - nsGkAtoms::scrollbar, nullptr, kNameSpaceID_XUL, nsINode::ELEMENT_NODE); - NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY); - if (canHaveHorizontal) { - RefPtr ni = nodeInfo; - NS_TrustedNewXULElement(getter_AddRefs(mHScrollbarContent), ni.forget()); -#ifdef DEBUG - // Scrollbars can get restyled by theme changes. Whether such a restyle - // will actually reconstruct them correctly if it involves a frame - // reconstruct... I don't know. :( - mHScrollbarContent->SetProperty(nsGkAtoms::restylableAnonymousNode, - reinterpret_cast(true)); -#endif // DEBUG + { + RefPtr nodeInfo = nodeInfoManager->GetNodeInfo( + nsGkAtoms::scrollbar, nullptr, kNameSpaceID_XUL, nsINode::ELEMENT_NODE); + NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY); - mHScrollbarContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, - NS_LITERAL_STRING("horizontal"), false); - mHScrollbarContent->SetAttr(kNameSpaceID_None, nsGkAtoms::clickthrough, - NS_LITERAL_STRING("always"), false); - if (mIsRoot) { - mHScrollbarContent->SetProperty(nsGkAtoms::docLevelNativeAnonymousContent, - reinterpret_cast(true)); - - mHScrollbarContent->SetAttr(kNameSpaceID_None, nsGkAtoms::root_, - NS_LITERAL_STRING("true"), false); + if (canHaveHorizontal) { + AnonymousContentKey key; + mHScrollbarContent = MakeScrollbar(nodeInfo, /* aVertical */ false, key); + aElements.AppendElement(ContentInfo(mHScrollbarContent, key)); } - if (!aElements.AppendElement(mHScrollbarContent)) - return NS_ERROR_OUT_OF_MEMORY; - } - if (canHaveVertical) { - RefPtr ni = nodeInfo; - NS_TrustedNewXULElement(getter_AddRefs(mVScrollbarContent), ni.forget()); -#ifdef DEBUG - // Scrollbars can get restyled by theme changes. Whether such a restyle - // will actually reconstruct them correctly if it involves a frame - // reconstruct... I don't know. :( - mVScrollbarContent->SetProperty(nsGkAtoms::restylableAnonymousNode, - reinterpret_cast(true)); -#endif // DEBUG - - mVScrollbarContent->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, - NS_LITERAL_STRING("vertical"), false); - mVScrollbarContent->SetAttr(kNameSpaceID_None, nsGkAtoms::clickthrough, - NS_LITERAL_STRING("always"), false); - if (mIsRoot) { - mVScrollbarContent->SetProperty(nsGkAtoms::docLevelNativeAnonymousContent, - reinterpret_cast(true)); - mVScrollbarContent->SetAttr(kNameSpaceID_None, nsGkAtoms::root_, - NS_LITERAL_STRING("true"), false); + if (canHaveVertical) { + AnonymousContentKey key; + mVScrollbarContent = MakeScrollbar(nodeInfo, /* aVertical */ true, key); + aElements.AppendElement(ContentInfo(mVScrollbarContent, key)); } - if (!aElements.AppendElement(mVScrollbarContent)) - return NS_ERROR_OUT_OF_MEMORY; } if (isResizable) { + AnonymousContentKey key = AnonymousContentKey::Type_Resizer; + RefPtr nodeInfo; nodeInfo = nodeInfoManager->GetNodeInfo( nsGkAtoms::resizer, nullptr, kNameSpaceID_XUL, nsINode::ELEMENT_NODE); @@ -4901,20 +4914,25 @@ nsresult ScrollFrameHelper::CreateAnonymousContent( case StyleResize::Horizontal: if (IsScrollbarOnRight()) { dir.AssignLiteral("right"); + key |= AnonymousContentKey::Flag_Resizer_Right; } else { dir.AssignLiteral("left"); } break; case StyleResize::Vertical: dir.AssignLiteral("bottom"); + key |= AnonymousContentKey::Flag_Resizer_Bottom; if (!IsScrollbarOnRight()) { mResizerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::flip, EmptyString(), false); + key |= AnonymousContentKey::Flag_Resizer_Flip; } break; case StyleResize::Both: + key |= AnonymousContentKey::Flag_Resizer_Bottom; if (IsScrollbarOnRight()) { dir.AssignLiteral("bottomright"); + key |= AnonymousContentKey::Flag_Resizer_Right; } else { dir.AssignLiteral("bottomleft"); } @@ -4940,12 +4958,13 @@ nsresult ScrollFrameHelper::CreateAnonymousContent( mResizerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::clickthrough, NS_LITERAL_STRING("always"), false); - if (!aElements.AppendElement(mResizerContent)) - return NS_ERROR_OUT_OF_MEMORY; + aElements.AppendElement(ContentInfo(mResizerContent, key)); } if (canHaveHorizontal && canHaveVertical) { - nodeInfo = + AnonymousContentKey key = AnonymousContentKey::Type_ScrollCorner; + + RefPtr nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollcorner, nullptr, kNameSpaceID_XUL, nsINode::ELEMENT_NODE); NS_TrustedNewXULElement(getter_AddRefs(mScrollCornerContent), @@ -4955,8 +4974,15 @@ nsresult ScrollFrameHelper::CreateAnonymousContent( nsGkAtoms::docLevelNativeAnonymousContent, reinterpret_cast(true)); } - if (!aElements.AppendElement(mScrollCornerContent)) - return NS_ERROR_OUT_OF_MEMORY; + aElements.AppendElement(ContentInfo(mScrollCornerContent, key)); + } + + // Don't cache styles if we are a child of a 's attributes. + if (mOuter->GetContent()->IsHTMLElement(nsGkAtoms::select)) { + for (auto& info : aElements) { + info.mKey = AnonymousContentKey::None; + } } return NS_OK; diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 2f5498c93f8a..21c2f1d76884 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -513,12 +513,17 @@ class ScrollFrameHelper : public nsIReflowCallback { void UpdateMinimumScaleSize(const nsRect& aScrollableOverflow, const nsSize& aICBSize); + // Return the scroll frame's "true outer size". // This is mOuter->GetSize(), except when mOuter has been sized to reflect // a virtual (layout) viewport in which case this returns the outer size // used to size the physical (visual) viewport. nsSize TrueOuterSize() const; + already_AddRefed MakeScrollbar(dom::NodeInfo* aNodeInfo, + bool aVertical, + AnonymousContentKey& aKey); + // owning references to the nsIAnonymousContentCreator-built content nsCOMPtr mHScrollbarContent; nsCOMPtr mVScrollbarContent; diff --git a/layout/generic/nsIAnonymousContentCreator.h b/layout/generic/nsIAnonymousContentCreator.h index 0d29610de74d..af7372a45186 100644 --- a/layout/generic/nsIAnonymousContentCreator.h +++ b/layout/generic/nsIAnonymousContentCreator.h @@ -12,6 +12,7 @@ #ifndef nsIAnonymousContentCreator_h___ #define nsIAnonymousContentCreator_h___ +#include "mozilla/AnonymousContentKey.h" #include "mozilla/ComputedStyle.h" #include "nsQueryFrame.h" @@ -31,9 +32,12 @@ class nsIAnonymousContentCreator { NS_DECL_QUERYFRAME_TARGET(nsIAnonymousContentCreator) struct ContentInfo { - explicit ContentInfo(nsIContent* aContent) : mContent(aContent) {} + explicit ContentInfo(nsIContent* aContent, + mozilla::AnonymousContentKey aKey = mozilla::AnonymousContentKey::None) + : mContent(aContent), mKey(aKey) {} nsIContent* mContent; + mozilla::AnonymousContentKey mKey; }; /** diff --git a/layout/generic/nsPlaceholderFrame.cpp b/layout/generic/nsPlaceholderFrame.cpp index ce8e877d8f7d..81173f15cb44 100644 --- a/layout/generic/nsPlaceholderFrame.cpp +++ b/layout/generic/nsPlaceholderFrame.cpp @@ -207,7 +207,7 @@ ComputedStyle* nsPlaceholderFrame::GetParentComputedStyleForOutOfFlow( mContent ? mContent->GetFlattenedTreeParentElement() : nullptr; if (parentElement && Servo_Element_IsDisplayContents(parentElement)) { RefPtr style = - PresShell()->StyleSet()->ResolveServoStyle(*parentElement); + ServoStyleSet::ResolveServoStyle(*parentElement); *aProviderFrame = nullptr; // See the comment in GetParentComputedStyle to see why returning this as a // weak ref is fine. diff --git a/layout/reftests/css-animations/reftest.list b/layout/reftests/css-animations/reftest.list index b30c73077238..6b5d1403eadf 100644 --- a/layout/reftests/css-animations/reftest.list +++ b/layout/reftests/css-animations/reftest.list @@ -8,7 +8,7 @@ fails != print-no-animations.html print-no-animations-notref.html # reftest harn == animation-on-empty-height-frame.html about:blank == in-visibility-hidden-animation.html in-visibility-hidden-animation-ref.html == in-visibility-hidden-animation-pseudo-element.html in-visibility-hidden-animation-pseudo-element-ref.html -== in-visibility-hidden-animation-marker-pseudo-element.html in-visibility-hidden-animation-marker-pseudo-element-ref.html +pref(layout.css.marker.restricted,false) == in-visibility-hidden-animation-marker-pseudo-element.html in-visibility-hidden-animation-marker-pseudo-element-ref.html == partially-out-of-view-animation.html partially-out-of-view-animation-ref.html == animate-display-table-opacity.html animate-display-table-opacity-ref.html # We need to run 100% opacity test case when OMTA is disabled to check that the animation creates a stacking context even if the animation is not running on the compositor @@ -58,13 +58,13 @@ fails-if(layerChecksEnabled) == background-position-important.html background-po == stop-animation-on-discarded-pseudo-element.html about:blank == updating-animation-on-pseudo-element.html updating-animation-on-pseudo-element-ref.html -== updating-animation-on-marker-pseudo-element.html updating-animation-on-marker-pseudo-element-ref.html +pref(layout.css.marker.restricted,false) == updating-animation-on-marker-pseudo-element.html updating-animation-on-marker-pseudo-element-ref.html == content-on-pseudo-element-at-beginning.html content-on-pseudo-element-ref.html == content-on-pseudo-element-at-half.html content-on-pseudo-element-ref.html -== content-on-marker-pseudo-element-at-beginning.html content-on-marker-pseudo-element-at-beginning-ref.html -== content-on-marker-pseudo-element-at-half.html content-on-marker-pseudo-element-at-beginning-ref.html +pref(layout.css.marker.restricted,false) == content-on-marker-pseudo-element-at-beginning.html content-on-marker-pseudo-element-at-beginning-ref.html +pref(layout.css.marker.restricted,false) == content-on-marker-pseudo-element-at-half.html content-on-marker-pseudo-element-at-beginning-ref.html == reframe-and-animation-starts-at-the-same-time.html reframe-and-animation-starts-at-the-same-time-ref.html -== marker-reframe-and-animation-starts-at-the-same-time.html marker-reframe-and-animation-starts-at-the-same-time-ref.html +pref(layout.css.marker.restricted,false) == marker-reframe-and-animation-starts-at-the-same-time.html marker-reframe-and-animation-starts-at-the-same-time-ref.html == change-animation-name-to-none-in-rule.html change-animation-name-in-rule-ref.html == change-animation-name-to-other-in-rule.html change-animation-name-in-rule-ref.html == change-animation-name-to-non-existent-in-rule.html change-animation-name-in-rule-ref.html diff --git a/layout/reftests/details-summary/details-absolute-children.html b/layout/reftests/details-summary/details-absolute-children.html index 19a9c9c9d23e..b26b3bcdb19e 100644 --- a/layout/reftests/details-summary/details-absolute-children.html +++ b/layout/reftests/details-summary/details-absolute-children.html @@ -9,11 +9,9 @@ width: 500px; height: 200px; } - summary::marker { + summary { /* Hide the triangle for comparing with div in reftest. */ list-style-type: none; - } - summary { background-color: green; width: 50%; } diff --git a/layout/reftests/details-summary/details-display-inline.html b/layout/reftests/details-summary/details-display-inline.html index 7a9150137a89..94c5db219a0d 100644 --- a/layout/reftests/details-summary/details-display-inline.html +++ b/layout/reftests/details-summary/details-display-inline.html @@ -7,7 +7,7 @@ details { display: inline; } - summary::marker { + summary { /* Hide the triangle for comparing with div in reftest. */ list-style-type: none; } diff --git a/layout/reftests/details-summary/details-in-ol.html b/layout/reftests/details-summary/details-in-ol.html index 434bbe9f6924..2d9a9d1943fd 100644 --- a/layout/reftests/details-summary/details-in-ol.html +++ b/layout/reftests/details-summary/details-in-ol.html @@ -4,7 +4,7 @@ +
+
+ diff --git a/layout/svg/SVGObserverUtils.cpp b/layout/svg/SVGObserverUtils.cpp index d9e37b710049..1e2a06d8435f 100644 --- a/layout/svg/SVGObserverUtils.cpp +++ b/layout/svg/SVGObserverUtils.cpp @@ -539,7 +539,9 @@ class BackgroundClipRenderingObserver : public SVGRenderingObserver { NS_DECL_ISUPPORTS private: - virtual ~BackgroundClipRenderingObserver() { StopObserving(); } + // We do not call StopObserving() since the observing and observed element + // are the same element (and because we could crash - see bug 1556441). + virtual ~BackgroundClipRenderingObserver() = default; Element* GetReferencedElementWithoutObserving() final { return mFrame->GetContent()->AsElement(); diff --git a/layout/xul/nsScrollbarFrame.cpp b/layout/xul/nsScrollbarFrame.cpp index 4b8d5331e6a4..11769cad2f13 100644 --- a/layout/xul/nsScrollbarFrame.cpp +++ b/layout/xul/nsScrollbarFrame.cpp @@ -282,21 +282,50 @@ int32_t nsScrollbarFrame::MoveToNewPosition() { return curpos; } +static already_AddRefed MakeScrollbarButton( + dom::NodeInfo* aNodeInfo, bool aVertical, bool aBottom, bool aDown, + AnonymousContentKey& aKey) { + MOZ_ASSERT(aNodeInfo); + MOZ_ASSERT( + aNodeInfo->Equals(nsGkAtoms::scrollbarbutton, nullptr, kNameSpaceID_XUL)); + + static constexpr nsLiteralString kSbattrValues[2][2] = { + { + NS_LITERAL_STRING("scrollbar-up-top"), + NS_LITERAL_STRING("scrollbar-up-bottom"), + }, + { + NS_LITERAL_STRING("scrollbar-down-top"), + NS_LITERAL_STRING("scrollbar-down-bottom"), + }, + }; + + static constexpr nsLiteralString kTypeValues[2] = { + NS_LITERAL_STRING("decrement"), + NS_LITERAL_STRING("increment"), + }; + + aKey = AnonymousContentKey::Type_ScrollbarButton; + if (aVertical) { + aKey |= AnonymousContentKey::Flag_Vertical; + } + if (aBottom) { + aKey |= AnonymousContentKey::Flag_ScrollbarButton_Bottom; + } + if (aDown) { + aKey |= AnonymousContentKey::Flag_ScrollbarButton_Down; + } + + RefPtr e; + NS_TrustedNewXULElement(getter_AddRefs(e), do_AddRef(aNodeInfo)); + e->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr, + kSbattrValues[aDown][aBottom], false); + e->SetAttr(kNameSpaceID_None, nsGkAtoms::type, kTypeValues[aDown], false); + return e.forget(); +} + nsresult nsScrollbarFrame::CreateAnonymousContent( nsTArray& aElements) { - // clang-format off - - // - // - // - // - // - // - // - - // clang-format on - nsNodeInfoManager* nodeInfoManager = mContent->NodeInfo()->NodeInfoManager(); Element* el(GetContent()->AsElement()); @@ -309,82 +338,79 @@ nsresult nsScrollbarFrame::CreateAnonymousContent( nsAutoString orient; el->GetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient); + bool vertical = orient.EqualsLiteral("vertical"); - NS_TrustedNewXULElement( - getter_AddRefs(mUpTopButton), + RefPtr sbbNodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr, - kNameSpaceID_XUL, nsINode::ELEMENT_NODE)); - mUpTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr, - NS_LITERAL_STRING("scrollbar-up-top"), false); - mUpTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type, - NS_LITERAL_STRING("decrement"), false); + kNameSpaceID_XUL, nsINode::ELEMENT_NODE); - if (!aElements.AppendElement(mUpTopButton)) { - return NS_ERROR_OUT_OF_MEMORY; + { + AnonymousContentKey key; + mUpTopButton = + MakeScrollbarButton(sbbNodeInfo, vertical, /* aBottom */ false, + /* aDown */ false, key); + aElements.AppendElement(ContentInfo(mUpTopButton, key)); } - NS_TrustedNewXULElement( - getter_AddRefs(mDownTopButton), - nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr, - kNameSpaceID_XUL, nsINode::ELEMENT_NODE)); - mDownTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr, - NS_LITERAL_STRING("scrollbar-down-top"), false); - mDownTopButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type, - NS_LITERAL_STRING("increment"), false); - - if (!aElements.AppendElement(mDownTopButton)) { - return NS_ERROR_OUT_OF_MEMORY; + { + AnonymousContentKey key; + mDownTopButton = + MakeScrollbarButton(sbbNodeInfo, vertical, /* aBottom */ false, + /* aDown */ true, key); + aElements.AppendElement(ContentInfo(mDownTopButton, key)); } - NS_TrustedNewXULElement( - getter_AddRefs(mSlider), - nodeInfoManager->GetNodeInfo(nsGkAtoms::slider, nullptr, kNameSpaceID_XUL, - nsINode::ELEMENT_NODE)); - mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient, false); - mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::flex, NS_LITERAL_STRING("1"), - false); + { + AnonymousContentKey key = AnonymousContentKey::Type_Slider; + if (vertical) { + key |= AnonymousContentKey::Flag_Vertical; + } - if (!aElements.AppendElement(mSlider)) { - return NS_ERROR_OUT_OF_MEMORY; + NS_TrustedNewXULElement( + getter_AddRefs(mSlider), + nodeInfoManager->GetNodeInfo(nsGkAtoms::slider, nullptr, + kNameSpaceID_XUL, nsINode::ELEMENT_NODE)); + mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient, false); + mSlider->SetAttr(kNameSpaceID_None, nsGkAtoms::flex, NS_LITERAL_STRING("1"), + false); + + aElements.AppendElement(ContentInfo(mSlider, key)); + + NS_TrustedNewXULElement( + getter_AddRefs(mThumb), + nodeInfoManager->GetNodeInfo(nsGkAtoms::thumb, nullptr, + kNameSpaceID_XUL, nsINode::ELEMENT_NODE)); + mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient, false); + mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::align, + NS_LITERAL_STRING("center"), false); + mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::pack, + NS_LITERAL_STRING("center"), false); + mSlider->AppendChildTo(mThumb, false); } - NS_TrustedNewXULElement( - getter_AddRefs(mThumb), - nodeInfoManager->GetNodeInfo(nsGkAtoms::thumb, nullptr, kNameSpaceID_XUL, - nsINode::ELEMENT_NODE)); - mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr, - NS_LITERAL_STRING("scrollbar-thumb"), false); - mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::orient, orient, false); - mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::align, - NS_LITERAL_STRING("center"), false); - mThumb->SetAttr(kNameSpaceID_None, nsGkAtoms::pack, - NS_LITERAL_STRING("center"), false); - mSlider->AppendChildTo(mThumb, false); - - NS_TrustedNewXULElement( - getter_AddRefs(mUpBottomButton), - nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr, - kNameSpaceID_XUL, nsINode::ELEMENT_NODE)); - mUpBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type, - NS_LITERAL_STRING("decrement"), false); - mUpBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr, - NS_LITERAL_STRING("scrollbar-up-bottom"), false); - - if (!aElements.AppendElement(mUpBottomButton)) { - return NS_ERROR_OUT_OF_MEMORY; + { + AnonymousContentKey key; + mUpBottomButton = + MakeScrollbarButton(sbbNodeInfo, vertical, /* aBottom */ true, + /* aDown */ false, key); + aElements.AppendElement(ContentInfo(mUpBottomButton, key)); } - NS_TrustedNewXULElement( - getter_AddRefs(mDownBottomButton), - nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollbarbutton, nullptr, - kNameSpaceID_XUL, nsINode::ELEMENT_NODE)); - mDownBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::sbattr, - NS_LITERAL_STRING("scrollbar-down-bottom"), false); - mDownBottomButton->SetAttr(kNameSpaceID_None, nsGkAtoms::type, - NS_LITERAL_STRING("increment"), false); + { + AnonymousContentKey key; + mDownBottomButton = + MakeScrollbarButton(sbbNodeInfo, vertical, /* aBottom */ true, + /* aDown */ true, key); + aElements.AppendElement(ContentInfo(mDownBottomButton, key)); + } - if (!aElements.AppendElement(mDownBottomButton)) { - return NS_ERROR_OUT_OF_MEMORY; + // Don't cache styles if we are inside a 's attributes. + if (GetContent()->GetParent() && + GetContent()->GetParent()->IsHTMLElement(nsGkAtoms::select)) { + for (auto& info : aElements) { + info.mKey = AnonymousContentKey::None; + } } UpdateChildrenAttributeValue(nsGkAtoms::curpos, false); diff --git a/modules/libpref/init/StaticPrefList.h b/modules/libpref/init/StaticPrefList.h index 441ab7e5133e..1066b68bb7ae 100644 --- a/modules/libpref/init/StaticPrefList.h +++ b/modules/libpref/init/StaticPrefList.h @@ -4703,6 +4703,14 @@ VARCACHE_PREF( RelaxedAtomicUint32, 4096 ) +// Is the codepath for using cached scrollbar styles enabled? +VARCACHE_PREF( + Live, + "layout.css.cached-scrollbar-styles.enabled", + layout_css_cached_scrollbar_styles_enabled, + bool, false +) + // Is path() supported in clip-path? VARCACHE_PREF( Live, @@ -4903,6 +4911,17 @@ VARCACHE_PREF( bool, false ) +// Pref to control whether the ::marker property restrictions defined in [1] +// apply. +// +// [1]: https://drafts.csswg.org/css-pseudo-4/#selectordef-marker +VARCACHE_PREF( + Live, + "layout.css.marker.restricted", + layout_css_marker_restricted, + bool, true +) + // Pref to control whether @-moz-document rules are enabled in content pages. VARCACHE_PREF( Live, diff --git a/servo/components/style/gecko/pseudo_element.rs b/servo/components/style/gecko/pseudo_element.rs index defa6bec18d5..501611830ffd 100644 --- a/servo/components/style/gecko/pseudo_element.rs +++ b/servo/components/style/gecko/pseudo_element.rs @@ -182,13 +182,18 @@ impl PseudoElement { /// Property flag that properties must have to apply to this pseudo-element. #[inline] pub fn property_restriction(&self) -> Option { - match *self { - PseudoElement::FirstLetter => Some(PropertyFlags::APPLIES_TO_FIRST_LETTER), - PseudoElement::FirstLine => Some(PropertyFlags::APPLIES_TO_FIRST_LINE), - PseudoElement::Placeholder => Some(PropertyFlags::APPLIES_TO_PLACEHOLDER), - PseudoElement::Cue => Some(PropertyFlags::APPLIES_TO_CUE), - _ => None, - } + Some(match *self { + PseudoElement::FirstLetter => PropertyFlags::APPLIES_TO_FIRST_LETTER, + PseudoElement::FirstLine => PropertyFlags::APPLIES_TO_FIRST_LINE, + PseudoElement::Placeholder => PropertyFlags::APPLIES_TO_PLACEHOLDER, + PseudoElement::Cue => PropertyFlags::APPLIES_TO_CUE, + PseudoElement::Marker + if unsafe { structs::StaticPrefs::sVarCache_layout_css_marker_restricted } => + { + PropertyFlags::APPLIES_TO_MARKER + }, + _ => return None, + }) } /// Whether this pseudo-element should actually exist if it has diff --git a/servo/components/style/properties/longhands/counters.mako.rs b/servo/components/style/properties/longhands/counters.mako.rs index f8971315603f..fce23f3a1eaf 100644 --- a/servo/components/style/properties/longhands/counters.mako.rs +++ b/servo/components/style/properties/longhands/counters.mako.rs @@ -13,6 +13,7 @@ ${helpers.predefined_type( initial_specified_value="specified::Content::normal()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-content/#propdef-content", + flags="APPLIES_TO_MARKER", servo_restyle_damage="rebuild_and_reflow", )} diff --git a/servo/components/style/properties/longhands/font.mako.rs b/servo/components/style/properties/longhands/font.mako.rs index 056828838046..098cb06b3a6d 100644 --- a/servo/components/style/properties/longhands/font.mako.rs +++ b/servo/components/style/properties/longhands/font.mako.rs @@ -12,7 +12,7 @@ ${helpers.predefined_type( "FontFamily", initial_value="computed::FontFamily::serif()", animation_value_type="discrete", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-family", servo_restyle_damage="rebuild_and_reflow", )} @@ -23,7 +23,7 @@ ${helpers.predefined_type( initial_value="computed::FontStyle::normal()", initial_specified_value="specified::FontStyle::normal()", animation_value_type="FontStyle", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-style", servo_restyle_damage="rebuild_and_reflow", )} @@ -42,7 +42,7 @@ ${helpers.single_keyword_system( gecko_ffi_name="mFont.variantCaps", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps", custom_consts=font_variant_caps_custom_consts, - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", animation_value_type="discrete", servo_restyle_damage="rebuild_and_reflow", )} @@ -53,7 +53,7 @@ ${helpers.predefined_type( initial_value="computed::FontWeight::normal()", initial_specified_value="specified::FontWeight::normal()", animation_value_type="Number", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight", servo_restyle_damage="rebuild_and_reflow", )} @@ -65,7 +65,7 @@ ${helpers.predefined_type( initial_specified_value="specified::FontSize::medium()", animation_value_type="NonNegativeLength", allow_quirks="Yes", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-size", servo_restyle_damage="rebuild_and_reflow", )} @@ -77,7 +77,7 @@ ${helpers.predefined_type( initial_value="computed::FontSizeAdjust::none()", initial_specified_value="specified::FontSizeAdjust::none()", animation_value_type="ComputedValue", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust", )} @@ -87,7 +87,7 @@ ${helpers.predefined_type( products="gecko", initial_value="specified::FontSynthesis::get_initial_value()", animation_value_type="discrete", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-synthesis", )} @@ -97,7 +97,7 @@ ${helpers.predefined_type( initial_value="computed::FontStretch::hundred()", initial_specified_value="specified::FontStretch::normal()", animation_value_type="Percentage", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch", servo_restyle_damage="rebuild_and_reflow", )} @@ -109,7 +109,7 @@ ${helpers.single_keyword_system( gecko_ffi_name="mFont.kerning", gecko_constant_prefix="NS_FONT_KERNING", spec="https://drafts.csswg.org/css-fonts/#propdef-font-kerning", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", animation_value_type="discrete", )} @@ -120,7 +120,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariantAlternates::get_initial_value()", initial_specified_value="specified::FontVariantAlternates::get_initial_specified_value()", animation_value_type="discrete", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates", )} @@ -131,7 +131,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariantEastAsian::empty()", initial_specified_value="specified::FontVariantEastAsian::empty()", animation_value_type="discrete", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian", )} @@ -142,7 +142,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariantLigatures::empty()", initial_specified_value="specified::FontVariantLigatures::empty()", animation_value_type="discrete", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures", )} @@ -153,7 +153,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariantNumeric::empty()", initial_specified_value="specified::FontVariantNumeric::empty()", animation_value_type="discrete", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric", )} @@ -164,7 +164,7 @@ ${helpers.single_keyword_system( gecko_ffi_name="mFont.variantPosition", gecko_constant_prefix="NS_FONT_VARIANT_POSITION", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", animation_value_type="discrete", )} @@ -176,7 +176,7 @@ ${helpers.predefined_type( initial_specified_value="specified::FontFeatureSettings::normal()", extra_prefixes="moz:layout.css.prefixes.font-features", animation_value_type="discrete", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings", )} @@ -195,7 +195,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariationSettings::normal()", initial_specified_value="specified::FontVariationSettings::normal()", animation_value_type="ComputedValue", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="${variation_spec}", )} @@ -207,7 +207,7 @@ ${helpers.predefined_type( initial_specified_value="specified::FontLanguageOverride::normal()", animation_value_type="discrete", extra_prefixes="moz:layout.css.prefixes.font-features", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override", )} @@ -219,7 +219,7 @@ ${helpers.single_keyword_system( gecko_ffi_name="mFont.opticalSizing", gecko_constant_prefix="NS_FONT_OPTICAL_SIZING", animation_value_type="discrete", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://www.w3.org/TR/css-fonts-4/#font-optical-sizing-def", )} @@ -514,7 +514,7 @@ ${helpers.single_keyword( gecko_pref="layout.css.osx-font-smoothing.enabled", products="gecko", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth)", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", animation_value_type="discrete", )} diff --git a/servo/components/style/properties/longhands/inherited_box.mako.rs b/servo/components/style/properties/longhands/inherited_box.mako.rs index a7dee5dc03d4..94ed265defa7 100644 --- a/servo/components/style/properties/longhands/inherited_box.mako.rs +++ b/servo/components/style/properties/longhands/inherited_box.mako.rs @@ -38,6 +38,7 @@ ${helpers.single_keyword( animation_value_type="none", spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction", needs_conversion=True, + flags="APPLIES_TO_MARKER", servo_restyle_damage="rebuild_and_reflow", )} diff --git a/servo/components/style/properties/longhands/inherited_text.mako.rs b/servo/components/style/properties/longhands/inherited_text.mako.rs index 7de8b5e20b11..f10f347e7f8d 100644 --- a/servo/components/style/properties/longhands/inherited_text.mako.rs +++ b/servo/components/style/properties/longhands/inherited_text.mako.rs @@ -11,7 +11,7 @@ ${helpers.predefined_type( "ColorPropertyValue", "::cssparser::RGBA::new(0, 0, 0, 255)", animation_value_type="AnimatedRGBA", - flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", ignored_when_colors_disabled="True", spec="https://drafts.csswg.org/css-color/#color", )} @@ -349,7 +349,7 @@ ${helpers.single_keyword( products="gecko", animation_value_type="discrete", spec="https://drafts.csswg.org/css-writing-modes-3/#text-combine-upright", - flags="APPLIES_TO_CUE", + flags="APPLIES_TO_CUE APPLIES_TO_MARKER", )} // SVG 1.1: Section 11 - Painting: Filling, Stroking and Marker Symbols diff --git a/servo/components/style/properties/longhands/text.mako.rs b/servo/components/style/properties/longhands/text.mako.rs index f7c77a160299..44adc21766dd 100644 --- a/servo/components/style/properties/longhands/text.mako.rs +++ b/servo/components/style/properties/longhands/text.mako.rs @@ -23,6 +23,7 @@ ${helpers.single_keyword( "normal embed isolate bidi-override isolate-override plaintext", animation_value_type="none", spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi", + flags="APPLIES_TO_MARKER", servo_restyle_damage="rebuild_and_reflow", )} diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index 72a194b0c2c7..4f07d6feb841 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -956,13 +956,15 @@ bitflags! { const APPLIES_TO_PLACEHOLDER = 1 << 5; /// This longhand property applies to ::cue. const APPLIES_TO_CUE = 1 << 6; + /// This longhand property applies to ::marker. + const APPLIES_TO_MARKER = 1 << 7; /// This property's getComputedStyle implementation requires layout /// to be flushed. - const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 7; + const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 8; /// This property is a legacy shorthand. /// /// https://drafts.csswg.org/css-cascade/#legacy-shorthand - const IS_LEGACY_SHORTHAND = 1 << 8; + const IS_LEGACY_SHORTHAND = 1 << 9; /* The following flags are currently not used in Rust code, they * only need to be listed in corresponding properties so that @@ -2836,6 +2838,19 @@ impl ComputedValues { pub fn resolve_color(&self, color: computed::Color) -> RGBA { color.to_rgba(self.get_inherited_text().clone_color()) } + + /// Returns which longhand properties have different values in the two + /// ComputedValues. + #[cfg(feature = "gecko_debug")] + pub fn differing_properties(&self, other: &ComputedValues) -> LonghandIdSet { + let mut set = LonghandIdSet::new(); + % for prop in data.longhands: + if self.clone_${prop.ident}() != other.clone_${prop.ident}() { + set.insert(LonghandId::${prop.camel_case}); + } + % endfor + set + } } #[cfg(feature = "servo")] diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index b5cecf773cc1..dad9700fabd4 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -3746,6 +3746,69 @@ pub extern "C" fn Servo_ComputedValues_GetStyleRuleList( })) } +/// println_stderr!() calls Gecko's printf_stderr(), which, unlike eprintln!(), +/// will funnel output to Android logcat. +#[cfg(feature = "gecko_debug")] +macro_rules! println_stderr { + ($($e:expr),+) => { + { + let mut s = nsCString::new(); + write!(s, $($e),+).unwrap(); + s.write_char('\n').unwrap(); + unsafe { bindings::Gecko_PrintfStderr(&s); } + } + } +} + +#[cfg(feature = "gecko_debug")] +fn dump_properties_and_rules(cv: &ComputedValues, properties: &LonghandIdSet) { + println_stderr!(" Properties:"); + for p in properties.iter() { + let mut v = String::new(); + cv.get_longhand_property_value(p, &mut CssWriter::new(&mut v)).unwrap(); + println_stderr!(" {:?}: {}", p, v); + } + println_stderr!(" Rules:"); + let global_style_data = &*GLOBAL_STYLE_DATA; + let guard = global_style_data.shared_lock.read(); + for rn in cv.rules().self_and_ancestors() { + if rn.importance().important() { + continue; + } + if let Some(d) = rn.style_source().and_then(|s| s.as_declarations()) { + println_stderr!(" [DeclarationBlock: {:?}]", d); + } + if let Some(r) = rn.style_source().and_then(|s| s.as_rule()) { + let mut s = nsString::new(); + r.read_with(&guard).to_css(&guard, &mut s).unwrap(); + println_stderr!(" {}", s); + } + } +} + +#[cfg(feature = "gecko_debug")] +#[no_mangle] +pub extern "C" fn Servo_ComputedValues_EqualForCachedAnonymousContentStyle( + a: &ComputedValues, + b: &ComputedValues, +) -> bool { + let mut differing_properties = a.differing_properties(b); + + // Ignore any difference in -x-lang, which we can't override in the + // rules in minimal-xul.css, but which makes no difference for the + // anonymous content subtrees we cache style for. + differing_properties.remove(LonghandId::XLang); + + if !differing_properties.is_empty() { + println_stderr!("Actual style:"); + dump_properties_and_rules(a, &differing_properties); + println_stderr!("Expected style:"); + dump_properties_and_rules(b, &differing_properties); + } + + differing_properties.is_empty() +} + #[no_mangle] pub extern "C" fn Servo_StyleSet_Init(doc: &structs::Document) -> *mut RawServoStyleSet { let data = Box::new(PerDocumentStyleData::new(doc)); @@ -5089,7 +5152,6 @@ pub extern "C" fn Servo_TakeChangeHint( #[no_mangle] pub extern "C" fn Servo_ResolveStyle( element: &RawGeckoElement, - _raw_data: &RawServoStyleSet, ) -> Strong { let element = GeckoElement(element); debug!("Servo_ResolveStyle: {:?}", element); diff --git a/testing/talos/talos/tests/perf-reftest-singletons/perf_reftest_singletons.manifest b/testing/talos/talos/tests/perf-reftest-singletons/perf_reftest_singletons.manifest index ff57c498187c..37f0d17dc8d4 100644 --- a/testing/talos/talos/tests/perf-reftest-singletons/perf_reftest_singletons.manifest +++ b/testing/talos/talos/tests/perf-reftest-singletons/perf_reftest_singletons.manifest @@ -13,9 +13,7 @@ % http://localhost/tests/perf-reftest-singletons/tiny-traversal-singleton.html % http://localhost/tests/perf-reftest-singletons/nth-index-1.html % http://localhost/tests/perf-reftest-singletons/nth-index-2.html - % http://localhost/tests/perf-reftest-singletons/bidi-resolution-1.html - % http://localhost/tests/perf-reftest-singletons/id-getter-1.html % http://localhost/tests/perf-reftest-singletons/id-getter-2.html % http://localhost/tests/perf-reftest-singletons/id-getter-3.html @@ -23,5 +21,5 @@ % http://localhost/tests/perf-reftest-singletons/id-getter-5.html % http://localhost/tests/perf-reftest-singletons/id-getter-6.html % http://localhost/tests/perf-reftest-singletons/id-getter-7.html - % http://localhost/tests/perf-reftest-singletons/abspos-reflow-1.html +% http://localhost/tests/perf-reftest-singletons/scrollbar-styles-1.html diff --git a/testing/talos/talos/tests/perf-reftest-singletons/scrollbar-styles-1.html b/testing/talos/talos/tests/perf-reftest-singletons/scrollbar-styles-1.html new file mode 100644 index 000000000000..cc69f3b7c57e --- /dev/null +++ b/testing/talos/talos/tests/perf-reftest-singletons/scrollbar-styles-1.html @@ -0,0 +1,16 @@ + + + + + diff --git a/testing/web-platform/meta/css/css-animations/__dir__.ini b/testing/web-platform/meta/css/css-animations/__dir__.ini index c6ea259f0f3d..dd0148c56e1b 100644 --- a/testing/web-platform/meta/css/css-animations/__dir__.ini +++ b/testing/web-platform/meta/css/css-animations/__dir__.ini @@ -1 +1 @@ -prefs: [dom.animations-api.compositing.enabled:true, dom.animations-api.core.enabled:true, dom.animations-api.getAnimations.enabled:true, dom.animations-api.implicit-keyframes.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.step-position-jump.enabled:true] +prefs: [dom.animations-api.compositing.enabled:true, dom.animations-api.core.enabled:true, dom.animations-api.getAnimations.enabled:true, dom.animations-api.implicit-keyframes.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.step-position-jump.enabled:true, layout.css.marker.restricted:false] diff --git a/testing/web-platform/meta/css/css-pseudo/marker-content-007.html.ini b/testing/web-platform/meta/css/css-pseudo/marker-content-007.html.ini new file mode 100644 index 000000000000..c01d3ff3990b --- /dev/null +++ b/testing/web-platform/meta/css/css-pseudo/marker-content-007.html.ini @@ -0,0 +1,2 @@ +[marker-content-007.html] + prefs: [layout.css.marker.restricted:false] diff --git a/testing/web-platform/meta/css/css-pseudo/marker-content-008.html.ini b/testing/web-platform/meta/css/css-pseudo/marker-content-008.html.ini new file mode 100644 index 000000000000..f382523adb48 --- /dev/null +++ b/testing/web-platform/meta/css/css-pseudo/marker-content-008.html.ini @@ -0,0 +1,2 @@ +[marker-content-008.html] + prefs: [layout.css.marker.restricted:false] diff --git a/testing/web-platform/meta/css/css-pseudo/marker-content-009.html.ini b/testing/web-platform/meta/css/css-pseudo/marker-content-009.html.ini new file mode 100644 index 000000000000..aaa8d45b6763 --- /dev/null +++ b/testing/web-platform/meta/css/css-pseudo/marker-content-009.html.ini @@ -0,0 +1,2 @@ +[marker-content-009.html] + prefs: [layout.css.marker.restricted:false] diff --git a/testing/web-platform/meta/css/css-pseudo/marker-content-011.html.ini b/testing/web-platform/meta/css/css-pseudo/marker-content-011.html.ini new file mode 100644 index 000000000000..ea15ac842d5f --- /dev/null +++ b/testing/web-platform/meta/css/css-pseudo/marker-content-011.html.ini @@ -0,0 +1,2 @@ +[marker-content-011.html] + prefs: [layout.css.marker.restricted:false] diff --git a/testing/web-platform/meta/css/css-transitions/__dir__.ini b/testing/web-platform/meta/css/css-transitions/__dir__.ini index c6ea259f0f3d..dd0148c56e1b 100644 --- a/testing/web-platform/meta/css/css-transitions/__dir__.ini +++ b/testing/web-platform/meta/css/css-transitions/__dir__.ini @@ -1 +1 @@ -prefs: [dom.animations-api.compositing.enabled:true, dom.animations-api.core.enabled:true, dom.animations-api.getAnimations.enabled:true, dom.animations-api.implicit-keyframes.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.step-position-jump.enabled:true] +prefs: [dom.animations-api.compositing.enabled:true, dom.animations-api.core.enabled:true, dom.animations-api.getAnimations.enabled:true, dom.animations-api.implicit-keyframes.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.step-position-jump.enabled:true, layout.css.marker.restricted:false] diff --git a/testing/web-platform/meta/web-animations/__dir__.ini b/testing/web-platform/meta/web-animations/__dir__.ini index 7e0e6bed671f..3057f6101169 100644 --- a/testing/web-platform/meta/web-animations/__dir__.ini +++ b/testing/web-platform/meta/web-animations/__dir__.ini @@ -1 +1 @@ -prefs: [dom.animations-api.autoremove.enabled:true, dom.animations-api.compositing.enabled:true, dom.animations-api.core.enabled:true, dom.animations-api.getAnimations.enabled:true, dom.animations-api.implicit-keyframes.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.step-position-jump.enabled:true] +prefs: [dom.animations-api.autoremove.enabled:true, dom.animations-api.compositing.enabled:true, dom.animations-api.core.enabled:true, dom.animations-api.getAnimations.enabled:true, dom.animations-api.implicit-keyframes.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.step-position-jump.enabled:true, layout.css.marker.restricted:false] diff --git a/testing/web-platform/tests/mediacapture-streams/MediaStreamTrack-end-manual.https.html b/testing/web-platform/tests/mediacapture-streams/MediaStreamTrack-end-manual.https.html index 310d1b050b70..b27b455d147a 100644 --- a/testing/web-platform/tests/mediacapture-streams/MediaStreamTrack-end-manual.https.html +++ b/testing/web-platform/tests/mediacapture-streams/MediaStreamTrack-end-manual.https.html @@ -17,22 +17,34 @@ correctly set into inactive state when permission is revoked.

diff --git a/testing/web-platform/tests/mediacapture-streams/historical.https.html b/testing/web-platform/tests/mediacapture-streams/historical.https.html index 74efc7584211..9437c51552ab 100644 --- a/testing/web-platform/tests/mediacapture-streams/historical.https.html +++ b/testing/web-platform/tests/mediacapture-streams/historical.https.html @@ -20,4 +20,14 @@ test(() => { const mediaStream = new MediaStream(); assert_throws(new TypeError(), () => URL.createObjectURL(mediaStream)); }, "Passing MediaStream to URL.createObjectURL() should throw"); + +test(() => { + const mediaStream = new MediaStream(); + assert_false("onactive" in mediaStream); +}, "MediaStream.onactive should not exist"); + +test(() => { + const mediaStream = new MediaStream(); + assert_false("oninactive" in mediaStream); +}, "MediaStream.oninactive should not exist"); diff --git a/toolkit/content/minimal-xul.css b/toolkit/content/minimal-xul.css index 9e1d3d9f29d2..40732c96d913 100644 --- a/toolkit/content/minimal-xul.css +++ b/toolkit/content/minimal-xul.css @@ -38,6 +38,61 @@ visibility: collapse; } +/* Rules required for style caching of anonymous content scrollbar parts */ + +scrollcorner, resizer, scrollbar, scrollbarbutton, slider { + /* All scrollbar parts must not inherit any properties from the scrollable + * element (except for visibility), for the anonymous content style caching + * system to work. + */ + all: initial; + visibility: inherit; + + /* These properties are not included in 'all'. */ + -moz-list-reversed: initial; + -moz-font-smoothing-background-color: initial; + + /* Using initial is not sufficient for direction, since its initial value can + * depend on the document's language. + * + * LTR is what we want for all scrollbar parts anyway, so that e.g. we don't + * reverse the rendering of a horizontal scrollbar. + */ + direction: ltr; + + /* Similarly for font properties, whose initial values depend on the + * document's language. Scrollbar parts don't have any text or rely on + * font metrics. + */ + font: 16px sans-serif; + + /* Duplicate the rules from the '*' rule above, which were clobbered by the + * 'all: initial' declaration. + * + * The other zero specificity rules above are on :root, and scrollbar parts + * cannot match :root, so no need to duplicate them. + */ + -moz-user-focus: ignore; + -moz-user-select: none; + display: -moz-box; + box-sizing: border-box; +} + +thumb { + /* Prevent -moz-user-modify declaration from designmode.css having an + * effect. */ + -moz-user-modify: initial; +} + +/* There are other rules that set direction and cursor on scrollbar, + * expecting them to inherit into its children. Explicitly inherit those, + * overriding the 'all: initial; direction: ltr;' declarations above. + */ +scrollbarbutton, slider, thumb { + direction: inherit; + cursor: inherit; +} + /********** resizer **********/ resizer { @@ -97,11 +152,6 @@ resizer[dir="topright"] { /********** scrollbar **********/ -/* Scrollbars are never flipped even if BiDI kicks in. */ -scrollbar[orient="horizontal"] { - direction: ltr; -} - thumb { display: -moz-box !important; } @@ -152,7 +202,7 @@ scrollbar[value="hidden"] { } @media (-moz-scrollbar-thumb-proportional) { - thumb[sbattr="scrollbar-thumb"] { + thumb { -moz-box-flex: 1; } }