Merge inbound to mozilla-central. a=merge

This commit is contained in:
Noemi Erli 2018-01-19 12:10:24 +02:00
Родитель 4c1eb3b8bf a1dd98ef44
Коммит 1e1fdc2b3d
88 изменённых файлов: 1302 добавлений и 406 удалений

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

@ -121,21 +121,16 @@ this.ShieldPreferences = {
viewStudies.classList.add("learnMore", "text-link");
hContainer.appendChild(viewStudies);
const optOutPref = doc.createElementNS(XUL_NS, "preference");
optOutPref.setAttribute("id", OPT_OUT_STUDIES_ENABLED_PREF);
optOutPref.setAttribute("name", OPT_OUT_STUDIES_ENABLED_PREF);
optOutPref.setAttribute("type", "bool");
// Preference instances for prefs that we need to monitor while the page is open.
doc.defaultView.Preferences.add({ id: OPT_OUT_STUDIES_ENABLED_PREF, type: "bool" });
// Weirdly, FHR doesn't have a <preference> element on the page, so we create it.
// Weirdly, FHR doesn't have a Preference instance on the page, so we create it.
const fhrPref = doc.defaultView.Preferences.add({ id: FHR_UPLOAD_ENABLED_PREF, type: "bool" });
fhrPref.on("change", function(event) {
// Avoid reference to the document directly, to avoid leaks.
const eventTargetCheckbox = event.target.ownerDocument.getElementById("optOutStudiesEnabled");
eventTargetCheckbox.disabled = !Services.prefs.getBoolPref(FHR_UPLOAD_ENABLED_PREF);
});
function onChangeFHRPref(event) {
checkbox.disabled = !Services.prefs.getBoolPref(FHR_UPLOAD_ENABLED_PREF);
}
fhrPref.on("change", onChangeFHRPref);
doc.defaultView.addEventListener("unload", () => fhrPref.off("change", onChangeFHRPref), { once: true });
// Actually inject the elements we've created.
const parent = doc.getElementById("submitHealthReportBox").closest("description");

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

@ -171,9 +171,11 @@ decorate_task(
await BrowserTestUtils.waitForLocationChange(gBrowser);
is(
browser.currentURI.spec,
gBrowser.currentURI.spec,
"about:studies",
"Clicking the view studies link opens about:studies."
"Clicking the view studies link opens about:studies in a new tab."
);
gBrowser.removeCurrentTab();
}
);

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

@ -39,7 +39,6 @@ XPIDL_SOURCES += [
'nsCDefaultURIFixup.idl',
'nsIClipboardCommands.idl',
'nsIContentViewer.idl',
'nsIContentViewerContainer.idl',
'nsIContentViewerEdit.idl',
'nsIDocCharset.idl',
'nsIDocShell.idl',

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

@ -513,7 +513,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocShell)
NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIContentViewerContainer)
NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)
NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
NS_INTERFACE_MAP_ENTRY(nsILoadContext)
@ -6856,11 +6855,7 @@ nsDocShell::RefreshURIFromQueue()
return NS_OK;
}
//*****************************************************************************
// nsDocShell::nsIContentViewerContainer
//*****************************************************************************
NS_IMETHODIMP
nsresult
nsDocShell::Embed(nsIContentViewer* aContentViewer,
const char* aCommand, nsISupports* aExtraInfo)
{
@ -6923,12 +6918,6 @@ nsDocShell::Embed(nsIContentViewer* aContentViewer,
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetIsPrinting(bool aIsPrinting)
{
mIsPrintingOrPP = aIsPrinting;
return NS_OK;
}
//*****************************************************************************
// nsDocShell::nsIWebProgressListener
@ -13857,6 +13846,13 @@ nsDocShell::StopDocumentLoad(void)
return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
}
NS_IMETHODIMP
nsDocShell::SetIsPrinting(bool aIsPrinting)
{
mIsPrintingOrPP = aIsPrinting;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
{

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

@ -20,7 +20,6 @@
#include "nsIAuthPromptProvider.h"
#include "nsIBaseWindow.h"
#include "nsIClipboardCommands.h"
#include "nsIContentViewerContainer.h"
#include "nsIDeprecationWarner.h"
#include "nsIDocCharset.h"
#include "nsIDocShell.h"
@ -127,7 +126,6 @@ class nsDocShell final
, public nsIScrollable
, public nsITextScroll
, public nsIDocCharset
, public nsIContentViewerContainer
, public nsIRefreshURI
, public nsIWebProgressListener
, public nsIWebPageDescriptor
@ -183,7 +181,6 @@ public:
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWEBPROGRESSLISTENER
NS_DECL_NSIREFRESHURI
NS_DECL_NSICONTENTVIEWERCONTAINER
NS_DECL_NSIWEBPAGEDESCRIPTOR
NS_DECL_NSIAUTHPROMPTPROVIDER
NS_DECL_NSICLIPBOARDCOMMANDS
@ -869,6 +866,8 @@ private: // member functions
nsresult EnsureFind();
nsresult EnsureCommandHandler();
nsresult RefreshURIFromQueue();
nsresult Embed(nsIContentViewer* aContentViewer,
const char* aCommand, nsISupports* aExtraInfo);
nsresult GetEldestPresContext(nsPresContext** aPresContext);
nsresult CheckLoadingPermissions();
nsresult PersistLayoutHistoryState();

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

@ -1,20 +0,0 @@
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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/. */
#include "nsISupports.idl"
interface nsIContentViewer;
[scriptable, uuid(ea2ce7a0-5c3d-11d4-90c2-0050041caf44)]
interface nsIContentViewerContainer : nsISupports {
void embed(in nsIContentViewer aDocViewer, in string aCommand, in nsISupports aExtraInfo);
/**
* Allows nsPrintJob to make this call on an internal interface to the
* DocShell.
*/
void setIsPrinting(in boolean aIsPrinting);
};

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

@ -655,6 +655,12 @@ interface nsIDocShell : nsIDocShellTreeItem
**/
attribute boolean isOffScreenBrowser;
/**
* Allows nsDocumentViewer to tell the top-level same-type docshell that
* one of the documents under it is printing.
*/
void setIsPrinting(in boolean aIsPrinting);
/**
* If the current content viewer isn't initialized for print preview,
* it is replaced with one which is and to which an about:blank document

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

@ -32,7 +32,6 @@
#include "nsIIOService.h"
#include "nsNetUtil.h"
#include "nsIPrivateBrowsingChannel.h"
#include "nsIContentViewerContainer.h"
#include "nsIContentViewer.h"
#include "nsDocShell.h"
#include "nsDocShellLoadTypes.h"

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

@ -473,12 +473,6 @@ cubeb* GetCubebContextUnlocked()
NS_WARNING_ASSERTION(rv == CUBEB_OK, "Could not get a cubeb context.");
sCubebState = (rv == CUBEB_OK) ? CubebState::Initialized : CubebState::Uninitialized;
if (MOZ_LOG_TEST(gCubebLog, LogLevel::Verbose)) {
cubeb_set_log_callback(CUBEB_LOG_VERBOSE, CubebLogCallback);
} else if (MOZ_LOG_TEST(gCubebLog, LogLevel::Error)) {
cubeb_set_log_callback(CUBEB_LOG_NORMAL, CubebLogCallback);
}
return sCubebContext;
}
@ -550,10 +544,15 @@ void InitLibrary()
Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_LATENCY_MSG);
Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_BACKEND);
Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_SANDBOX);
if (MOZ_LOG_TEST(gCubebLog, LogLevel::Verbose)) {
cubeb_set_log_callback(CUBEB_LOG_VERBOSE, CubebLogCallback);
} else if (MOZ_LOG_TEST(gCubebLog, LogLevel::Error)) {
cubeb_set_log_callback(CUBEB_LOG_NORMAL, CubebLogCallback);
}
// We don't want to call the callback on startup, because the pref is the
// empty string by default ("", which means "logging disabled"). Because the
// logging can be enabled via environment variables (MOZ_LOG="module:5"),
// calling this callback on init would immediately re-disble the logging.
// calling this callback on init would immediately re-disable the logging.
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LOGGING_LEVEL);
#ifndef MOZ_WIDGET_ANDROID
AbstractThread::MainThread()->Dispatch(

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

@ -65,6 +65,8 @@
using JS::SourceBufferHolder;
using mozilla::Telemetry::LABELS_DOM_SCRIPT_PRELOAD_RESULT;
namespace mozilla {
namespace dom {
@ -180,6 +182,10 @@ ScriptLoader::~ScriptLoader()
for (uint32_t j = 0; j < mPendingChildLoaders.Length(); ++j) {
mPendingChildLoaders[j]->RemoveParserBlockingScriptExecutionBlocker();
}
for (size_t i = 0; i < mPreloads.Length(); i++) {
AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::NotUsed);
}
}
// Collect telemtry data about the cache information, and the kind of source
@ -195,6 +201,13 @@ CollectScriptTelemetry(nsIIncrementalStreamLoader* aLoader,
return;
}
// Report the script kind.
if (aRequest->IsModuleRequest()) {
AccumulateCategorical(LABELS_DOM_SCRIPT_KIND::ModuleScript);
} else {
AccumulateCategorical(LABELS_DOM_SCRIPT_KIND::ClassicScript);
}
// Report the type of source, as well as the size of the source.
if (aRequest->IsLoadingSource()) {
if (aRequest->mIsInline) {
@ -1316,6 +1329,7 @@ ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
// Probably plans have changed; even though the preload was allowed seems
// like the actual load is not; let's cancel the preload request.
request->Cancel();
AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::RejectedByPolicy);
return false;
}
@ -1326,6 +1340,8 @@ ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
// update them here.
request->SetScriptMode(aElement->GetScriptDeferred(),
aElement->GetScriptAsync());
AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::Used);
} else {
// No usable preload found.
@ -1581,6 +1597,7 @@ ScriptLoader::LookupPreloadRequest(nsIScriptElement* aElement,
mDocument->GetReferrerPolicy() != request->mReferrerPolicy ||
aScriptKind != request->mKind) {
// Drop the preload.
AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::RequestMismatch);
return nullptr;
}
@ -2957,6 +2974,7 @@ ScriptLoader::HandleLoadError(ScriptLoadRequest *aRequest, nsresult aResult)
mCurrentParserInsertedScript = oldParserInsertedScript;
} else {
mPreloads.RemoveElement(aRequest, PreloadRequestComparator());
AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::LoadError);
}
}

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

@ -11,7 +11,6 @@
#include "nsIXMLContentSink.h"
#include "nsPresContext.h"
#include "nsIContent.h"
#include "nsIContentViewerContainer.h"
#include "nsIContentViewer.h"
#include "nsIDocShell.h"
#include "nsHTMLParts.h"

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

@ -242,9 +242,9 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
copy.CopyBuffer();
}
}
} else {
gfxWarning() << "[Tiling:Client] Failed to aquire the discarded front buffer's draw target";
}
} else {
gfxWarning() << "[Tiling:Client] Failed to aquire the discarded front buffer's draw target";
}
} else {
gfxWarning() << "[Tiling:Client] Failed to aquire the discarded front buffer's draw target";
@ -336,12 +336,6 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
mTile.Flip();
UnlockTile(mTile);
if (backBuffer->HasIntermediateBuffer()) {
// If our new buffer has an internal buffer, we don't want to keep another
// TextureClient around unnecessarily, so discard the back-buffer.
mTile.DiscardBackBuffer();
}
mValidRegion = aNewValidRegion;
mLastPaintSurfaceMode = mode;
mLastPaintContentType = content;

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

@ -1995,9 +1995,18 @@ gfxFont::DrawMissingGlyph(const TextRunDrawParams& aRunParams,
float advance = aDetails->mAdvance;
if (aRunParams.drawMode != DrawMode::GLYPH_PATH && advance > 0) {
auto* textDrawer = aRunParams.context->GetTextDrawer();
const Matrix* matPtr = nullptr;
Matrix mat;
if (textDrawer) {
textDrawer->FoundUnsupportedFeature();
return false;
// Generate an orientation matrix for the current writing mode
wr::FontInstanceFlags flags = textDrawer->GetWRGlyphFlags();
if (flags.bits & wr::FontInstanceFlags::TRANSPOSE) {
std::swap(mat._11, mat._12);
std::swap(mat._21, mat._22);
}
mat.PostScale(flags.bits & wr::FontInstanceFlags::FLIP_X ? -1.0f : 1.0f,
flags.bits & wr::FontInstanceFlags::FLIP_Y ? -1.0f : 1.0f);
matPtr = &mat;
}
Point pt(Float(ToDeviceUnits(aPt.x, aRunParams.devPerApp)),
@ -2005,7 +2014,8 @@ gfxFont::DrawMissingGlyph(const TextRunDrawParams& aRunParams,
Float advanceDevUnits =
Float(ToDeviceUnits(advance, aRunParams.devPerApp));
Float height = GetMetrics(eHorizontal).maxAscent;
Rect glyphRect = aFontParams.isVerticalFont ?
// Horizontally center if drawing vertically upright with no sideways transform.
Rect glyphRect = aFontParams.isVerticalFont && !mat.HasNonAxisAlignedTransform() ?
Rect(pt.x - height / 2, pt.y,
height, advanceDevUnits) :
Rect(pt.x, pt.y - height,
@ -2028,7 +2038,7 @@ gfxFont::DrawMissingGlyph(const TextRunDrawParams& aRunParams,
gfxFontMissingGlyphs::DrawMissingGlyph(
aDetails->mGlyphID, glyphRect, *aRunParams.dt,
PatternFromState(aRunParams.context),
1.0 / aRunParams.devPerApp);
1.0 / aRunParams.devPerApp, matPtr);
}
return true;
}

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

@ -158,13 +158,39 @@ static const Float BOX_BORDER_OPACITY = 0.5;
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
static void
DrawHexChar(uint32_t aDigit, const Point& aPt, DrawTarget& aDrawTarget,
const Pattern &aPattern)
const Pattern &aPattern, const Matrix* aMat)
{
uint32_t glyphBits = glyphMicroFont[aDigit];
if (aMat) {
// If using an orientation matrix instead of a DT transform, step
// with the matrix basis vectors, filling individual rectangles of
// the size indicated by the matrix.
Point stepX(aMat->_11, aMat->_12);
Point stepY(aMat->_21, aMat->_22);
Point corner = stepX + stepY;
// Get the rectangle at the origin that will be stepped into place.
Rect startRect(std::min(corner.x, 0.0f), std::min(corner.y, 0.0f),
fabs(corner.x), fabs(corner.y));
startRect.MoveBy(aMat->TransformPoint(aPt));
for (int y = 0; y < MINIFONT_HEIGHT; ++y) {
Rect curRect = startRect;
for (int x = 0; x < MINIFONT_WIDTH; ++x) {
if (glyphBits & 1) {
aDrawTarget.FillRect(curRect, aPattern);
}
glyphBits >>= 1;
curRect.MoveBy(stepX);
}
startRect.MoveBy(stepY);
}
return;
}
// To avoid the potential for seams showing between rects when we're under
// a transform we concat all the rects into a PathBuilder and fill the
// resulting Path (rather than using DrawTarget::FillRect).
RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder();
uint32_t glyphBits = glyphMicroFont[aDigit];
for (int y = 0; y < MINIFONT_HEIGHT; ++y) {
for (int x = 0; x < MINIFONT_WIDTH; ++x) {
if (glyphBits & 1) {
@ -189,8 +215,17 @@ gfxFontMissingGlyphs::DrawMissingGlyph(uint32_t aChar,
const Rect& aRect,
DrawTarget& aDrawTarget,
const Pattern& aPattern,
uint32_t aAppUnitsPerDevPixel)
uint32_t aAppUnitsPerDevPixel,
const Matrix* aMat)
{
Rect rect(aRect);
// If there is an orientation transform, reorient the bounding rect.
if (aMat) {
rect.MoveBy(-aRect.BottomLeft());
rect = aMat->TransformBounds(rect);
rect.MoveBy(aRect.BottomLeft());
}
// If we're currently drawing with some kind of pattern, we just draw the
// missing-glyph data in black.
ColorPattern color = aPattern.GetType() == PatternType::COLOR ?
@ -201,11 +236,11 @@ gfxFontMissingGlyphs::DrawMissingGlyph(uint32_t aChar,
// from the left edge of the glyph box and the stroke's right edge
// is inset one pixel from the right edge of the glyph box.
Float halfBorderWidth = BOX_BORDER_WIDTH / 2.0;
Float borderLeft = aRect.X() + BOX_HORIZONTAL_INSET + halfBorderWidth;
Float borderRight = aRect.XMost() - BOX_HORIZONTAL_INSET - halfBorderWidth;
Rect borderStrokeRect(borderLeft, aRect.Y() + halfBorderWidth,
Float borderLeft = rect.X() + BOX_HORIZONTAL_INSET + halfBorderWidth;
Float borderRight = rect.XMost() - BOX_HORIZONTAL_INSET - halfBorderWidth;
Rect borderStrokeRect(borderLeft, rect.Y() + halfBorderWidth,
borderRight - borderLeft,
aRect.Height() - 2.0 * halfBorderWidth);
rect.Height() - 2.0 * halfBorderWidth);
if (!borderStrokeRect.IsEmpty()) {
ColorPattern adjustedColor = color;
color.mColor.a *= BOX_BORDER_OPACITY;
@ -218,7 +253,7 @@ gfxFontMissingGlyphs::DrawMissingGlyph(uint32_t aChar,
}
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
Point center = aRect.Center();
Point center = rect.Center();
Float halfGap = HEX_CHAR_GAP / 2.f;
Float top = -(MINIFONT_HEIGHT + halfGap);
// We always want integer scaling, otherwise the "bitmap" glyphs will look
@ -226,46 +261,65 @@ gfxFontMissingGlyphs::DrawMissingGlyph(uint32_t aChar,
int32_t devPixelsPerCSSPx =
std::max<int32_t>(1, nsDeviceContext::AppUnitsPerCSSPixel() /
aAppUnitsPerDevPixel);
AutoRestoreTransform autoRestoreTransform(&aDrawTarget);
aDrawTarget.SetTransform(
aDrawTarget.GetTransform().PreTranslate(center).
PreScale(devPixelsPerCSSPx,
devPixelsPerCSSPx));
Matrix tempMat;
if (aMat) {
// If there is an orientation transform, since draw target transforms may
// not be supported, scale and translate it so that it can be directly used
// for rendering the mini font without changing the draw target transform.
tempMat = Matrix(*aMat).PostScale(devPixelsPerCSSPx, devPixelsPerCSSPx)
.PostTranslate(center);
aMat = &tempMat;
} else {
// Otherwise, scale and translate the draw target transform assuming it
// supports that.
tempMat = aDrawTarget.GetTransform();
aDrawTarget.SetTransform(
Matrix(tempMat).PreTranslate(center)
.PreScale(devPixelsPerCSSPx, devPixelsPerCSSPx));
}
if (aChar < 0x10000) {
if (aRect.Width() >= 2 * (MINIFONT_WIDTH + HEX_CHAR_GAP) &&
aRect.Height() >= 2 * MINIFONT_HEIGHT + HEX_CHAR_GAP) {
if (rect.Width() >= 2 * (MINIFONT_WIDTH + HEX_CHAR_GAP) &&
rect.Height() >= 2 * MINIFONT_HEIGHT + HEX_CHAR_GAP) {
// Draw 4 digits for BMP
Float left = -(MINIFONT_WIDTH + halfGap);
DrawHexChar((aChar >> 12) & 0xF,
Point(left, top), aDrawTarget, color);
Point(left, top), aDrawTarget, color, aMat);
DrawHexChar((aChar >> 8) & 0xF,
Point(halfGap, top), aDrawTarget, color);
Point(halfGap, top), aDrawTarget, color, aMat);
DrawHexChar((aChar >> 4) & 0xF,
Point(left, halfGap), aDrawTarget, color);
Point(left, halfGap), aDrawTarget, color, aMat);
DrawHexChar(aChar & 0xF,
Point(halfGap, halfGap), aDrawTarget, color);
Point(halfGap, halfGap), aDrawTarget, color, aMat);
}
} else {
if (aRect.Width() >= 3 * (MINIFONT_WIDTH + HEX_CHAR_GAP) &&
aRect.Height() >= 2 * MINIFONT_HEIGHT + HEX_CHAR_GAP) {
if (rect.Width() >= 3 * (MINIFONT_WIDTH + HEX_CHAR_GAP) &&
rect.Height() >= 2 * MINIFONT_HEIGHT + HEX_CHAR_GAP) {
// Draw 6 digits for non-BMP
Float first = -(MINIFONT_WIDTH * 1.5 + HEX_CHAR_GAP);
Float second = -(MINIFONT_WIDTH / 2.0);
Float third = (MINIFONT_WIDTH / 2.0 + HEX_CHAR_GAP);
DrawHexChar((aChar >> 20) & 0xF,
Point(first, top), aDrawTarget, color);
Point(first, top), aDrawTarget, color, aMat);
DrawHexChar((aChar >> 16) & 0xF,
Point(second, top), aDrawTarget, color);
Point(second, top), aDrawTarget, color, aMat);
DrawHexChar((aChar >> 12) & 0xF,
Point(third, top), aDrawTarget, color);
Point(third, top), aDrawTarget, color, aMat);
DrawHexChar((aChar >> 8) & 0xF,
Point(first, halfGap), aDrawTarget, color);
Point(first, halfGap), aDrawTarget, color, aMat);
DrawHexChar((aChar >> 4) & 0xF,
Point(second, halfGap), aDrawTarget, color);
Point(second, halfGap), aDrawTarget, color, aMat);
DrawHexChar(aChar & 0xF,
Point(third, halfGap), aDrawTarget, color);
Point(third, halfGap), aDrawTarget, color, aMat);
}
}
if (!aMat) {
// The draw target transform was changed, so it must be restored to
// the original value.
aDrawTarget.SetTransform(tempMat);
}
#endif
}

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

@ -38,12 +38,14 @@ public:
* @param aPattern the pattern currently being used to paint
* @param aAppUnitsPerDevPixel the appUnits to devPixel ratio we're using,
* (so we can scale glyphs to a sensible size)
* @param aMat optional local-space orientation matrix
*/
static void DrawMissingGlyph(uint32_t aChar,
const Rect& aRect,
DrawTarget& aDrawTarget,
const Pattern& aPattern,
uint32_t aAppUnitsPerDevPixel);
uint32_t aAppUnitsPerDevPixel,
const Matrix* aMat = nullptr);
/**
* @return the desired minimum width for a glyph-box that will allow
* the hexboxes to be drawn reasonably.

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

@ -7,16 +7,26 @@
#include "RenderCompositor.h"
#include "GLContext.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/webrender/RenderCompositorOGL.h"
#include "mozilla/widget/CompositorWidget.h"
#ifdef XP_WIN
#include "mozilla/webrender/RenderCompositorANGLE.h"
#endif
namespace mozilla {
namespace wr {
/* static */ UniquePtr<RenderCompositor>
RenderCompositor::Create(RefPtr<widget::CompositorWidget>&& aWidget)
{
#ifdef XP_WIN
if (gfx::gfxVars::UseWebRenderANGLE()) {
return RenderCompositorANGLE::Create(Move(aWidget));
}
#endif
return RenderCompositorOGL::Create(Move(aWidget));
}

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

@ -0,0 +1,162 @@
/* -*- 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/. */
#include "RenderCompositorANGLE.h"
#include "GLContext.h"
#include "GLContextEGL.h"
#include "GLContextProvider.h"
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/layers/HelpersD3D11.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/widget/CompositorWidget.h"
#include <d3d11.h>
namespace mozilla {
namespace wr {
/* static */ UniquePtr<RenderCompositor>
RenderCompositorANGLE::Create(RefPtr<widget::CompositorWidget>&& aWidget)
{
UniquePtr<RenderCompositorANGLE> compositor = MakeUnique<RenderCompositorANGLE>(Move(aWidget));
if (!compositor->Initialize()) {
return nullptr;
}
return compositor;
}
RenderCompositorANGLE::RenderCompositorANGLE(RefPtr<widget::CompositorWidget>&& aWidget)
: RenderCompositor(Move(aWidget))
{
}
RenderCompositorANGLE::~RenderCompositorANGLE()
{
}
bool
RenderCompositorANGLE::Initialize()
{
mDevice = gfx::DeviceManagerDx::Get()->GetCompositorDevice();
if (!mDevice) {
gfxCriticalNote << "[D3D11] failed to get compositor device.";
return false;
}
mDevice->GetImmediateContext(getter_AddRefs(mCtx));
if (!mCtx) {
gfxCriticalNote << "[D3D11] failed to get immediate context.";
return false;
}
mSyncObject = layers::SyncObjectHost::CreateSyncObjectHost(mDevice);
if (!mSyncObject->Init()) {
// Some errors occur. Clear the mSyncObject here.
// Then, there will be no texture synchronization.
return false;
}
mGL = gl::GLContextProviderEGL::CreateForCompositorWidget(mWidget, true);
if (!mGL || !mGL->IsANGLE()) {
gfxCriticalNote << "Failed ANGLE GL context creation for WebRender: " << gfx::hexa(mGL.get());
return false;
}
if (!mGL->MakeCurrent()) {
gfxCriticalNote << "Failed GL context creation for WebRender: " << gfx::hexa(mGL.get());
return false;
}
return true;
}
bool
RenderCompositorANGLE::Destroy()
{
return true;
}
bool
RenderCompositorANGLE::BeginFrame()
{
if (!mGL->MakeCurrent()) {
gfxCriticalNote << "Failed to make render context current, can't draw.";
return false;
}
if (mSyncObject) {
// XXX: if the synchronization is failed, we should handle the device reset.
mSyncObject->Synchronize();
}
return true;
}
void
RenderCompositorANGLE::EndFrame()
{
InsertPresentWaitQuery();
mGL->SwapBuffers();
// Note: this waits on the query we inserted in the previous frame,
// not the one we just inserted now. Example:
// Insert query #1
// Present #1
// (first frame, no wait)
// Insert query #2
// Present #2
// Wait for query #1.
// Insert query #3
// Present #3
// Wait for query #2.
//
// This ensures we're done reading textures before swapping buffers.
WaitForPreviousPresentQuery();
}
void
RenderCompositorANGLE::Pause()
{
}
bool
RenderCompositorANGLE::Resume()
{
return true;
}
LayoutDeviceIntSize
RenderCompositorANGLE::GetClientSize()
{
return mWidget->GetClientSize();
}
void
RenderCompositorANGLE::InsertPresentWaitQuery()
{
CD3D11_QUERY_DESC desc(D3D11_QUERY_EVENT);
HRESULT hr = mDevice->CreateQuery(&desc, getter_AddRefs(mNextWaitForPresentQuery));
if (FAILED(hr) || !mNextWaitForPresentQuery) {
gfxWarning() << "Could not create D3D11_QUERY_EVENT: " << hexa(hr);
return;
}
mCtx->End(mNextWaitForPresentQuery);
}
void
RenderCompositorANGLE::WaitForPreviousPresentQuery()
{
if (mWaitForPresentQuery) {
BOOL result;
layers::WaitForGPUQuery(mDevice, mCtx, mWaitForPresentQuery, &result);
}
mWaitForPresentQuery = mNextWaitForPresentQuery.forget();
}
} // namespace wr
} // namespace mozilla

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

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_RENDERCOMPOSITOR_ANGLE_H
#define MOZILLA_GFX_RENDERCOMPOSITOR_ANGLE_H
#include "mozilla/webrender/RenderCompositor.h"
struct ID3D11DeviceContext;
struct ID3D11Device;
struct ID3D11Query;
namespace mozilla {
namespace wr {
class RenderCompositorANGLE : public RenderCompositor
{
public:
static UniquePtr<RenderCompositor> Create(RefPtr<widget::CompositorWidget>&& aWidget);
explicit RenderCompositorANGLE(RefPtr<widget::CompositorWidget>&& aWidget);
virtual ~RenderCompositorANGLE();
bool Initialize();
bool Destroy() override;
bool BeginFrame() override;
void EndFrame() override;
void Pause() override;
bool Resume() override;
gl::GLContext* gl() const override { return mGL; }
bool UseANGLE() const override { return true; }
LayoutDeviceIntSize GetClientSize() override;
protected:
void InsertPresentWaitQuery();
void WaitForPreviousPresentQuery();
RefPtr<gl::GLContext> mGL;
RefPtr<ID3D11Device> mDevice;
RefPtr<ID3D11DeviceContext> mCtx;
RefPtr<ID3D11Query> mWaitForPresentQuery;
RefPtr<ID3D11Query> mNextWaitForPresentQuery;
};
} // namespace wr
} // namespace mozilla
#endif

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

@ -8,14 +8,8 @@
#include "GLContext.h"
#include "GLContextProvider.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/widget/CompositorWidget.h"
#ifdef XP_WIN
#include "GLContextEGL.h"
#endif
namespace mozilla {
namespace wr {
@ -23,16 +17,7 @@ namespace wr {
RenderCompositorOGL::Create(RefPtr<widget::CompositorWidget>&& aWidget)
{
RefPtr<gl::GLContext> gl;
if (gfx::gfxVars::UseWebRenderANGLE()) {
gl = gl::GLContextProviderEGL::CreateForCompositorWidget(aWidget, true);
if (!gl || !gl->IsANGLE()) {
gfxCriticalNote << "Failed ANGLE GL context creation for WebRender: " << gfx::hexa(gl.get());
return nullptr;
}
}
if (!gl) {
gl = gl::GLContextProvider::CreateForCompositorWidget(aWidget, true);
}
gl = gl::GLContextProvider::CreateForCompositorWidget(aWidget, true);
if (!gl || !gl->MakeCurrent()) {
gfxCriticalNote << "Failed GL context creation for WebRender: " << gfx::hexa(gl.get());
return nullptr;
@ -41,34 +26,11 @@ RenderCompositorOGL::Create(RefPtr<widget::CompositorWidget>&& aWidget)
}
RenderCompositorOGL::RenderCompositorOGL(RefPtr<gl::GLContext>&& aGL,
RefPtr<widget::CompositorWidget>&& aWidget)
RefPtr<widget::CompositorWidget>&& aWidget)
: RenderCompositor(Move(aWidget))
, mGL(aGL)
{
MOZ_ASSERT(mGL);
#ifdef XP_WIN
if (mGL->IsANGLE()) {
gl::GLLibraryEGL* egl = &gl::sEGLLibrary;
// Fetch the D3D11 device.
EGLDeviceEXT eglDevice = nullptr;
egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
MOZ_ASSERT(eglDevice);
ID3D11Device* device = nullptr;
egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE, (EGLAttrib*)&device);
MOZ_ASSERT(device);
mSyncObject = layers::SyncObjectHost::CreateSyncObjectHost(device);
if (mSyncObject) {
if (!mSyncObject->Init()) {
// Some errors occur. Clear the mSyncObject here.
// Then, there will be no texture synchronization.
mSyncObject = nullptr;
}
}
}
#endif
}
RenderCompositorOGL::~RenderCompositorOGL()
@ -88,11 +50,6 @@ RenderCompositorOGL::BeginFrame()
gfxCriticalNote << "Failed to make render context current, can't draw.";
return false;
}
if (mSyncObject) {
// XXX: if the synchronization is failed, we should handle the device reset.
mSyncObject->Synchronize();
}
return true;
}
@ -128,12 +85,6 @@ RenderCompositorOGL::Resume()
#endif
}
bool
RenderCompositorOGL::UseANGLE() const
{
return mGL->IsANGLE();
}
LayoutDeviceIntSize
RenderCompositorOGL::GetClientSize()
{

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

@ -10,19 +10,7 @@
#include "mozilla/webrender/RenderCompositor.h"
namespace mozilla {
/*
namespace gl {
class GLContext;
}
namespace layers {
class SyncObjectHost;
}
namespace widget {
class CompositorWidget;
}
*/
namespace wr {
class RenderCompositorOGL : public RenderCompositor
@ -31,7 +19,7 @@ public:
static UniquePtr<RenderCompositor> Create(RefPtr<widget::CompositorWidget>&& aWidget);
RenderCompositorOGL(RefPtr<gl::GLContext>&& aGL,
RefPtr<widget::CompositorWidget>&& aWidget);
RefPtr<widget::CompositorWidget>&& aWidget);
virtual ~RenderCompositorOGL();
bool Destroy() override;
@ -42,7 +30,7 @@ public:
gl::GLContext* gl() const override { return mGL; }
bool UseANGLE() const override;
bool UseANGLE() const override { return false; }
LayoutDeviceIntSize GetClientSize() override;

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

@ -47,9 +47,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
EXPORTS.mozilla.webrender += [
'RenderCompositorANGLE.h',
'RenderD3D11TextureHostOGL.h',
]
UNIFIED_SOURCES += [
'RenderCompositorANGLE.cpp',
'RenderD3D11TextureHostOGL.cpp',
]

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

@ -1112,6 +1112,105 @@ function ArrayConcat(arg1) {
return A;
}
// https://tc39.github.io/proposal-flatMap/
// January 16, 2018
function ArrayFlatMap(mapperFunction/*, thisArg*/) {
// Step 1.
var O = ToObject(this);
// Step 2.
var sourceLen = ToLength(O.length);
// Step 3.
if (!IsCallable(mapperFunction))
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, mapperFunction));
// Step 4.
var T = arguments.length > 1 ? arguments[1] : undefined;
// Step 5.
var A = ArraySpeciesCreate(O, 0);
// Step 6.
FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T);
// Step 7.
return A;
}
// https://tc39.github.io/proposal-flatMap/
// January 16, 2018
function ArrayFlatten(/* depth */) {
// Step 1.
var O = ToObject(this);
// Step 2.
var sourceLen = ToLength(O.length);
// Step 3.
var depthNum = 1;
// Step 4.
if (arguments.length > 0 && arguments[0] !== undefined)
depthNum = ToInteger(arguments[0]);
// Step 5.
var A = ArraySpeciesCreate(O, 0);
// Step 6.
FlattenIntoArray(A, O, sourceLen, 0, depthNum);
// Step 7.
return A;
}
function FlattenIntoArray(target, source, sourceLen, start, depth, mapperFunction, thisArg) {
// Step 1.
var targetIndex = start;
// Steps 2-3.
for (var sourceIndex = 0; sourceIndex < sourceLen; sourceIndex++) {
// Steps 3.a-c.
if (sourceIndex in source) {
// Step 3.c.i.
var element = source[sourceIndex];
if (mapperFunction) {
// Step 3.c.ii.1.
assert(arguments.length === 7, "thisArg is present");
// Step 3.c.ii.2.
element = callContentFunction(mapperFunction, thisArg, element, sourceIndex, source);
}
// Step 3.c.iii.
var flattenable = IsArray(element);
// Step 3.c.iv.
if (flattenable && depth > 0) {
// Step 3.c.iv.1.
var elementLen = ToLength(element.length);
// Step 3.c.iv.2.
targetIndex = FlattenIntoArray(target, element, elementLen, targetIndex, depth - 1);
} else {
// Step 3.c.v.1.
if (targetIndex >= MAX_NUMERIC_INDEX)
ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
// Step 3.c.v.2.
_DefineDataProperty(target, targetIndex, element);
// Step 3.c.v.3.
targetIndex++;
}
}
}
// Step 4.
return targetIndex;
}
function ArrayStaticConcat(arr, arg1) {
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.concat");

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

@ -40,8 +40,8 @@
'#' + __LINE__ + ': ' + msg) \
} while (false)
#else
#define assert(b, info) do {} while (false) // Elided assertion.
#define dbg(msg) do {} while (false) // Elided debugging output.
#define assert(b, info) ; // Elided assertion.
#define dbg(msg) ; // Elided debugging output.
#endif
// All C++-implemented standard builtins library functions used in self-hosted

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

@ -8535,6 +8535,31 @@ CodeGenerator::visitBoundsCheckLower(LBoundsCheckLower* lir)
lir->snapshot());
}
void
CodeGenerator::visitSpectreMaskIndex(LSpectreMaskIndex* lir)
{
MOZ_ASSERT(JitOptions.spectreIndexMasking);
const LAllocation* index = lir->index();
const LAllocation* length = lir->length();
Register output = ToRegister(lir->output());
if (index->isConstant()) {
int32_t idx = ToInt32(index);
if (length->isRegister())
masm.spectreMaskIndex(idx, ToRegister(length), output);
else
masm.spectreMaskIndex(idx, ToAddress(length), output);
return;
}
Register indexReg = ToRegister(index);
if (length->isRegister())
masm.spectreMaskIndex(indexReg, ToRegister(length), output);
else
masm.spectreMaskIndex(indexReg, ToAddress(length), output);
}
class OutOfLineStoreElementHole : public OutOfLineCodeBase<CodeGenerator>
{
LInstruction* ins_;

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

@ -251,6 +251,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitBoundsCheck(LBoundsCheck* lir) override;
void visitBoundsCheckRange(LBoundsCheckRange* lir) override;
void visitBoundsCheckLower(LBoundsCheckLower* lir) override;
void visitSpectreMaskIndex(LSpectreMaskIndex* lir) override;
void visitLoadFixedSlotV(LLoadFixedSlotV* ins) override;
void visitLoadFixedSlotAndUnbox(LLoadFixedSlotAndUnbox* lir) override;
void visitLoadFixedSlotT(LLoadFixedSlotT* ins) override;

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

@ -7835,7 +7835,8 @@ IonBuilder::checkTypedObjectIndexInBounds(uint32_t elemSize,
MDefinition* obj,
MDefinition* index,
TypedObjectPrediction objPrediction,
LinearSum* indexAsByteOffset)
LinearSum* indexAsByteOffset,
BoundsCheckKind kind)
{
// Ensure index is an integer.
MInstruction* idInt32 = MToInt32::New(alloc(), index);
@ -7862,7 +7863,7 @@ IonBuilder::checkTypedObjectIndexInBounds(uint32_t elemSize,
return false;
}
index = addBoundsCheck(idInt32, length);
index = addBoundsCheck(idInt32, length, kind);
return indexAsByteOffset->add(index, AssertedCast<int32_t>(elemSize));
}
@ -7882,8 +7883,11 @@ IonBuilder::getElemTryScalarElemOfTypedObject(bool* emitted,
MOZ_ASSERT(elemSize == ScalarTypeDescr::alignment(elemType));
LinearSum indexAsByteOffset(alloc());
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset))
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset,
BoundsCheckKind::IsLoad))
{
return Ok();
}
trackOptimizationSuccess();
*emitted = true;
@ -7904,8 +7908,11 @@ IonBuilder::getElemTryReferenceElemOfTypedObject(bool* emitted,
uint32_t elemSize = ReferenceTypeDescr::size(elemType);
LinearSum indexAsByteOffset(alloc());
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset))
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset,
BoundsCheckKind::IsLoad))
{
return Ok();
}
trackOptimizationSuccess();
*emitted = true;
@ -8025,8 +8032,11 @@ IonBuilder::getElemTryComplexElemOfTypedObject(bool* emitted,
MDefinition* elemTypeObj = typeObjectForElementFromArrayStructType(type);
LinearSum indexAsByteOffset(alloc());
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset))
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset,
BoundsCheckKind::IsLoad))
{
return Ok();
}
return pushDerivedTypedObject(emitted, obj, indexAsByteOffset,
elemPrediction, elemTypeObj);
@ -8317,7 +8327,7 @@ IonBuilder::getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index
MStringLength* length = MStringLength::New(alloc(), obj);
current->add(length);
index = addBoundsCheck(index, length);
index = addBoundsCheck(index, length, BoundsCheckKind::IsLoad);
MCharCodeAt* charCode = MCharCodeAt::New(alloc(), obj, index);
current->add(charCode);
@ -8359,7 +8369,7 @@ IonBuilder::getElemTryArguments(bool* emitted, MDefinition* obj, MDefinition* in
index = idInt32;
// Bailouts if we read more than the number of actual arguments.
index = addBoundsCheck(index, length);
index = addBoundsCheck(index, length, BoundsCheckKind::IsLoad);
// Load the argument from the actual arguments.
bool modifiesArgs = script()->baselineScript()->modifiesArguments();
@ -8447,7 +8457,8 @@ IonBuilder::getElemTryArgumentsInlinedIndex(bool* emitted, MDefinition* obj, MDe
// cannot re-enter because reading out of bounds arguments will disable the
// lazy arguments optimization for this script, when this code would be
// executed in Baseline. (see GetElemOptimizedArguments)
index = addBoundsCheck(index, constantInt(inlineCallInfo_->argc()));
index = addBoundsCheck(index, constantInt(inlineCallInfo_->argc()),
BoundsCheckKind::IsLoad);
// Get an instruction to represent the state of the argument vector.
MInstruction* args = MArgumentState::New(alloc().fallible(), inlineCallInfo_->argv());
@ -8646,7 +8657,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index)
// in-bounds elements, and the array is packed or its holes are not
// read. This is the best case: we can separate the bounds check for
// hoisting.
index = addBoundsCheck(index, initLength);
index = addBoundsCheck(index, initLength, BoundsCheckKind::IsLoad);
load = MLoadElement::New(alloc(), elements, index, needsHoleCheck, loadDouble);
current->add(load);
@ -8685,7 +8696,8 @@ void
IonBuilder::addTypedArrayLengthAndData(MDefinition* obj,
BoundsChecking checking,
MDefinition** index,
MInstruction** length, MInstruction** elements)
MInstruction** length, MInstruction** elements,
BoundsCheckKind boundsCheckKind)
{
MOZ_ASSERT((index != nullptr) == (elements != nullptr));
@ -8719,7 +8731,7 @@ IonBuilder::addTypedArrayLengthAndData(MDefinition* obj,
if (index) {
if (checking == DoBoundsCheck)
*index = addBoundsCheck(*index, *length);
*index = addBoundsCheck(*index, *length, boundsCheckKind);
*elements = MConstantElements::New(alloc(), data);
current->add(*elements);
@ -8734,7 +8746,7 @@ IonBuilder::addTypedArrayLengthAndData(MDefinition* obj,
if (index) {
if (checking == DoBoundsCheck)
*index = addBoundsCheck(*index, *length);
*index = addBoundsCheck(*index, *length, boundsCheckKind);
*elements = MTypedArrayElements::New(alloc(), obj);
current->add(*elements);
@ -8816,7 +8828,8 @@ IonBuilder::jsop_getelem_typed(MDefinition* obj, MDefinition* index,
// Get length, bounds-check, then get elements, and add all instructions.
MInstruction* length;
MInstruction* elements;
addTypedArrayLengthAndData(obj, DoBoundsCheck, &index, &length, &elements);
addTypedArrayLengthAndData(obj, DoBoundsCheck, &index, &length, &elements,
BoundsCheckKind::IsLoad);
// Load the element.
MLoadUnboxedScalar* load = MLoadUnboxedScalar::New(alloc(), elements, index, arrayType);
@ -9001,8 +9014,11 @@ IonBuilder::setElemTryReferenceElemOfTypedObject(bool* emitted,
uint32_t elemSize = ReferenceTypeDescr::size(elemType);
LinearSum indexAsByteOffset(alloc());
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset))
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset,
BoundsCheckKind::IsStore))
{
return Ok();
}
return setPropTryReferenceTypedObjectValue(emitted, obj, indexAsByteOffset,
elemType, value, nullptr);
@ -9022,8 +9038,11 @@ IonBuilder::setElemTryScalarElemOfTypedObject(bool* emitted,
MOZ_ASSERT(elemSize == ScalarTypeDescr::alignment(elemType));
LinearSum indexAsByteOffset(alloc());
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset))
if (!checkTypedObjectIndexInBounds(elemSize, obj, index, objPrediction, &indexAsByteOffset,
BoundsCheckKind::IsStore))
{
return Ok();
}
return setPropTryScalarTypedObjectValue(emitted, obj, indexAsByteOffset, elemType, value);
}
@ -9319,7 +9338,7 @@ IonBuilder::initOrSetElemDense(TemporaryTypeSet::DoubleConversion conversion,
} else {
MInstruction* initLength = initializedLength(obj, elements);
id = addBoundsCheck(id, initLength);
id = addBoundsCheck(id, initLength, BoundsCheckKind::IsStore);
bool needsHoleCheck = !packed && hasExtraIndexedProperty;
MStoreElement* ins = MStoreElement::New(alloc(), elements, id, newValue, needsHoleCheck);
@ -9367,7 +9386,8 @@ IonBuilder::jsop_setelem_typed(Scalar::Type arrayType,
MInstruction* length;
MInstruction* elements;
BoundsChecking checking = expectOOB ? SkipBoundsCheck : DoBoundsCheck;
addTypedArrayLengthAndData(obj, checking, &id, &length, &elements);
addTypedArrayLengthAndData(obj, checking, &id, &length, &elements,
BoundsCheckKind::IsStore);
// Clamp value to [0, 255] for Uint8ClampedArray.
MDefinition* toWrite = value;
@ -12901,7 +12921,7 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
// If there are no holes, speculate the InArray check will not fail.
if (!needsHoleCheck && !failedBoundsCheck_) {
addBoundsCheck(idInt32, initLength);
addBoundsCheck(idInt32, initLength, BoundsCheckKind::UnusedIndex);
pushConstant(BooleanValue(true));
return Ok();
}
@ -13246,7 +13266,7 @@ IonBuilder::addMaybeCopyElementsForWrite(MDefinition* object, bool checkNative)
}
MInstruction*
IonBuilder::addBoundsCheck(MDefinition* index, MDefinition* length)
IonBuilder::addBoundsCheck(MDefinition* index, MDefinition* length, BoundsCheckKind kind)
{
MInstruction* check = MBoundsCheck::New(alloc(), index, length);
current->add(check);
@ -13255,6 +13275,11 @@ IonBuilder::addBoundsCheck(MDefinition* index, MDefinition* length)
if (failedBoundsCheck_)
check->setNotMovable();
if (kind == BoundsCheckKind::IsLoad && JitOptions.spectreIndexMasking) {
check = MSpectreMaskIndex::New(alloc(), check, length);
current->add(check);
}
return check;
}

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

@ -195,7 +195,10 @@ class IonBuilder
MInstruction* addConvertElementsToDoubles(MDefinition* elements);
MDefinition* addMaybeCopyElementsForWrite(MDefinition* object, bool checkNative);
MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length);
enum class BoundsCheckKind { IsLoad, IsStore, UnusedIndex };
MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length, BoundsCheckKind kind);
MInstruction* addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bailoutKind);
MInstruction* addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bailoutKind);
MInstruction* addUnboxedExpandoGuard(MDefinition* obj, bool hasExpando, BailoutKind bailoutKind);
@ -375,7 +378,8 @@ class IonBuilder
MDefinition* obj,
MDefinition* index,
TypedObjectPrediction objTypeDescrs,
LinearSum* indexAsByteOffset);
LinearSum* indexAsByteOffset,
BoundsCheckKind kind);
AbortReasonOr<Ok> pushDerivedTypedObject(bool* emitted,
MDefinition* obj,
const LinearSum& byteOffset,
@ -464,14 +468,16 @@ class IonBuilder
void addTypedArrayLengthAndData(MDefinition* obj,
BoundsChecking checking,
MDefinition** index,
MInstruction** length, MInstruction** elements);
MInstruction** length, MInstruction** elements,
BoundsCheckKind boundsCheckKind);
// Add an instruction to compute a typed array's length to the current
// block. If you also need the typed array's data, use the above method
// instead.
MInstruction* addTypedArrayLength(MDefinition* obj) {
MInstruction* length;
addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr);
addTypedArrayLengthAndData(obj, SkipBoundsCheck, nullptr, &length, nullptr,
BoundsCheckKind::UnusedIndex);
return length;
}
@ -766,7 +772,7 @@ class IonBuilder
bool prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType,
MInstruction** elements, MDefinition** index,
Scalar::Type* arrayType);
Scalar::Type* arrayType, BoundsCheckKind boundsCheckKind);
InliningResult inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type,
unsigned numElems);
InliningResult inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type,
@ -830,7 +836,8 @@ class IonBuilder
bool atomicsMeetsPreconditions(CallInfo& callInfo, Scalar::Type* arrayElementType,
bool* requiresDynamicCheck,
AtomicCheckResult checkResult=DoCheckAtomicResult);
void atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index);
void atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index,
BoundsCheckKind kind);
bool testNeedsArgumentCheck(JSFunction* target, CallInfo& callInfo);

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

@ -3129,6 +3129,26 @@ LIRGenerator::visitBoundsCheck(MBoundsCheck* ins)
add(check, ins);
}
void
LIRGenerator::visitSpectreMaskIndex(MSpectreMaskIndex* ins)
{
MOZ_ASSERT(ins->index()->type() == MIRType::Int32);
MOZ_ASSERT(ins->length()->type() == MIRType::Int32);
MOZ_ASSERT(ins->type() == MIRType::Int32);
// On 64-bit platforms, the length must be in a register, so
// MacroAssembler::maskIndex can emit more efficient code.
#if JS_BITS_PER_WORD == 64
LAllocation lengthUse = useRegister(ins->length());
#else
LAllocation lengthUse = useAny(ins->length());
#endif
LSpectreMaskIndex* lir =
new(alloc()) LSpectreMaskIndex(useRegisterOrConstant(ins->index()), lengthUse);
define(lir, ins);
}
void
LIRGenerator::visitBoundsCheckLower(MBoundsCheckLower* ins)
{

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

@ -229,6 +229,7 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitNot(MNot* ins) override;
void visitBoundsCheck(MBoundsCheck* ins) override;
void visitBoundsCheckLower(MBoundsCheckLower* ins) override;
void visitSpectreMaskIndex(MSpectreMaskIndex* ins) override;
void visitLoadElement(MLoadElement* ins) override;
void visitLoadElementHole(MLoadElementHole* ins) override;
void visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull* ins) override;

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

@ -1868,7 +1868,7 @@ IonBuilder::inlineStrCharCodeAt(CallInfo& callInfo)
MStringLength* length = MStringLength::New(alloc(), callInfo.thisArg());
current->add(length);
index = addBoundsCheck(index, length);
index = addBoundsCheck(index, length, BoundsCheckKind::IsLoad);
MCharCodeAt* charCode = MCharCodeAt::New(alloc(), callInfo.thisArg(), index);
current->add(charCode);
@ -1978,7 +1978,7 @@ IonBuilder::inlineStrCharAt(CallInfo& callInfo)
MStringLength* length = MStringLength::New(alloc(), callInfo.thisArg());
current->add(length);
index = addBoundsCheck(index, length);
index = addBoundsCheck(index, length, BoundsCheckKind::IsLoad);
// String.charAt(x) = String.fromCharCode(String.charCodeAt(x))
MCharCodeAt* charCode = MCharCodeAt::New(alloc(), callInfo.thisArg(), index);
@ -3269,7 +3269,7 @@ IonBuilder::inlineAtomicsCompareExchange(CallInfo& callInfo)
MInstruction* elements;
MDefinition* index;
atomicsCheckBounds(callInfo, &elements, &index);
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsLoad);
if (requiresCheck)
addSharedTypedArrayGuard(callInfo.getArg(0));
@ -3305,7 +3305,7 @@ IonBuilder::inlineAtomicsExchange(CallInfo& callInfo)
MInstruction* elements;
MDefinition* index;
atomicsCheckBounds(callInfo, &elements, &index);
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsLoad);
if (requiresCheck)
addSharedTypedArrayGuard(callInfo.getArg(0));
@ -3337,7 +3337,7 @@ IonBuilder::inlineAtomicsLoad(CallInfo& callInfo)
MInstruction* elements;
MDefinition* index;
atomicsCheckBounds(callInfo, &elements, &index);
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsLoad);
if (requiresCheck)
addSharedTypedArrayGuard(callInfo.getArg(0));
@ -3389,7 +3389,7 @@ IonBuilder::inlineAtomicsStore(CallInfo& callInfo)
MInstruction* elements;
MDefinition* index;
atomicsCheckBounds(callInfo, &elements, &index);
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsStore);
if (requiresCheck)
addSharedTypedArrayGuard(callInfo.getArg(0));
@ -3433,7 +3433,7 @@ IonBuilder::inlineAtomicsBinop(CallInfo& callInfo, InlinableNative target)
MInstruction* elements;
MDefinition* index;
atomicsCheckBounds(callInfo, &elements, &index);
atomicsCheckBounds(callInfo, &elements, &index, BoundsCheckKind::IsLoad);
AtomicOp k = AtomicFetchAddOp;
switch (target) {
@ -3530,14 +3530,15 @@ IonBuilder::atomicsMeetsPreconditions(CallInfo& callInfo, Scalar::Type* arrayTyp
}
void
IonBuilder::atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index)
IonBuilder::atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index,
BoundsCheckKind kind)
{
// Perform bounds checking and extract the elements vector.
MDefinition* obj = callInfo.getArg(0);
MInstruction* length = nullptr;
*index = callInfo.getArg(1);
*elements = nullptr;
addTypedArrayLengthAndData(obj, DoBoundsCheck, index, &length, elements);
addTypedArrayLengthAndData(obj, DoBoundsCheck, index, &length, elements, kind);
}
IonBuilder::InliningResult
@ -4251,7 +4252,8 @@ SimdTypeToArrayElementType(SimdType type)
bool
IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, MInstruction** elements,
MDefinition** index, Scalar::Type* arrayType)
MDefinition** index, Scalar::Type* arrayType,
BoundsCheckKind boundsCheckKind)
{
MDefinition* array = callInfo.getArg(0);
*index = callInfo.getArg(1);
@ -4281,15 +4283,13 @@ IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, M
}
MInstruction* length;
addTypedArrayLengthAndData(array, SkipBoundsCheck, index, &length, elements);
addTypedArrayLengthAndData(array, SkipBoundsCheck, index, &length, elements, boundsCheckKind);
// It can be that the index is out of bounds, while the added index for the
// bounds check is in bounds, so we actually need two bounds checks here.
MInstruction* positiveCheck = MBoundsCheck::New(alloc(), *index, length);
current->add(positiveCheck);
*index = addBoundsCheck(*index, length, boundsCheckKind);
MInstruction* fullCheck = MBoundsCheck::New(alloc(), indexForBoundsCheck, length);
current->add(fullCheck);
addBoundsCheck(indexForBoundsCheck, length, BoundsCheckKind::UnusedIndex);
return true;
}
@ -4305,8 +4305,11 @@ IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type, u
MDefinition* index = nullptr;
MInstruction* elements = nullptr;
Scalar::Type arrayType;
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType))
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType,
BoundsCheckKind::IsLoad))
{
return InliningStatus_NotInlined;
}
MLoadUnboxedScalar* load = MLoadUnboxedScalar::New(alloc(), elements, index, arrayType);
load->setResultType(SimdTypeToMIRType(type));
@ -4327,8 +4330,11 @@ IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type,
MDefinition* index = nullptr;
MInstruction* elements = nullptr;
Scalar::Type arrayType;
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType))
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType,
BoundsCheckKind::IsStore))
{
return InliningStatus_NotInlined;
}
MDefinition* valueToWrite = unboxSimd(callInfo.getArg(2), type);
MStoreUnboxedScalar* store = MStoreUnboxedScalar::New(alloc(), elements, index,

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

@ -9549,6 +9549,38 @@ class MBoundsCheckLower
void collectRangeInfoPreTrunc() override;
};
class MSpectreMaskIndex
: public MBinaryInstruction,
public MixPolicy<IntPolicy<0>, IntPolicy<1>>::Data
{
MSpectreMaskIndex(MDefinition* index, MDefinition* length)
: MBinaryInstruction(classOpcode, index, length)
{
setGuard();
setMovable();
MOZ_ASSERT(index->type() == MIRType::Int32);
MOZ_ASSERT(length->type() == MIRType::Int32);
// Returns the masked index.
setResultType(MIRType::Int32);
}
public:
INSTRUCTION_HEADER(SpectreMaskIndex)
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, index), (1, length))
bool congruentTo(const MDefinition* ins) const override {
return congruentIfOperandsEqual(ins);
}
virtual AliasSet getAliasSet() const override {
return AliasSet::None();
}
void computeRange(TempAllocator& alloc) override;
ALLOW_CLONE(MSpectreMaskIndex)
};
// Instructions which access an object's elements can either do so on a
// definition accessing that elements pointer, or on the object itself, if its
// elements are inline. In the latter case there must be an offset associated

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

@ -215,6 +215,7 @@ namespace jit {
_(Not) \
_(BoundsCheck) \
_(BoundsCheckLower) \
_(SpectreMaskIndex) \
_(InArray) \
_(LoadElement) \
_(LoadElementHole) \

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

@ -3413,6 +3413,73 @@ MacroAssembler::debugAssertIsObject(const ValueOperand& val)
#endif
}
template <typename T>
void
MacroAssembler::spectreMaskIndexImpl(Register index, const T& length, Register output)
{
// mask := ((index - length) & ~index) >> 31
// output := index & mask
mov(index, output);
sub32(length, output);
not32(index);
and32(index, output);
not32(index); // Restore index register to its original value.
rshift32Arithmetic(Imm32(31), output);
and32(index, output);
}
template <typename T>
void
MacroAssembler::spectreMaskIndexImpl(int32_t index, const T& length, Register output)
{
// mask := ((index - length) & ~index) >> 31
// output := index & mask
move32(Imm32(index), output);
if (index == 0)
return;
sub32(length, output);
and32(Imm32(~index), output);
rshift32Arithmetic(Imm32(31), output);
and32(Imm32(index), output);
}
void
MacroAssembler::spectreMaskIndex(int32_t index, Register length, Register output)
{
spectreMaskIndexImpl(index, length, output);
}
void
MacroAssembler::spectreMaskIndex(int32_t index, const Address& length, Register output)
{
spectreMaskIndexImpl(index, length, output);
}
void
MacroAssembler::spectreMaskIndex(Register index, Register length, Register output)
{
#if JS_BITS_PER_WORD == 64
// On 64-bit platforms, we can use a faster algorithm:
//
// mask := (uint64_t(index) - uint64_t(length)) >> 32
// output := index & mask
//
// mask is 0x11…11 if index < length, 0 otherwise.
move32(index, output);
subPtr(length, output);
rshiftPtr(Imm32(32), output);
and32(index, output);
#else
spectreMaskIndexImpl(index, length, output);
#endif
}
void
MacroAssembler::spectreMaskIndex(Register index, const Address& length, Register output)
{
spectreMaskIndexImpl(index, length, output);
}
namespace js {
namespace jit {

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

@ -1894,6 +1894,19 @@ class MacroAssembler : public MacroAssemblerSpecific
store32(Imm32(key.constant()), dest);
}
private:
template <typename T>
void spectreMaskIndexImpl(Register index, const T& length, Register output);
template <typename T>
void spectreMaskIndexImpl(int32_t index, const T& length, Register output);
public:
void spectreMaskIndex(int32_t index, Register length, Register output);
void spectreMaskIndex(int32_t index, const Address& length, Register output);
void spectreMaskIndex(Register index, Register length, Register output);
void spectreMaskIndex(Register index, const Address& length, Register output);
template <typename T>
void guardedCallPreBarrier(const T& address, MIRType type) {
Label done;
@ -2325,16 +2338,10 @@ class MacroAssembler : public MacroAssemblerSpecific
//
// Convenience functions for converting values to int32.
//
void convertValueToInt32(ValueOperand value, FloatRegister temp, Register output, Label* fail,
bool negativeZeroCheck)
{
convertValueToInt(value, temp, output, fail, negativeZeroCheck
? IntConversion_NegativeZeroCheck
: IntConversion_Normal);
}
void convertValueToInt32(ValueOperand value, MDefinition* input,
FloatRegister temp, Register output, Label* fail,
bool negativeZeroCheck, IntConversionInputKind conversion = IntConversion_Any)
bool negativeZeroCheck,
IntConversionInputKind conversion = IntConversion_Any)
{
convertValueToInt(value, input, nullptr, nullptr, nullptr, InvalidReg, temp, output, fail,
negativeZeroCheck
@ -2342,36 +2349,10 @@ class MacroAssembler : public MacroAssemblerSpecific
: IntConversion_Normal,
conversion);
}
MOZ_MUST_USE bool convertValueToInt32(JSContext* cx, const Value& v, Register output,
Label* fail, bool negativeZeroCheck)
{
return convertValueToInt(cx, v, output, fail, negativeZeroCheck
? IntConversion_NegativeZeroCheck
: IntConversion_Normal);
}
MOZ_MUST_USE bool convertConstantOrRegisterToInt32(JSContext* cx,
const ConstantOrRegister& src,
FloatRegister temp, Register output,
Label* fail, bool negativeZeroCheck)
{
return convertConstantOrRegisterToInt(cx, src, temp, output, fail, negativeZeroCheck
? IntConversion_NegativeZeroCheck
: IntConversion_Normal);
}
void convertTypedOrValueToInt32(TypedOrValueRegister src, FloatRegister temp, Register output,
Label* fail, bool negativeZeroCheck)
{
convertTypedOrValueToInt(src, temp, output, fail, negativeZeroCheck
? IntConversion_NegativeZeroCheck
: IntConversion_Normal);
}
//
// Convenience functions for truncating values to int32.
//
void truncateValueToInt32(ValueOperand value, FloatRegister temp, Register output, Label* fail) {
convertValueToInt(value, temp, output, fail, IntConversion_Truncate);
}
void truncateValueToInt32(ValueOperand value, MDefinition* input,
Label* handleStringEntry, Label* handleStringRejoin,
Label* truncateDoubleSlow,
@ -2380,16 +2361,13 @@ class MacroAssembler : public MacroAssemblerSpecific
convertValueToInt(value, input, handleStringEntry, handleStringRejoin, truncateDoubleSlow,
stringReg, temp, output, fail, IntConversion_Truncate);
}
void truncateValueToInt32(ValueOperand value, MDefinition* input,
FloatRegister temp, Register output, Label* fail)
void truncateValueToInt32(ValueOperand value, FloatRegister temp, Register output, Label* fail)
{
convertValueToInt(value, input, nullptr, nullptr, nullptr, InvalidReg, temp, output, fail,
IntConversion_Truncate);
}
MOZ_MUST_USE bool truncateValueToInt32(JSContext* cx, const Value& v, Register output,
Label* fail) {
return convertValueToInt(cx, v, output, fail, IntConversion_Truncate);
truncateValueToInt32(value, nullptr, nullptr, nullptr, nullptr, InvalidReg, temp, output,
fail);
}
MOZ_MUST_USE bool truncateConstantOrRegisterToInt32(JSContext* cx,
const ConstantOrRegister& src,
FloatRegister temp, Register output,
@ -2397,16 +2375,8 @@ class MacroAssembler : public MacroAssemblerSpecific
{
return convertConstantOrRegisterToInt(cx, src, temp, output, fail, IntConversion_Truncate);
}
void truncateTypedOrValueToInt32(TypedOrValueRegister src, FloatRegister temp, Register output,
Label* fail)
{
convertTypedOrValueToInt(src, temp, output, fail, IntConversion_Truncate);
}
// Convenience functions for clamping values to uint8.
void clampValueToUint8(ValueOperand value, FloatRegister temp, Register output, Label* fail) {
convertValueToInt(value, temp, output, fail, IntConversion_ClampToUint8);
}
void clampValueToUint8(ValueOperand value, MDefinition* input,
Label* handleStringEntry, Label* handleStringRejoin,
Register stringReg, FloatRegister temp, Register output, Label* fail)
@ -2414,16 +2384,7 @@ class MacroAssembler : public MacroAssemblerSpecific
convertValueToInt(value, input, handleStringEntry, handleStringRejoin, nullptr,
stringReg, temp, output, fail, IntConversion_ClampToUint8);
}
void clampValueToUint8(ValueOperand value, MDefinition* input,
FloatRegister temp, Register output, Label* fail)
{
convertValueToInt(value, input, nullptr, nullptr, nullptr, InvalidReg, temp, output, fail,
IntConversion_ClampToUint8);
}
MOZ_MUST_USE bool clampValueToUint8(JSContext* cx, const Value& v, Register output,
Label* fail) {
return convertValueToInt(cx, v, output, fail, IntConversion_ClampToUint8);
}
MOZ_MUST_USE bool clampConstantOrRegisterToUint8(JSContext* cx,
const ConstantOrRegister& src,
FloatRegister temp, Register output,
@ -2432,11 +2393,6 @@ class MacroAssembler : public MacroAssemblerSpecific
return convertConstantOrRegisterToInt(cx, src, temp, output, fail,
IntConversion_ClampToUint8);
}
void clampTypedOrValueToUint8(TypedOrValueRegister src, FloatRegister temp, Register output,
Label* fail)
{
convertTypedOrValueToInt(src, temp, output, fail, IntConversion_ClampToUint8);
}
public:
class AfterICSaveLive {

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

@ -1860,6 +1860,13 @@ MBoundsCheck::computeRange(TempAllocator& alloc)
setRange(new(alloc) Range(index()));
}
void
MSpectreMaskIndex::computeRange(TempAllocator& alloc)
{
// Just transfer the incoming index range to the output for now.
setRange(new(alloc) Range(index()));
}
void
MArrayPush::computeRange(TempAllocator& alloc)
{

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

@ -861,6 +861,8 @@ IndexOf(MDefinition* ins, int32_t* res)
{
MOZ_ASSERT(ins->isLoadElement() || ins->isStoreElement());
MDefinition* indexDef = ins->getOperand(1); // ins->index();
if (indexDef->isSpectreMaskIndex())
indexDef = indexDef->toSpectreMaskIndex()->index();
if (indexDef->isBoundsCheck())
indexDef = indexDef->toBoundsCheck()->index();
if (indexDef->isToInt32())

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

@ -5550,6 +5550,23 @@ class LBoundsCheckLower : public LInstructionHelper<0, 1, 0>
}
};
class LSpectreMaskIndex : public LInstructionHelper<1, 2, 0>
{
public:
LIR_HEADER(SpectreMaskIndex)
LSpectreMaskIndex(const LAllocation& index, const LAllocation& length) {
setOperand(0, index);
setOperand(1, length);
}
const LAllocation* index() {
return getOperand(0);
}
const LAllocation* length() {
return getOperand(1);
}
};
// Load a value from a dense array's elements vector. Bail out if it's the hole value.
class LLoadElementV : public LInstructionHelper<BOX_PIECES, 2, 0>
{

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

@ -277,6 +277,7 @@
_(BoundsCheck) \
_(BoundsCheckRange) \
_(BoundsCheckLower) \
_(SpectreMaskIndex) \
_(LoadElementV) \
_(LoadElementT) \
_(LoadElementHole) \

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

@ -3549,6 +3549,12 @@ static const JSFunctionSpec array_methods[] = {
/* ES7 additions */
JS_SELF_HOSTED_FN("includes", "ArrayIncludes", 2,0),
#ifdef NIGHTLY_BUILD
JS_SELF_HOSTED_FN("flatMap", "ArrayFlatMap", 1,0),
JS_SELF_HOSTED_FN("flatten", "ArrayFlatten", 0,0),
#endif
JS_FS_END
};

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

@ -49,6 +49,9 @@ skip-if(!this.hasOwnProperty("SharedArrayBuffer")) script test262/built-ins/Arra
skip-if(!this.hasOwnProperty("SharedArrayBuffer")) script test262/built-ins/ArrayBuffer/prototype/slice/this-is-sharedarraybuffer.js
skip-if(!this.hasOwnProperty("SharedArrayBuffer")) script test262/built-ins/TypedArrays/internals/Get/indexed-value-sab.js
# flatMap and flatten are Nightly-only
skip-if(!Array.prototype.flatMap) include test262/built-ins/Array/prototype/flatMap/jstests.list
skip-if(!Array.prototype.flatten) include test262/built-ins/Array/prototype/flatten/jstests.list
#####################################
# Test262 tests disabled on browser #

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

@ -20,8 +20,6 @@ from itertools import chain, imap
# Skip all tests which use features not supported in SpiderMonkey.
UNSUPPORTED_FEATURES = set([
"tail-call-optimization",
"Array.prototype.flatMap",
"Array.prototype.flatten",
"BigInt",
"class-fields-public",
"class-fields-private",

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatMap is not supported
'use strict';
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -1,4 +1,3 @@
// |reftest| skip -- Array.prototype.flatten is not supported
// Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

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

@ -807,8 +807,7 @@ GenerateImportJitExit(MacroAssembler& masm, const FuncImport& fi, Label* throwLa
case ExprType::Void:
break;
case ExprType::I32:
masm.convertValueToInt32(JSReturnOperand, ReturnDoubleReg, ReturnReg, &oolConvert,
/* -0 check */ false);
masm.truncateValueToInt32(JSReturnOperand, ReturnDoubleReg, ReturnReg, &oolConvert);
break;
case ExprType::I64:
masm.breakpoint();

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

@ -207,6 +207,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
"constructor"];
if (isNightlyBuild) {
gPrototypeProperties['Array'].push("values");
gPrototypeProperties['Array'].push("flatten", "flatMap");
}
gConstructorProperties['Array'] =
constructorProps(["join", "reverse", "sort", "push", "pop", "shift",

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

@ -16,7 +16,6 @@
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsIContent.h"
#include "nsIContentViewerContainer.h"
#include "nsIContentViewer.h"
#include "nsIDocumentViewerPrint.h"
#include "mozilla/dom/BeforeUnloadEvent.h"
@ -4327,7 +4326,7 @@ nsDocumentViewer::SetIsPrintingInDocShellTree(nsIDocShellTreeItem* aParentNode,
}
// Check to see if the DocShell's ContentViewer is printing/PP
nsCOMPtr<nsIContentViewerContainer> viewerContainer(do_QueryInterface(parentItem));
nsCOMPtr<nsIDocShell> viewerContainer = do_QueryInterface(parentItem);
if (viewerContainer) {
viewerContainer->SetIsPrinting(aIsPrintingOrPP);
}

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

@ -399,14 +399,48 @@ public:
void FillRect(const Rect &aRect,
const Pattern &aPattern,
const DrawOptions &aOptions = DrawOptions()) override {
MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
auto rect = mSc.ToRelativeLayoutRect(LayoutDeviceRect::FromUnknownRect(aRect));
auto color = wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
mBuilder.PushRect(rect, mClipRect, mBackfaceVisible, color);
}
void StrokeRect(const Rect &aRect,
const Pattern &aPattern,
const StrokeOptions &aStrokeOptions,
const DrawOptions &aOptions) override {
MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR &&
aStrokeOptions.mDashLength == 0);
wr::Line line;
line.wavyLineThickness = 0; // dummy value, unused
line.color = wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
line.style = wr::LineStyle::Solid;
// Top horizontal line
LayoutDevicePoint top(aRect.x, aRect.y - aStrokeOptions.mLineWidth / 2);
LayoutDeviceSize horiSize(aRect.width, aStrokeOptions.mLineWidth);
line.bounds = mSc.ToRelativeLayoutRect(LayoutDeviceRect(top, horiSize));
line.orientation = wr::LineOrientation::Horizontal;
mBuilder.PushLine(mClipRect, mBackfaceVisible, line);
// Bottom horizontal line
LayoutDevicePoint bottom(aRect.x, aRect.YMost() - aStrokeOptions.mLineWidth / 2);
line.bounds = mSc.ToRelativeLayoutRect(LayoutDeviceRect(bottom, horiSize));
mBuilder.PushLine(mClipRect, mBackfaceVisible, line);
// Left vertical line
LayoutDevicePoint left(aRect.x + aStrokeOptions.mLineWidth / 2, aRect.y + aStrokeOptions.mLineWidth / 2);
LayoutDeviceSize vertSize(aStrokeOptions.mLineWidth, aRect.height - aStrokeOptions.mLineWidth);
line.bounds = mSc.ToRelativeLayoutRect(LayoutDeviceRect(left, vertSize));
line.orientation = wr::LineOrientation::Vertical;
mBuilder.PushLine(mClipRect, mBackfaceVisible, line);
// Right vertical line
LayoutDevicePoint right(aRect.XMost() - aStrokeOptions.mLineWidth / 2, aRect.y + aStrokeOptions.mLineWidth / 2);
line.bounds = mSc.ToRelativeLayoutRect(LayoutDeviceRect(right, vertSize));
mBuilder.PushLine(mClipRect, mBackfaceVisible, line);
}
void StrokeLine(const Point &aStart,

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

@ -4532,12 +4532,17 @@ nsGridContainerFrame::Tracks::FindUsedFlexFraction(
auto pb = Some(aState.PercentageBasisFor(mAxis, item));
nscoord spaceToFill = ContentContribution(item, aState, rc, wm, mAxis, pb,
nsLayoutUtils::PREF_ISIZE);
const LineRange& range =
mAxis == eLogicalAxisInline ? item.mArea.mCols : item.mArea.mRows;
MOZ_ASSERT(range.Extent() >= 1);
const auto spannedGaps = range.Extent() - 1;
if (spannedGaps > 0) {
spaceToFill -= mGridGap * spannedGaps;
}
if (spaceToFill <= 0) {
continue;
}
// ... and all its spanned tracks as input.
const LineRange& range =
mAxis == eLogicalAxisInline ? item.mArea.mCols : item.mArea.mRows;
nsTArray<uint32_t> itemFlexTracks;
for (uint32_t i = range.mStart, end = range.mEnd; i < end; ++i) {
if (mSizes[i].mState & TrackSize::eFlexMaxSizing) {

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

@ -313,13 +313,13 @@ void UpdateASR(nsDisplayItem* aItem,
*
* The basic algorithm is:
*
* For-each item in the new list:
* For-each item i in the new list:
* If the item has a matching item in the old list:
* Remove items from the bottom of the old list until we reach the matching item:
* Remove items from the start of the old list up until we reach an item that also exists in the new list (leaving the matched item in place):
* Add valid items to the merged list, destroy invalid items.
* Destroy the matching item from the old list.
* Add the item from the new list into the merged list.
* Add all remaining valid items from the old list into the merged list.
* Add i into the merged list.
* If the start of the old list matches i, remove and destroy it, otherwise mark the old version of i as used.
* Add all remaining valid items from the old list into the merged list, skipping over (and destroying) any that are marked as used.
*
* If any item has a child display list, then we recurse into the merge
* algorithm once we match up the new/old versions (if present).
@ -327,7 +327,7 @@ void UpdateASR(nsDisplayItem* aItem,
* Example 1:
*
* Old List: A,B,C,D
* New List: A,D
* Modified List: A,D
* Invalidations: C,D
*
* We first match the A items, and add the new one to the merged list.
@ -337,10 +337,23 @@ void UpdateASR(nsDisplayItem* aItem,
*
* Merged List: A,B,D
*
* Example 2:
* Example 2 (layout/reftests/retained-dl-zindex-1.html):
*
* Old List: A, B
* New List, B, A
* Modified List: B, A
* Invalidations: A
*
* In this example A has been explicitly moved to the back.
*
* We match the B items, but don't copy A since it's invalid, and then add the
* new B into the merged list. We then add A, and we're done.
*
* Merged List: B, A
*
* Example 3:
*
* Old List: A, B
* Modified List: B, A
* Invalidations: -
*
* This can happen because a prior merge might have changed the ordering
@ -350,6 +363,28 @@ void UpdateASR(nsDisplayItem* aItem,
* and then add the new B into the merged list. We then add A, and we're done.
*
* Merged List: B, A
*
* Example 4 (layout/reftests/retained-dl-zindex-2.html):
*
* Element A has two elements covering it (B and C), that don't intersect each
* other. We then move C to the back.
*
* The correct initial ordering has B and C after A, in any order.
*
* Old List: A, B, C
* Modified List: C, A
* Invalidations: C
*
* We match the C items, but don't add anything from the old list because A is present
* in both lists. We add C to the merged list, and mark the old version of C as reused.
*
* We then match A, add the new version the merged list and delete the old version.
*
* We then process the remainder of the old list, B is added (since it is valid,
* and hasn't been mark as reused), C is destroyed since it's marked as reused and
* is already present in the merged list.
*
* Merged List: C, A, B
*/
void
RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
@ -414,39 +449,49 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
// The new item has a matching counterpart in the old list that we haven't yet reached,
// so copy all valid items from the old list into the merged list until we get to the
// matched item.
if (!oldItem->IsReused()) {
nsDisplayItem* old = nullptr;
while ((old = aOldList->RemoveBottom()) && !IsSameItem(newItem, old)) {
if (IsAnyAncestorModified(old->FrameForInvalidation())) {
// The old item is invalid, discard it.
oldListLookup.Remove({ old->Frame(), old->GetPerFrameKey() });
old->Destroy(&mBuilder);
} else if (newListLookup.Get({ old->Frame(), old->GetPerFrameKey() })) {
// The old item is also in the new list, but we haven't got to it yet.
// Mark that we've found it, and we'll deal with it when we get to the new
// entry.
old->SetReused(true);
} else {
// Recurse into the child list (without a matching new list) to
// ensure that we find and remove any invalidated items.
if (old->GetChildren()) {
nsDisplayList empty;
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
MergeDisplayLists(&empty, old->GetChildren(),
old->GetChildren(), containerASRForChildren);
UpdateASR(old, containerASRForChildren);
old->UpdateBounds(&mBuilder);
}
ReuseItem(old);
nsDisplayItem* old = nullptr;
while ((old = aOldList->GetBottom()) && old != oldItem) {
if (IsAnyAncestorModified(old->FrameForInvalidation())) {
// The old item is invalid, discard it.
oldListLookup.Remove({ old->Frame(), old->GetPerFrameKey() });
aOldList->RemoveBottom();
old->Destroy(&mBuilder);
} else if (newListLookup.Get({ old->Frame(), old->GetPerFrameKey() })) {
// This old item is also in the new list, but we haven't got to it yet.
// Stop now, and we'll deal with it when we get to the new entry.
break;
} else {
// Recurse into the child list (without a matching new list) to
// ensure that we find and remove any invalidated items.
if (old->GetChildren()) {
nsDisplayList empty;
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
MergeDisplayLists(&empty, old->GetChildren(),
old->GetChildren(), containerASRForChildren);
UpdateASR(old, containerASRForChildren);
old->UpdateBounds(&mBuilder);
}
aOldList->RemoveBottom();
ReuseItem(old);
}
MOZ_ASSERT(old && IsSameItem(newItem, old));
MOZ_ASSERT(old == oldItem);
}
bool destroy = false;
if (old == oldItem) {
// If we advanced the old list until the matching item then we can pop
// the matching item off the old list and make sure we clean it up.
aOldList->RemoveBottom();
destroy = true;
} else {
// If we didn't get to the matching item, then mark the old item
// as being reused (since we're adding the new version to the new
// list now) so that we don't add it twice at the end.
oldItem->SetReused(true);
}
// Recursively merge any child lists, destroy the old item and add
// the new one to the list.
if (oldItem->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS &&
if (destroy &&
oldItem->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS &&
!IsAnyAncestorModified(oldItem->FrameForInvalidation())) {
// Event regions items don't have anything interesting other than
// the lists of regions and frames, so we have no need to use the
@ -466,7 +511,9 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
newItem->UpdateBounds(&mBuilder);
}
oldItem->Destroy(&mBuilder);
if (destroy) {
oldItem->Destroy(&mBuilder);
}
UseItem(newItem);
}
} else {
@ -478,7 +525,8 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
// Reuse the remaining valid items from the old display list.
while (nsDisplayItem* old = aOldList->RemoveBottom()) {
if (!IsAnyAncestorModified(old->FrameForInvalidation())) {
if (!IsAnyAncestorModified(old->FrameForInvalidation()) &&
!old->IsReused()) {
if (old->GetChildren()) {
// We are calling MergeDisplayLists() to ensure that the display items
// with modified or deleted children will be correctly handled.

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

@ -106,7 +106,6 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro
#include "nsILayoutHistoryState.h"
#include "nsFrameManager.h"
#include "mozilla/ReflowInput.h"
#include "nsIContentViewerContainer.h"
#include "nsIContentViewer.h"
#include "nsIDocumentViewerPrint.h"

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

@ -18,7 +18,7 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
}
.c1 { grid-column: 1 / span 2; min-width:40px; }
.r1 { grid-column: 2 / span 3; min-width:70px; margin-left:41px; }
.r1 { grid-column: 2 / span 3; min-width:70px; margin-left:40px; }
.c3 { grid-column: 3 / span 1; min-width:0; margin-left:138px; }
span {
@ -39,8 +39,8 @@ x { display:inline-block; width:10px; height:18px; }
<body>
<div class="grid">
<span class="c1" style="width:43px"><x></x></span>
<span class="r1" style="width:79px"><x></x></span>
<span class="c1" style="width:40px"><x></x></span>
<span class="r1" style="width:74px"><x></x></span>
</div>
<div class="grid">
@ -50,10 +50,10 @@ x { display:inline-block; width:10px; height:18px; }
</div>
<div class="grid">
<span class="c1" style="width:43px"><x></x></span>
<span class="r1" style="width:79px"><x></x></span>
<span class="r1" style="width:79px"><x></x></span>
<span class="r1" style="width:79px"><x></x></span>
<span class="c1" style="width:40px"><x></x></span>
<span class="r1" style="width:74px"><x></x></span>
<span class="r1" style="width:74px"><x></x></span>
<span class="r1" style="width:74px"><x></x></span>
</div>
<div class="grid" style="">
<span class="c1" style="width:413px"><x></x></span>
@ -76,14 +76,14 @@ x { display:inline-block; width:10px; height:18px; }
<div class="grid">
<span class="c1" style="width:100px"><x></x></span>
<span class="r1" style="margin-left:117px; margin-right:11px; width:300px"><x></x></span>
<span class="c3" style="margin-left:228px; width:83px"><x></x></span>
<span class="r1" style="margin-left:115px; margin-right:5px; width:300px"><x></x></span>
<span class="c3" style="margin-left:224px; width:81px"><x></x></span>
</div>
<div class="grid">
<span class="c1" style="width:100px; border-sizing:border-box"><x></x></span>
<span class="r1" style="margin-left:117px; margin-right:11px; width:300px; border-sizing:border-box"><x></x></span>
<span class="c3" style="margin-left:228px; width:83px"><x></x></span>
<span class="r1" style="margin-left:115px; margin-right:5px; width:300px; border-sizing:border-box"><x></x></span>
<span class="c3" style="margin-left:224px; width:81px"><x></x></span>
</div>
</body>

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

@ -8,6 +8,8 @@ skip-if(!retainedDisplayList) == retained-dl-scroll-out-of-view-1.html retained-
skip-if(!retainedDisplayList) == retained-dl-displayport-1.html retained-dl-displayport-1-ref.html
skip-if(!retainedDisplayList) == retained-dl-prerender-transform-1.html retained-dl-prerender-transform-1-ref.html
== retained-dl-wrap-list.html retained-dl-wrap-list-ref.html
== retained-dl-zindex-1.html retained-dl-zindex-1-ref.html
== retained-dl-zindex-2.html retained-dl-zindex-2-ref.html
fuzzy(1,235200) == 1413073.html 1413073-ref.html
== 1416291.html 1416291-ref.html
== 1417601-1.html 1417601-1-ref.html

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

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 200px;
height: 200px;
position:relative;
will-change: transform;
}
#one {
top:120px;
background-color:blue;
}
#two {
top: -200px;
left: 100px;
background-color:green;
z-index: -1;
}
</style>
</head>
<body>
<div id="one"></div>
<div id="two"></div>
</body>
</html>

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

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<style>
div {
width: 200px;
height: 200px;
position:relative;
will-change: transform;
}
#one {
top:120px;
background-color:blue;
}
#two {
top: -200px;
left: 100px;
background-color:green;
z-index: 1;
}
</style>
</head>
<body>
<div id="one"></div>
<div id="two"></div>
</body>
<script>
function doTest() {
document.getElementById("two").style.zIndex = -1;
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", doTest);
</script>
</html>

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

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 200px;
height: 200px;
position:relative;
will-change:transform;
}
#one {
top:120px;
background-color:blue;
}
#two {
top: -200px;
left: 100px;
background-color:green;
}
#three {
top: -180px;
left: 100px;
background-color:red;
z-index: -1;
}
</style>
</head>
<body>
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
</body>
</html>

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

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<style>
div {
width: 200px;
height: 200px;
position:relative;
will-change:transform;
}
#one {
top:120px;
background-color:blue;
}
#two {
top: -200px;
left: 100px;
background-color:green;
}
#three {
top: -180px;
left: 100px;
background-color:red;
z-index: 1;
}
</style>
</head>
<body>
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
</body>
<script>
function doTest() {
document.getElementById("three").style.zIndex = -1;
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", doTest);
</script>
</html>

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

@ -1289,14 +1289,10 @@ pref("dom.min_timeout_value", 4);
pref("dom.min_background_timeout_value", 1000);
// Timeout clamp in ms for tracking timeouts we clamp
// Note that this requires the privacy.trackingprotection.annotate_channels pref to be on in order to have any effect.
#ifdef NIGHTLY_BUILD
pref("dom.min_tracking_timeout_value", 10000);
#else
pref("dom.min_tracking_timeout_value", 4);
#endif
// And for background windows
// Note that this requires the privacy.trackingprotection.annotate_channels pref to be on in order to have any effect.
pref("dom.min_tracking_background_timeout_value", 10000);
pref("dom.min_tracking_background_timeout_value", 4);
// Delay in ms from document load until we start throttling background timeouts.
pref("dom.timeout.throttling_delay", 30000);

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

@ -273,8 +273,10 @@ CacheFileMetadata::WriteMetadata(uint32_t aOffset,
p += mKey.Length();
*p = 0;
p++;
memcpy(p, mBuf, mElementsSize);
p += mElementsSize;
if (mElementsSize) {
memcpy(p, mBuf, mElementsSize);
p += mElementsSize;
}
CacheHash::Hash32_t hash;
hash = CacheHash::Hash(mWriteBuf + sizeof(uint32_t),

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

@ -7,19 +7,11 @@
#include <stdio.h>
#include "pkixtestutil.h"
#include "pkixtestnss.h"
#include "TLSServer.h"
#include "secder.h"
#include "secerr.h"
namespace mozilla { namespace pkix { namespace test {
// Ownership of privateKey is transfered.
TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg,
const SECKEYPublicKey& publicKey,
SECKEYPrivateKey* privateKey);
} } } // namespace mozilla::pkix::test
using namespace mozilla;
using namespace mozilla::pkix;
using namespace mozilla::pkix::test;
@ -28,15 +20,15 @@ using namespace mozilla::test;
static TestKeyPair*
CreateTestKeyPairFromCert(const UniqueCERTCertificate& cert)
{
UniqueSECKEYPrivateKey privateKey(PK11_FindKeyByAnyCert(cert.get(), nullptr));
ScopedSECKEYPrivateKey privateKey(PK11_FindKeyByAnyCert(cert.get(), nullptr));
if (!privateKey) {
return nullptr;
}
UniqueSECKEYPublicKey publicKey(CERT_ExtractPublicKey(cert.get()));
ScopedSECKEYPublicKey publicKey(CERT_ExtractPublicKey(cert.get()));
if (!publicKey) {
return nullptr;
}
return CreateTestKeyPair(RSA_PKCS1(), *publicKey.get(), privateKey.release());
return CreateTestKeyPair(RSA_PKCS1(), publicKey, privateKey);
}
SECItemArray*

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

@ -390,6 +390,7 @@ PK11_ImportCert
PK11_ImportCertForKey
PK11_ImportCRL
PK11_ImportDERPrivateKeyInfoAndReturnKey
PK11_ImportEncryptedPrivateKeyInfoAndReturnKey
PK11_ImportPublicKey
PK11_ImportSymKey
PK11_InitPin

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

@ -23,6 +23,7 @@
*/
#include "pkixtestutil.h"
#include "pkixtestnss.h"
#include <limits>
@ -42,17 +43,18 @@ namespace mozilla { namespace pkix { namespace test {
namespace {
typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
ScopedSECKEYPublicKey;
typedef ScopedPtr<SECKEYPrivateKey, SECKEY_DestroyPrivateKey>
ScopedSECKEYPrivateKey;
inline void
SECITEM_FreeItem_true(SECItem* item)
{
SECITEM_FreeItem(item, true);
}
inline void
SECKEY_DestroyEncryptedPrivateKeyInfo_true(SECKEYEncryptedPrivateKeyInfo* e)
{
SECKEY_DestroyEncryptedPrivateKeyInfo(e, true);
}
typedef mozilla::pkix::ScopedPtr<SECItem, SECITEM_FreeItem_true> ScopedSECItem;
TestKeyPair* GenerateKeyPairInner();
@ -78,12 +80,15 @@ InitReusedKeyPair()
class NSSTestKeyPair final : public TestKeyPair
{
public:
// NSSTestKeyPair takes ownership of privateKey.
NSSTestKeyPair(const TestPublicKeyAlgorithm& publicKeyAlg,
const ByteString& spk,
SECKEYPrivateKey* privateKey)
const ByteString& encryptedPrivateKey,
const ByteString& encryptionAlgorithm,
const ByteString& encryptionParams)
: TestKeyPair(publicKeyAlg, spk)
, privateKey(privateKey)
, encryptedPrivateKey(encryptedPrivateKey)
, encryptionAlgorithm(encryptionAlgorithm)
, encryptionParams(encryptionParams)
{
}
@ -121,10 +126,50 @@ public:
abort();
}
ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
if (!slot) {
return MapPRErrorCodeToResult(PR_GetError());
}
SECItem encryptedPrivateKeyInfoItem = {
siBuffer,
const_cast<uint8_t*>(encryptedPrivateKey.data()),
static_cast<unsigned int>(encryptedPrivateKey.length())
};
SECItem encryptionAlgorithmItem = {
siBuffer,
const_cast<uint8_t*>(encryptionAlgorithm.data()),
static_cast<unsigned int>(encryptionAlgorithm.length())
};
SECItem encryptionParamsItem = {
siBuffer,
const_cast<uint8_t*>(encryptionParams.data()),
static_cast<unsigned int>(encryptionParams.length())
};
SECKEYEncryptedPrivateKeyInfo encryptedPrivateKeyInfo = {
nullptr,
{ encryptionAlgorithmItem, encryptionParamsItem },
encryptedPrivateKeyInfoItem
};
SECItem passwordItem = { siBuffer, nullptr, 0 };
SECItem publicValueItem = {
siBuffer,
const_cast<uint8_t*>(subjectPublicKey.data()),
static_cast<unsigned int>(subjectPublicKey.length())
};
SECKEYPrivateKey* privateKey;
// This should always be an RSA key (we'll have aborted above if we're not
// doing an RSA signature).
if (PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(
slot.get(), &encryptedPrivateKeyInfo, &passwordItem, nullptr,
&publicValueItem, false, false, rsaKey, KU_ALL, &privateKey,
nullptr) != SECSuccess) {
return MapPRErrorCodeToResult(PR_GetError());
}
ScopedSECKEYPrivateKey scopedPrivateKey(privateKey);
SECItem signatureItem;
if (SEC_SignData(&signatureItem, tbs.data(),
static_cast<int>(tbs.length()),
privateKey.get(), oidTag) != SECSuccess) {
scopedPrivateKey.get(), oidTag) != SECSuccess) {
return MapPRErrorCodeToResult(PR_GetError());
}
signature.assign(signatureItem.data, signatureItem.len);
@ -134,40 +179,64 @@ public:
TestKeyPair* Clone() const override
{
ScopedSECKEYPrivateKey
privateKeyCopy(SECKEY_CopyPrivateKey(privateKey.get()));
if (!privateKeyCopy) {
return nullptr;
}
return new (std::nothrow) NSSTestKeyPair(publicKeyAlg,
subjectPublicKey,
privateKeyCopy.release());
encryptedPrivateKey,
encryptionAlgorithm,
encryptionParams);
}
private:
ScopedSECKEYPrivateKey privateKey;
const ByteString encryptedPrivateKey;
const ByteString encryptionAlgorithm;
const ByteString encryptionParams;
};
} // namespace
// This private function is also used by Gecko's PSM test framework
// (OCSPCommon.cpp).
//
// Ownership of privateKey is transfered.
TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg,
const SECKEYPublicKey& publicKey,
SECKEYPrivateKey* privateKey)
const ScopedSECKEYPublicKey& publicKey,
const ScopedSECKEYPrivateKey& privateKey)
{
ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
spki(SECKEY_CreateSubjectPublicKeyInfo(&publicKey));
spki(SECKEY_CreateSubjectPublicKeyInfo(publicKey.get()));
if (!spki) {
return nullptr;
}
SECItem spkDER = spki->subjectPublicKey;
DER_ConvertBitString(&spkDER); // bits to bytes
return new (std::nothrow) NSSTestKeyPair(publicKeyAlg,
ByteString(spkDER.data, spkDER.len),
privateKey);
ScopedPtr<PK11SlotInfo, PK11_FreeSlot> slot(PK11_GetInternalSlot());
if (!slot) {
return nullptr;
}
// Because NSSTestKeyPair isn't tracked by XPCOM and won't otherwise be aware
// of shutdown, we don't have a way to release NSS resources at the
// appropriate time. To work around this, NSSTestKeyPair doesn't hold on to
// NSS resources. Instead, we export the generated private key part as an
// encrypted blob (with an empty password and fairly lame encryption). When we
// need to use it (e.g. to sign something), we decrypt it and create a
// temporary key object.
SECItem passwordItem = { siBuffer, nullptr, 0 };
ScopedPtr<SECKEYEncryptedPrivateKeyInfo,
SECKEY_DestroyEncryptedPrivateKeyInfo_true> encryptedPrivateKey(
PK11_ExportEncryptedPrivKeyInfo(
slot.get(), SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC,
&passwordItem, privateKey.get(), 1, nullptr));
if (!encryptedPrivateKey) {
return nullptr;
}
return new (std::nothrow) NSSTestKeyPair(
publicKeyAlg,
ByteString(spkDER.data, spkDER.len),
ByteString(encryptedPrivateKey->encryptedData.data,
encryptedPrivateKey->encryptedData.len),
ByteString(encryptedPrivateKey->algorithm.algorithm.data,
encryptedPrivateKey->algorithm.algorithm.len),
ByteString(encryptedPrivateKey->algorithm.parameters.data,
encryptedPrivateKey->algorithm.parameters.len));
}
namespace {
@ -194,7 +263,7 @@ GenerateKeyPairInner()
nullptr));
ScopedSECKEYPublicKey publicKey(publicKeyTemp);
if (privateKey) {
return CreateTestKeyPair(RSA_PKCS1(), *publicKey, privateKey.release());
return CreateTestKeyPair(RSA_PKCS1(), publicKey, privateKey);
}
assert(!publicKeyTemp);
@ -275,7 +344,7 @@ GenerateDSSKeyPair()
return nullptr;
}
ScopedSECKEYPublicKey publicKey(publicKeyTemp);
return CreateTestKeyPair(DSS(), *publicKey, privateKey.release());
return CreateTestKeyPair(DSS(), publicKey, privateKey);
}
Result

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

@ -0,0 +1,49 @@
/* -*- 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 code is made available to you under your choice of the following sets
* of licensing terms:
*/
/* 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/.
*/
/* Copyright 2018 Mozilla Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// This file provides some implementation-specific test utilities. This is only
// necessary because some PSM xpcshell test utilities overlap in functionality
// with these test utilities, so the underlying implementation is shared.
#ifndef mozilla_pkix_test_pkixtestnss_h
#define mozilla_pkix_test_pkixtestnss_h
#include "keyhi.h"
#include "keythi.h"
#include "pkixtestutil.h"
namespace mozilla { namespace pkix { namespace test {
typedef ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
ScopedSECKEYPublicKey;
typedef ScopedPtr<SECKEYPrivateKey, SECKEY_DestroyPrivateKey>
ScopedSECKEYPrivateKey;
TestKeyPair* CreateTestKeyPair(const TestPublicKeyAlgorithm publicKeyAlg,
const ScopedSECKEYPublicKey& publicKey,
const ScopedSECKEYPrivateKey& privateKey);
} } } // namespace mozilla::pkix::test
#endif // mozilla_pkix_test_pkixtestnss_h

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

@ -22,8 +22,8 @@
* limitations under the License.
*/
#ifndef mozilla_pkix_test_pkixtestutils_h
#define mozilla_pkix_test_pkixtestutils_h
#ifndef mozilla_pkix_test_pkixtestutil_h
#define mozilla_pkix_test_pkixtestutil_h
#include <ctime>
#include <stdint.h> // Some Mozilla-supported compilers lack <cstdint>
@ -445,4 +445,4 @@ ByteString CreateEncodedOCSPResponse(OCSPResponseContext& context);
} } } // namespace mozilla::pkix::test
#endif // mozilla_pkix_test_pkixtestutils_h
#endif // mozilla_pkix_test_pkixtestutil_h

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

@ -78,6 +78,9 @@ if CONFIG['MOZ_GMP_SANDBOX']:
'SandboxOpenedFiles.cpp',
]
if CONFIG['MOZ_ALSA']:
DEFINES['MOZ_ALSA'] = True
# This copy of SafeSPrintf doesn't need to avoid the Chromium logging
# dependency like the one in libxul does, but this way the behavior is
# consistent. See also the comment in SandboxLogging.h.

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

@ -12450,6 +12450,15 @@
"n_values": 12,
"description": "Plugin drawing model. 0 when windowed, otherwise NPDrawingModel + 1."
},
"DOM_SCRIPT_KIND": {
"record_in_processes": ["main", "content"],
"alert_emails": ["jcoppeard@mozilla.com"],
"expires_in_version": "63",
"kind": "categorical",
"bug_numbers": [1430145],
"labels": ["ClassicScript", "ModuleScript"],
"description": "Record the kind of every script loaded in a document."
},
"DOM_SCRIPT_SRC_ENCODING": {
"record_in_processes": ["main", "content"],
"alert_emails": ["dteller@mozilla.com"],
@ -12602,6 +12611,15 @@
"bug_numbers": [1362114],
"description": "Number of script tags evaluated per document."
},
"DOM_SCRIPT_PRELOAD_RESULT": {
"record_in_processes": ["main", "content"],
"alert_emails": ["jcoppeard@mozilla.com"],
"expires_in_version": "63",
"kind": "categorical",
"bug_numbers": [1430145],
"labels": ["Used", "RejectedByPolicy", "RequestMismatch", "LoadError", "NotUsed"],
"description": "Whether a preloaded script was used or the reason it was not used."
},
"VIDEO_FASTSEEK_USED": {
"record_in_processes": ["main", "content"],
"alert_emails": ["cpearce@mozilla.com", "tkuo@mozilla.com"],

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

@ -360,10 +360,21 @@ const Preferences = window.Preferences = (function() {
* constructor or property getters appropriately handle this state.
*/
function setValue(element, attribute, value) {
if (attribute in element)
if (attribute in element) {
element[attribute] = value;
else
} else if (attribute === "checked") {
// The "checked" attribute can't simply be set to the specified value;
// it has to be set if the value is true and removed if the value
// is false in order to be interpreted correctly by the element.
if (value) {
// We can set it to anything; convention is to set it to itself.
element.setAttribute(attribute, attribute);
} else {
element.removeAttribute(attribute);
}
} else {
element.setAttribute(attribute, value);
}
}
if (aElement.localName == "checkbox" ||
aElement.localName == "listitem")

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

@ -105,11 +105,21 @@ public:
{
}
// XXX are you sure??
// auto-generated copy-constructor OK
// auto-generated copy-assignment operator OK
// auto-generated destructor OK
nsTDependentString(self_type&& aStr)
: string_type()
{
Rebind(aStr, /* aStartPos = */ 0);
aStr.SetToEmptyBuffer();
}
explicit
nsTDependentString(const self_type& aStr)
: string_type()
{
Rebind(aStr, /* aStartPos = */ 0);
}
/**
* allow this class to be bound to a different string...
@ -128,6 +138,7 @@ private:
// NOT USED
nsTDependentString(const substring_tuple_type&) = delete;
self_type& operator=(const self_type& aStr) = delete;
};
extern template class nsTDependentString<char>;

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

@ -68,6 +68,52 @@ TEST(Strings, IsChar)
#endif
}
TEST(Strings, DependentStrings)
{
// A few tests that make sure copying nsTDependentStrings behaves properly.
using DataFlags = mozilla::detail::StringDataFlags;
{
// Test copy ctor.
nsDependentCString tmp("foo");
auto data = tmp.Data();
nsDependentCString foo(tmp);
// Neither string should be using a shared buffer.
EXPECT_FALSE(tmp.GetDataFlags() & DataFlags::SHARED);
EXPECT_FALSE(foo.GetDataFlags() & DataFlags::SHARED);
// Both strings should be pointing to the original buffer.
EXPECT_EQ(data, tmp.Data());
EXPECT_EQ(data, foo.Data());
}
{
// Test move ctor.
nsDependentCString tmp("foo");
auto data = tmp.Data();
nsDependentCString foo(mozilla::Move(tmp));
// Neither string should be using a shared buffer.
EXPECT_FALSE(tmp.GetDataFlags() & DataFlags::SHARED);
EXPECT_FALSE(foo.GetDataFlags() & DataFlags::SHARED);
// First string should be reset, the second should be pointing to the
// original buffer.
EXPECT_NE(data, tmp.Data());
EXPECT_EQ(data, foo.Data());
EXPECT_TRUE(tmp.IsEmpty());
}
{
// Test copying to a nsCString.
nsDependentCString tmp("foo");
auto data = tmp.Data();
nsCString foo(tmp);
// Original string should not be shared, copy should be shared.
EXPECT_FALSE(tmp.GetDataFlags() & DataFlags::SHARED);
EXPECT_TRUE(foo.GetDataFlags() & DataFlags::SHARED);
// First string should remain the same, the second should be pointing to
// a new buffer.
EXPECT_EQ(data, tmp.Data());
EXPECT_NE(data, foo.Data());
}
}
TEST(Strings, assign)
{
nsCString result;