From a96a14649cbbc2b97027a5da4e017038b794b0bc Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 28 Oct 2015 10:50:36 -0700 Subject: [PATCH 01/95] Remove Windows-specific synchronous plugin drawing code. (bug 1218688 part 1, r=jimm) --- dom/plugins/ipc/PluginInstanceChild.cpp | 207 ----------------------- dom/plugins/ipc/PluginInstanceChild.h | 23 --- dom/plugins/ipc/PluginInstanceParent.cpp | 125 -------------- dom/plugins/ipc/PluginInstanceParent.h | 6 - dom/plugins/ipc/PluginMessageUtils.cpp | 16 -- dom/plugins/ipc/PluginMessageUtils.h | 20 --- gfx/thebes/gfxWindowsNativeDrawing.cpp | 22 --- gfx/thebes/gfxWindowsNativeDrawing.h | 3 - layout/generic/nsPluginFrame.cpp | 104 ------------ 9 files changed, 526 deletions(-) diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index 5802dc3cd67..f1dc7e893e7 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -188,9 +188,6 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface, mWsInfo.display = DefaultXDisplay(); #endif #endif // MOZ_X11 && XP_UNIX && !XP_MACOSX -#if defined(OS_WIN) - memset(&mAlphaExtract, 0, sizeof(mAlphaExtract)); -#endif // OS_WIN #if defined(OS_WIN) InitPopupMenuHook(); if (GetQuirks() & QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) { @@ -821,21 +818,6 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event, if (WM_NULL == evcopy.event) return true; - // Painting for win32. SharedSurfacePaint handles everything. - if (mWindow.type == NPWindowTypeDrawable) { - if (evcopy.event == WM_PAINT) { - *handled = SharedSurfacePaint(evcopy); - return true; - } - else if (DoublePassRenderingEvent() == evcopy.event) { - // We'll render to mSharedSurfaceDib first, then render to a cached bitmap - // we store locally. The two passes are for alpha extraction, so the second - // pass must be to a flat white surface in order for things to work. - mAlphaExtract.doublePass = RENDER_BACK_ONE; - *handled = true; - return true; - } - } *handled = WinlessHandleEvent(evcopy); return true; #endif @@ -1296,13 +1278,6 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow) } break; - case NPWindowTypeDrawable: - mWindow.type = aWindow.type; - if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) - SetupFlashMsgThrottle(); - return SharedSurfaceSetWindow(aWindow); - break; - default: NS_NOTREACHED("Bad plugin window type."); return false; @@ -2024,187 +1999,6 @@ PluginInstanceChild::WinlessHandleEvent(NPEvent& event) return handled; } -/* windowless drawing helpers */ - -bool -PluginInstanceChild::SharedSurfaceSetWindow(const NPRemoteWindow& aWindow) -{ - // If the surfaceHandle is empty, parent is telling us we can reuse our cached - // memory surface and hdc. Otherwise, we need to reset, usually due to a - // expanding plugin port size. - if (!aWindow.surfaceHandle) { - if (!mSharedSurfaceDib.IsValid()) { - return false; - } - } - else { - // Attach to the new shared surface parent handed us. - if (NS_FAILED(mSharedSurfaceDib.Attach((SharedDIB::Handle)aWindow.surfaceHandle, - aWindow.width, aWindow.height, false))) - return false; - // Free any alpha extraction resources if needed. This will be reset - // the next time it's used. - AlphaExtractCacheRelease(); - } - - // NPRemoteWindow's origin is the origin of our shared dib. - mWindow.x = aWindow.x; - mWindow.y = aWindow.y; - mWindow.width = aWindow.width; - mWindow.height = aWindow.height; - mWindow.type = aWindow.type; - - mWindow.window = reinterpret_cast(mSharedSurfaceDib.GetHDC()); - ::SetViewportOrgEx(mSharedSurfaceDib.GetHDC(), - -aWindow.x, -aWindow.y, nullptr); - - if (mPluginIface->setwindow) - mPluginIface->setwindow(&mData, &mWindow); - - return true; -} - -void -PluginInstanceChild::SharedSurfaceRelease() -{ - mSharedSurfaceDib.Close(); - AlphaExtractCacheRelease(); -} - -/* double pass cache buffer - (rarely) used in cases where alpha extraction - * occurs for windowless plugins. */ - -bool -PluginInstanceChild::AlphaExtractCacheSetup() -{ - AlphaExtractCacheRelease(); - - mAlphaExtract.hdc = ::CreateCompatibleDC(nullptr); - - if (!mAlphaExtract.hdc) - return false; - - BITMAPINFOHEADER bmih; - memset((void*)&bmih, 0, sizeof(BITMAPINFOHEADER)); - bmih.biSize = sizeof(BITMAPINFOHEADER); - bmih.biWidth = mWindow.width; - bmih.biHeight = mWindow.height; - bmih.biPlanes = 1; - bmih.biBitCount = 32; - bmih.biCompression = BI_RGB; - - void* ppvBits = nullptr; - mAlphaExtract.bmp = ::CreateDIBSection(mAlphaExtract.hdc, - (BITMAPINFO*)&bmih, - DIB_RGB_COLORS, - (void**)&ppvBits, - nullptr, - (unsigned long)sizeof(BITMAPINFOHEADER)); - if (!mAlphaExtract.bmp) - return false; - - DeleteObject(::SelectObject(mAlphaExtract.hdc, mAlphaExtract.bmp)); - return true; -} - -void -PluginInstanceChild::AlphaExtractCacheRelease() -{ - if (mAlphaExtract.bmp) - ::DeleteObject(mAlphaExtract.bmp); - - if (mAlphaExtract.hdc) - ::DeleteObject(mAlphaExtract.hdc); - - mAlphaExtract.bmp = nullptr; - mAlphaExtract.hdc = nullptr; -} - -void -PluginInstanceChild::UpdatePaintClipRect(RECT* aRect) -{ - if (aRect) { - // Update the clip rect on our internal hdc - HRGN clip = ::CreateRectRgnIndirect(aRect); - ::SelectClipRgn(mSharedSurfaceDib.GetHDC(), clip); - ::DeleteObject(clip); - } -} - -int16_t -PluginInstanceChild::SharedSurfacePaint(NPEvent& evcopy) -{ - if (!mPluginIface->event) - return false; - - RECT* pRect = reinterpret_cast(evcopy.lParam); - - switch(mAlphaExtract.doublePass) { - case RENDER_NATIVE: - // pass the internal hdc to the plugin - UpdatePaintClipRect(pRect); - evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC()); - return mPluginIface->event(&mData, reinterpret_cast(&evcopy)); - break; - case RENDER_BACK_ONE: - // Handle a double pass render used in alpha extraction for transparent - // plugins. (See nsPluginFrame and gfxWindowsNativeDrawing for details.) - // We render twice, once to the shared dib, and once to a cache which - // we copy back on a second paint. These paints can't be spread across - // multiple rpc messages as delays cause animation frame changes. - if (!mAlphaExtract.bmp && !AlphaExtractCacheSetup()) { - mAlphaExtract.doublePass = RENDER_NATIVE; - return false; - } - - // See gfxWindowsNativeDrawing, color order doesn't have to match. - UpdatePaintClipRect(pRect); - ::FillRect(mSharedSurfaceDib.GetHDC(), pRect, (HBRUSH)GetStockObject(WHITE_BRUSH)); - evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC()); - if (!mPluginIface->event(&mData, reinterpret_cast(&evcopy))) { - mAlphaExtract.doublePass = RENDER_NATIVE; - return false; - } - - // Copy to cache. We render to shared dib so we don't have to call - // setwindow between calls (flash issue). - ::BitBlt(mAlphaExtract.hdc, - pRect->left, - pRect->top, - pRect->right - pRect->left, - pRect->bottom - pRect->top, - mSharedSurfaceDib.GetHDC(), - pRect->left, - pRect->top, - SRCCOPY); - - ::FillRect(mSharedSurfaceDib.GetHDC(), pRect, (HBRUSH)GetStockObject(BLACK_BRUSH)); - if (!mPluginIface->event(&mData, reinterpret_cast(&evcopy))) { - mAlphaExtract.doublePass = RENDER_NATIVE; - return false; - } - mAlphaExtract.doublePass = RENDER_BACK_TWO; - return true; - break; - case RENDER_BACK_TWO: - // copy our cached surface back - UpdatePaintClipRect(pRect); - ::BitBlt(mSharedSurfaceDib.GetHDC(), - pRect->left, - pRect->top, - pRect->right - pRect->left, - pRect->bottom - pRect->top, - mAlphaExtract.hdc, - pRect->left, - pRect->top, - SRCCOPY); - mAlphaExtract.doublePass = RENDER_NATIVE; - return true; - break; - } - return false; -} - /* flash msg throttling helpers */ // Flash has the unfortunate habit of flooding dispatch loops with custom @@ -4049,7 +3843,6 @@ PluginInstanceChild::Destroy() mCachedElementActor = nullptr; #if defined(OS_WIN) - SharedSurfaceRelease(); DestroyWinlessPopupSurrogate(); UnhookWinlessFlashThrottle(); DestroyPluginWindow(); diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInstanceChild.h index 7b41c377283..eabae22f74a 100644 --- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -427,29 +427,6 @@ private: */ nsAutoPtr< nsTHashtable > mDeletingHash; -#if defined(OS_WIN) -private: - // Shared dib rendering management for windowless plugins. - bool SharedSurfaceSetWindow(const NPRemoteWindow& aWindow); - int16_t SharedSurfacePaint(NPEvent& evcopy); - void SharedSurfaceRelease(); - bool AlphaExtractCacheSetup(); - void AlphaExtractCacheRelease(); - void UpdatePaintClipRect(RECT* aRect); - -private: - enum { - RENDER_NATIVE, - RENDER_BACK_ONE, - RENDER_BACK_TWO - }; - gfx::SharedDIBWin mSharedSurfaceDib; - struct { - uint16_t doublePass; - HDC hdc; - HBITMAP bmp; - } mAlphaExtract; -#endif // defined(OS_WIN) #if defined(MOZ_WIDGET_COCOA) private: #if defined(__i386__) diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index a6930c746b5..9e1ee08fade 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -176,7 +176,6 @@ PluginInstanceParent::ActorDestroy(ActorDestroyReason why) if (why == AbnormalShutdown) { // If the plugin process crashes, this is the only // chance we get to destroy resources. - SharedSurfaceRelease(); UnsubclassPluginWindow(); } #endif @@ -204,7 +203,6 @@ PluginInstanceParent::Destroy() } #if defined(OS_WIN) - SharedSurfaceRelease(); UnsubclassPluginWindow(); #endif @@ -949,11 +947,6 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow) #if defined(OS_WIN) // On windowless controls, reset the shared memory surface as needed. if (mWindowType == NPWindowTypeDrawable) { - // SharedSurfaceSetWindow will take care of NPRemoteWindow. - if (!SharedSurfaceSetWindow(aWindow, window)) { - return NPERR_OUT_OF_MEMORY_ERROR; - } - MaybeCreateChildPopupSurrogate(); } else { SubclassPluginWindow(reinterpret_cast(aWindow->window)); @@ -1188,23 +1181,7 @@ PluginInstanceParent::NPP_HandleEvent(void* event) #if defined(OS_WIN) if (mWindowType == NPWindowTypeDrawable) { - if (DoublePassRenderingEvent() == npevent->event) { - return CallPaint(npremoteevent, &handled) && handled; - } - switch (npevent->event) { - case WM_PAINT: - { - RECT rect; - SharedSurfaceBeforePaint(rect, npremoteevent); - if (!CallPaint(npremoteevent, &handled)) { - handled = false; - } - SharedSurfaceAfterPaint(npevent); - return handled; - } - break; - case WM_KILLFOCUS: { // When the user selects fullscreen mode in Flash video players, @@ -1936,108 +1913,6 @@ PluginInstanceParent::UnsubclassPluginWindow() * painting: mPluginPort (nsIntRect, saved in SetWindow) */ -void -PluginInstanceParent::SharedSurfaceRelease() -{ - mSharedSurfaceDib.Close(); -} - -bool -PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow, - NPRemoteWindow& aRemoteWindow) -{ - aRemoteWindow.window = 0; - aRemoteWindow.x = aWindow->x; - aRemoteWindow.y = aWindow->y; - aRemoteWindow.width = aWindow->width; - aRemoteWindow.height = aWindow->height; - aRemoteWindow.type = aWindow->type; - - nsIntRect newPort(aWindow->x, aWindow->y, aWindow->width, aWindow->height); - - // save the the rect location within the browser window. - mPluginPort = newPort; - - // move the port to our shared surface origin - newPort.MoveTo(0,0); - - // check to see if we have the room in shared surface - if (mSharedSurfaceDib.IsValid() && mSharedSize.Contains(newPort)) { - // ok to paint - aRemoteWindow.surfaceHandle = 0; - return true; - } - - // allocate a new shared surface - SharedSurfaceRelease(); - if (NS_FAILED(mSharedSurfaceDib.Create(reinterpret_cast(aWindow->window), - newPort.width, newPort.height, false))) - return false; - - // save the new shared surface size we just allocated - mSharedSize = newPort; - - base::SharedMemoryHandle handle; - if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(OtherPid(), &handle))) { - return false; - } - - aRemoteWindow.surfaceHandle = handle; - - return true; -} - -void -PluginInstanceParent::SharedSurfaceBeforePaint(RECT& rect, - NPRemoteEvent& npremoteevent) -{ - RECT* dr = (RECT*)npremoteevent.event.lParam; - HDC parentHdc = (HDC)npremoteevent.event.wParam; - - nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top); - dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); // should always be smaller than dirtyRect - - ::BitBlt(mSharedSurfaceDib.GetHDC(), - dirtyRect.x, - dirtyRect.y, - dirtyRect.width, - dirtyRect.height, - parentHdc, - dr->left, - dr->top, - SRCCOPY); - - // setup the translated dirty rect we'll send to the child - rect.left = dirtyRect.x; - rect.top = dirtyRect.y; - rect.right = dirtyRect.x + dirtyRect.width; - rect.bottom = dirtyRect.y + dirtyRect.height; - - npremoteevent.event.wParam = WPARAM(0); - npremoteevent.event.lParam = LPARAM(&rect); -} - -void -PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent* npevent) -{ - RECT* dr = (RECT*)npevent->lParam; - HDC parentHdc = (HDC)npevent->wParam; - - nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top); - dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); - - // src copy the shared dib into the parent surface we are handed. - ::BitBlt(parentHdc, - dr->left, - dr->top, - dirtyRect.width, - dirtyRect.height, - mSharedSurfaceDib.GetHDC(), - dirtyRect.x, - dirtyRect.y, - SRCCOPY); -} - bool PluginInstanceParent::MaybeCreateAndParentChildPluginWindow() { diff --git a/dom/plugins/ipc/PluginInstanceParent.h b/dom/plugins/ipc/PluginInstanceParent.h index d9bcfea50a0..32a0ef5d860 100644 --- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -353,11 +353,6 @@ private: #if defined(OS_WIN) private: - // Used in rendering windowless plugins in other processes. - bool SharedSurfaceSetWindow(const NPWindow* aWindow, NPRemoteWindow& aRemoteWindow); - void SharedSurfaceBeforePaint(RECT &rect, NPRemoteEvent& npremoteevent); - void SharedSurfaceAfterPaint(NPEvent* npevent); - void SharedSurfaceRelease(); // Used in handling parent/child forwarding of events. static LRESULT CALLBACK PluginWindowHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); @@ -368,7 +363,6 @@ private: void MaybeCreateChildPopupSurrogate(); private: - gfx::SharedDIBWin mSharedSurfaceDib; nsIntRect mPluginPort; nsIntRect mSharedSize; HWND mPluginHWND; diff --git a/dom/plugins/ipc/PluginMessageUtils.cpp b/dom/plugins/ipc/PluginMessageUtils.cpp index b09d9c39889..178bd25baa0 100644 --- a/dom/plugins/ipc/PluginMessageUtils.cpp +++ b/dom/plugins/ipc/PluginMessageUtils.cpp @@ -54,9 +54,6 @@ NPRemoteWindow::NPRemoteWindow() : , visualID(0) , colormap(0) #endif /* XP_UNIX */ -#if defined(XP_WIN) - ,surfaceHandle(0) -#endif #if defined(XP_MACOSX) ,contentsScaleFactor(1.0) #endif @@ -156,18 +153,5 @@ void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v) VOID_TO_NPVARIANT(*v); } -#ifdef XP_WIN - -// The private event used for double-pass widgetless plugin rendering. -UINT DoublePassRenderingEvent() -{ - static UINT gEventID = 0; - if (!gEventID) - gEventID = ::RegisterWindowMessage(L"MozDoublePassMsg"); - return gEventID; -} - -#endif - } // namespace plugins } // namespace mozilla diff --git a/dom/plugins/ipc/PluginMessageUtils.h b/dom/plugins/ipc/PluginMessageUtils.h index a3a0a9b3044..82121d1ac2c 100644 --- a/dom/plugins/ipc/PluginMessageUtils.h +++ b/dom/plugins/ipc/PluginMessageUtils.h @@ -93,9 +93,6 @@ struct NPRemoteWindow VisualID visualID; Colormap colormap; #endif /* XP_UNIX */ -#if defined(XP_WIN) - base::SharedMemoryHandle surfaceHandle; -#endif #if defined(XP_MACOSX) double contentsScaleFactor; #endif @@ -254,11 +251,6 @@ struct DeletingObjectEntry : public nsPtrHashKey bool mDeleted; }; -#ifdef XP_WIN -// The private event used for double-pass widgetless plugin rendering. -UINT DoublePassRenderingEvent(); -#endif - } /* namespace plugins */ } /* namespace mozilla */ @@ -345,9 +337,6 @@ struct ParamTraits aMsg->WriteULong(aParam.visualID); aMsg->WriteULong(aParam.colormap); #endif -#if defined(XP_WIN) - WriteParam(aMsg, aParam.surfaceHandle); -#endif #if defined(XP_MACOSX) aMsg->WriteDouble(aParam.contentsScaleFactor); #endif @@ -377,12 +366,6 @@ struct ParamTraits return false; #endif -#if defined(XP_WIN) - base::SharedMemoryHandle surfaceHandle; - if (!ReadParam(aMsg, aIter, &surfaceHandle)) - return false; -#endif - #if defined(XP_MACOSX) double contentsScaleFactor; if (!aMsg->ReadDouble(aIter, &contentsScaleFactor)) @@ -400,9 +383,6 @@ struct ParamTraits aResult->visualID = visualID; aResult->colormap = colormap; #endif -#if defined(XP_WIN) - aResult->surfaceHandle = surfaceHandle; -#endif #if defined(XP_MACOSX) aResult->contentsScaleFactor = contentsScaleFactor; #endif diff --git a/gfx/thebes/gfxWindowsNativeDrawing.cpp b/gfx/thebes/gfxWindowsNativeDrawing.cpp index 08bb04a0dbd..88f00bd7668 100644 --- a/gfx/thebes/gfxWindowsNativeDrawing.cpp +++ b/gfx/thebes/gfxWindowsNativeDrawing.cpp @@ -184,28 +184,6 @@ gfxWindowsNativeDrawing::BeginNativeDrawing() } } -bool -gfxWindowsNativeDrawing::IsDoublePass() -{ - if (mContext->GetDrawTarget()->GetBackendType() != mozilla::gfx::BackendType::CAIRO || - mContext->GetDrawTarget()->IsDualDrawTarget()) { - return true; - } - - RefPtr surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y); - if (!surf || surf->CairoStatus()) - return false; - if (surf->GetType() != gfxSurfaceType::Win32 && - surf->GetType() != gfxSurfaceType::Win32Printing) { - return true; - } - if ((surf->GetContentType() != gfxContentType::COLOR || - (surf->GetContentType() == gfxContentType::COLOR_ALPHA && - !(mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA)))) - return true; - return false; -} - bool gfxWindowsNativeDrawing::ShouldRenderAgain() { diff --git a/gfx/thebes/gfxWindowsNativeDrawing.h b/gfx/thebes/gfxWindowsNativeDrawing.h index ab2544736ed..3490326c29a 100644 --- a/gfx/thebes/gfxWindowsNativeDrawing.h +++ b/gfx/thebes/gfxWindowsNativeDrawing.h @@ -79,9 +79,6 @@ public: /* Returns true if the native drawing should be executed again */ bool ShouldRenderAgain(); - /* Returns true if double pass alpha extraction is taking place. */ - bool IsDoublePass(); - /* Places the result to the context, if necessary */ void PaintToContext(); diff --git a/layout/generic/nsPluginFrame.cpp b/layout/generic/nsPluginFrame.cpp index cf8a4f24262..69f59cc0f58 100644 --- a/layout/generic/nsPluginFrame.cpp +++ b/layout/generic/nsPluginFrame.cpp @@ -1666,110 +1666,6 @@ nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder, mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect); } } -#elif defined(XP_WIN) - RefPtr inst; - GetPluginInstance(getter_AddRefs(inst)); - if (inst) { - gfxRect frameGfxRect = - PresContext()->AppUnitsToGfxUnits(aPluginRect); - gfxRect dirtyGfxRect = - PresContext()->AppUnitsToGfxUnits(aDirtyRect); - gfxContext *ctx = aRenderingContext.ThebesContext(); - gfxMatrix currentMatrix = ctx->CurrentMatrix(); - - if (ctx->UserToDevicePixelSnapped(frameGfxRect, false)) { - dirtyGfxRect = ctx->UserToDevice(dirtyGfxRect); - ctx->SetMatrix(gfxMatrix()); - } - dirtyGfxRect.RoundOut(); - - // Look if it's windowless - NPWindow *window; - mInstanceOwner->GetWindow(window); - - if (window->type == NPWindowTypeDrawable) { - // the offset of the DC - nsPoint origin; - - gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect); - if (nativeDraw.IsDoublePass()) { - // OOP plugin specific: let the shim know before we paint if we are doing a - // double pass render. If this plugin isn't oop, the register window message - // will be ignored. - NPEvent pluginEvent; - pluginEvent.event = plugins::DoublePassRenderingEvent(); - pluginEvent.wParam = 0; - pluginEvent.lParam = 0; - if (pluginEvent.event) - inst->HandleEvent(&pluginEvent, nullptr); - } - do { - HDC hdc = nativeDraw.BeginNativeDrawing(); - if (!hdc) - return; - - RECT dest; - nativeDraw.TransformToNativeRect(frameGfxRect, dest); - RECT dirty; - nativeDraw.TransformToNativeRect(dirtyGfxRect, dirty); - - window->window = hdc; - window->x = dest.left; - window->y = dest.top; - window->clipRect.left = 0; - window->clipRect.top = 0; - // if we're painting, we're visible. - window->clipRect.right = window->width; - window->clipRect.bottom = window->height; - - // Windowless plugins on windows need a special event to update their location, - // see bug 135737. - // - // bug 271442: note, the rectangle we send is now purely the bounds of the plugin - // relative to the window it is contained in, which is useful for the plugin to - // correctly translate mouse coordinates. - // - // this does not mesh with the comments for bug 135737 which imply that the rectangle - // must be clipped in some way to prevent the plugin attempting to paint over areas - // it shouldn't. - // - // since the two uses of the rectangle are mutually exclusive in some cases, and - // since I don't see any incorrect painting (at least with Flash and ViewPoint - - // the originator of bug 135737), it seems that windowless plugins are not relying - // on information here for clipping their drawing, and we can safely use this message - // to tell the plugin exactly where it is in all cases. - - nsIntPoint origin = GetWindowOriginInPixels(true); - nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height)); - - if (!mWindowlessRect.IsEqualEdges(winlessRect)) { - mWindowlessRect = winlessRect; - - WINDOWPOS winpos; - memset(&winpos, 0, sizeof(winpos)); - winpos.x = mWindowlessRect.x; - winpos.y = mWindowlessRect.y; - winpos.cx = mWindowlessRect.width; - winpos.cy = mWindowlessRect.height; - - // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event - NPEvent pluginEvent; - pluginEvent.event = WM_WINDOWPOSCHANGED; - pluginEvent.wParam = 0; - pluginEvent.lParam = (LPARAM)&winpos; - inst->HandleEvent(&pluginEvent, nullptr); - } - - inst->SetWindow(window); - - mInstanceOwner->Paint(dirty, hdc); - nativeDraw.EndNativeDrawing(); - } while (nativeDraw.ShouldRenderAgain()); - nativeDraw.PaintToContext(); - } - - ctx->SetMatrix(currentMatrix); - } #endif } From 73f490902b1e58c06f32a4892582ae93f71dba5c Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 28 Oct 2015 10:50:41 -0700 Subject: [PATCH 02/95] Remove Linux-specific synchronous plugin drawing code. (bug 1218688 part 2, r=jimm) --- layout/generic/nsPluginFrame.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/layout/generic/nsPluginFrame.cpp b/layout/generic/nsPluginFrame.cpp index 69f59cc0f58..23ed1f86f8b 100644 --- a/layout/generic/nsPluginFrame.cpp +++ b/layout/generic/nsPluginFrame.cpp @@ -1652,20 +1652,6 @@ nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder, mInstanceOwner->Paint(tmpRect, nullptr); } } -#elif defined(MOZ_X11) - if (mInstanceOwner) { - NPWindow *window; - mInstanceOwner->GetWindow(window); - if (window->type == NPWindowTypeDrawable) { - gfxRect frameGfxRect = - PresContext()->AppUnitsToGfxUnits(aPluginRect); - gfxRect dirtyGfxRect = - PresContext()->AppUnitsToGfxUnits(aDirtyRect); - gfxContext* ctx = aRenderingContext.ThebesContext(); - - mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect); - } - } #endif } From c2680d5da6bb3d2e15a3b49a93d656b5b3f9fefb Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 28 Oct 2015 10:50:45 -0700 Subject: [PATCH 03/95] Remove Mac-specific synchronous plugin drawing code. (bug 1218688 part 3, r=benwa) --- dom/plugins/base/nsPluginInstanceOwner.cpp | 108 +-------------------- dom/plugins/base/nsPluginInstanceOwner.h | 15 --- layout/generic/nsPluginFrame.cpp | 99 ------------------- 3 files changed, 1 insertion(+), 221 deletions(-) diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 2b423d2fe18..fb30d7fa3ab 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -341,13 +341,10 @@ nsPluginInstanceOwner::nsPluginInstanceOwner() mPluginFrame = nullptr; mWidgetCreationComplete = false; #ifdef XP_MACOSX - memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext)); - mInCGPaintLevel = 0; mSentInitialTopLevelWindowEvent = false; mLastWindowIsActive = false; mLastContentFocused = false; mLastScaleFactor = 1.0; - mColorProfile = nullptr; mShouldBlurOnActivate = false; #endif mContentFocused = false; @@ -1208,91 +1205,6 @@ void nsPluginInstanceOwner::RemoveFromCARefreshTimer() { } } -void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext, - int aWidth, int aHeight) -{ - if (aWidth == 0 || aHeight == 0) - return; - - if (!mCARenderer) { - mCARenderer = new nsCARenderer(); - } - - // aWidth and aHeight are in "display pixels". In non-HiDPI modes - // "display pixels" are device pixels. But in HiDPI modes each - // display pixel corresponds to more than one device pixel. - double scaleFactor = 1.0; - GetContentsScaleFactor(&scaleFactor); - - if (!mIOSurface || - (mIOSurface->GetWidth() != (size_t)aWidth || - mIOSurface->GetHeight() != (size_t)aHeight || - mIOSurface->GetContentsScaleFactor() != scaleFactor)) { - mIOSurface = nullptr; - - // If the renderer is backed by an IOSurface, resize it as required. - mIOSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight, scaleFactor); - if (mIOSurface) { - RefPtr attachSurface = MacIOSurface::LookupSurface( - mIOSurface->GetIOSurfaceID(), - scaleFactor); - if (attachSurface) { - mCARenderer->AttachIOSurface(attachSurface); - } else { - NS_ERROR("IOSurface attachment failed"); - mIOSurface = nullptr; - } - } - } - - if (!mColorProfile) { - mColorProfile = CreateSystemColorSpace(); - } - - if (mCARenderer->isInit() == false) { - void *caLayer = nullptr; - nsresult rv = mInstance->GetValueFromPlugin(NPPVpluginCoreAnimationLayer, &caLayer); - if (NS_FAILED(rv) || !caLayer) { - return; - } - - // We don't run Flash in-process so we can unconditionally disallow - // the offliner renderer. - mCARenderer->SetupRenderer(caLayer, aWidth, aHeight, scaleFactor, - DISALLOW_OFFLINE_RENDERER); - - // Setting up the CALayer requires resetting the painting otherwise we - // get garbage for the first few frames. - FixUpPluginWindow(ePluginPaintDisable); - FixUpPluginWindow(ePluginPaintEnable); - } - - CGImageRef caImage = nullptr; - nsresult rt = mCARenderer->Render(aWidth, aHeight, scaleFactor, &caImage); - if (rt == NS_OK && mIOSurface && mColorProfile) { - nsCARenderer::DrawSurfaceToCGContext(aCGContext, mIOSurface, mColorProfile, - 0, 0, aWidth, aHeight); - } else if (rt == NS_OK && caImage != nullptr) { - // Significant speed up by resetting the scaling - ::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone ); - ::CGContextTranslateCTM(aCGContext, 0, (double) aHeight * scaleFactor); - ::CGContextScaleCTM(aCGContext, scaleFactor, -scaleFactor); - - ::CGContextDrawImage(aCGContext, CGRectMake(0,0,aWidth,aHeight), caImage); - } else { - NS_NOTREACHED("nsCARenderer::Render failure"); - } -} - -void* nsPluginInstanceOwner::GetPluginPortCopy() -{ - if (GetDrawingModel() == NPDrawingModelCoreGraphics || - GetDrawingModel() == NPDrawingModelCoreAnimation || - GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation) - return &mCGPluginPortCopy; - return nullptr; -} - void nsPluginInstanceOwner::SetPluginPort() { void* pluginPort = GetPluginPort(); @@ -1300,18 +1212,6 @@ void nsPluginInstanceOwner::SetPluginPort() return; mPluginWindow->window = pluginPort; } - -void nsPluginInstanceOwner::BeginCGPaint() -{ - ++mInCGPaintLevel; -} - -void nsPluginInstanceOwner::EndCGPaint() -{ - --mInCGPaintLevel; - NS_ASSERTION(mInCGPaintLevel >= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPaint()!"); -} - #endif // static @@ -2544,8 +2444,6 @@ nsPluginInstanceOwner::Destroy() #ifdef XP_MACOSX RemoveFromCARefreshTimer(); - if (mColorProfile) - ::CGColorSpaceRelease(mColorProfile); #endif nsCOMPtr content = do_QueryReferent(mContent); @@ -3136,11 +3034,7 @@ void nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState) return; } - // If we've already set up a CGContext in nsPluginFrame::PaintPlugin(), we - // don't want calls to SetPluginPort() to step on our work. - if (mInCGPaintLevel < 1) { - SetPluginPort(); - } + SetPluginPort(); nsIntSize widgetClip = mPluginFrame->GetWidgetlessClipRect().Size(); diff --git a/dom/plugins/base/nsPluginInstanceOwner.h b/dom/plugins/base/nsPluginInstanceOwner.h index b05cf7fd062..31d2dfb88cf 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -136,19 +136,9 @@ public: // This calls into the plugin (NPP_SetWindow) and can run script. void FixUpPluginWindow(int32_t inPaintState); void HidePluginWindow(); - // Return a pointer to the internal nsPluginPort structure that's used to - // store a copy of plugin port info and to detect when it's been changed. - void* GetPluginPortCopy(); // Set plugin port info in the plugin (in the 'window' member of the // NPWindow structure passed to the plugin by SetWindow()). void SetPluginPort(); - // Flag when we've set up a Thebes (and CoreGraphics) context in - // nsPluginFrame::PaintPlugin(). We need to know this in - // FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has - // been called from nsPluginFrame::PaintPlugin() when we're using the - // CoreGraphics drawing model). - void BeginCGPaint(); - void EndCGPaint(); #else // XP_MACOSX void UpdateWindowPositionAndClipRect(bool aSetWindow); void UpdateWindowVisibility(bool aVisible); @@ -293,11 +283,6 @@ private: RefPtr mPluginHost; #ifdef XP_MACOSX - NP_CGContext mCGPluginPortCopy; - int32_t mInCGPaintLevel; - RefPtr mIOSurface; - RefPtr mCARenderer; - CGColorSpaceRef mColorProfile; static nsCOMPtr *sCATimer; static nsTArray *sCARefreshListeners; bool mSentInitialTopLevelWindowEvent; diff --git a/layout/generic/nsPluginFrame.cpp b/layout/generic/nsPluginFrame.cpp index 23ed1f86f8b..377c25aa756 100644 --- a/layout/generic/nsPluginFrame.cpp +++ b/layout/generic/nsPluginFrame.cpp @@ -1541,10 +1541,6 @@ nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, const nsRect& aPluginRect) { -#if defined(XP_MACOSX) - DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget(); -#endif - #if defined(MOZ_WIDGET_ANDROID) if (mInstanceOwner) { gfxRect frameGfxRect = @@ -1558,101 +1554,6 @@ nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder, return; } #endif - - // Screen painting code -#if defined(XP_MACOSX) - // delegate all painting to the plugin instance. - if (mInstanceOwner) { - if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics || - mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation || - mInstanceOwner->GetDrawingModel() == - NPDrawingModelInvalidatingCoreAnimation) { - int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel(); - // Clip to the content area where the plugin should be drawn. If - // we don't do this, the plugin can draw outside its bounds. - nsIntRect contentPixels = aPluginRect.ToNearestPixels(appUnitsPerDevPixel); - nsIntRect dirtyPixels = aDirtyRect.ToOutsidePixels(appUnitsPerDevPixel); - nsIntRect clipPixels; - clipPixels.IntersectRect(contentPixels, dirtyPixels); - - // Don't invoke the drawing code if the clip is empty. - if (clipPixels.IsEmpty()) - return; - - gfxRect nativeClipRect(clipPixels.x, clipPixels.y, - clipPixels.width, clipPixels.height); - gfxContext* ctx = aRenderingContext.ThebesContext(); - - gfxContextAutoSaveRestore save(ctx); - ctx->NewPath(); - ctx->Rectangle(nativeClipRect); - ctx->Clip(); - gfxPoint offset(contentPixels.x, contentPixels.y); - ctx->SetMatrix( - ctx->CurrentMatrix().Translate(offset)); - - gfxQuartzNativeDrawing nativeDrawing(aDrawTarget, - ToRect(nativeClipRect - offset)); - - CGContextRef cgContext = nativeDrawing.BeginNativeDrawing(); - if (!cgContext) { - NS_WARNING("null CGContextRef during PaintPlugin"); - return; - } - - RefPtr inst; - GetPluginInstance(getter_AddRefs(inst)); - if (!inst) { - NS_WARNING("null plugin instance during PaintPlugin"); - nativeDrawing.EndNativeDrawing(); - return; - } - NPWindow* window; - mInstanceOwner->GetWindow(window); - if (!window) { - NS_WARNING("null plugin window during PaintPlugin"); - nativeDrawing.EndNativeDrawing(); - return; - } - NP_CGContext* cgPluginPortCopy = - static_cast(mInstanceOwner->GetPluginPortCopy()); - if (!cgPluginPortCopy) { - NS_WARNING("null plugin port copy during PaintPlugin"); - nativeDrawing.EndNativeDrawing(); - return; - } - - mInstanceOwner->BeginCGPaint(); - if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation || - mInstanceOwner->GetDrawingModel() == - NPDrawingModelInvalidatingCoreAnimation) { - // CoreAnimation is updated, render the layer and perform a readback. - mInstanceOwner->RenderCoreAnimation(cgContext, window->width, window->height); - } else { - mInstanceOwner->Paint(nativeClipRect - offset, cgContext); - } - mInstanceOwner->EndCGPaint(); - - nativeDrawing.EndNativeDrawing(); - } else { - gfxContext* ctx = aRenderingContext.ThebesContext(); - - // Translate the context: - gfxPoint devPixelPt = - nsLayoutUtils::PointToGfxPoint(aPluginRect.TopLeft(), - PresContext()->AppUnitsPerDevPixel()); - - gfxContextMatrixAutoSaveRestore autoSR(ctx); - ctx->SetMatrix(ctx->CurrentMatrix().Translate(devPixelPt)); - - // FIXME - Bug 385435: Doesn't aDirtyRect need translating too? - - // this rect is used only in the CoreGraphics drawing model - gfxRect tmpRect(0, 0, 0, 0); - mInstanceOwner->Paint(tmpRect, nullptr); - } - } -#endif } nsresult From a27af3298b2e39cb6e8188ba6f4be46b1dfe355c Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 28 Oct 2015 10:50:53 -0700 Subject: [PATCH 04/95] Assert that we do not attempt synchronous painting of windowless Desktop plugins. (bug 1218688 part 4, r=bsmedberg) --- layout/generic/nsPluginFrame.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/layout/generic/nsPluginFrame.cpp b/layout/generic/nsPluginFrame.cpp index 377c25aa756..e32ba310716 100644 --- a/layout/generic/nsPluginFrame.cpp +++ b/layout/generic/nsPluginFrame.cpp @@ -1553,6 +1553,17 @@ nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder, mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect); return; } +#else +# if defined(DEBUG) + // On Desktop, we should have built a layer as we no longer support in-process + // plugins or synchronous painting. We can only get here for windowed plugins + // (which draw themselves), or via some error/unload state. + if (mInstanceOwner) { + NPWindow *window = nullptr; + mInstanceOwner->GetWindow(window); + MOZ_ASSERT(!window || window->type == NPWindowTypeWindow); + } +# endif #endif } From b291337c8d269bd160002e6546190981ee14d7d7 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 28 Oct 2015 14:02:33 -0400 Subject: [PATCH 05/95] Bug 1190469 - Refactor some code to have a general-purpose snap function available in APZC. r=botond --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 18 +++++++++--------- gfx/layers/apz/src/AsyncPanZoomController.h | 7 ++++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index be055132c58..57465e78001 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -663,7 +663,14 @@ public: bool continueX = mApzc.mX.SampleOverscrollAnimation(aDelta); bool continueY = mApzc.mY.SampleOverscrollAnimation(aDelta); if (!continueX && !continueY) { - mApzc.OverscrollAnimationEnding(); + // If we got into overscroll from a fling, that fling did not request a + // fling snap to avoid a resulting scrollTo from cancelling the overscroll + // animation too early. We do still want to request a fling snap, though, + // in case the end of the axis at which we're overscrolled is not a valid + // snap point, so we request one now. If there are no snap points, this will + // do nothing. If there are snap points, we'll get a scrollTo that snaps us + // back to the nearest valid snap point. + mApzc.RequestSnap(); return false; } return true; @@ -3531,14 +3538,7 @@ void AsyncPanZoomController::ShareCompositorFrameMetrics() { } } -void AsyncPanZoomController::OverscrollAnimationEnding() { - // If we got into overscroll from a fling, that fling did not request a - // fling snap to avoid a resulting scrollTo from cancelling the overscroll - // animation too early. We do still want to request a fling snap, though, - // in case the end of the axis at which we're overscrolled is not a valid - // snap point, so we request one now. If there are no snap points, this will - // do nothing. If there are snap points, we'll get a scrollTo that snaps us - // back to the nearest valid snap point. +void AsyncPanZoomController::RequestSnap() { if (RefPtr controller = GetGeckoContentController()) { controller->RequestFlingSnap(mFrameMetrics.GetScrollId(), mFrameMetrics.GetScrollOffset()); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index c36db4e124a..a4d46d450e5 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -647,9 +647,10 @@ protected: // Common processing at the end of a touch block. void OnTouchEndOrCancel(); - // This is called by OverscrollAnimation to notify us when the overscroll - // animation is ending. - void OverscrollAnimationEnding(); + // This is called to request that the main thread snap the scroll position + // to a nearby snap position if appropriate. The current scroll position is + // used as the final destination. + void RequestSnap(); uint64_t mLayersId; RefPtr mCompositorParent; From 6e308571a441e0fa5400bf37dc9964c33cdfc8e1 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 28 Oct 2015 14:02:36 -0400 Subject: [PATCH 06/95] Bug 1190469 - Request scroll snapping in a few places that animations are cancelled so that we don't leave things unsnapped. r=botond --- gfx/layers/apz/src/APZUtils.h | 12 ++++++++++-- gfx/layers/apz/src/AsyncPanZoomController.cpp | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/gfx/layers/apz/src/APZUtils.h b/gfx/layers/apz/src/APZUtils.h index ad8d157371b..a85fddc03ee 100644 --- a/gfx/layers/apz/src/APZUtils.h +++ b/gfx/layers/apz/src/APZUtils.h @@ -21,10 +21,18 @@ enum HitTestResult { }; enum CancelAnimationFlags : uint32_t { - Default = 0, /* Cancel all animations */ - ExcludeOverscroll = 1 /* Don't clear overscroll */ + Default = 0x0, /* Cancel all animations */ + ExcludeOverscroll = 0x1, /* Don't clear overscroll */ + RequestSnap = 0x2 /* Request snapping to snap points */ }; +inline CancelAnimationFlags +operator|(CancelAnimationFlags a, CancelAnimationFlags b) +{ + return static_cast(static_cast(a) + | static_cast(b)); +} + enum class ScrollSource { // scrollTo() or something similar. DOM, diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 57465e78001..38f7ecf1c5e 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -889,7 +889,7 @@ AsyncPanZoomController::Destroy() { APZThreadUtils::AssertOnCompositorThread(); - CancelAnimation(); + CancelAnimation(CancelAnimationFlags::RequestSnap); { // scope the lock MonitorAutoLock lock(mRefPtrMonitor); @@ -1318,6 +1318,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) // previous overscroll pan. Make sure to snap back in this situation. if (!SnapBackIfOverscrolled()) { SetState(NOTHING); + RequestSnap(); } return nsEventStatus_eIgnore; @@ -1511,6 +1512,10 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent } else { ClearOverscroll(); } + // Along with clearing the overscroll, we also want to snap to the nearest + // snap point as appropriate, so ask the main thread (which knows about such + // things) to handle it. + RequestSnap(); ScheduleComposite(); RequestContentRepaint(); @@ -2497,6 +2502,11 @@ void AsyncPanZoomController::CancelAnimation(CancelAnimationFlags aFlags) { ClearOverscroll(); repaint = true; } + // Similar to relieving overscroll, we also need to snap to any snap points + // if appropriate, so ask the main thread to do that. + if (aFlags & CancelAnimationFlags::RequestSnap) { + RequestSnap(); + } if (repaint) { RequestContentRepaint(); ScheduleComposite(); @@ -3352,7 +3362,7 @@ AsyncPanZoomController::CancelAnimationAndGestureState() { mX.CancelGesture(); mY.CancelGesture(); - CancelAnimation(); + CancelAnimation(CancelAnimationFlags::RequestSnap); } bool From 6fa555f4323d6b028196f0862c38518fdbd99161 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 28 Oct 2015 11:16:06 -0700 Subject: [PATCH 07/95] Bug 1219371 - Add suppression for Aurora-only Windows leak. r=erahm --- testing/mozbase/mozleak/mozleak/leaklog.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testing/mozbase/mozleak/mozleak/leaklog.py b/testing/mozbase/mozleak/mozleak/leaklog.py index a68a6820747..c766960f3d0 100644 --- a/testing/mozbase/mozleak/mozleak/leaklog.py +++ b/testing/mozbase/mozleak/mozleak/leaklog.py @@ -61,6 +61,11 @@ def expectedTabProcessLeakCounts(): 'nsTArray_base': 2, }) + # Bug 1219369 - On Aurora, we leak a SyncObject in Windows. + appendExpectedLeakCounts({ + 'SyncObject': 1 + }) + return leaks From 3c6f5a02eb6ffa404779bf31b6529b4c2f041307 Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Wed, 28 Oct 2015 19:25:26 +0100 Subject: [PATCH 08/95] Bug 1217887 - Fix reference to href in ContentClick.jsm. r=mak --- browser/modules/ContentClick.jsm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/modules/ContentClick.jsm b/browser/modules/ContentClick.jsm index 0b869c1e6ac..8b024eb8f04 100644 --- a/browser/modules/ContentClick.jsm +++ b/browser/modules/ContentClick.jsm @@ -80,7 +80,7 @@ var ContentClick = { // visits across frames should be preserved. try { if (!PrivateBrowsingUtils.isWindowPrivate(window)) - PlacesUIUtils.markPageAsFollowedLink(href); + PlacesUIUtils.markPageAsFollowedLink(json.href); } catch (ex) { /* Skip invalid URIs. */ } } }; From 932edeaaa48d67a698a5a065618547050bc2a97b Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 27 Oct 2015 20:13:45 -0400 Subject: [PATCH 09/95] Bug 1219085 - Import the fetch-request-redirect.https.html test from Blink; r=jdm --- .../web-platform/mozilla/meta/MANIFEST.json | 6 + .../fetch-request-redirect.https.html | 175 ++++++++++++++++++ .../service-worker/resources/dummy.html | 2 + .../fetch-request-redirect-iframe.html | 35 ++++ .../service-worker/resources/silence.oga | Bin 0 -> 12983 bytes .../service-worker/resources/square.png | Bin 0 -> 18299 bytes 6 files changed, 218 insertions(+) create mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-request-redirect.https.html create mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.html create mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html create mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/silence.oga create mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/square.png diff --git a/testing/web-platform/mozilla/meta/MANIFEST.json b/testing/web-platform/mozilla/meta/MANIFEST.json index 66b89e3add3..8560b3788cf 100644 --- a/testing/web-platform/mozilla/meta/MANIFEST.json +++ b/testing/web-platform/mozilla/meta/MANIFEST.json @@ -211,6 +211,12 @@ "url": "/_mozilla/service-workers/service-worker/fetch-request-no-freshness-headers.https.html" } ], + "service-workers/service-worker/fetch-request-redirect.https.html": [ + { + "path": "service-workers/service-worker/fetch-request-redirect.https.html", + "url": "/_mozilla/service-workers/service-worker/fetch-request-redirect.https.html" + } + ], "service-workers/service-worker/fetch-request-resources.https.html": [ { "path": "service-workers/service-worker/fetch-request-resources.https.html", diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-request-redirect.https.html b/testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-request-redirect.https.html new file mode 100644 index 00000000000..bda8f4f4a45 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-request-redirect.https.html @@ -0,0 +1,175 @@ + +Service Worker: FetchEvent for resources + + + + + diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.html b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.html new file mode 100644 index 00000000000..12a179980df --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.html @@ -0,0 +1,2 @@ + +Hello world diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html new file mode 100644 index 00000000000..ffd76bfc499 --- /dev/null +++ b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html @@ -0,0 +1,35 @@ + diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/silence.oga b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/silence.oga new file mode 100644 index 0000000000000000000000000000000000000000..af591880436af43abb4cee59fde320081bcac7ed GIT binary patch literal 12983 zcmaiabzD?!*Y1Fl0wR(MNOw01(%nOMHzP3vNaF({-8sO}AVWzDNJw``w{(L@mz<5y z`+e^@f1Ufc_nte}UbEu5*IsMSsM*?Tf>1&KY2$DI?WE+oG^0?WcsRRR*h3$tP^3%$ zT`}AJ_wy@?+QXgy+aB&j0Y>fzZtrlF?*H5R9{tOO0$9|ucd_G8bF-y#vbWIr%bQAp ziie9!h?|>7@Zs(kz$v3Dr6w%{7PYZ~xLDir!0fD@-OSm!IC%I_(EerhN>WM(phf|a zT52)Nrh$JbhLJ%NxnYDM-2`sMFsJIK##MTqF0%sX@%o06^Q?m0It9Xf!bUM z72*i{D(RGduqlm8YiRpT3TSJeyBkkG98`Q(L=RlW<%`k^UQo5;Sdn7l>Z5_E0OQFr zwc|hfAM=1Ln1n+aYBqhL(LpxCb}U_+Fc+H1O@((Xo0}QXVPVE}Xt&T-1~lBwhT9IH z%YYID*)adxLv(IRI3geBx`m5^TxCfCI(W^dgoD5oFh^WdDD1$|1@ve(HWeTolR$4+ z7$Et3L6Q_fT~r@9=bmpGyptpWdT+^!e4vsKbN{9L*F1o}5~Knlu0>SxS$Q8wWkT(H z^D!3lI_T_h+^~z~^77)qyHtr<-3rW^|7wm20#OGOg5{|{{^t@(9YSi+%UqQ44>n72 zer`BVKU?)6&%ncF?@RUY>wT_Hd?}o=8UiJi+DSdjvWBe;N4y^f_GPtGip&Lomzn?C zFA#7KCYe>NgzN+7Q0l@Aw|?f&*{FZb2`oPB5|KWrv>fceM-Nm)E>T(mIBJv!CY05P zv?r5{4X3OZ&mra{9*Y<5%NOoz(;v(?6V z*Fk2dAg0NXu{&|tD-yzv@IW=7;J)nsxJWnWkO+KDZ zAvs?Gv7w)9<4|bpjr@%Imqh%5WGtqpPu9m<)~tM(ep|9=O^ zUx3GgK%;TweR1Rfz!iWF%3tdOdjS>Xg3}WVfF3~ne{@tk1q^CDhW39u00iQq>j1OK zLHQICwUlbLRBE-9h_uzT|9_2NWt>k1Ff2W=>p*Q5QQtSHsOjl9mhjv06A;`C)U_tm zkK^K(xY3D%5Ing!ZcCDD_(7C_(Vl^%0nNLqdhnsW!g9q41j1XNVTmuc$P1#uw#;3r z7DG%)GvLxFXf#-^EHBZ5jol*=997&6paqp2IN5>$@gIXUK%ii5dFFgVi%8+345>)w ztyE|T_a-?sT6ilP24>mHfT=2Wk^;k`3@G?DV-i$Vkue9r2M7Z=pX7|j5}}A^fC44r zMbv)tX(aNg5z1)7j5YX-r+VBFzv-;$oz$|A+d*sHe^xDcwSI@`rLT-+)sbX-SW4H_L=gyyXZK~deR+Y z=x%I$p{$v#GM!{S?hctxvNra#p1t57hZ&D+ThGFbXFaTS>y7o#{l?utE+<)=>RRiQ zdKh1PG@MS_fEh39TI&kx0IP=6A6KT_&C^8Gv;oe>BYeiX?#8CN#?w>$N2Wd=H%G1&no*A2{nKyD!23Vr%_NZQXNs{pqBYDaeYT@$`kZ{`p5>^?`GP zyD{lo?K3}3kB=)b>*eW>%lhw(g_6hI{mhdfD|*)Y!u~6I$%_|B)&MI#$SkRjK5>ZY zW#-1Y-`ab3W3qRPTZ4^9I6X)CH~r(25X&^bMSUAn&*&A>*R8+SijfuR<*YbGY)@Jb z_PVQYTB;(;_im8DkY&ETa_J>oGrZ&*`K_Xh6Fh8h9MmPa(0+Q+QT0>v!@rb z43tA|TK4*@-XW1r0O!32A)N+Vj{1>@e-->IMiu*f)zLsz>CImSAH+a%3{*j0Ry*A^ z+QI)L70Y}T`%NPt)lq-Ba|yC^?_qd&UGB2i$n~wt=>}PP-N-uM=)A`>f9@v@Kv0t( zG7sz%0D|Y%z|PpA_U!H#Gk5TOtdw`Q`L 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 literal 0 HcmV?d00001 diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/square.png b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/square.png new file mode 100644 index 0000000000000000000000000000000000000000..01c9666a8de9d5535615aff830810e5df4b2156f GIT binary patch literal 18299 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 bDgs((CoOJ&@$4~l+kmsZyIqm(x-I_(KvUo& literal 0 HcmV?d00001 From c6966a8aa68fa8138111db97166d8651cf6002f9 Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Wed, 28 Oct 2015 18:51:59 +0000 Subject: [PATCH 10/95] Bug 1186973 - Evaluate assertEqBytecode: Print length as numbers. r=h4writer --- js/src/jit-test/tests/xdr/bug1186973.js | 15 +++++++++++++++ js/src/shell/js.cpp | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 js/src/jit-test/tests/xdr/bug1186973.js diff --git a/js/src/jit-test/tests/xdr/bug1186973.js b/js/src/jit-test/tests/xdr/bug1186973.js new file mode 100644 index 00000000000..780ef55dc6a --- /dev/null +++ b/js/src/jit-test/tests/xdr/bug1186973.js @@ -0,0 +1,15 @@ +// |jit-test| error: cache does not have the same size +load(libdir + 'bytecode-cache.js'); + +var test = (function () { + function f(x) { + function ifTrue() {}; + function ifFalse() {}; + + if (generation % 2 == 0) + return ifTrue(); + return ifFalse(); + } + return f.toSource() + "; f()"; +})(); +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index a236ac67a95..126dace94dd 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1316,8 +1316,13 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp) // replace the current bytecode by the same stream of bytes. if (loadBytecode && assertEqBytecode) { if (saveLength != loadLength) { + char loadLengthStr[16]; + JS_snprintf(loadLengthStr, sizeof(loadLengthStr), "%u", loadLength); + char saveLengthStr[16]; + JS_snprintf(saveLengthStr, sizeof(saveLengthStr), "%u", saveLength); + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_CACHE_EQ_SIZE_FAILED, - loadLength, saveLength); + loadLengthStr, saveLengthStr); return false; } From e2745b6fcb36eb90d7b8f40a57189830a8ec6166 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 23 Oct 2015 15:37:19 -0400 Subject: [PATCH 11/95] bug 1218564 - remove check for password roles in AccessibleWrap::get_accValue r=surkov The text computed for a password entry's accessible should not include the actual password text, so this check is not necessary. --- accessible/windows/msaa/AccessibleWrap.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/accessible/windows/msaa/AccessibleWrap.cpp b/accessible/windows/msaa/AccessibleWrap.cpp index e3144266530..881e4e376b3 100644 --- a/accessible/windows/msaa/AccessibleWrap.cpp +++ b/accessible/windows/msaa/AccessibleWrap.cpp @@ -350,9 +350,6 @@ AccessibleWrap::get_accValue( if (IsProxy()) return E_NOTIMPL; - if (xpAccessible->NativeRole() == roles::PASSWORD_TEXT) - return E_ACCESSDENIED; - nsAutoString value; xpAccessible->Value(value); From babbefcab9ca9e7e53c9ec71f32c5c1552ae6b15 Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Fri, 12 Jun 2015 08:48:42 -0400 Subject: [PATCH 12/95] bug 1170987 - Fix gfx/2d to build on iOS. r=jrmuizel --- gfx/2d/2D.h | 2 +- gfx/2d/BorrowedContext.h | 2 +- gfx/2d/DrawTargetCG.cpp | 21 +++++++++++++++++++++ gfx/2d/DrawTargetCG.h | 7 +++++++ gfx/2d/DrawTargetCairo.cpp | 2 ++ gfx/2d/Factory.cpp | 12 ++++++------ gfx/2d/MacIOSurface.h | 27 +++++++++++++++++++-------- gfx/2d/PathCG.h | 5 +++++ gfx/2d/ScaledFontMac.cpp | 18 ++++++++++++++++-- gfx/2d/ScaledFontMac.h | 8 +++++++- gfx/2d/SourceSurfaceCG.cpp | 4 ++++ gfx/2d/SourceSurfaceCG.h | 8 ++++++++ gfx/2d/moz.build | 6 ++++-- 13 files changed, 101 insertions(+), 21 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index f2433b12d8b..6ede3d18ed4 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -1249,7 +1249,7 @@ public: static bool DoesBackendSupportDataDrawtarget(BackendType aType); -#ifdef XP_MACOSX +#ifdef XP_DARWIN static already_AddRefed CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize); static already_AddRefed CreateCGGlyphRenderingOptions(const Color &aFontSmoothingBackgroundColor); diff --git a/gfx/2d/BorrowedContext.h b/gfx/2d/BorrowedContext.h index 477ec9d12da..0b5612ad8ef 100644 --- a/gfx/2d/BorrowedContext.h +++ b/gfx/2d/BorrowedContext.h @@ -137,7 +137,7 @@ private: }; #endif -#ifdef XP_MACOSX +#ifdef XP_DARWIN /* This is a helper class that let's you borrow a CGContextRef from a * DrawTargetCG. This is used for drawing themed widgets. * diff --git a/gfx/2d/DrawTargetCG.cpp b/gfx/2d/DrawTargetCG.cpp index d315400107a..a45d63f5f49 100644 --- a/gfx/2d/DrawTargetCG.cpp +++ b/gfx/2d/DrawTargetCG.cpp @@ -3,6 +3,7 @@ * 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 #include "BorrowedContext.h" #include "DataSurfaceHelpers.h" #include "DrawTargetCG.h" @@ -177,6 +178,7 @@ DrawTargetCG::GetType() const BackendType DrawTargetCG::GetBackendType() const { +#ifdef MOZ_WIDGET_COCOA // It may be worth spliting Bitmap and IOSurface DrawTarget // into seperate classes. if (GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) { @@ -184,15 +186,20 @@ DrawTargetCG::GetBackendType() const } else { return BackendType::COREGRAPHICS; } +#else + return BackendType::COREGRAPHICS; +#endif } already_AddRefed DrawTargetCG::Snapshot() { if (!mSnapshot) { +#ifdef MOZ_WIDGET_COCOA if (GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) { return MakeAndAddRef(this); } +#endif Flush(); mSnapshot = new SourceSurfaceCGBitmapContext(this); } @@ -1717,12 +1724,14 @@ DrawTargetCG::Init(BackendType aType, mSize = aSize; +#ifdef MOZ_WIDGET_COCOA if (aType == BackendType::COREGRAPHICS_ACCELERATED) { RefPtr ioSurface = MacIOSurface::CreateIOSurface(aSize.width, aSize.height); mCg = ioSurface->CreateIOSurfaceContext(); // If we don't have the symbol for 'CreateIOSurfaceContext' mCg will be null // and we will fallback to software below } +#endif mFormat = SurfaceFormat::B8G8R8A8; @@ -1820,6 +1829,7 @@ EnsureValidPremultipliedData(CGContextRef aContext) void DrawTargetCG::Flush() { +#ifdef MOZ_WIDGET_COCOA if (GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE) { CGContextFlush(mCg); } else if (GetContextType(mCg) == CG_CONTEXT_TYPE_BITMAP && @@ -1835,6 +1845,9 @@ DrawTargetCG::Flush() EnsureValidPremultipliedData(mCg); mMayContainInvalidPremultipliedData = false; } +#else + //TODO +#endif } bool @@ -1874,7 +1887,9 @@ DrawTargetCG::Init(CGContextRef cgContext, const IntSize &aSize) mOriginalTransform = CGContextGetCTM(mCg); mFormat = SurfaceFormat::B8G8R8A8; +#ifdef MOZ_WIDGET_COCOA if (GetContextType(mCg) == CG_CONTEXT_TYPE_BITMAP) { +#endif CGColorSpaceRef colorspace; CGBitmapInfo bitinfo = CGBitmapContextGetBitmapInfo(mCg); colorspace = CGBitmapContextGetColorSpace (mCg); @@ -1883,7 +1898,9 @@ DrawTargetCG::Init(CGContextRef cgContext, const IntSize &aSize) } else if ((bitinfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaNoneSkipFirst) { mFormat = SurfaceFormat::B8G8R8X8; } +#ifdef MOZ_WIDGET_COCOA } +#endif return true; } @@ -1906,12 +1923,16 @@ DrawTargetCG::CreatePathBuilder(FillRule aFillRule) const void* DrawTargetCG::GetNativeSurface(NativeSurfaceType aType) { +#ifdef MOZ_WIDGET_COCOA if ((aType == NativeSurfaceType::CGCONTEXT && GetContextType(mCg) == CG_CONTEXT_TYPE_BITMAP) || (aType == NativeSurfaceType::CGCONTEXT_ACCELERATED && GetContextType(mCg) == CG_CONTEXT_TYPE_IOSURFACE)) { return mCg; } else { return nullptr; } +#else + return mCg; +#endif } void diff --git a/gfx/2d/DrawTargetCG.h b/gfx/2d/DrawTargetCG.h index 30e901bd6b6..50c13818003 100644 --- a/gfx/2d/DrawTargetCG.h +++ b/gfx/2d/DrawTargetCG.h @@ -6,7 +6,14 @@ #ifndef mozilla_gfx_DrawTargetCG_h #define mozilla_gfx_DrawTargetCG_h +#ifdef MOZ_WIDGET_COCOA #include +#import +#else +#include +#include +#include +#endif #include "2D.h" #include "Rect.h" diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index f8eeacfdd17..a5234326b98 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -24,8 +24,10 @@ #ifdef CAIRO_HAS_QUARTZ_SURFACE #include "cairo-quartz.h" +#ifdef MOZ_WIDGET_COCOA #include #endif +#endif #ifdef CAIRO_HAS_XLIB_SURFACE #include "cairo-xlib.h" diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index adfb66969c5..5446b58f9fb 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -23,12 +23,12 @@ #include "ScaledFontWin.h" #endif -#ifdef XP_MACOSX +#ifdef XP_DARWIN #include "ScaledFontMac.h" #endif -#ifdef XP_MACOSX +#ifdef XP_DARWIN #include "DrawTargetCG.h" #endif @@ -299,7 +299,7 @@ Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFor } break; } -#elif defined XP_MACOSX +#elif defined XP_DARWIN case BackendType::COREGRAPHICS: case BackendType::COREGRAPHICS_ACCELERATED: { @@ -382,7 +382,7 @@ Factory::CreateDrawTargetForData(BackendType aBackend, break; } #endif -#ifdef XP_MACOSX +#ifdef XP_DARWIN case BackendType::COREGRAPHICS: { RefPtr newTarget = new DrawTargetCG(); @@ -489,7 +489,7 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz } #endif #endif -#ifdef XP_MACOSX +#ifdef XP_DARWIN case NativeFontType::MAC_FONT_FACE: { return MakeAndAddRef(static_cast(aNativeFont.mFont), aSize); @@ -791,7 +791,7 @@ Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSiz return retVal.forget(); } -#ifdef XP_MACOSX +#ifdef XP_DARWIN already_AddRefed Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize) { diff --git a/gfx/2d/MacIOSurface.h b/gfx/2d/MacIOSurface.h index dc2d773e508..737affceabc 100644 --- a/gfx/2d/MacIOSurface.h +++ b/gfx/2d/MacIOSurface.h @@ -6,10 +6,23 @@ #ifndef MacIOSurface_h__ #define MacIOSurface_h__ -#ifdef XP_MACOSX +#ifdef XP_DARWIN #include +#include #include +struct _CGLContextObject; + +typedef _CGLContextObject* CGLContextObj; +typedef struct CGContext* CGContextRef; +typedef struct CGImage* CGImageRef; +typedef uint32_t IOSurfaceID; + +#ifdef XP_IOS +typedef kern_return_t IOReturn; +typedef int CGLError; +#endif + typedef CFTypeRef IOSurfacePtr; typedef IOSurfacePtr (*IOSurfaceCreateFunc) (CFDictionaryRef properties); typedef IOSurfacePtr (*IOSurfaceLookupFunc) (uint32_t io_surface_id); @@ -42,18 +55,16 @@ typedef IOSurfacePtr (*CVPixelBufferGetIOSurfaceFunc)( typedef OSType (*IOSurfacePixelFormatFunc)(IOSurfacePtr io_surface); +#ifdef XP_MACOSX #import +#else +#import +#endif + #include "2D.h" #include "mozilla/RefPtr.h" #include "mozilla/RefCounted.h" -struct _CGLContextObject; - -typedef _CGLContextObject* CGLContextObj; -typedef struct CGContext* CGContextRef; -typedef struct CGImage* CGImageRef; -typedef uint32_t IOSurfaceID; - enum CGContextType { CG_CONTEXT_TYPE_UNKNOWN = 0, // These are found by inspection, it's possible they could be changed diff --git a/gfx/2d/PathCG.h b/gfx/2d/PathCG.h index e627ab706a0..0c8e571e2e0 100644 --- a/gfx/2d/PathCG.h +++ b/gfx/2d/PathCG.h @@ -6,7 +6,12 @@ #ifndef MOZILLA_GFX_PATHCG_H_ #define MOZILLA_GFX_PATHCG_H_ +#ifdef MOZ_WIDGET_COCOA #include +#else +#include +#endif + #include "2D.h" namespace mozilla { diff --git a/gfx/2d/ScaledFontMac.cpp b/gfx/2d/ScaledFontMac.cpp index 7c68b90d993..75180b913fb 100644 --- a/gfx/2d/ScaledFontMac.cpp +++ b/gfx/2d/ScaledFontMac.cpp @@ -13,11 +13,16 @@ #include "DrawTargetCG.h" #include #include +#ifdef MOZ_WIDGET_UIKIT +#include +#endif +#ifdef MOZ_WIDGET_COCOA // prototype for private API extern "C" { CGPathRef CGFontGetGlyphPath(CGFontRef fontRef, CGAffineTransform *textTransform, int unknown, CGGlyph glyph); }; +#endif namespace mozilla { @@ -81,11 +86,12 @@ ScaledFontMac::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aT { if (aTarget->GetBackendType() == BackendType::COREGRAPHICS || aTarget->GetBackendType() == BackendType::COREGRAPHICS_ACCELERATED) { +#ifdef MOZ_WIDGET_COCOA CGMutablePathRef path = CGPathCreateMutable(); - for (unsigned int i = 0; i < aBuffer.mNumGlyphs; i++) { // XXX: we could probably fold both of these transforms together to avoid extra work CGAffineTransform flip = CGAffineTransformMakeScale(1, -1); + CGPathRef glyphPath = ::CGFontGetGlyphPath(mFont, &flip, 0, aBuffer.mGlyphs[i].mIndex); CGAffineTransform matrix = CGAffineTransformMake(mSize, 0, 0, mSize, @@ -97,6 +103,10 @@ ScaledFontMac::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aT RefPtr ret = new PathCG(path, FillRule::FILL_WINDING); CGPathRelease(path); return ret.forget(); +#else + //TODO: probably want CTFontCreatePathForGlyph + MOZ_CRASH("This needs implemented"); +#endif } return ScaledFontBase::GetPathForGlyphs(aBuffer, aTarget); } @@ -108,7 +118,7 @@ ScaledFontMac::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBui ScaledFontBase::CopyGlyphsToBuilder(aBuffer, aBuilder, aBackendType, aTransformHint); return; } - +#ifdef MOZ_WIDGET_COCOA PathBuilderCG *pathBuilderCG = static_cast(aBuilder); // XXX: check builder type @@ -123,6 +133,10 @@ ScaledFontMac::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBui CGPathAddPath(pathBuilderCG->mCGPath, &matrix, glyphPath); CGPathRelease(glyphPath); } +#else + //TODO: probably want CTFontCreatePathForGlyph + MOZ_CRASH("This needs implemented"); +#endif } uint32_t diff --git a/gfx/2d/ScaledFontMac.h b/gfx/2d/ScaledFontMac.h index 7862a0a497f..982b5f7c527 100644 --- a/gfx/2d/ScaledFontMac.h +++ b/gfx/2d/ScaledFontMac.h @@ -6,7 +6,13 @@ #ifndef MOZILLA_GFX_SCALEDFONTMAC_H_ #define MOZILLA_GFX_SCALEDFONTMAC_H_ -#import +#ifdef MOZ_WIDGET_COCOA +#include +#else +#include +#include +#endif + #include "2D.h" #include "ScaledFontBase.h" diff --git a/gfx/2d/SourceSurfaceCG.cpp b/gfx/2d/SourceSurfaceCG.cpp index b2627b44036..fdfde62d8cd 100644 --- a/gfx/2d/SourceSurfaceCG.cpp +++ b/gfx/2d/SourceSurfaceCG.cpp @@ -9,7 +9,9 @@ #include "DataSurfaceHelpers.h" #include "mozilla/Types.h" // for decltype +#ifdef MOZ_WIDGET_COCOA #include "MacIOSurface.h" +#endif #include "Tools.h" namespace mozilla { @@ -384,6 +386,7 @@ SourceSurfaceCGBitmapContext::~SourceSurfaceCGBitmapContext() CGImageRelease(mImage); } +#ifdef MOZ_WIDGET_COCOA SourceSurfaceCGIOSurfaceContext::SourceSurfaceCGIOSurfaceContext(DrawTargetCG *aDrawTarget) { CGContextRef cg = (CGContextRef)aDrawTarget->GetNativeSurface(NativeSurfaceType::CGCONTEXT_ACCELERATED); @@ -452,6 +455,7 @@ SourceSurfaceCGIOSurfaceContext::GetData() { return (unsigned char*)mData; } +#endif } // namespace gfx } // namespace mozilla diff --git a/gfx/2d/SourceSurfaceCG.h b/gfx/2d/SourceSurfaceCG.h index 5d8655d503a..e365c93e0ae 100644 --- a/gfx/2d/SourceSurfaceCG.h +++ b/gfx/2d/SourceSurfaceCG.h @@ -6,11 +6,17 @@ #ifndef _MOZILLA_GFX_SOURCESURFACECG_H #define _MOZILLA_GFX_SOURCESURFACECG_H +#ifdef MOZ_WIDGET_COCOA #include +#else +#include +#endif #include "2D.h" +#ifdef MOZ_WIDGET_COCOA class MacIOSurface; +#endif namespace mozilla { namespace gfx { @@ -163,6 +169,7 @@ private: IntSize mSize; }; +#ifdef MOZ_WIDGET_COCOA class SourceSurfaceCGIOSurfaceContext : public SourceSurfaceCGContext { public: @@ -196,6 +203,7 @@ private: IntSize mSize; }; +#endif } // namespace gfx diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index 58165d3b3d2..e82182604e9 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -48,10 +48,9 @@ EXPORTS.mozilla.gfx += [ 'UserData.h', ] -if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'): EXPORTS.mozilla.gfx += [ 'MacIOSurface.h', - 'QuartzSupport.h', ] UNIFIED_SOURCES += [ 'DrawTargetCG.cpp', @@ -160,6 +159,9 @@ SOURCES += [ ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + EXPORTS.mozilla.gfx += [ + 'QuartzSupport.h', + ] SOURCES += [ 'MacIOSurface.cpp', 'QuartzSupport.mm', From 55c2c6433201cc8bb1ee629c52785b2a7cfdd3c9 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 28 Sep 2015 17:09:56 -0500 Subject: [PATCH 13/95] Bug 1174703 - Add GLContextEAGL and GLContextProviderEAGL as an OpenGL provider for iOS. r=jgilbert --- gfx/gl/GLContextEAGL.h | 79 ++++++++++ gfx/gl/GLContextProvider.h | 9 ++ gfx/gl/GLContextProviderEAGL.mm | 271 ++++++++++++++++++++++++++++++++ gfx/gl/GLContextTypes.h | 3 +- gfx/gl/moz.build | 11 ++ 5 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 gfx/gl/GLContextEAGL.h create mode 100644 gfx/gl/GLContextProviderEAGL.mm diff --git a/gfx/gl/GLContextEAGL.h b/gfx/gl/GLContextEAGL.h new file mode 100644 index 00000000000..83f3687b42a --- /dev/null +++ b/gfx/gl/GLContextEAGL.h @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 GLCONTEXTEAGL_H_ +#define GLCONTEXTEAGL_H_ + +#include "GLContext.h" + +#include +#include + +namespace mozilla { +namespace gl { + +class GLContextEAGL : public GLContext +{ + friend class GLContextProviderEAGL; + + EAGLContext* const mContext; + +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEAGL, override) + GLContextEAGL(const SurfaceCaps& caps, EAGLContext* context, + GLContext* sharedContext, + bool isOffscreen, ContextProfile profile); + + ~GLContextEAGL(); + + virtual GLContextType GetContextType() const override { + return GLContextType::EAGL; + } + + static GLContextEAGL* Cast(GLContext* gl) { + MOZ_ASSERT(gl->GetContextType() == GLContextType::EAGL); + return static_cast(gl); + } + + bool Init() override; + + bool AttachToWindow(nsIWidget* aWidget); + + EAGLContext* GetEAGLContext() const { return mContext; } + + virtual bool MakeCurrentImpl(bool aForce) override; + + virtual bool IsCurrent() override; + + virtual bool SetupLookupFunction() override; + + virtual bool IsDoubleBuffered() const override; + + virtual bool SupportsRobustness() const override; + + virtual bool SwapBuffers() override; + + virtual GLuint GetDefaultFramebuffer() override { + return mBackbufferFB; + } + + virtual bool RenewSurface() override { + return RecreateRB(); + } + +private: + GLuint mBackbufferRB; + GLuint mBackbufferFB; + + void* mLayer; + + bool RecreateRB(); +}; + +} // namespace gl +} // namespace mozilla + +#endif // GLCONTEXTEAGL_H_ diff --git a/gfx/gl/GLContextProvider.h b/gfx/gl/GLContextProvider.h index 8b4175a9621..ac83e3e6fca 100644 --- a/gfx/gl/GLContextProvider.h +++ b/gfx/gl/GLContextProvider.h @@ -53,6 +53,15 @@ namespace gl { #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL #endif +#if defined(MOZ_WIDGET_UIKIT) +#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEAGL +#include "GLContextProviderImpl.h" +#undef GL_CONTEXT_PROVIDER_NAME +#ifndef GL_CONTEXT_PROVIDER_DEFAULT +#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEAGL +#endif +#endif + #ifdef MOZ_GL_PROVIDER #define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER #include "GLContextProviderImpl.h" diff --git a/gfx/gl/GLContextProviderEAGL.mm b/gfx/gl/GLContextProviderEAGL.mm new file mode 100644 index 00000000000..3b80f062e87 --- /dev/null +++ b/gfx/gl/GLContextProviderEAGL.mm @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * 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 "GLContextProvider.h" +#include "GLContextEAGL.h" +#include "nsDebug.h" +#include "nsIWidget.h" +#include "gfxPrefs.h" +#include "gfxFailure.h" +#include "prenv.h" +#include "mozilla/Preferences.h" +#include "GeckoProfiler.h" + +#import + +namespace mozilla { +namespace gl { + +GLContextEAGL::GLContextEAGL(const SurfaceCaps& caps, EAGLContext* context, + GLContext* sharedContext, + bool isOffscreen, ContextProfile profile) + : GLContext(caps, sharedContext, isOffscreen) + , mContext(context) + , mBackbufferRB(0) + , mBackbufferFB(0) + , mLayer(nil) +{ + SetProfileVersion(ContextProfile::OpenGLES, + [context API] == kEAGLRenderingAPIOpenGLES3 ? 300 : 200); +} + +GLContextEAGL::~GLContextEAGL() +{ + MakeCurrent(); + + if (mBackbufferFB) { + fDeleteFramebuffers(1, &mBackbufferFB); + } + + if (mBackbufferRB) { + fDeleteRenderbuffers(1, &mBackbufferRB); + } + + MarkDestroyed(); + + if (mLayer) { + mLayer = nil; + } + + if (mContext) { + [EAGLContext setCurrentContext:nil]; + [mContext release]; + } +} + +bool +GLContextEAGL::Init() +{ + if (!InitWithPrefix("gl", true)) + return false; + + return true; +} + +bool +GLContextEAGL::AttachToWindow(nsIWidget* aWidget) +{ + // This should only be called once + MOZ_ASSERT(!mBackbufferFB && !mBackbufferRB); + + UIView* view = + reinterpret_cast(aWidget->GetNativeData(NS_NATIVE_WIDGET)); + + if (!view) { + MOZ_CRASH("no view!"); + } + + mLayer = [view layer]; + + fGenFramebuffers(1, &mBackbufferFB); + return RecreateRB(); +} + +bool +GLContextEAGL::RecreateRB() +{ + MakeCurrent(); + + CAEAGLLayer* layer = (CAEAGLLayer*)mLayer; + + if (mBackbufferRB) { + // It doesn't seem to be enough to just call renderbufferStorage: below, + // we apparently have to recreate the RB. + fDeleteRenderbuffers(1, &mBackbufferRB); + mBackbufferRB = 0; + } + + fGenRenderbuffers(1, &mBackbufferRB); + fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mBackbufferRB); + + [mContext renderbufferStorage:LOCAL_GL_RENDERBUFFER + fromDrawable:layer]; + + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackbufferFB); + fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_RENDERBUFFER, mBackbufferRB); + + return LOCAL_GL_FRAMEBUFFER_COMPLETE == fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); +} + +bool +GLContextEAGL::MakeCurrentImpl(bool aForce) +{ + if (!aForce && [EAGLContext currentContext] == mContext) { + return true; + } + + if (mContext) { + if(![EAGLContext setCurrentContext:mContext]) { + return false; + } + } + return true; +} + +bool +GLContextEAGL::IsCurrent() { + return [EAGLContext currentContext] == mContext; +} + +bool +GLContextEAGL::SetupLookupFunction() +{ + return false; +} + +bool +GLContextEAGL::IsDoubleBuffered() const +{ + return true; +} + +bool +GLContextEAGL::SupportsRobustness() const +{ + return false; +} + +bool +GLContextEAGL::SwapBuffers() +{ + PROFILER_LABEL("GLContextEAGL", "SwapBuffers", + js::ProfileEntry::Category::GRAPHICS); + + [mContext presentRenderbuffer:LOCAL_GL_RENDERBUFFER]; + return true; +} + + +already_AddRefed +GLContextProviderEAGL::CreateWrappingExisting(void*, void*) +{ + return nullptr; +} + +static GLContextEAGL* +GetGlobalContextEAGL() +{ + return static_cast(GLContextProviderEAGL::GetGlobalContext()); +} + +static already_AddRefed +CreateEAGLContext(bool aOffscreen, GLContextEAGL* sharedContext) +{ + EAGLRenderingAPI apis[] = { kEAGLRenderingAPIOpenGLES3, kEAGLRenderingAPIOpenGLES2 }; + + // Try to create a GLES3 context if we can, otherwise fall back to GLES2 + EAGLContext* context = nullptr; + for (EAGLRenderingAPI api : apis) { + if (sharedContext) { + context = [[EAGLContext alloc] initWithAPI:api + sharegroup:sharedContext->GetEAGLContext().sharegroup]; + } else { + context = [[EAGLContext alloc] initWithAPI:api]; + } + + if (context) { + break; + } + } + + if (!context) { + return nullptr; + } + + SurfaceCaps caps = SurfaceCaps::ForRGBA(); + ContextProfile profile = ContextProfile::OpenGLES; + RefPtr glContext = new GLContextEAGL(caps, context, + sharedContext, + aOffscreen, + profile); + + if (!glContext->Init()) { + glContext = nullptr; + return nullptr; + } + + return glContext.forget(); +} + +already_AddRefed +GLContextProviderEAGL::CreateForWindow(nsIWidget* aWidget) +{ + RefPtr glContext = CreateEAGLContext(false, GetGlobalContextEAGL()); + if (!glContext) { + return nullptr; + } + + if (!GLContextEAGL::Cast(glContext)->AttachToWindow(aWidget)) { + return nullptr; + } + + return glContext.forget(); +} + +already_AddRefed +GLContextProviderEAGL::CreateHeadless(CreateContextFlags flags) +{ + return CreateEAGLContext(true, GetGlobalContextEAGL()); +} + +already_AddRefed +GLContextProviderEAGL::CreateOffscreen(const mozilla::gfx::IntSize& size, + const SurfaceCaps& caps, + CreateContextFlags flags) +{ + RefPtr glContext = CreateHeadless(flags); + if (!glContext->InitOffscreen(size, caps)) { + return nullptr; + } + + return glContext.forget(); +} + +static RefPtr gGlobalContext; + +GLContext* +GLContextProviderEAGL::GetGlobalContext() +{ + if (!gGlobalContext) { + gGlobalContext = CreateEAGLContext(true, nullptr); + if (!gGlobalContext || + !static_cast(gGlobalContext.get())->Init()) + { + MOZ_CRASH("Failed to create global context"); + } + } + + return gGlobalContext; +} + +void +GLContextProviderEAGL::Shutdown() +{ + gGlobalContext = nullptr; +} + +} /* namespace gl */ +} /* namespace mozilla */ diff --git a/gfx/gl/GLContextTypes.h b/gfx/gl/GLContextTypes.h index a9225e2d830..c99c03ec15b 100644 --- a/gfx/gl/GLContextTypes.h +++ b/gfx/gl/GLContextTypes.h @@ -19,7 +19,8 @@ enum class GLContextType { WGL, CGL, GLX, - EGL + EGL, + EAGL }; enum class OriginPos : uint8_t { diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build index 6e062730aa3..6a0b78e62f9 100644 --- a/gfx/gl/moz.build +++ b/gfx/gl/moz.build @@ -10,6 +10,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': gl_provider = 'WGL' elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': gl_provider = 'CGL' +elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit': + gl_provider = 'EAGL' elif CONFIG['MOZ_WIDGET_GTK']: if CONFIG['MOZ_EGL_XRENDER_COMPOSITE']: gl_provider = 'EGL' @@ -103,6 +105,15 @@ if gl_provider == 'CGL': SOURCES += [ 'SharedSurfaceIO.cpp', ] +elif gl_provider == 'EAGL': + # These files include ObjC headers that are unfriendly to unified builds + SOURCES += [ + 'GLContextProviderEAGL.mm', + ] + EXPORTS += [ + 'GLContextEAGL.h', + ] + elif gl_provider == 'GLX': # GLContextProviderGLX.cpp needs to be kept out of UNIFIED_SOURCES # as it includes X11 headers which cause conflicts. From 0706108b136e8e55d8ffef6128b9de7886659dc7 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Thu, 24 Sep 2015 09:11:53 -0500 Subject: [PATCH 14/95] Bug 1208513 - Resurrect SharedSurface_GLTexture for use on iOS r=jgilbert --- gfx/gl/GLScreenBuffer.cpp | 2 + gfx/gl/SharedSurfaceGL.cpp | 83 ++++++++++++++++++++++++++++ gfx/gl/SharedSurfaceGL.h | 72 ++++++++++++++++++++++++ gfx/gl/SurfaceTypes.h | 1 + gfx/layers/composite/TextureHost.cpp | 1 + gfx/layers/ipc/LayersSurfaces.ipdlh | 9 +++ gfx/layers/opengl/TextureHostOGL.cpp | 81 +++++++++++++++++++++++++++ gfx/layers/opengl/TextureHostOGL.h | 50 +++++++++++++++++ 8 files changed, 299 insertions(+) diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index e0fb75cb7fd..37f8702f3c3 100755 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -82,6 +82,8 @@ GLScreenBuffer::CreateFactory(GLContext* gl, #elif defined(GL_PROVIDER_GLX) if (sGLXLibrary.UseSurfaceSharing()) factory = SurfaceFactory_GLXDrawable::Create(gl, caps, forwarder, flags); +#elif defined(MOZ_WIDGET_UIKIT) + factory = MakeUnique(mGLContext, caps, forwarder, mFlags); #else if (gl->GetContextType() == GLContextType::EGL) { if (XRE_IsParentProcess()) { diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp index 5aa7d2cb3bf..7969686dfef 100644 --- a/gfx/gl/SharedSurfaceGL.cpp +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -95,6 +95,7 @@ SharedSurface_Basic::~SharedSurface_Basic() mGL->fDeleteTextures(1, &mTex); } + //////////////////////////////////////////////////////////////////////// SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps, @@ -102,6 +103,88 @@ SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& cap : SurfaceFactory(SharedSurfaceType::Basic, gl, caps, nullptr, flags) { } + +//////////////////////////////////////////////////////////////////////// +// SharedSurface_GLTexture + +/*static*/ UniquePtr +SharedSurface_GLTexture::Create(GLContext* prodGL, + const GLFormats& formats, + const IntSize& size, + bool hasAlpha) +{ + MOZ_ASSERT(prodGL); + + prodGL->MakeCurrent(); + + UniquePtr ret; + GLContext::LocalErrorScope localError(*prodGL); + + GLuint tex = CreateTextureForOffscreen(prodGL, formats, size); + + GLenum err = localError.GetError(); + MOZ_ASSERT_IF(err, err == LOCAL_GL_OUT_OF_MEMORY); + if (err) { + prodGL->fDeleteTextures(1, &tex); + return Move(ret); + } + + ret.reset(new SharedSurface_GLTexture(prodGL, size, + hasAlpha, tex)); + return Move(ret); +} + +SharedSurface_GLTexture::~SharedSurface_GLTexture() +{ + if (!mGL->MakeCurrent()) + return; + + if (mTex) { + mGL->fDeleteTextures(1, &mTex); + } + + if (mSync) { + mGL->fDeleteSync(mSync); + } +} + +void +SharedSurface_GLTexture::ProducerReleaseImpl() +{ + mGL->MakeCurrent(); + + if (mGL->IsExtensionSupported(GLContext::ARB_sync)) { + if (mSync) { + mGL->fDeleteSync(mSync); + mSync = 0; + } + + mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + if (mSync) { + mGL->fFlush(); + return; + } + } + MOZ_ASSERT(!mSync); + + mGL->fFinish(); +} + +bool +SharedSurface_GLTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + *out_descriptor = layers::SurfaceDescriptorSharedGLTexture(ProdTexture(), + ProdTextureTarget(), + (uintptr_t)mSync, + mSize, + mHasAlpha); + + // Transfer ownership of the fence to the host + mSync = nullptr; + return true; +} + + } // namespace gl } /* namespace mozilla */ diff --git a/gfx/gl/SharedSurfaceGL.h b/gfx/gl/SharedSurfaceGL.h index be3ccecfb5c..eb13d141cb5 100644 --- a/gfx/gl/SharedSurfaceGL.h +++ b/gfx/gl/SharedSurfaceGL.h @@ -93,6 +93,78 @@ public: } }; + +// Using shared GL textures: +class SharedSurface_GLTexture + : public SharedSurface +{ +public: + static UniquePtr Create(GLContext* prodGL, + const GLFormats& formats, + const gfx::IntSize& size, + bool hasAlpha); + + static SharedSurface_GLTexture* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::SharedGLTexture); + + return (SharedSurface_GLTexture*)surf; + } + +protected: + const GLuint mTex; + GLsync mSync; + + SharedSurface_GLTexture(GLContext* prodGL, + const gfx::IntSize& size, + bool hasAlpha, + GLuint tex) + : SharedSurface(SharedSurfaceType::SharedGLTexture, + AttachmentType::GLTexture, + prodGL, + size, + hasAlpha, true) + , mTex(tex) + , mSync(0) + { + } + +public: + virtual ~SharedSurface_GLTexture(); + + virtual void LockProdImpl() override {} + virtual void UnlockProdImpl() override {} + + virtual void ProducerReleaseImpl() override; + + virtual void Fence() override {} + virtual bool WaitSync() override { MOZ_CRASH("should not be called"); } + virtual bool PollSync() override { MOZ_CRASH("should not be called"); } + + virtual GLuint ProdTexture() override { + return mTex; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; +}; + +class SurfaceFactory_GLTexture + : public SurfaceFactory +{ +public: + SurfaceFactory_GLTexture(GLContext* prodGL, + const SurfaceCaps& caps, + const RefPtr& allocator, + const layers::TextureFlags& flags) + : SurfaceFactory(SharedSurfaceType::SharedGLTexture, prodGL, caps, allocator, flags) + { + } + + virtual UniquePtr CreateShared(const gfx::IntSize& size) override { + bool hasAlpha = mReadCaps.alpha; + return SharedSurface_GLTexture::Create(mGL, mFormats, size, hasAlpha); + } +}; + } // namespace gl } /* namespace mozilla */ diff --git a/gfx/gl/SurfaceTypes.h b/gfx/gl/SurfaceTypes.h index f4507291cd4..b3b9a127ac4 100644 --- a/gfx/gl/SurfaceTypes.h +++ b/gfx/gl/SurfaceTypes.h @@ -77,6 +77,7 @@ enum class SharedSurfaceType : uint8_t { Gralloc, IOSurface, GLXDrawable, + SharedGLTexture, Max }; diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index a47e37e881f..d2f625fe2b4 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -215,6 +215,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc, case SurfaceDescriptor::TEGLImageDescriptor: case SurfaceDescriptor::TSurfaceTextureDescriptor: + case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: return CreateTextureHostOGL(aDesc, aDeallocator, aFlags); case SurfaceDescriptor::TNewSurfaceDescriptorGralloc: diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index 03f305c8672..3a07984ed70 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -82,6 +82,14 @@ struct EGLImageDescriptor { bool hasAlpha; }; +struct SurfaceDescriptorSharedGLTexture { + uint32_t texture; + uint32_t target; + uintptr_t fence; + IntSize size; + bool hasAlpha; +}; + struct NewSurfaceDescriptorGralloc { MaybeMagicGrallocBufferHandle buffer; bool isOpaque; @@ -116,6 +124,7 @@ union SurfaceDescriptor { EGLImageDescriptor; SurfaceDescriptorMacIOSurface; NewSurfaceDescriptorGralloc; + SurfaceDescriptorSharedGLTexture; null_t; }; diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index e8f7d56409d..b0bff91adfd 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -104,6 +104,16 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc, break; } #endif + + case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: { + const auto& desc = aDesc.get_SurfaceDescriptorSharedGLTexture(); + result = new GLTextureHost(aFlags, desc.texture(), + desc.target(), + (GLsync)desc.fence(), + desc.size(), + desc.hasAlpha()); + break; + } default: return nullptr; } return result.forget(); @@ -645,5 +655,76 @@ EGLImageTextureHost::GetFormat() const return mTextureSource->GetFormat(); } +// + +GLTextureHost::GLTextureHost(TextureFlags aFlags, + GLuint aTextureHandle, + GLenum aTarget, + GLsync aSync, + gfx::IntSize aSize, + bool aHasAlpha) + : TextureHost(aFlags) + , mTexture(aTextureHandle) + , mTarget(aTarget) + , mSync(aSync) + , mSize(aSize) + , mHasAlpha(aHasAlpha) + , mCompositor(nullptr) +{} + +GLTextureHost::~GLTextureHost() +{} + +gl::GLContext* +GLTextureHost::gl() const +{ + return mCompositor ? mCompositor->gl() : nullptr; +} + +bool +GLTextureHost::Lock() +{ + if (!mCompositor) { + return false; + } + + if (mSync) { + gl()->MakeCurrent(); + gl()->fWaitSync(mSync, 0, LOCAL_GL_TIMEOUT_IGNORED); + gl()->fDeleteSync(mSync); + mSync = 0; + } + + if (!mTextureSource) { + gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 + : gfx::SurfaceFormat::R8G8B8X8; + mTextureSource = new GLTextureSource(mCompositor, + mTexture, + mTarget, + mSize, + format, + false /* owned by the client */); + } + + return true; +} +void +GLTextureHost::SetCompositor(Compositor* aCompositor) +{ + MOZ_ASSERT(aCompositor); + CompositorOGL* glCompositor = static_cast(aCompositor); + mCompositor = glCompositor; + if (mTextureSource) { + mTextureSource->SetCompositor(glCompositor); + } +} + +gfx::SurfaceFormat +GLTextureHost::GetFormat() const +{ + MOZ_ASSERT(mTextureSource); + return mTextureSource->GetFormat(); +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index d028cad8e62..92bc5b51756 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -279,6 +279,56 @@ protected: bool mExternallyOwned; }; +class GLTextureHost : public TextureHost +{ +public: + GLTextureHost(TextureFlags aFlags, + GLuint aTextureHandle, + GLenum aTarget, + GLsync aSync, + gfx::IntSize aSize, + bool aHasAlpha); + + virtual ~GLTextureHost(); + + // We don't own anything. + virtual void DeallocateDeviceData() override {} + + virtual void SetCompositor(Compositor* aCompositor) override; + + virtual bool Lock() override; + + virtual void Unlock() override {} + + virtual gfx::SurfaceFormat GetFormat() const override; + + virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override + { + aTexture = mTextureSource; + return !!aTexture; + } + + virtual already_AddRefed GetAsSurface() override + { + return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) + } + + gl::GLContext* gl() const; + + virtual gfx::IntSize GetSize() const override { return mSize; } + + virtual const char* Name() override { return "GLTextureHost"; } + +protected: + const GLuint mTexture; + const GLenum mTarget; + GLsync mSync; + const gfx::IntSize mSize; + const bool mHasAlpha; + RefPtr mCompositor; + RefPtr mTextureSource; +}; + //////////////////////////////////////////////////////////////////////// // SurfaceTexture From 5d2067f15df9cefac6339cb243ff56b62dcffb20 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Fri, 25 Sep 2015 09:29:53 -0500 Subject: [PATCH 15/95] Bug 1207672 - Add support for APPLE_framebuffer_multisample r=snorp --- gfx/gl/GLContext.cpp | 31 ++++++++++++++++------------ gfx/gl/GLContext.h | 11 ++++++++++ gfx/gl/GLContextFeatures.cpp | 14 +++++++++++++ gfx/gl/GLContextSymbols.h | 4 ++++ gfx/gl/GLScreenBuffer.cpp | 40 ++++++++++++++++++------------------ gfx/gl/ScopedGLHelpers.cpp | 2 +- 6 files changed, 68 insertions(+), 34 deletions(-) diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 6caf6623137..13484e7c20a 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -783,7 +783,6 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } if (!IsSupported(GLFeature::framebuffer_object)) { - // Check for aux symbols based on extensions if (IsSupported(GLFeature::framebuffer_object_EXT_OES)) { @@ -811,11 +810,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } } - if (IsExtensionSupported(GLContext::ANGLE_framebuffer_blit) || - IsExtensionSupported(GLContext::EXT_framebuffer_blit) || - IsExtensionSupported(GLContext::NV_framebuffer_blit)) - - { + if (IsSupported(GLFeature::framebuffer_blit)) { SymLoadStruct extSymbols[] = { EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV), END_SYMBOLS @@ -826,11 +821,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } } - if (IsExtensionSupported(GLContext::ANGLE_framebuffer_multisample) || - IsExtensionSupported(GLContext::APPLE_framebuffer_multisample) || - IsExtensionSupported(GLContext::EXT_framebuffer_multisample) || - IsExtensionSupported(GLContext::EXT_multisampled_render_to_texture)) - { + if (IsSupported(GLFeature::framebuffer_multisample)) { SymLoadStruct extSymbols[] = { EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT), END_SYMBOLS @@ -1546,7 +1537,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) if (IsSupported(GLFeature::read_buffer)) { SymLoadStruct extSymbols[] = { - { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } }, + { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } }, END_SYMBOLS }; @@ -1558,6 +1549,20 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } } + if (IsExtensionSupported(APPLE_framebuffer_multisample)) { + SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fResolveMultisampleFramebufferAPPLE, { "ResolveMultisampleFramebufferAPPLE", nullptr } }, + END_SYMBOLS + }; + + if (!LoadSymbols(&extSymbols[0], trygl, prefix)) { + NS_ERROR("GL supports APPLE_framebuffer_multisample without supplying its functions."); + + MarkExtensionUnsupported(APPLE_framebuffer_multisample); + ClearSymbols(extSymbols); + } + } + // Load developer symbols, don't fail if we can't find them. SymLoadStruct auxSymbols[] = { { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } }, @@ -2913,7 +2918,7 @@ GLContext::GetReadFB() if (mScreen) return mScreen->GetReadFB(); - GLenum bindEnum = IsSupported(GLFeature::framebuffer_blit) + GLenum bindEnum = IsSupported(GLFeature::split_framebuffer) ? LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT : LOCAL_GL_FRAMEBUFFER_BINDING; diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index e86d7551a96..44eede53076 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -124,6 +124,7 @@ enum class GLFeature { sRGB_framebuffer, sRGB_texture, sampler_objects, + split_framebuffer, standard_derivatives, sync, texture_3D, @@ -3139,6 +3140,16 @@ public: return ret; } +// ----------------------------------------------------------------------------- +// APPLE_framebuffer_multisample + + void fResolveMultisampleFramebufferAPPLE() { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fResolveMultisampleFramebufferAPPLE); + mSymbols.fResolveMultisampleFramebufferAPPLE(); + AFTER_GL_CALL; + } + // ----------------------------------------------------------------------------- // Constructor protected: diff --git a/gfx/gl/GLContextFeatures.cpp b/gfx/gl/GLContextFeatures.cpp index 780a9950169..63a15a35dc9 100644 --- a/gfx/gl/GLContextFeatures.cpp +++ b/gfx/gl/GLContextFeatures.cpp @@ -547,6 +547,20 @@ static const FeatureInfo sFeatureInfoArr[] = { GLContext::Extensions_End } }, + { + // Do we have separate DRAW and READ framebuffer bind points? + "split_framebuffer", + GLVersion::GL3, + GLESVersion::ES3, + GLContext::ARB_framebuffer_object, + { + GLContext::ANGLE_framebuffer_blit, + GLContext::APPLE_framebuffer_multisample, + GLContext::EXT_framebuffer_blit, + GLContext::NV_framebuffer_blit, + GLContext::Extensions_End + } + }, { "standard_derivatives", GLVersion::GL2, diff --git a/gfx/gl/GLContextSymbols.h b/gfx/gl/GLContextSymbols.h index b78a021b1b1..efed07959d8 100644 --- a/gfx/gl/GLContextSymbols.h +++ b/gfx/gl/GLContextSymbols.h @@ -686,6 +686,10 @@ struct GLContextSymbols // get_string_indexed typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC)(GLenum name, GLuint index); PFNGLGETSTRINGIPROC fGetStringi; + + // APPLE_framebuffer_multisample + typedef void (GLAPIENTRY * PFNRESOLVEMULTISAMPLEFRAMEBUFFERAPPLE) (void); + PFNRESOLVEMULTISAMPLEFRAMEBUFFERAPPLE fResolveMultisampleFramebufferAPPLE; }; } // namespace gl diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index 37f8702f3c3..b3cde76a0f5 100755 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -146,7 +146,7 @@ GLScreenBuffer::BindAsFramebuffer(GLContext* const gl, GLenum target) const GLuint drawFB = DrawFB(); GLuint readFB = ReadFB(); - if (!gl->IsSupported(GLFeature::framebuffer_blit)) { + if (!gl->IsSupported(GLFeature::split_framebuffer)) { MOZ_ASSERT(drawFB == readFB); gl->raw_fBindFramebuffer(target, readFB); return; @@ -159,16 +159,10 @@ GLScreenBuffer::BindAsFramebuffer(GLContext* const gl, GLenum target) const break; case LOCAL_GL_DRAW_FRAMEBUFFER_EXT: - if (!gl->IsSupported(GLFeature::framebuffer_blit)) - NS_WARNING("DRAW_FRAMEBUFFER requested but unavailable."); - gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB); break; case LOCAL_GL_READ_FRAMEBUFFER_EXT: - if (!gl->IsSupported(GLFeature::framebuffer_blit)) - NS_WARNING("READ_FRAMEBUFFER requested but unavailable."); - gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB); break; @@ -191,7 +185,7 @@ GLScreenBuffer::BindFB(GLuint fb) if (mInternalDrawFB == mInternalReadFB) { mGL->raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mInternalDrawFB); } else { - MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); } @@ -205,7 +199,7 @@ GLScreenBuffer::BindFB(GLuint fb) void GLScreenBuffer::BindDrawFB(GLuint fb) { - MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); GLuint drawFB = DrawFB(); mUserDrawFB = fb; @@ -221,7 +215,7 @@ GLScreenBuffer::BindDrawFB(GLuint fb) void GLScreenBuffer::BindReadFB(GLuint fb) { - MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); GLuint readFB = ReadFB(); mUserReadFB = fb; @@ -250,7 +244,7 @@ GLScreenBuffer::BindFB_Internal(GLuint fb) void GLScreenBuffer::BindDrawFB_Internal(GLuint fb) { - MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); mInternalDrawFB = mUserDrawFB = fb; mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); @@ -263,7 +257,7 @@ GLScreenBuffer::BindDrawFB_Internal(GLuint fb) void GLScreenBuffer::BindReadFB_Internal(GLuint fb) { - MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); mInternalReadFB = mUserReadFB = fb; mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); @@ -309,7 +303,7 @@ GLScreenBuffer::GetReadFB() const // We use raw_ here because this is debug code and we need to see what // the driver thinks. GLuint actual = 0; - if (mGL->IsSupported(GLFeature::framebuffer_blit)) + if (mGL->IsSupported(GLFeature::split_framebuffer)) mGL->raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual); else mGL->raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)&actual); @@ -424,7 +418,7 @@ GLScreenBuffer::AssureBlitted() MOZ_ASSERT(drawFB != 0); MOZ_ASSERT(drawFB != readFB); - MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); MOZ_ASSERT(mDraw->mSize == mRead->Size()); ScopedBindFramebuffer boundFB(mGL); @@ -433,13 +427,19 @@ GLScreenBuffer::AssureBlitted() BindReadFB_Internal(drawFB); BindDrawFB_Internal(readFB); - const gfx::IntSize& srcSize = mDraw->mSize; - const gfx::IntSize& destSize = mRead->Size(); + if (mGL->IsSupported(GLFeature::framebuffer_blit)) { + const gfx::IntSize& srcSize = mDraw->mSize; + const gfx::IntSize& destSize = mRead->Size(); - mGL->raw_fBlitFramebuffer(0, 0, srcSize.width, srcSize.height, - 0, 0, destSize.width, destSize.height, - LOCAL_GL_COLOR_BUFFER_BIT, - LOCAL_GL_NEAREST); + mGL->raw_fBlitFramebuffer(0, 0, srcSize.width, srcSize.height, + 0, 0, destSize.width, destSize.height, + LOCAL_GL_COLOR_BUFFER_BIT, + LOCAL_GL_NEAREST); + } else if (mGL->IsExtensionSupported(GLContext::APPLE_framebuffer_multisample)) { + mGL->fResolveMultisampleFramebufferAPPLE(); + } else { + MOZ_CRASH("No available blit methods."); + } // Done! } diff --git a/gfx/gl/ScopedGLHelpers.cpp b/gfx/gl/ScopedGLHelpers.cpp index 46227afc4da..a70c53137a3 100644 --- a/gfx/gl/ScopedGLHelpers.cpp +++ b/gfx/gl/ScopedGLHelpers.cpp @@ -62,7 +62,7 @@ ScopedGLState::UnwrapImpl() void ScopedBindFramebuffer::Init() { - if (mGL->IsSupported(GLFeature::framebuffer_blit)) { + if (mGL->IsSupported(GLFeature::split_framebuffer)) { mOldReadFB = mGL->GetReadFB(); mOldDrawFB = mGL->GetDrawFB(); } else { From 71f53f1cdbb0012c27c9b6ca6b9b0b6744b6ba35 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 28 Sep 2015 09:41:08 -0500 Subject: [PATCH 16/95] Bug 1208513 - Add support for GL_APPLE_sync r=jgilbert --- gfx/gl/GLContext.cpp | 1 + gfx/gl/GLContext.h | 1 + gfx/gl/GLContextFeatures.cpp | 4 +++- gfx/gl/SharedSurfaceGL.cpp | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 13484e7c20a..f00fff1fdbe 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -77,6 +77,7 @@ static const char *sExtensionNames[] = { "GL_ANGLE_timer_query", "GL_APPLE_client_storage", "GL_APPLE_framebuffer_multisample", + "GL_APPLE_sync", "GL_APPLE_texture_range", "GL_APPLE_vertex_array_object", "GL_ARB_ES2_compatibility", diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 44eede53076..b9391eea13e 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -391,6 +391,7 @@ public: ANGLE_timer_query, APPLE_client_storage, APPLE_framebuffer_multisample, + APPLE_sync, APPLE_texture_range, APPLE_vertex_array_object, ARB_ES2_compatibility, diff --git a/gfx/gl/GLContextFeatures.cpp b/gfx/gl/GLContextFeatures.cpp index 63a15a35dc9..8234374f56c 100644 --- a/gfx/gl/GLContextFeatures.cpp +++ b/gfx/gl/GLContextFeatures.cpp @@ -575,8 +575,10 @@ static const FeatureInfo sFeatureInfoArr[] = { "sync", GLVersion::GL3_2, GLESVersion::ES3, - GLContext::ARB_sync, + GLContext::Extension_None, { + GLContext::ARB_sync, + GLContext::APPLE_sync, GLContext::Extensions_End } }, diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp index 7969686dfef..f050ec9246c 100644 --- a/gfx/gl/SharedSurfaceGL.cpp +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -153,7 +153,7 @@ SharedSurface_GLTexture::ProducerReleaseImpl() { mGL->MakeCurrent(); - if (mGL->IsExtensionSupported(GLContext::ARB_sync)) { + if (mGL->IsSupported(GLFeature::sync)) { if (mSync) { mGL->fDeleteSync(mSync); mSync = 0; From 82677a460969406414e70481a0b85d3834f8bf83 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 28 Sep 2015 17:09:00 -0500 Subject: [PATCH 17/95] Bug 1213970 - Enable APZ on iOS r=kats --- gfx/layers/client/ClientLayerManager.cpp | 2 +- layout/base/ZoomConstraintsClient.cpp | 2 +- layout/base/nsLayoutUtils.cpp | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index e4cd7687ce2..2141347e951 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -215,7 +215,7 @@ ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) // // Desktop does not support async zoom yet, so we ignore this for those // platforms. -#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_UIKIT) if (mWidget && mWidget->GetOwningTabChild()) { mCompositorMightResample = AsyncPanZoomEnabled(); } diff --git a/layout/base/ZoomConstraintsClient.cpp b/layout/base/ZoomConstraintsClient.cpp index d9a03441977..cd33e3d31dd 100644 --- a/layout/base/ZoomConstraintsClient.cpp +++ b/layout/base/ZoomConstraintsClient.cpp @@ -46,7 +46,7 @@ static nsIWidget* GetWidget(nsIPresShell* aShell) { if (nsIFrame* rootFrame = aShell->GetRootFrame()) { -#ifdef MOZ_WIDGET_ANDROID +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) return rootFrame->GetNearestWidget(); #else if (nsView* view = rootFrame->GetView()) { diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index cc9ddd0bbfa..b006eadf78a 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2687,7 +2687,7 @@ nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame, nsDisplayListBuilder builder(root, nsDisplayListBuilder::OTHER, false/*don't build caret*/); - nsDisplayList list; + nsDisplayList list; nsDisplayTransform* item = new (&builder) nsDisplayTransform(&builder, aFrame, &list, nsRect()); @@ -3269,7 +3269,7 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram // For the viewport frame in print preview/page layout we want to paint // the grey background behind the page, not the canvas color. - if (frameType == nsGkAtoms::viewportFrame && + if (frameType == nsGkAtoms::viewportFrame && nsLayoutUtils::NeedsPrintPreviewBackground(presContext)) { nsRect bounds = nsRect(builder.ToReferenceFrame(aFrame), aFrame->GetSize()); @@ -4833,7 +4833,7 @@ nsLayoutUtils::ComputeISizeValue( nscoord result; if (aCoord.IsCoordPercentCalcUnit()) { - result = nsRuleNode::ComputeCoordPercentCalc(aCoord, + result = nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockISize); // The result of a calc() expression might be less than 0; we // should clamp at runtime (below). (Percentages and coords that @@ -5851,7 +5851,7 @@ nsLayoutUtils::CalculateContentBEnd(WritingMode aWM, nsIFrame* aFrame) nsIFrame::ChildListIterator lists(aFrame); for (; !lists.IsDone(); lists.Next()) { if (!skip.Contains(lists.CurrentID())) { - nsFrameList::Enumerator childFrames(lists.CurrentList()); + nsFrameList::Enumerator childFrames(lists.CurrentList()); for (; !childFrames.AtEnd(); childFrames.Next()) { nsIFrame* child = childFrames.get(); nscoord offset = @@ -7666,7 +7666,7 @@ nsLayoutUtils::FontSizeInflationEnabled(nsPresContext *aPresContext) } /* static */ nsRect -nsLayoutUtils::GetBoxShadowRectForFrame(nsIFrame* aFrame, +nsLayoutUtils::GetBoxShadowRectForFrame(nsIFrame* aFrame, const nsSize& aFrameSize) { nsCSSShadowArray* boxShadows = aFrame->StyleBorder()->mBoxShadow; @@ -7688,7 +7688,7 @@ nsLayoutUtils::GetBoxShadowRectForFrame(nsIFrame* aFrame, nsRect frameRect = nativeTheme ? aFrame->GetVisualOverflowRectRelativeToSelf() : nsRect(nsPoint(0, 0), aFrameSize); - + nsRect shadows; int32_t A2D = aFrame->PresContext()->AppUnitsPerDevPixel(); for (uint32_t i = 0; i < boxShadows->Length(); ++i) { @@ -7812,7 +7812,7 @@ UpdateCompositionBoundsForRCDRSF(ParentLayerRect& aCompBounds, return false; } -#ifdef MOZ_WIDGET_ANDROID +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) nsIWidget* widget = rootFrame->GetNearestWidget(); #else nsView* view = rootFrame->GetView(); @@ -8145,7 +8145,7 @@ void StrokeLineWithSnapping(const nsPoint& aP1, const nsPoint& aP2, namespace layout { - + void MaybeSetupTransactionIdAllocator(layers::LayerManager* aManager, nsView* aView) { From c8500a43e5203439c2abbd0ecb263e071b722c73 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 12 Oct 2015 12:04:09 -0500 Subject: [PATCH 18/95] Bug 1213968 - Renew the surface on iOS when resuming the compositor r=kats --- gfx/layers/opengl/CompositorOGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index 231565e1d9c..e2f1b386d72 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -1532,7 +1532,7 @@ CompositorOGL::Pause() bool CompositorOGL::Resume() { -#ifdef MOZ_WIDGET_ANDROID +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) if (!gl() || gl()->IsDestroyed()) return false; From 45f3fb7b19d2e2ce1f2a5f1c0b98f06749706ba6 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 14 Oct 2015 09:38:21 -0500 Subject: [PATCH 19/95] Bug 1214678 - Allow Apple media decoders to work on iOS r=jya --- configure.in | 2 +- dom/media/apple/AppleMP3Reader.cpp | 7 ++++--- dom/media/platforms/apple/AppleATDecoder.cpp | 3 +++ dom/media/platforms/apple/AppleCMLinker.cpp | 9 ++++++++- dom/media/platforms/apple/AppleVDADecoder.cpp | 20 +++++++++++++++++-- modules/libpref/init/all.js | 3 +++ 6 files changed, 37 insertions(+), 7 deletions(-) diff --git a/configure.in b/configure.in index d8ce5bad744..a93ab3235aa 100644 --- a/configure.in +++ b/configure.in @@ -5164,7 +5164,7 @@ fi; dnl ======================================================== dnl = Apple platform decoder support dnl ======================================================== -if test "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then +if test "$MOZ_WIDGET_TOOLKIT" = "cocoa" || test "$MOZ_WIDGET_TOOLKIT" = "uikit"; then MOZ_APPLEMEDIA=1 fi diff --git a/dom/media/apple/AppleMP3Reader.cpp b/dom/media/apple/AppleMP3Reader.cpp index c5c7a6b006d..f38f530aa65 100644 --- a/dom/media/apple/AppleMP3Reader.cpp +++ b/dom/media/apple/AppleMP3Reader.cpp @@ -430,9 +430,10 @@ AppleMP3Reader::SetupDecoder() // Set output format #if defined(MOZ_SAMPLE_TYPE_FLOAT32) outputFormat.mBitsPerChannel = 32; - outputFormat.mFormatFlags = - kLinearPCMFormatFlagIsFloat | - 0; + outputFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat; +#elif defined(MOZ_SAMPLE_TYPE_S16) + outputFormat.mBitsPerChannel = 32; + outputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; #else #error Unknown audio sample type #endif diff --git a/dom/media/platforms/apple/AppleATDecoder.cpp b/dom/media/platforms/apple/AppleATDecoder.cpp index d4a97536f17..d1df024c62c 100644 --- a/dom/media/platforms/apple/AppleATDecoder.cpp +++ b/dom/media/platforms/apple/AppleATDecoder.cpp @@ -397,6 +397,9 @@ AppleATDecoder::SetupDecoder(MediaRawData* aSample) mOutputFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat | 0; +#elif defined(MOZ_SAMPLE_TYPE_S16) + mOutputFormat.mBitsPerChannel = 16; + mOutputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | 0; #else # error Unknown audio sample type #endif diff --git a/dom/media/platforms/apple/AppleCMLinker.cpp b/dom/media/platforms/apple/AppleCMLinker.cpp index ce97e7fd8bd..d32119ba906 100644 --- a/dom/media/platforms/apple/AppleCMLinker.cpp +++ b/dom/media/platforms/apple/AppleCMLinker.cpp @@ -9,9 +9,12 @@ #include "AppleCMLinker.h" #include "MainThreadUtils.h" #include "mozilla/ArrayUtils.h" -#include "nsCocoaFeatures.h" #include "nsDebug.h" +#ifndef MOZ_WIDGET_UIKIT +#include "nsCocoaFeatures.h" +#endif + extern PRLogModuleInfo* GetPDMLog(); #define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__)) @@ -57,7 +60,11 @@ AppleCMLinker::Link() goto fail; } +#ifdef MOZ_WIDGET_UIKIT + if (true) { +#else if (nsCocoaFeatures::OnLionOrLater()) { +#endif #define LINK_FUNC2(func) \ func = (typeof(func))dlsym(sLink, #func); \ if (!func) { \ diff --git a/dom/media/platforms/apple/AppleVDADecoder.cpp b/dom/media/platforms/apple/AppleVDADecoder.cpp index 4bd5f156205..1851852ec1a 100644 --- a/dom/media/platforms/apple/AppleVDADecoder.cpp +++ b/dom/media/platforms/apple/AppleVDADecoder.cpp @@ -14,16 +14,19 @@ #include "mp4_demuxer/H264.h" #include "MP4Decoder.h" #include "MediaData.h" -#include "MacIOSurfaceImage.h" #include "mozilla/ArrayUtils.h" #include "nsAutoPtr.h" -#include "nsCocoaFeatures.h" #include "nsThreadUtils.h" #include "mozilla/Logging.h" #include "VideoUtils.h" #include #include "gfxPlatform.h" +#ifndef MOZ_WIDGET_UIKIT +#include "nsCocoaFeatures.h" +#include "MacIOSurfaceImage.h" +#endif + extern PRLogModuleInfo* GetPDMLog(); #define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__)) //#define LOG_MEDIA_SHA1 @@ -43,8 +46,13 @@ AppleVDADecoder::AppleVDADecoder(const VideoInfo& aConfig, , mDisplayHeight(aConfig.mDisplay.height) , mInputIncoming(0) , mIsShutDown(false) +#ifdef MOZ_WIDGET_UIKIT + , mUseSoftwareImages(true) + , mIs106(false) +#else , mUseSoftwareImages(false) , mIs106(!nsCocoaFeatures::OnLionOrLater()) + #endif , mQueuedSamples(0) , mMonitor("AppleVideoDecoder") , mIsFlushing(false) @@ -383,6 +391,7 @@ AppleVDADecoder::OutputFrame(CVPixelBufferRef aImage, // Unlock the returned image data. CVPixelBufferUnlockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly); } else { +#ifndef MOZ_WIDGET_UIKIT IOSurfacePtr surface = MacIOSurfaceLib::CVPixelBufferGetIOSurface(aImage); MOZ_ASSERT(surface, "Decoder didn't return an IOSurface backed buffer"); @@ -404,6 +413,9 @@ AppleVDADecoder::OutputFrame(CVPixelBufferRef aImage, aFrameRef.is_sync_point, aFrameRef.decode_timestamp.ToMicroseconds(), visible); +#else + MOZ_ASSERT_UNREACHABLE("No MacIOSurface on iOS"); +#endif } if (!data) { @@ -608,6 +620,7 @@ AppleVDADecoder::CreateOutputConfiguration() &kCFTypeDictionaryValueCallBacks); } +#ifndef MOZ_WIDGET_UIKIT // Construct IOSurface Properties const void* IOSurfaceKeys[] = { MacIOSurfaceLib::kPropIsGlobal }; const void* IOSurfaceValues[] = { kCFBooleanTrue }; @@ -638,6 +651,9 @@ AppleVDADecoder::CreateOutputConfiguration() ArrayLength(outputKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); +#else + MOZ_ASSERT_UNREACHABLE("No MacIOSurface on iOS"); +#endif } /* static */ diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 121d1cb87da..73a04990355 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -353,6 +353,9 @@ pref("media.gstreamer.enabled", true); pref("media.gstreamer.enable-blacklist", true); #endif #ifdef MOZ_APPLEMEDIA +#ifdef MOZ_WIDGET_UIKIT +pref("media.mp3.enabled", true); +#endif pref("media.apple.mp3.enabled", true); pref("media.apple.mp4.enabled", true); #endif From 2801d6c924f66110116976acade06452eac2f8f1 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Fri, 23 Oct 2015 12:50:26 -0500 Subject: [PATCH 20/95] No bug, add missing include to StackWalk.cpp, DONTBUILD --- mozglue/misc/StackWalk.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mozglue/misc/StackWalk.cpp b/mozglue/misc/StackWalk.cpp index 7a561e3af67..cd8d177c863 100644 --- a/mozglue/misc/StackWalk.cpp +++ b/mozglue/misc/StackWalk.cpp @@ -11,6 +11,8 @@ #include "mozilla/IntegerPrintfMacros.h" #include "mozilla/StackWalk.h" +#include + #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif From 9169ab855584ed4302eaab5e444d2d5438c24751 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 26 Oct 2015 12:44:21 -0500 Subject: [PATCH 21/95] Bug 1209260 - Don't use sincos on iOS r=npb --- js/src/jit/JitOptions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp index b45c31e3ec5..e3cc76986fc 100644 --- a/js/src/jit/JitOptions.cpp +++ b/js/src/jit/JitOptions.cpp @@ -112,7 +112,7 @@ JitOptions::JitOptions() // Toggles whether sincos optimization is globally disabled. // See bug984018: The MacOS is the only one that has the sincos fast. - #if defined(XP_DARWIN) + #if defined(XP_MACOSX) SET_DEFAULT(disableSincos, false); #else SET_DEFAULT(disableSincos, true); From ae37b99ce1f82a687fd3566a7dca83f36b9ff932 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Tue, 27 Oct 2015 16:03:49 -0500 Subject: [PATCH 22/95] Bug 1218991 - Save initial zoom constraints to be used once compositor is created r=kats --- widget/nsBaseWidget.cpp | 21 ++++++++++++++++++++- widget/nsBaseWidget.h | 15 +++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index f28cb81ca12..4bf7df7a007 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -943,6 +943,19 @@ nsBaseWidget::UpdateZoomConstraints(const uint32_t& aPresShellId, const Maybe& aConstraints) { if (!mCompositorParent || !mAPZC) { + if (mInitialZoomConstraints) { + MOZ_ASSERT(mInitialZoomConstraints->mPresShellID == aPresShellId); + MOZ_ASSERT(mInitialZoomConstraints->mViewID == aViewId); + if (!aConstraints) { + mInitialZoomConstraints.reset(); + } + } + + if (aConstraints) { + // We have some constraints, but the compositor and APZC aren't created yet. + // Save these so we can use them later. + mInitialZoomConstraints = Some(InitialZoomConstraints(aPresShellId, aViewId, aConstraints.ref())); + } return; } uint64_t layersId = mCompositorParent->RootLayerTreeId(); @@ -1109,6 +1122,13 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) ConfigureAPZCTreeManager(); } + if (mInitialZoomConstraints) { + UpdateZoomConstraints(mInitialZoomConstraints->mPresShellID, + mInitialZoomConstraints->mViewID, + Some(mInitialZoomConstraints->mConstraints)); + mInitialZoomConstraints.reset(); + } + TextureFactoryIdentifier textureFactoryIdentifier; PLayerTransactionChild* shadowManager = nullptr; @@ -2920,4 +2940,3 @@ nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut, ////////////////////////////////////////////////////////////// #endif // DEBUG - diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index f4d0be67dfc..647c7bcfed8 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -526,6 +526,21 @@ protected: // so it can be cleared automatically. static nsIContent* mLastRollup; + struct InitialZoomConstraints { + InitialZoomConstraints(const uint32_t& aPresShellID, + const FrameMetrics::ViewID& aViewID, + const ZoomConstraints& aConstraints) + : mPresShellID(aPresShellID), mViewID(aViewID), mConstraints(aConstraints) + { + } + + uint32_t mPresShellID; + FrameMetrics::ViewID mViewID; + ZoomConstraints mConstraints; + }; + + mozilla::Maybe mInitialZoomConstraints; + #ifdef DEBUG protected: static nsAutoString debug_GuiEventToString(mozilla::WidgetGUIEvent* aGuiEvent); From 0cbc95c2f71214e417f5eb6b6e3bce5f68b84a4b Mon Sep 17 00:00:00 2001 From: James Willcox Date: Tue, 27 Oct 2015 16:07:51 -0500 Subject: [PATCH 23/95] No bug, use attached widget listener mode on iOS, NPOTB --- layout/base/nsDocumentViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index f84f0438559..794fb8b8ad3 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -4149,7 +4149,7 @@ nsDocumentViewer::ShouldAttachToTopLevel() if (nsIWidget::UsePuppetWidgets()) return true; -#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_ANDROID) +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) // On windows, in the parent process we also attach, but just to // chrome items nsWindowType winType = mParentWidget->WindowType(); From bc1db78ef1d576fd0738983b54cf57a0f51e14fc Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 28 Oct 2015 19:10:20 +0000 Subject: [PATCH 24/95] Bug 1215092 - WebSocketEventService and WebSocket discovering - part 1 - Renaming WebSocketFrameService, r=michal --- dom/base/test/test_websocket_frame.html | 8 +- layout/build/nsLayoutModule.cpp | 14 ++-- netwerk/ipc/NeckoChild.cpp | 16 ++-- netwerk/ipc/NeckoChild.h | 6 +- netwerk/ipc/NeckoParent.cpp | 16 ++-- netwerk/ipc/NeckoParent.h | 6 +- netwerk/ipc/PNecko.ipdl | 6 +- ...ener.ipdl => PWebSocketEventListener.ipdl} | 2 +- .../protocol/websocket/WebSocketChannel.cpp | 32 +++---- netwerk/protocol/websocket/WebSocketChannel.h | 4 +- ...ld.cpp => WebSocketEventListenerChild.cpp} | 18 ++-- ...rChild.h => WebSocketEventListenerChild.h} | 20 ++--- ...t.cpp => WebSocketEventListenerParent.cpp} | 28 +++---- ...arent.h => WebSocketEventListenerParent.h} | 24 +++--- ...eService.cpp => WebSocketEventService.cpp} | 83 +++++++++---------- ...FrameService.h => WebSocketEventService.h} | 24 +++--- netwerk/protocol/websocket/WebSocketFrame.h | 2 +- netwerk/protocol/websocket/moz.build | 16 ++-- ...rvice.idl => nsIWebSocketEventService.idl} | 8 +- 19 files changed, 166 insertions(+), 167 deletions(-) rename netwerk/protocol/websocket/{PWebSocketFrameListener.ipdl => PWebSocketEventListener.ipdl} (95%) rename netwerk/protocol/websocket/{WebSocketFrameListenerChild.cpp => WebSocketEventListenerChild.cpp} (70%) rename netwerk/protocol/websocket/{WebSocketFrameListenerChild.h => WebSocketEventListenerChild.h} (62%) rename netwerk/protocol/websocket/{WebSocketFrameListenerParent.cpp => WebSocketEventListenerParent.cpp} (64%) rename netwerk/protocol/websocket/{WebSocketFrameListenerParent.h => WebSocketEventListenerParent.h} (50%) rename netwerk/protocol/websocket/{WebSocketFrameService.cpp => WebSocketEventService.cpp} (78%) rename netwerk/protocol/websocket/{WebSocketFrameService.h => WebSocketEventService.h} (80%) rename netwerk/protocol/websocket/{nsIWebSocketFrameService.idl => nsIWebSocketEventService.idl} (87%) diff --git a/dom/base/test/test_websocket_frame.html b/dom/base/test/test_websocket_frame.html index a0a2bed27cf..03db0ecaa55 100644 --- a/dom/base/test/test_websocket_frame.html +++ b/dom/base/test/test_websocket_frame.html @@ -28,12 +28,12 @@ var innerId = .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; ok(innerId, "We have a valid innerWindowID: " + innerId); -var service = Cc["@mozilla.org/websocketframe/service;1"] - .getService(Ci.nsIWebSocketFrameService); -ok(!!service, "We have the nsIWebSocketFrameService"); +var service = Cc["@mozilla.org/websocketevent/service;1"] + .getService(Ci.nsIWebSocketEventService); +ok(!!service, "We have the nsIWebSocketEventService"); var listener = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebSocketFrameListener]), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebSocketEventListener]), frameReceived: function(aWebSocketSerialID, aFrame) { ok(!!aFrame, "We have received a frame"); diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index e2543f729d6..9185e4be837 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -231,7 +231,7 @@ static void Shutdown(); #include "mozilla/dom/nsMixedContentBlocker.h" #include "AudioChannelService.h" -#include "mozilla/net/WebSocketFrameService.h" +#include "mozilla/net/WebSocketEventService.h" #include "mozilla/dom/DataStoreService.h" @@ -633,8 +633,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(Geolocation, Init) #define NS_AUDIOCHANNEL_SERVICE_CID \ { 0xf712e983, 0x048a, 0x443f, { 0x88, 0x02, 0xfc, 0xc3, 0xd9, 0x27, 0xce, 0xac }} -#define NS_WEBSOCKETFRAME_SERVICE_CID \ - { 0x5973dd8f, 0xed2c, 0x41ff, { 0x9e, 0x64, 0x25, 0x1f, 0xf5, 0x5a, 0x67, 0xb9 }} +#define NS_WEBSOCKETEVENT_SERVICE_CID \ + { 0x31689828, 0xda66, 0x49a6, { 0x87, 0x0c, 0xdf, 0x62, 0xb8, 0x3f, 0xe7, 0x89 }} #define NS_DATASTORE_SERVICE_CID \ { 0x0d4285fe, 0xf1b3, 0x49fa, { 0xbc, 0x51, 0xa4, 0xa8, 0x3f, 0x0a, 0xaf, 0x85 }} @@ -643,7 +643,7 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationServ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AudioChannelService, AudioChannelService::GetOrCreate) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WebSocketFrameService, WebSocketFrameService::GetOrCreate) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WebSocketEventService, WebSocketEventService::GetOrCreate) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DataStoreService, DataStoreService::GetOrCreate) @@ -795,7 +795,7 @@ NS_DEFINE_NAMED_CID(NS_TEXTSERVICESDOCUMENT_CID); NS_DEFINE_NAMED_CID(NS_GEOLOCATION_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_GEOLOCATION_CID); NS_DEFINE_NAMED_CID(NS_AUDIOCHANNEL_SERVICE_CID); -NS_DEFINE_NAMED_CID(NS_WEBSOCKETFRAME_SERVICE_CID); +NS_DEFINE_NAMED_CID(NS_WEBSOCKETEVENT_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_DATASTORE_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_FOCUSMANAGER_CID); NS_DEFINE_NAMED_CID(NS_CONTENTSECURITYMANAGER_CID); @@ -1103,7 +1103,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_GEOLOCATION_SERVICE_CID, false, nullptr, nsGeolocationServiceConstructor }, { &kNS_GEOLOCATION_CID, false, nullptr, GeolocationConstructor }, { &kNS_AUDIOCHANNEL_SERVICE_CID, false, nullptr, AudioChannelServiceConstructor }, - { &kNS_WEBSOCKETFRAME_SERVICE_CID, false, nullptr, WebSocketFrameServiceConstructor }, + { &kNS_WEBSOCKETEVENT_SERVICE_CID, false, nullptr, WebSocketEventServiceConstructor }, { &kNS_DATASTORE_SERVICE_CID, false, nullptr, DataStoreServiceConstructor }, { &kNS_FOCUSMANAGER_CID, false, nullptr, CreateFocusManager }, #ifdef MOZ_WEBSPEECH_TEST_BACKEND @@ -1271,7 +1271,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { "@mozilla.org/geolocation/service;1", &kNS_GEOLOCATION_SERVICE_CID }, { "@mozilla.org/geolocation;1", &kNS_GEOLOCATION_CID }, { "@mozilla.org/audiochannel/service;1", &kNS_AUDIOCHANNEL_SERVICE_CID }, - { "@mozilla.org/websocketframe/service;1", &kNS_WEBSOCKETFRAME_SERVICE_CID }, + { "@mozilla.org/websocketevent/service;1", &kNS_WEBSOCKETEVENT_SERVICE_CID }, { "@mozilla.org/datastore-service;1", &kNS_DATASTORE_SERVICE_CID }, { "@mozilla.org/focus-manager;1", &kNS_FOCUSMANAGER_CID }, #ifdef MOZ_WEBSPEECH_TEST_BACKEND diff --git a/netwerk/ipc/NeckoChild.cpp b/netwerk/ipc/NeckoChild.cpp index b327e04d7df..3809d637703 100644 --- a/netwerk/ipc/NeckoChild.cpp +++ b/netwerk/ipc/NeckoChild.cpp @@ -15,7 +15,7 @@ #include "mozilla/net/WyciwygChannelChild.h" #include "mozilla/net/FTPChannelChild.h" #include "mozilla/net/WebSocketChannelChild.h" -#include "mozilla/net/WebSocketFrameListenerChild.h" +#include "mozilla/net/WebSocketEventListenerChild.h" #include "mozilla/net/DNSRequestChild.h" #include "mozilla/net/RemoteOpenFileChild.h" #include "mozilla/net/ChannelDiverterChild.h" @@ -159,19 +159,19 @@ NeckoChild::DeallocPWebSocketChild(PWebSocketChild* child) return true; } -PWebSocketFrameListenerChild* -NeckoChild::AllocPWebSocketFrameListenerChild(const uint64_t& aInnerWindowID) +PWebSocketEventListenerChild* +NeckoChild::AllocPWebSocketEventListenerChild(const uint64_t& aInnerWindowID) { - RefPtr c = - new WebSocketFrameListenerChild(aInnerWindowID); + RefPtr c = + new WebSocketEventListenerChild(aInnerWindowID); return c.forget().take(); } bool -NeckoChild::DeallocPWebSocketFrameListenerChild(PWebSocketFrameListenerChild* aActor) +NeckoChild::DeallocPWebSocketEventListenerChild(PWebSocketEventListenerChild* aActor) { - RefPtr c = - dont_AddRef(static_cast(aActor)); + RefPtr c = + dont_AddRef(static_cast(aActor)); MOZ_ASSERT(c); return true; } diff --git a/netwerk/ipc/NeckoChild.h b/netwerk/ipc/NeckoChild.h index b7bcaf757f6..37f03550269 100644 --- a/netwerk/ipc/NeckoChild.h +++ b/netwerk/ipc/NeckoChild.h @@ -79,9 +79,9 @@ protected: const nsString& aRealm, const uint64_t& aCallbackId) override; virtual bool RecvAppOfflineStatus(const uint32_t& aId, const bool& aOffline) override; - virtual PWebSocketFrameListenerChild* - AllocPWebSocketFrameListenerChild(const uint64_t& aInnerWindowID) override; - virtual bool DeallocPWebSocketFrameListenerChild(PWebSocketFrameListenerChild*) override; + virtual PWebSocketEventListenerChild* + AllocPWebSocketEventListenerChild(const uint64_t& aInnerWindowID) override; + virtual bool DeallocPWebSocketEventListenerChild(PWebSocketEventListenerChild*) override; /* Predictor Messsages */ virtual bool RecvPredOnPredictPreconnect(const URIParams& aURI) override; diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp index 9beef791f00..1bf8c4a2677 100644 --- a/netwerk/ipc/NeckoParent.cpp +++ b/netwerk/ipc/NeckoParent.cpp @@ -13,7 +13,7 @@ #include "mozilla/net/WyciwygChannelParent.h" #include "mozilla/net/FTPChannelParent.h" #include "mozilla/net/WebSocketChannelParent.h" -#include "mozilla/net/WebSocketFrameListenerParent.h" +#include "mozilla/net/WebSocketEventListenerParent.h" #include "mozilla/net/DataChannelParent.h" #ifdef NECKO_PROTOCOL_rtsp #include "mozilla/net/RtspControllerParent.h" @@ -348,19 +348,19 @@ NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor) return true; } -PWebSocketFrameListenerParent* -NeckoParent::AllocPWebSocketFrameListenerParent(const uint64_t& aInnerWindowID) +PWebSocketEventListenerParent* +NeckoParent::AllocPWebSocketEventListenerParent(const uint64_t& aInnerWindowID) { - RefPtr c = - new WebSocketFrameListenerParent(aInnerWindowID); + RefPtr c = + new WebSocketEventListenerParent(aInnerWindowID); return c.forget().take(); } bool -NeckoParent::DeallocPWebSocketFrameListenerParent(PWebSocketFrameListenerParent* aActor) +NeckoParent::DeallocPWebSocketEventListenerParent(PWebSocketEventListenerParent* aActor) { - RefPtr c = - dont_AddRef(static_cast(aActor)); + RefPtr c = + dont_AddRef(static_cast(aActor)); MOZ_ASSERT(c); return true; } diff --git a/netwerk/ipc/NeckoParent.h b/netwerk/ipc/NeckoParent.h index 4309cab594c..dbbc525cfd4 100644 --- a/netwerk/ipc/NeckoParent.h +++ b/netwerk/ipc/NeckoParent.h @@ -172,9 +172,9 @@ protected: virtual bool RecvCancelHTMLDNSPrefetch(const nsString& hostname, const uint16_t& flags, const nsresult& reason) override; - virtual PWebSocketFrameListenerParent* - AllocPWebSocketFrameListenerParent(const uint64_t& aInnerWindowID) override; - virtual bool DeallocPWebSocketFrameListenerParent(PWebSocketFrameListenerParent*) override; + virtual PWebSocketEventListenerParent* + AllocPWebSocketEventListenerParent(const uint64_t& aInnerWindowID) override; + virtual bool DeallocPWebSocketEventListenerParent(PWebSocketEventListenerParent*) override; virtual mozilla::ipc::IProtocol* CloneProtocol(Channel* aChannel, diff --git a/netwerk/ipc/PNecko.ipdl b/netwerk/ipc/PNecko.ipdl index 65596318370..5ea25d72c5d 100644 --- a/netwerk/ipc/PNecko.ipdl +++ b/netwerk/ipc/PNecko.ipdl @@ -12,7 +12,7 @@ include protocol PBrowser; include protocol PWyciwygChannel; include protocol PFTPChannel; include protocol PWebSocket; -include protocol PWebSocketFrameListener; +include protocol PWebSocketEventListener; include protocol PTCPSocket; include protocol PTCPServerSocket; include protocol PUDPSocket; @@ -46,7 +46,7 @@ prio(normal upto urgent) sync protocol PNecko manages PWyciwygChannel; manages PFTPChannel; manages PWebSocket; - manages PWebSocketFrameListener; + manages PWebSocketEventListener; manages PTCPSocket; manages PTCPServerSocket; manages PUDPSocket; @@ -74,7 +74,7 @@ parent: PDNSRequest(nsCString hostName, uint32_t flags, nsCString networkInterface); - PWebSocketFrameListener(uint64_t aInnerWindowID); + PWebSocketEventListener(uint64_t aInnerWindowID); /* Predictor Methods */ PredPredict(OptionalURIParams targetURI, OptionalURIParams sourceURI, diff --git a/netwerk/protocol/websocket/PWebSocketFrameListener.ipdl b/netwerk/protocol/websocket/PWebSocketEventListener.ipdl similarity index 95% rename from netwerk/protocol/websocket/PWebSocketFrameListener.ipdl rename to netwerk/protocol/websocket/PWebSocketEventListener.ipdl index b4355ba1b45..dfe2a6c7e51 100644 --- a/netwerk/protocol/websocket/PWebSocketFrameListener.ipdl +++ b/netwerk/protocol/websocket/PWebSocketEventListener.ipdl @@ -12,7 +12,7 @@ using mozilla::net::WebSocketFrameData from "ipc/IPCMessageUtils.h"; namespace mozilla { namespace net { -async protocol PWebSocketFrameListener +async protocol PWebSocketEventListener { manager PNecko; diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp index 48d2f3660ff..0158be5328e 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -12,7 +12,7 @@ #include "mozilla/Attributes.h" #include "mozilla/Endian.h" #include "mozilla/MathAlgorithms.h" -#include "mozilla/net/WebSocketFrameService.h" +#include "mozilla/net/WebSocketEventService.h" #include "nsIURI.h" #include "nsIChannel.h" @@ -1196,7 +1196,7 @@ WebSocketChannel::WebSocketChannel() : mSerial = sSerialSeed++; - mFrameService = WebSocketFrameService::GetOrCreate(); + mService = WebSocketEventService::GetOrCreate(); } WebSocketChannel::~WebSocketChannel() @@ -1228,7 +1228,7 @@ WebSocketChannel::~WebSocketChannel() NS_ReleaseOnMainThread(mLoadGroup); NS_ReleaseOnMainThread(mLoadInfo); - NS_ReleaseOnMainThread(static_cast(mFrameService.forget().take())); + NS_ReleaseOnMainThread(static_cast(mService.forget().take())); } NS_IMETHODIMP @@ -1699,11 +1699,11 @@ WebSocketChannel::ProcessInput(uint8_t *buffer, uint32_t count) } RefPtr frame = - mFrameService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, - opcode, maskBit, mask, utf8Data); + mService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, + opcode, maskBit, mask, utf8Data); if (frame) { - mFrameService->FrameReceived(mSerial, mInnerWindowID, frame); + mService->FrameReceived(mSerial, mInnerWindowID, frame); } mTargetThread->Dispatch(new CallOnMessageAvailable(this, utf8Data, -1), @@ -1722,9 +1722,9 @@ WebSocketChannel::ProcessInput(uint8_t *buffer, uint32_t count) } RefPtr frame = - mFrameService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, - opcode, maskBit, mask, payload, - payloadLength); + mService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, + opcode, maskBit, mask, payload, + payloadLength); if (opcode == nsIWebSocketFrame::OPCODE_CLOSE) { LOG(("WebSocketChannel:: close received\n")); @@ -1762,7 +1762,7 @@ WebSocketChannel::ProcessInput(uint8_t *buffer, uint32_t count) if (frame) { // We send the frame immediately becuase we want to have it dispatched // before the CallOnServerClose. - mFrameService->FrameReceived(mSerial, mInnerWindowID, frame); + mService->FrameReceived(mSerial, mInnerWindowID, frame); frame = nullptr; } @@ -1802,7 +1802,7 @@ WebSocketChannel::ProcessInput(uint8_t *buffer, uint32_t count) } if (frame) { - mFrameService->FrameReceived(mSerial, mInnerWindowID, frame); + mService->FrameReceived(mSerial, mInnerWindowID, frame); } } else if (opcode == nsIWebSocketFrame::OPCODE_BINARY) { bool isDeflated = mPMCECompressor && mPMCECompressor->IsMessageDeflated(); @@ -1828,10 +1828,10 @@ WebSocketChannel::ProcessInput(uint8_t *buffer, uint32_t count) } RefPtr frame = - mFrameService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, - opcode, maskBit, mask, binaryData); + mService->CreateFrameIfNeeded(finBit, rsvBit1, rsvBit2, rsvBit3, + opcode, maskBit, mask, binaryData); if (frame) { - mFrameService->FrameReceived(mSerial, mInnerWindowID, frame); + mService->FrameReceived(mSerial, mInnerWindowID, frame); } mTargetThread->Dispatch( @@ -2177,7 +2177,7 @@ WebSocketChannel::PrimeNewOutgoingMessage() // For real data frames we ship the bulk of the payload off to ApplyMask() RefPtr frame = - mFrameService->CreateFrameIfNeeded( + mService->CreateFrameIfNeeded( mOutHeader[0] & WebSocketChannel::kFinalFragBit, mOutHeader[0] & WebSocketChannel::kRsv1Bit, mOutHeader[0] & WebSocketChannel::kRsv2Bit, @@ -2190,7 +2190,7 @@ WebSocketChannel::PrimeNewOutgoingMessage() mCurrentOut->OrigLength()); if (frame) { - mFrameService->FrameSent(mSerial, mInnerWindowID, frame); + mService->FrameSent(mSerial, mInnerWindowID, frame); } while (payload < (mOutHeader + mHdrOutToSend)) { diff --git a/netwerk/protocol/websocket/WebSocketChannel.h b/netwerk/protocol/websocket/WebSocketChannel.h index 6e6218a4936..3fdb1ca0ecd 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.h +++ b/netwerk/protocol/websocket/WebSocketChannel.h @@ -50,7 +50,7 @@ class CallOnMessageAvailable; class CallOnStop; class CallOnServerClose; class CallAcknowledge; -class WebSocketFrameService; +class WebSocketEventService; // Used to enforce "1 connecting websocket per host" rule, and reconnect delays enum wsConnectingState { @@ -227,7 +227,7 @@ private: const static int32_t kLingeringCloseTimeout = 1000; const static int32_t kLingeringCloseThreshold = 50; - RefPtr mFrameService; + RefPtr mService; int32_t mMaxConcurrentConnections; diff --git a/netwerk/protocol/websocket/WebSocketFrameListenerChild.cpp b/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp similarity index 70% rename from netwerk/protocol/websocket/WebSocketFrameListenerChild.cpp rename to netwerk/protocol/websocket/WebSocketEventListenerChild.cpp index 80c54942038..6644b75f2aa 100644 --- a/netwerk/protocol/websocket/WebSocketFrameListenerChild.cpp +++ b/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp @@ -4,26 +4,26 @@ * 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 "WebSocketFrameListenerChild.h" +#include "WebSocketEventListenerChild.h" +#include "WebSocketEventService.h" #include "WebSocketFrame.h" -#include "WebSocketFrameService.h" namespace mozilla { namespace net { -WebSocketFrameListenerChild::WebSocketFrameListenerChild(uint64_t aInnerWindowID) - : mService(WebSocketFrameService::GetOrCreate()) +WebSocketEventListenerChild::WebSocketEventListenerChild(uint64_t aInnerWindowID) + : mService(WebSocketEventService::GetOrCreate()) , mInnerWindowID(aInnerWindowID) {} -WebSocketFrameListenerChild::~WebSocketFrameListenerChild() +WebSocketEventListenerChild::~WebSocketEventListenerChild() { MOZ_ASSERT(!mService); } bool -WebSocketFrameListenerChild::RecvFrameReceived(const uint32_t& aWebSocketSerialID, +WebSocketEventListenerChild::RecvFrameReceived(const uint32_t& aWebSocketSerialID, const WebSocketFrameData& aFrameData) { if (mService) { @@ -35,7 +35,7 @@ WebSocketFrameListenerChild::RecvFrameReceived(const uint32_t& aWebSocketSerialI } bool -WebSocketFrameListenerChild::RecvFrameSent(const uint32_t& aWebSocketSerialID, +WebSocketEventListenerChild::RecvFrameSent(const uint32_t& aWebSocketSerialID, const WebSocketFrameData& aFrameData) { if (mService) { @@ -47,14 +47,14 @@ WebSocketFrameListenerChild::RecvFrameSent(const uint32_t& aWebSocketSerialID, } void -WebSocketFrameListenerChild::Close() +WebSocketEventListenerChild::Close() { mService = nullptr; SendClose(); } void -WebSocketFrameListenerChild::ActorDestroy(ActorDestroyReason aWhy) +WebSocketEventListenerChild::ActorDestroy(ActorDestroyReason aWhy) { mService = nullptr; } diff --git a/netwerk/protocol/websocket/WebSocketFrameListenerChild.h b/netwerk/protocol/websocket/WebSocketEventListenerChild.h similarity index 62% rename from netwerk/protocol/websocket/WebSocketFrameListenerChild.h rename to netwerk/protocol/websocket/WebSocketEventListenerChild.h index 3cfbdb61012..529c87ab02b 100644 --- a/netwerk/protocol/websocket/WebSocketFrameListenerChild.h +++ b/netwerk/protocol/websocket/WebSocketEventListenerChild.h @@ -4,22 +4,22 @@ * 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_net_WebSocketFrameListenerChild_h -#define mozilla_net_WebSocketFrameListenerChild_h +#ifndef mozilla_net_WebSocketEventListenerChild_h +#define mozilla_net_WebSocketEventListenerChild_h -#include "mozilla/net/PWebSocketFrameListenerChild.h" +#include "mozilla/net/PWebSocketEventListenerChild.h" namespace mozilla { namespace net { -class WebSocketFrameService; +class WebSocketEventService; -class WebSocketFrameListenerChild final : public PWebSocketFrameListenerChild +class WebSocketEventListenerChild final : public PWebSocketEventListenerChild { public: - NS_INLINE_DECL_REFCOUNTING(WebSocketFrameListenerChild) + NS_INLINE_DECL_REFCOUNTING(WebSocketEventListenerChild) - explicit WebSocketFrameListenerChild(uint64_t aInnerWindowID); + explicit WebSocketEventListenerChild(uint64_t aInnerWindowID); bool RecvFrameReceived(const uint32_t& aWebSocketSerialID, const WebSocketFrameData& aFrameData) override; @@ -30,15 +30,15 @@ public: void Close(); private: - ~WebSocketFrameListenerChild(); + ~WebSocketEventListenerChild(); virtual void ActorDestroy(ActorDestroyReason aWhy) override; - RefPtr mService; + RefPtr mService; uint64_t mInnerWindowID; }; } // namespace net } // namespace mozilla -#endif // mozilla_net_WebSocketFrameListenerChild_h +#endif // mozilla_net_WebSocketEventListenerChild_h diff --git a/netwerk/protocol/websocket/WebSocketFrameListenerParent.cpp b/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp similarity index 64% rename from netwerk/protocol/websocket/WebSocketFrameListenerParent.cpp rename to netwerk/protocol/websocket/WebSocketEventListenerParent.cpp index 0cc1fcd224b..c13d6f3ff10 100644 --- a/netwerk/protocol/websocket/WebSocketFrameListenerParent.cpp +++ b/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp @@ -4,34 +4,34 @@ * 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 "WebSocketFrameListenerParent.h" +#include "WebSocketEventListenerParent.h" #include "mozilla/unused.h" namespace mozilla { namespace net { -NS_INTERFACE_MAP_BEGIN(WebSocketFrameListenerParent) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketFrameListener) - NS_INTERFACE_MAP_ENTRY(nsIWebSocketFrameListener) +NS_INTERFACE_MAP_BEGIN(WebSocketEventListenerParent) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketEventListener) + NS_INTERFACE_MAP_ENTRY(nsIWebSocketEventListener) NS_INTERFACE_MAP_END -NS_IMPL_ADDREF(WebSocketFrameListenerParent) -NS_IMPL_RELEASE(WebSocketFrameListenerParent) +NS_IMPL_ADDREF(WebSocketEventListenerParent) +NS_IMPL_RELEASE(WebSocketEventListenerParent) -WebSocketFrameListenerParent::WebSocketFrameListenerParent(uint64_t aInnerWindowID) - : mService(WebSocketFrameService::GetOrCreate()) +WebSocketEventListenerParent::WebSocketEventListenerParent(uint64_t aInnerWindowID) + : mService(WebSocketEventService::GetOrCreate()) , mInnerWindowID(aInnerWindowID) { mService->AddListener(mInnerWindowID, this); } -WebSocketFrameListenerParent::~WebSocketFrameListenerParent() +WebSocketEventListenerParent::~WebSocketEventListenerParent() { MOZ_ASSERT(!mService); } bool -WebSocketFrameListenerParent::RecvClose() +WebSocketEventListenerParent::RecvClose() { if (mService) { UnregisterListener(); @@ -42,13 +42,13 @@ WebSocketFrameListenerParent::RecvClose() } void -WebSocketFrameListenerParent::ActorDestroy(ActorDestroyReason aWhy) +WebSocketEventListenerParent::ActorDestroy(ActorDestroyReason aWhy) { UnregisterListener(); } void -WebSocketFrameListenerParent::UnregisterListener() +WebSocketEventListenerParent::UnregisterListener() { if (mService) { mService->RemoveListener(mInnerWindowID, this); @@ -57,7 +57,7 @@ WebSocketFrameListenerParent::UnregisterListener() } NS_IMETHODIMP -WebSocketFrameListenerParent::FrameReceived(uint32_t aWebSocketSerialID, +WebSocketEventListenerParent::FrameReceived(uint32_t aWebSocketSerialID, nsIWebSocketFrame* aFrame) { if (!aFrame) { @@ -70,7 +70,7 @@ WebSocketFrameListenerParent::FrameReceived(uint32_t aWebSocketSerialID, } NS_IMETHODIMP -WebSocketFrameListenerParent::FrameSent(uint32_t aWebSocketSerialID, +WebSocketEventListenerParent::FrameSent(uint32_t aWebSocketSerialID, nsIWebSocketFrame* aFrame) { if (!aFrame) { diff --git a/netwerk/protocol/websocket/WebSocketFrameListenerParent.h b/netwerk/protocol/websocket/WebSocketEventListenerParent.h similarity index 50% rename from netwerk/protocol/websocket/WebSocketFrameListenerParent.h rename to netwerk/protocol/websocket/WebSocketEventListenerParent.h index e02bb13032b..5b5b10d7345 100644 --- a/netwerk/protocol/websocket/WebSocketFrameListenerParent.h +++ b/netwerk/protocol/websocket/WebSocketEventListenerParent.h @@ -4,28 +4,28 @@ * 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_net_WebSocketFrameListenerParent_h -#define mozilla_net_WebSocketFrameListenerParent_h +#ifndef mozilla_net_WebSocketEventListenerParent_h +#define mozilla_net_WebSocketEventListenerParent_h -#include "mozilla/net/PWebSocketFrameListenerParent.h" -#include "nsIWebSocketFrameService.h" +#include "mozilla/net/PWebSocketEventListenerParent.h" +#include "nsIWebSocketEventService.h" namespace mozilla { namespace net { -class WebSocketFrameService; +class WebSocketEventService; -class WebSocketFrameListenerParent final : public PWebSocketFrameListenerParent - , public nsIWebSocketFrameListener +class WebSocketEventListenerParent final : public PWebSocketEventListenerParent + , public nsIWebSocketEventListener { public: NS_DECL_ISUPPORTS - NS_DECL_NSIWEBSOCKETFRAMELISTENER + NS_DECL_NSIWEBSOCKETEVENTLISTENER - explicit WebSocketFrameListenerParent(uint64_t aInnerWindowID); + explicit WebSocketEventListenerParent(uint64_t aInnerWindowID); private: - ~WebSocketFrameListenerParent(); + ~WebSocketEventListenerParent(); virtual bool RecvClose() override; @@ -33,11 +33,11 @@ private: void UnregisterListener(); - RefPtr mService; + RefPtr mService; uint64_t mInnerWindowID; }; } // namespace net } // namespace mozilla -#endif // mozilla_net_WebSocketFrameListenerParent_h +#endif // mozilla_net_WebSocketEventListenerParent_h diff --git a/netwerk/protocol/websocket/WebSocketFrameService.cpp b/netwerk/protocol/websocket/WebSocketEventService.cpp similarity index 78% rename from netwerk/protocol/websocket/WebSocketFrameService.cpp rename to netwerk/protocol/websocket/WebSocketEventService.cpp index f5b2f8f7d79..057e3fd677b 100644 --- a/netwerk/protocol/websocket/WebSocketFrameService.cpp +++ b/netwerk/protocol/websocket/WebSocketEventService.cpp @@ -4,9 +4,9 @@ * 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 "WebSocketEventListenerChild.h" +#include "WebSocketEventService.h" #include "WebSocketFrame.h" -#include "WebSocketFrameListenerChild.h" -#include "WebSocketFrameService.h" #include "mozilla/net/NeckoChild.h" #include "mozilla/StaticPtr.h" @@ -20,7 +20,7 @@ namespace net { namespace { -StaticRefPtr gWebSocketFrameService; +StaticRefPtr gWebSocketEventService; bool IsChildProcess() @@ -47,20 +47,19 @@ public: { MOZ_ASSERT(NS_IsMainThread()); - RefPtr service = - WebSocketFrameService::GetOrCreate(); + RefPtr service = WebSocketEventService::GetOrCreate(); MOZ_ASSERT(service); - WebSocketFrameService::WindowListeners* listeners = + WebSocketEventService::WindowListeners* listeners = service->GetListeners(mInnerWindowID); if (!listeners) { return NS_OK; } nsresult rv; - WebSocketFrameService::WindowListeners::ForwardIterator iter(*listeners); + WebSocketEventService::WindowListeners::ForwardIterator iter(*listeners); while (iter.HasMore()) { - nsCOMPtr listener = iter.GetNext(); + nsCOMPtr listener = iter.GetNext(); if (mFrameSent) { rv = listener->FrameSent(mWebSocketSerialID, mFrame); @@ -86,29 +85,29 @@ protected: bool mFrameSent; }; -/* static */ already_AddRefed -WebSocketFrameService::GetOrCreate() +/* static */ already_AddRefed +WebSocketEventService::GetOrCreate() { MOZ_ASSERT(NS_IsMainThread()); - if (!gWebSocketFrameService) { - gWebSocketFrameService = new WebSocketFrameService(); + if (!gWebSocketEventService) { + gWebSocketEventService = new WebSocketEventService(); } - RefPtr service = gWebSocketFrameService.get(); + RefPtr service = gWebSocketEventService.get(); return service.forget(); } -NS_INTERFACE_MAP_BEGIN(WebSocketFrameService) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketFrameService) +NS_INTERFACE_MAP_BEGIN(WebSocketEventService) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketEventService) NS_INTERFACE_MAP_ENTRY(nsIObserver) - NS_INTERFACE_MAP_ENTRY(nsIWebSocketFrameService) + NS_INTERFACE_MAP_ENTRY(nsIWebSocketEventService) NS_INTERFACE_MAP_END -NS_IMPL_ADDREF(WebSocketFrameService) -NS_IMPL_RELEASE(WebSocketFrameService) +NS_IMPL_ADDREF(WebSocketEventService) +NS_IMPL_RELEASE(WebSocketEventService) -WebSocketFrameService::WebSocketFrameService() +WebSocketEventService::WebSocketEventService() : mCountListeners(0) { MOZ_ASSERT(NS_IsMainThread()); @@ -120,13 +119,13 @@ WebSocketFrameService::WebSocketFrameService() } } -WebSocketFrameService::~WebSocketFrameService() +WebSocketEventService::~WebSocketEventService() { MOZ_ASSERT(NS_IsMainThread()); } void -WebSocketFrameService::FrameReceived(uint32_t aWebSocketSerialID, +WebSocketEventService::FrameReceived(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID, WebSocketFrame* aFrame) { @@ -145,7 +144,7 @@ WebSocketFrameService::FrameReceived(uint32_t aWebSocketSerialID, } void -WebSocketFrameService::FrameSent(uint32_t aWebSocketSerialID, +WebSocketEventService::FrameSent(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID, WebSocketFrame* aFrame) { @@ -165,8 +164,8 @@ WebSocketFrameService::FrameSent(uint32_t aWebSocketSerialID, } NS_IMETHODIMP -WebSocketFrameService::AddListener(uint64_t aInnerWindowID, - nsIWebSocketFrameListener* aListener) +WebSocketEventService::AddListener(uint64_t aInnerWindowID, + nsIWebSocketEventListener* aListener) { MOZ_ASSERT(NS_IsMainThread()); @@ -181,10 +180,10 @@ WebSocketFrameService::AddListener(uint64_t aInnerWindowID, listener = new WindowListener(); if (IsChildProcess()) { - PWebSocketFrameListenerChild* actor = - gNeckoChild->SendPWebSocketFrameListenerConstructor(aInnerWindowID); + PWebSocketEventListenerChild* actor = + gNeckoChild->SendPWebSocketEventListenerConstructor(aInnerWindowID); - listener->mActor = static_cast(actor); + listener->mActor = static_cast(actor); MOZ_ASSERT(listener->mActor); } @@ -197,8 +196,8 @@ WebSocketFrameService::AddListener(uint64_t aInnerWindowID, } NS_IMETHODIMP -WebSocketFrameService::RemoveListener(uint64_t aInnerWindowID, - nsIWebSocketFrameListener* aListener) +WebSocketEventService::RemoveListener(uint64_t aInnerWindowID, + nsIWebSocketEventListener* aListener) { MOZ_ASSERT(NS_IsMainThread()); @@ -231,7 +230,7 @@ WebSocketFrameService::RemoveListener(uint64_t aInnerWindowID, } NS_IMETHODIMP -WebSocketFrameService::Observe(nsISupports* aSubject, const char* aTopic, +WebSocketEventService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { MOZ_ASSERT(NS_IsMainThread()); @@ -269,37 +268,37 @@ WebSocketFrameService::Observe(nsISupports* aSubject, const char* aTopic, } void -WebSocketFrameService::Shutdown() +WebSocketEventService::Shutdown() { MOZ_ASSERT(NS_IsMainThread()); - if (gWebSocketFrameService) { + if (gWebSocketEventService) { nsCOMPtr obs = mozilla::services::GetObserverService(); if (obs) { - obs->RemoveObserver(gWebSocketFrameService, "xpcom-shutdown"); - obs->RemoveObserver(gWebSocketFrameService, "inner-window-destroyed"); + obs->RemoveObserver(gWebSocketEventService, "xpcom-shutdown"); + obs->RemoveObserver(gWebSocketEventService, "inner-window-destroyed"); } mWindows.Clear(); - gWebSocketFrameService = nullptr; + gWebSocketEventService = nullptr; } } bool -WebSocketFrameService::HasListeners() const +WebSocketEventService::HasListeners() const { return !!mCountListeners; } -WebSocketFrameService::WindowListeners* -WebSocketFrameService::GetListeners(uint64_t aInnerWindowID) const +WebSocketEventService::WindowListeners* +WebSocketEventService::GetListeners(uint64_t aInnerWindowID) const { WindowListener* listener = mWindows.Get(aInnerWindowID); return listener ? &listener->mListeners : nullptr; } void -WebSocketFrameService::ShutdownActorListener(WindowListener* aListener) +WebSocketEventService::ShutdownActorListener(WindowListener* aListener) { MOZ_ASSERT(aListener); MOZ_ASSERT(aListener->mActor); @@ -308,7 +307,7 @@ WebSocketFrameService::ShutdownActorListener(WindowListener* aListener) } WebSocketFrame* -WebSocketFrameService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1, +WebSocketEventService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1, bool aRsvBit2, bool aRsvBit3, uint8_t aOpCode, bool aMaskBit, uint32_t aMask, @@ -323,7 +322,7 @@ WebSocketFrameService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1, } WebSocketFrame* -WebSocketFrameService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1, +WebSocketEventService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1, bool aRsvBit2, bool aRsvBit3, uint8_t aOpCode, bool aMaskBit, uint32_t aMask, uint8_t* aPayload, @@ -344,7 +343,7 @@ WebSocketFrameService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1, } WebSocketFrame* -WebSocketFrameService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1, +WebSocketEventService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1, bool aRsvBit2, bool aRsvBit3, uint8_t aOpCode, bool aMaskBit, uint32_t aMask, diff --git a/netwerk/protocol/websocket/WebSocketFrameService.h b/netwerk/protocol/websocket/WebSocketEventService.h similarity index 80% rename from netwerk/protocol/websocket/WebSocketFrameService.h rename to netwerk/protocol/websocket/WebSocketEventService.h index 5e7cd7a3fa6..09ddf710062 100644 --- a/netwerk/protocol/websocket/WebSocketFrameService.h +++ b/netwerk/protocol/websocket/WebSocketEventService.h @@ -4,11 +4,11 @@ * 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_net_WebSocketFrameService_h -#define mozilla_net_WebSocketFrameService_h +#ifndef mozilla_net_WebSocketEventService_h +#define mozilla_net_WebSocketEventService_h #include "mozilla/Atomics.h" -#include "nsIWebSocketFrameService.h" +#include "nsIWebSocketEventService.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsClassHashtable.h" @@ -21,9 +21,9 @@ namespace mozilla { namespace net { class WebSocketFrame; -class WebSocketFrameListenerChild; +class WebSocketEventListenerChild; -class WebSocketFrameService final : public nsIWebSocketFrameService +class WebSocketEventService final : public nsIWebSocketEventService , public nsIObserver { friend class WebSocketFrameRunnable; @@ -31,9 +31,9 @@ class WebSocketFrameService final : public nsIWebSocketFrameService public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER - NS_DECL_NSIWEBSOCKETFRAMESERVICE + NS_DECL_NSIWEBSOCKETEVENTSERVICE - static already_AddRefed GetOrCreate(); + static already_AddRefed GetOrCreate(); void FrameReceived(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID, @@ -60,18 +60,18 @@ public: uint8_t* aPayload, uint32_t aPayloadLength); private: - WebSocketFrameService(); - ~WebSocketFrameService(); + WebSocketEventService(); + ~WebSocketEventService(); bool HasListeners() const; void Shutdown(); - typedef nsTObserverArray> WindowListeners; + typedef nsTObserverArray> WindowListeners; struct WindowListener { WindowListeners mListeners; - RefPtr mActor; + RefPtr mActor; }; WindowListeners* GetListeners(uint64_t aInnerWindowID) const; @@ -86,4 +86,4 @@ private: } // net namespace } // mozilla namespace -#endif // mozilla_net_WebSocketFrameService_h +#endif // mozilla_net_WebSocketEventService_h diff --git a/netwerk/protocol/websocket/WebSocketFrame.h b/netwerk/protocol/websocket/WebSocketFrame.h index 315eb43a3ce..56f1a27e9a7 100644 --- a/netwerk/protocol/websocket/WebSocketFrame.h +++ b/netwerk/protocol/websocket/WebSocketFrame.h @@ -8,7 +8,7 @@ #define mozilla_net_WebSocketFrame_h #include "nsAutoPtr.h" -#include "nsIWebSocketFrameService.h" +#include "nsIWebSocketEventService.h" #include "nsString.h" namespace IPC { diff --git a/netwerk/protocol/websocket/moz.build b/netwerk/protocol/websocket/moz.build index c80e399809d..86848c368ed 100644 --- a/netwerk/protocol/websocket/moz.build +++ b/netwerk/protocol/websocket/moz.build @@ -6,7 +6,7 @@ XPIDL_SOURCES += [ 'nsIWebSocketChannel.idl', - 'nsIWebSocketFrameService.idl', + 'nsIWebSocketEventService.idl', 'nsIWebSocketListener.idl', ] @@ -17,10 +17,10 @@ EXPORTS.mozilla.net += [ 'WebSocketChannel.h', 'WebSocketChannelChild.h', 'WebSocketChannelParent.h', + 'WebSocketEventListenerChild.h', + 'WebSocketEventListenerParent.h', + 'WebSocketEventService.h', 'WebSocketFrame.h', - 'WebSocketFrameListenerChild.h', - 'WebSocketFrameListenerParent.h', - 'WebSocketFrameService.h', ] UNIFIED_SOURCES += [ @@ -28,15 +28,15 @@ UNIFIED_SOURCES += [ 'WebSocketChannel.cpp', 'WebSocketChannelChild.cpp', 'WebSocketChannelParent.cpp', + 'WebSocketEventListenerChild.cpp', + 'WebSocketEventListenerParent.cpp', + 'WebSocketEventService.cpp', 'WebSocketFrame.cpp', - 'WebSocketFrameListenerChild.cpp', - 'WebSocketFrameListenerParent.cpp', - 'WebSocketFrameService.cpp', ] IPDL_SOURCES += [ 'PWebSocket.ipdl', - 'PWebSocketFrameListener.ipdl', + 'PWebSocketEventListener.ipdl', ] include('/ipc/chromium/chromium-config.mozbuild') diff --git a/netwerk/protocol/websocket/nsIWebSocketFrameService.idl b/netwerk/protocol/websocket/nsIWebSocketEventService.idl similarity index 87% rename from netwerk/protocol/websocket/nsIWebSocketFrameService.idl rename to netwerk/protocol/websocket/nsIWebSocketEventService.idl index d32c493da5e..0642fada9d1 100644 --- a/netwerk/protocol/websocket/nsIWebSocketFrameService.idl +++ b/netwerk/protocol/websocket/nsIWebSocketEventService.idl @@ -37,7 +37,7 @@ interface nsIWebSocketFrame : nsISupports }; [scriptable, uuid(f6a7ec44-23b2-4c77-bb94-f11a8df5a874)] -interface nsIWebSocketFrameListener : nsISupports +interface nsIWebSocketEventListener : nsISupports { void frameReceived(in unsigned long aWebSocketSerialID, in nsIWebSocketFrame aFrame); @@ -47,11 +47,11 @@ interface nsIWebSocketFrameListener : nsISupports }; [scriptable, builtinclass, uuid(b89d1b90-2cf3-4d8f-ac21-5aedfb25c760)] -interface nsIWebSocketFrameService : nsISupports +interface nsIWebSocketEventService : nsISupports { void addListener(in unsigned long long aInnerWindowID, - in nsIWebSocketFrameListener aListener); + in nsIWebSocketEventListener aListener); void removeListener(in unsigned long long aInnerWindowID, - in nsIWebSocketFrameListener aListener); + in nsIWebSocketEventListener aListener); }; From f24f602d6221f16e842e7ff1b3e434ef4583639b Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 28 Oct 2015 19:10:42 +0000 Subject: [PATCH 25/95] Bug 1215092 - WebSocketEventService and WebSocket discovering - part 2 - Unique Serial number for WebSocketChannel in IPC, r=michal --- netwerk/ipc/NeckoChild.cpp | 3 +- netwerk/ipc/NeckoChild.h | 3 +- netwerk/ipc/NeckoParent.cpp | 6 ++- netwerk/ipc/NeckoParent.h | 3 +- netwerk/ipc/PNecko.ipdl | 3 +- .../websocket/BaseWebSocketChannel.cpp | 49 +++++++++++++++++++ .../protocol/websocket/BaseWebSocketChannel.h | 4 ++ .../protocol/websocket/WebSocketChannel.cpp | 4 -- netwerk/protocol/websocket/WebSocketChannel.h | 2 - .../websocket/WebSocketChannelChild.cpp | 3 +- .../websocket/WebSocketChannelParent.cpp | 9 +++- .../websocket/WebSocketChannelParent.h | 4 +- .../websocket/nsIWebSocketChannel.idl | 7 ++- 13 files changed, 84 insertions(+), 16 deletions(-) diff --git a/netwerk/ipc/NeckoChild.cpp b/netwerk/ipc/NeckoChild.cpp index 3809d637703..3ceb8bea589 100644 --- a/netwerk/ipc/NeckoChild.cpp +++ b/netwerk/ipc/NeckoChild.cpp @@ -145,7 +145,8 @@ NeckoChild::DeallocPWyciwygChannelChild(PWyciwygChannelChild* channel) PWebSocketChild* NeckoChild::AllocPWebSocketChild(const PBrowserOrId& browser, - const SerializedLoadContext& aSerialized) + const SerializedLoadContext& aSerialized, + const uint32_t& aSerial) { NS_NOTREACHED("AllocPWebSocketChild should not be called"); return nullptr; diff --git a/netwerk/ipc/NeckoChild.h b/netwerk/ipc/NeckoChild.h index 37f03550269..19f481dfe1f 100644 --- a/netwerk/ipc/NeckoChild.h +++ b/netwerk/ipc/NeckoChild.h @@ -40,7 +40,8 @@ protected: virtual bool DeallocPFTPChannelChild(PFTPChannelChild*) override; virtual PWebSocketChild* AllocPWebSocketChild(const PBrowserOrId&, - const SerializedLoadContext&) override; + const SerializedLoadContext&, + const uint32_t&) override; virtual bool DeallocPWebSocketChild(PWebSocketChild*) override; virtual PTCPSocketChild* AllocPTCPSocketChild(const nsString& host, const uint16_t& port) override; diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp index 1bf8c4a2677..85d3eba66a0 100644 --- a/netwerk/ipc/NeckoParent.cpp +++ b/netwerk/ipc/NeckoParent.cpp @@ -320,7 +320,8 @@ NeckoParent::DeallocPWyciwygChannelParent(PWyciwygChannelParent* channel) PWebSocketParent* NeckoParent::AllocPWebSocketParent(const PBrowserOrId& browser, - const SerializedLoadContext& serialized) + const SerializedLoadContext& serialized, + const uint32_t& aSerial) { nsCOMPtr loadContext; const char *error = CreateChannelLoadContext(browser, Manager(), @@ -335,7 +336,8 @@ NeckoParent::AllocPWebSocketParent(const PBrowserOrId& browser, RefPtr tabParent = TabParent::GetFrom(browser.get_PBrowserParent()); PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized); WebSocketChannelParent* p = new WebSocketChannelParent(tabParent, loadContext, - overrideStatus); + overrideStatus, + aSerial); p->AddRef(); return p; } diff --git a/netwerk/ipc/NeckoParent.h b/netwerk/ipc/NeckoParent.h index dbbc525cfd4..c548b1b6e04 100644 --- a/netwerk/ipc/NeckoParent.h +++ b/netwerk/ipc/NeckoParent.h @@ -124,7 +124,8 @@ protected: virtual bool DeallocPFTPChannelParent(PFTPChannelParent*) override; virtual PWebSocketParent* AllocPWebSocketParent(const PBrowserOrId& browser, - const SerializedLoadContext& aSerialized) override; + const SerializedLoadContext& aSerialized, + const uint32_t& aSerial) override; virtual bool DeallocPWebSocketParent(PWebSocketParent*) override; virtual PTCPSocketParent* AllocPTCPSocketParent(const nsString& host, const uint16_t& port) override; diff --git a/netwerk/ipc/PNecko.ipdl b/netwerk/ipc/PNecko.ipdl index 5ea25d72c5d..2e1f2f51829 100644 --- a/netwerk/ipc/PNecko.ipdl +++ b/netwerk/ipc/PNecko.ipdl @@ -68,7 +68,8 @@ parent: PFTPChannel(PBrowserOrId browser, SerializedLoadContext loadContext, FTPChannelCreationArgs args); - PWebSocket(PBrowserOrId browser, SerializedLoadContext loadContext); + PWebSocket(PBrowserOrId browser, SerializedLoadContext loadContext, + uint32_t aSerialID); PTCPServerSocket(uint16_t localPort, uint16_t backlog, bool useArrayBuffers); PUDPSocket(Principal principal, nsCString filter); diff --git a/netwerk/protocol/websocket/BaseWebSocketChannel.cpp b/netwerk/protocol/websocket/BaseWebSocketChannel.cpp index 91eb34f2cbc..dd9136b93aa 100644 --- a/netwerk/protocol/websocket/BaseWebSocketChannel.cpp +++ b/netwerk/protocol/websocket/BaseWebSocketChannel.cpp @@ -14,12 +14,25 @@ #include "nsStandardURL.h" #include "LoadInfo.h" #include "nsIDOMNode.h" +#include "mozilla/dom/ContentChild.h" + +using mozilla::dom::ContentChild; PRLogModuleInfo *webSocketLog = nullptr; namespace mozilla { namespace net { +static uint64_t gNextWebSocketID = 0; + +// We use only 53 bits for the WebSocket serial ID so that it can be converted +// to and from a JS value without loss of precision. The upper bits of the +// WebSocket serial ID hold the process ID. The lower bits identify the +// WebSocket. +static const uint64_t kWebSocketIDTotalBits = 53; +static const uint64_t kWebSocketIDProcessBits = 22; +static const uint64_t kWebSocketIDWebSocketBits = kWebSocketIDTotalBits - kWebSocketIDProcessBits; + BaseWebSocketChannel::BaseWebSocketChannel() : mWasOpened(0) , mClientSetPingInterval(0) @@ -31,6 +44,24 @@ BaseWebSocketChannel::BaseWebSocketChannel() { if (!webSocketLog) webSocketLog = PR_NewLogModule("nsWebSocket"); + + // Generation of a unique serial ID. + uint64_t processID = 0; + if (XRE_IsContentProcess()) { + ContentChild* cc = ContentChild::GetSingleton(); + processID = cc->GetID(); + } + + uint64_t processBits = processID & ((uint64_t(1) << kWebSocketIDProcessBits) - 1); + + // Make sure no actual webSocket ends up with mWebSocketID == 0 but less then + // what the kWebSocketIDProcessBits allows. + if (++gNextWebSocketID >= (uint64_t(1) << kWebSocketIDWebSocketBits)) { + gNextWebSocketID = 1; + } + + uint64_t webSocketBits = gNextWebSocketID & ((uint64_t(1) << kWebSocketIDWebSocketBits) - 1); + mSerial = (processBits << kWebSocketIDWebSocketBits) | webSocketBits; } //----------------------------------------------------------------------------- @@ -197,6 +228,24 @@ BaseWebSocketChannel::InitLoadInfo(nsIDOMNode* aLoadingNode, return NS_OK; } +NS_IMETHODIMP +BaseWebSocketChannel::GetSerial(uint32_t* aSerial) +{ + if (!aSerial) { + return NS_ERROR_FAILURE; + } + + *aSerial = mSerial; + return NS_OK; +} + +NS_IMETHODIMP +BaseWebSocketChannel::SetSerial(uint32_t aSerial) +{ + mSerial = aSerial; + return NS_OK; +} + //----------------------------------------------------------------------------- // BaseWebSocketChannel::nsIProtocolHandler //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/websocket/BaseWebSocketChannel.h b/netwerk/protocol/websocket/BaseWebSocketChannel.h index d9f52864e64..34757d85bbe 100644 --- a/netwerk/protocol/websocket/BaseWebSocketChannel.h +++ b/netwerk/protocol/websocket/BaseWebSocketChannel.h @@ -55,6 +55,8 @@ class BaseWebSocketChannel : public nsIWebSocketChannel, NS_IMETHOD InitLoadInfo(nsIDOMNode* aLoadingNode, nsIPrincipal* aLoadingPrincipal, nsIPrincipal* aTriggeringPrincipal, uint32_t aSecurityFlags, uint32_t aContentPolicyType) override; + NS_IMETHOD GetSerial(uint32_t* aSerial) override; + NS_IMETHOD SetSerial(uint32_t aSerial) override; // Off main thread URI access. virtual void GetEffectiveURL(nsAString& aEffectiveURL) const = 0; @@ -98,6 +100,8 @@ class BaseWebSocketChannel : public nsIWebSocketChannel, uint32_t mPingInterval; /* milliseconds */ uint32_t mPingResponseTimeout; /* milliseconds */ + + uint32_t mSerial; }; } // namespace net diff --git a/netwerk/protocol/websocket/WebSocketChannel.cpp b/netwerk/protocol/websocket/WebSocketChannel.cpp index 0158be5328e..ca850695d8a 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.cpp +++ b/netwerk/protocol/websocket/WebSocketChannel.cpp @@ -1138,8 +1138,6 @@ NS_IMPL_ISUPPORTS(OutboundEnqueuer, nsIRunnable) // WebSocketChannel //----------------------------------------------------------------------------- -uint32_t WebSocketChannel::sSerialSeed = 0; - WebSocketChannel::WebSocketChannel() : mPort(0), mCloseTimeout(20000), @@ -1194,8 +1192,6 @@ WebSocketChannel::WebSocketChannel() : if (NS_FAILED(rv)) LOG(("Failed to initiate dashboard service.")); - mSerial = sSerialSeed++; - mService = WebSocketEventService::GetOrCreate(); } diff --git a/netwerk/protocol/websocket/WebSocketChannel.h b/netwerk/protocol/websocket/WebSocketChannel.h index 3fdb1ca0ecd..de9fed7064c 100644 --- a/netwerk/protocol/websocket/WebSocketChannel.h +++ b/netwerk/protocol/websocket/WebSocketChannel.h @@ -294,8 +294,6 @@ private: bool mPrivateBrowsing; nsCOMPtr mConnectionLogService; - uint32_t mSerial; - static uint32_t sSerialSeed; // These members are used for network per-app metering (bug 855949) // Currently, they are only available on gonk. diff --git a/netwerk/protocol/websocket/WebSocketChannelChild.cpp b/netwerk/protocol/websocket/WebSocketChannelChild.cpp index fafbcc23fae..34f87a9868a 100644 --- a/netwerk/protocol/websocket/WebSocketChannelChild.cpp +++ b/netwerk/protocol/websocket/WebSocketChannelChild.cpp @@ -489,7 +489,8 @@ WebSocketChannelChild::AsyncOpen(nsIURI *aURI, NS_ENSURE_SUCCESS(rv, rv); gNeckoChild->SendPWebSocketConstructor(this, tabChild, - IPC::SerializedLoadContext(this)); + IPC::SerializedLoadContext(this), + mSerial); if (!SendAsyncOpen(uri, nsCString(aOrigin), aInnerWindowID, mProtocol, mEncrypted, mPingInterval, mClientSetPingInterval, mPingResponseTimeout, mClientSetPingTimeout, loadInfoArgs)) { diff --git a/netwerk/protocol/websocket/WebSocketChannelParent.cpp b/netwerk/protocol/websocket/WebSocketChannelParent.cpp index d04b0c7509c..2354703b0fd 100644 --- a/netwerk/protocol/websocket/WebSocketChannelParent.cpp +++ b/netwerk/protocol/websocket/WebSocketChannelParent.cpp @@ -26,10 +26,12 @@ NS_IMPL_ISUPPORTS(WebSocketChannelParent, WebSocketChannelParent::WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider, nsILoadContext* aLoadContext, - PBOverrideStatus aOverrideStatus) + PBOverrideStatus aOverrideStatus, + uint32_t aSerial) : mAuthProvider(aAuthProvider) , mLoadContext(aLoadContext) , mIPCOpen(true) + , mSerial(aSerial) { // Websocket channels can't have a private browsing override MOZ_ASSERT_IF(!aLoadContext, aOverrideStatus == kPBOverride_Unset); @@ -95,6 +97,11 @@ WebSocketChannelParent::RecvAsyncOpen(const URIParams& aURI, if (NS_FAILED(rv)) goto fail; + rv = mChannel->SetSerial(mSerial); + if (NS_WARN_IF(NS_FAILED(rv))) { + goto fail; + } + rv = LoadInfoArgsToLoadInfo(aLoadInfoArgs, getter_AddRefs(loadInfo)); if (NS_FAILED(rv)) goto fail; diff --git a/netwerk/protocol/websocket/WebSocketChannelParent.h b/netwerk/protocol/websocket/WebSocketChannelParent.h index 239e99d74c5..293223f8a67 100644 --- a/netwerk/protocol/websocket/WebSocketChannelParent.h +++ b/netwerk/protocol/websocket/WebSocketChannelParent.h @@ -35,7 +35,8 @@ class WebSocketChannelParent : public PWebSocketParent, WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider, nsILoadContext* aLoadContext, - PBOverrideStatus aOverrideStatus); + PBOverrideStatus aOverrideStatus, + uint32_t aSerial); private: bool RecvAsyncOpen(const URIParams& aURI, @@ -66,6 +67,7 @@ class WebSocketChannelParent : public PWebSocketParent, nsCOMPtr mLoadContext; bool mIPCOpen; + uint32_t mSerial; }; } // namespace net diff --git a/netwerk/protocol/websocket/nsIWebSocketChannel.idl b/netwerk/protocol/websocket/nsIWebSocketChannel.idl index 0adae64404a..10d446bd4d5 100644 --- a/netwerk/protocol/websocket/nsIWebSocketChannel.idl +++ b/netwerk/protocol/websocket/nsIWebSocketChannel.idl @@ -22,7 +22,7 @@ interface nsIPrincipal; * We are also making it scriptable for now, but this may change once we have * WebSockets for Workers. */ -[scriptable, uuid(352e0c08-f14c-40c8-ad06-2f8bb5d9d9e0)] +[scriptable, uuid(1bfc252b-ad46-413c-860b-2079bf1399c7)] interface nsIWebSocketChannel : nsISupports { /** @@ -223,4 +223,9 @@ interface nsIWebSocketChannel : nsISupports */ attribute unsigned long pingTimeout; + /** + * Unique ID for this channel. It's not readonly because when the channel is + * created via IPC, the serial number is received from the child process. + */ + attribute unsigned long serial; }; From 2687f516ac14d27b7f7629b88e26a6cd5660d8c1 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 28 Oct 2015 19:11:05 +0000 Subject: [PATCH 26/95] Bug 1215092 - WebSocketEventService and WebSocket discovering - part 3 - Events, r=michal --- dom/base/WebSocket.cpp | 31 ++- dom/base/test/test_websocket_frame.html | 44 +++- .../websocket/PWebSocketEventListener.ipdl | 14 ++ .../websocket/WebSocketEventListenerChild.cpp | 41 ++++ .../websocket/WebSocketEventListenerChild.h | 14 ++ .../WebSocketEventListenerParent.cpp | 32 +++ .../websocket/WebSocketEventService.cpp | 212 +++++++++++++++--- .../websocket/WebSocketEventService.h | 27 ++- .../websocket/nsIWebSocketChannel.idl | 14 +- .../websocket/nsIWebSocketEventService.idl | 16 +- 10 files changed, 400 insertions(+), 45 deletions(-) diff --git a/dom/base/WebSocket.cpp b/dom/base/WebSocket.cpp index bd3c045abba..56f5a39cc2b 100644 --- a/dom/base/WebSocket.cpp +++ b/dom/base/WebSocket.cpp @@ -37,6 +37,7 @@ #include "nsIStringBundle.h" #include "nsIConsoleService.h" #include "mozilla/dom/CloseEvent.h" +#include "mozilla/net/WebSocketEventService.h" #include "nsICryptoHash.h" #include "nsJSUtils.h" #include "nsIScriptError.h" @@ -240,6 +241,8 @@ public: mozilla::Mutex mMutex; bool mWorkerShuttingDown; + RefPtr mService; + private: ~WebSocketImpl() { @@ -630,11 +633,8 @@ WebSocketImpl::Disconnect() // until the end of the method. RefPtr kungfuDeathGrip = this; - nsCOMPtr mainThread; - if (NS_FAILED(NS_GetMainThread(getter_AddRefs(mainThread))) || - NS_FAILED(NS_ProxyRelease(mainThread, mChannel))) { - NS_WARNING("Failed to proxy release of channel, leaking instead!"); - } + NS_ReleaseOnMainThread(mChannel); + NS_ReleaseOnMainThread(static_cast(mService.forget().take())); mWebSocket->DontKeepAliveAnyMore(); mWebSocket->mImpl = nullptr; @@ -769,6 +769,11 @@ WebSocketImpl::OnStart(nsISupports* aContext) mWebSocket->SetReadyState(WebSocket::OPEN); + mService->WebSocketOpened(mChannel->Serial(),mInnerWindowID, + mWebSocket->mEffectiveURL, + mWebSocket->mEstablishedProtocol, + mWebSocket->mEstablishedExtensions); + // Let's keep the object alive because the webSocket can be CCed in the // onopen callback. RefPtr webSocket = mWebSocket; @@ -1359,6 +1364,12 @@ WebSocket::Constructor(const GlobalObject& aGlobal, return nullptr; } + // Let's inform devtools about this new active WebSocket. + webSocket->mImpl->mService->WebSocketCreated(webSocket->mImpl->mChannel->Serial(), + webSocket->mImpl->mInnerWindowID, + webSocket->mURI, + webSocket->mImpl->mRequestedProtocolList); + cws.Done(); return webSocket.forget(); } @@ -1444,6 +1455,8 @@ WebSocketImpl::Init(JSContext* aCx, AssertIsOnMainThread(); MOZ_ASSERT(aPrincipal); + mService = WebSocketEventService::GetOrCreate(); + // We need to keep the implementation alive in case the init disconnects it // because of some error. RefPtr kungfuDeathGrip = this; @@ -1658,6 +1671,8 @@ WebSocketImpl::AsyncOpen(nsIPrincipal* aPrincipal, uint64_t aInnerWindowID, if (NS_WARN_IF(aRv.Failed())) { return; } + + mInnerWindowID = aInnerWindowID; } //----------------------------------------------------------------------------- @@ -1883,11 +1898,15 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx, nsresult WebSocket::CreateAndDispatchCloseEvent(bool aWasClean, uint16_t aCode, - const nsAString &aReason) + const nsAString& aReason) { MOZ_ASSERT(mImpl); AssertIsOnTargetThread(); + mImpl->mService->WebSocketClosed(mImpl->mChannel->Serial(), + mImpl->mInnerWindowID, + aWasClean, aCode, aReason); + nsresult rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { return NS_OK; diff --git a/dom/base/test/test_websocket_frame.html b/dom/base/test/test_websocket_frame.html index 03db0ecaa55..78c12bd236f 100644 --- a/dom/base/test/test_websocket_frame.html +++ b/dom/base/test/test_websocket_frame.html @@ -12,8 +12,13 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components; +const URI = "ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic"; + var frameReceivedCounter = 0; var frameSentCounter = 0; +var webSocketCreatedCounter = 0; +var webSocketOpenedCounter = 0; +var webSocketClosedCounter = 0; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -35,6 +40,37 @@ ok(!!service, "We have the nsIWebSocketEventService"); var listener = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebSocketEventListener]), + webSocketCreated: function(aWebSocketSerialID, aURI, aProtocols) { + info("WebSocketCreated"); + + is(aURI, URI, "URI matches"); + is(aProtocols, "frame", "Protocol matches"); + + webSocketCreatedCounter++; + }, + + webSocketOpened: function(aWebSocketSerialID, aEffectiveURI, aProtocols, aExtensions) { + info("WebSocketOpened"); + + is(aEffectiveURI, URI, "EffectiveURI matches"); + is(aProtocols, "frame", "Protocol matches"); + is(aExtensions, "permessage-deflate", "No extensions"); + + webSocketOpenedCounter++; + }, + + webSocketClosed: function(aWebSocketSerialID, aWasClean, + aCode, aReason) { + info("WebSocketClosed"); + + ok(aWasClean, "The socket is closed in a clean state"); + is(aCode, 1000, "Exit code 1000"); + ok(!aReason.length, "No reason"); + + webSocketClosedCounter++; + checkListener(); + }, + frameReceived: function(aWebSocketSerialID, aFrame) { ok(!!aFrame, "We have received a frame"); @@ -98,10 +134,13 @@ function checkListener() { ok(frameReceivedCounter, "We received some frames!"); ok(frameSentCounter, "We sent some frames!"); + ok(webSocketCreatedCounter, "We have a create notification"); + ok(webSocketOpenedCounter, "We have a open notification"); + ok(webSocketClosedCounter, "We have a close notification"); SimpleTest.finish(); } -var ws = new WebSocket("ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic", "frame"); +var ws = new WebSocket(URI, "frame"); ws.onopen = function(e) { info("onopen"); @@ -110,9 +149,6 @@ ws.onopen = function(e) { ws.onclose = function(e) { info("onclose"); - - ws.close(); - checkListener(); } ws.onmessage = function(e) { diff --git a/netwerk/protocol/websocket/PWebSocketEventListener.ipdl b/netwerk/protocol/websocket/PWebSocketEventListener.ipdl index dfe2a6c7e51..20e16fa9fd3 100644 --- a/netwerk/protocol/websocket/PWebSocketEventListener.ipdl +++ b/netwerk/protocol/websocket/PWebSocketEventListener.ipdl @@ -17,6 +17,20 @@ async protocol PWebSocketEventListener manager PNecko; child: + WebSocketCreated(uint32_t awebSocketSerialID, + nsString aURI, + nsCString aProtocols); + + WebSocketOpened(uint32_t awebSocketSerialID, + nsString aEffectiveURI, + nsCString aProtocols, + nsCString aExtensions); + + WebSocketClosed(uint32_t awebSocketSerialID, + bool aWasClean, + uint16_t aCode, + nsString aReason); + FrameReceived(uint32_t aWebSocketSerialID, WebSocketFrameData aFrameData); diff --git a/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp b/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp index 6644b75f2aa..691d0fb1dd3 100644 --- a/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp +++ b/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp @@ -22,6 +22,47 @@ WebSocketEventListenerChild::~WebSocketEventListenerChild() MOZ_ASSERT(!mService); } +bool +WebSocketEventListenerChild::RecvWebSocketCreated(const uint32_t& aWebSocketSerialID, + const nsString& aURI, + const nsCString& aProtocols) +{ + if (mService) { + mService->WebSocketCreated(aWebSocketSerialID, mInnerWindowID, aURI, + aProtocols); + } + + return true; +} + +bool +WebSocketEventListenerChild::RecvWebSocketOpened(const uint32_t& aWebSocketSerialID, + const nsString& aEffectiveURI, + const nsCString& aProtocols, + const nsCString& aExtensions) +{ + if (mService) { + mService->WebSocketOpened(aWebSocketSerialID, mInnerWindowID, + aEffectiveURI, aProtocols, aExtensions); + } + + return true; +} + +bool +WebSocketEventListenerChild::RecvWebSocketClosed(const uint32_t& aWebSocketSerialID, + const bool& aWasClean, + const uint16_t& aCode, + const nsString& aReason) +{ + if (mService) { + mService->WebSocketClosed(aWebSocketSerialID, mInnerWindowID, + aWasClean, aCode, aReason); + } + + return true; +} + bool WebSocketEventListenerChild::RecvFrameReceived(const uint32_t& aWebSocketSerialID, const WebSocketFrameData& aFrameData) diff --git a/netwerk/protocol/websocket/WebSocketEventListenerChild.h b/netwerk/protocol/websocket/WebSocketEventListenerChild.h index 529c87ab02b..c8b5ecd3cfe 100644 --- a/netwerk/protocol/websocket/WebSocketEventListenerChild.h +++ b/netwerk/protocol/websocket/WebSocketEventListenerChild.h @@ -21,6 +21,20 @@ public: explicit WebSocketEventListenerChild(uint64_t aInnerWindowID); + bool RecvWebSocketCreated(const uint32_t& aWebSocketSerialID, + const nsString& aURI, + const nsCString& aProtocols) override; + + bool RecvWebSocketOpened(const uint32_t& aWebSocketSerialID, + const nsString& aEffectiveURI, + const nsCString& aProtocols, + const nsCString& aExtensions) override; + + bool RecvWebSocketClosed(const uint32_t& aWebSocketSerialID, + const bool& aWasClean, + const uint16_t& aCode, + const nsString& aReason) override; + bool RecvFrameReceived(const uint32_t& aWebSocketSerialID, const WebSocketFrameData& aFrameData) override; diff --git a/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp b/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp index c13d6f3ff10..79647ef28ef 100644 --- a/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp +++ b/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp @@ -56,6 +56,38 @@ WebSocketEventListenerParent::UnregisterListener() } } +NS_IMETHODIMP +WebSocketEventListenerParent::WebSocketCreated(uint32_t aWebSocketSerialID, + const nsAString& aURI, + const nsACString& aProtocols) +{ + unused << SendWebSocketCreated(aWebSocketSerialID, nsString(aURI), + nsCString(aProtocols)); + return NS_OK; +} + +NS_IMETHODIMP +WebSocketEventListenerParent::WebSocketOpened(uint32_t aWebSocketSerialID, + const nsAString& aEffectiveURI, + const nsACString& aProtocols, + const nsACString& aExtensions) +{ + unused << SendWebSocketOpened(aWebSocketSerialID, nsString(aEffectiveURI), + nsCString(aProtocols), nsCString(aExtensions)); + return NS_OK; +} + +NS_IMETHODIMP +WebSocketEventListenerParent::WebSocketClosed(uint32_t aWebSocketSerialID, + bool aWasClean, + uint16_t aCode, + const nsAString& aReason) +{ + unused << SendWebSocketClosed(aWebSocketSerialID, aWasClean, aCode, + nsString(aReason)); + return NS_OK; +} + NS_IMETHODIMP WebSocketEventListenerParent::FrameReceived(uint32_t aWebSocketSerialID, nsIWebSocketFrame* aFrame) diff --git a/netwerk/protocol/websocket/WebSocketEventService.cpp b/netwerk/protocol/websocket/WebSocketEventService.cpp index 057e3fd677b..8eb55c7872b 100644 --- a/netwerk/protocol/websocket/WebSocketEventService.cpp +++ b/netwerk/protocol/websocket/WebSocketEventService.cpp @@ -30,17 +30,13 @@ IsChildProcess() } // anonymous namespace -class WebSocketFrameRunnable final : public nsRunnable +class WebSocketBaseRunnable : public nsRunnable { public: - WebSocketFrameRunnable(uint32_t aWebSocketSerialID, - uint64_t aInnerWindowID, - WebSocketFrame* aFrame, - bool aFrameSent) + WebSocketBaseRunnable(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID) : mWebSocketSerialID(aWebSocketSerialID) , mInnerWindowID(aInnerWindowID) - , mFrame(aFrame) - , mFrameSent(aFrameSent) {} NS_IMETHOD Run() override @@ -50,41 +46,136 @@ public: RefPtr service = WebSocketEventService::GetOrCreate(); MOZ_ASSERT(service); - WebSocketEventService::WindowListeners* listeners = - service->GetListeners(mInnerWindowID); - if (!listeners) { - return NS_OK; - } + WebSocketEventService::WindowListeners listeners; + service->GetListeners(mInnerWindowID, listeners); - nsresult rv; - WebSocketEventService::WindowListeners::ForwardIterator iter(*listeners); - while (iter.HasMore()) { - nsCOMPtr listener = iter.GetNext(); - - if (mFrameSent) { - rv = listener->FrameSent(mWebSocketSerialID, mFrame); - } else { - rv = listener->FrameReceived(mWebSocketSerialID, mFrame); - } - - NS_WARN_IF(NS_FAILED(rv)); + for (uint32_t i = 0; i < listeners.Length(); ++i) { + DoWork(listeners[i]); } return NS_OK; } protected: - ~WebSocketFrameRunnable() + ~WebSocketBaseRunnable() {} + virtual void DoWork(nsIWebSocketEventListener* aListener) = 0; + uint32_t mWebSocketSerialID; uint64_t mInnerWindowID; +}; + +class WebSocketFrameRunnable final : public WebSocketBaseRunnable +{ +public: + WebSocketFrameRunnable(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + WebSocketFrame* aFrame, + bool aFrameSent) + : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID) + , mFrame(aFrame) + , mFrameSent(aFrameSent) + {} + +private: + virtual void DoWork(nsIWebSocketEventListener* aListener) override + { + nsresult rv; + + if (mFrameSent) { + rv = aListener->FrameSent(mWebSocketSerialID, mFrame); + } else { + rv = aListener->FrameReceived(mWebSocketSerialID, mFrame); + } + + NS_WARN_IF(NS_FAILED(rv)); + } RefPtr mFrame; - bool mFrameSent; }; +class WebSocketCreatedRunnable final : public WebSocketBaseRunnable +{ +public: + WebSocketCreatedRunnable(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsAString& aURI, + const nsACString& aProtocols) + : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID) + , mURI(aURI) + , mProtocols(aProtocols) + {} + +private: + virtual void DoWork(nsIWebSocketEventListener* aListener) override + { + nsresult rv = aListener->WebSocketCreated(mWebSocketSerialID, + mURI, mProtocols); + NS_WARN_IF(NS_FAILED(rv)); + } + + const nsString mURI; + const nsCString mProtocols; +}; + +class WebSocketOpenedRunnable final : public WebSocketBaseRunnable +{ +public: + WebSocketOpenedRunnable(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsAString& aEffectiveURI, + const nsACString& aProtocols, + const nsACString& aExtensions) + : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID) + , mEffectiveURI(aEffectiveURI) + , mProtocols(aProtocols) + , mExtensions(aExtensions) + {} + +private: + virtual void DoWork(nsIWebSocketEventListener* aListener) override + { + nsresult rv = aListener->WebSocketOpened(mWebSocketSerialID, + mEffectiveURI, + mProtocols, + mExtensions); + NS_WARN_IF(NS_FAILED(rv)); + } + + const nsString mEffectiveURI; + const nsCString mProtocols; + const nsCString mExtensions; +}; + +class WebSocketClosedRunnable final : public WebSocketBaseRunnable +{ +public: + WebSocketClosedRunnable(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + bool aWasClean, + uint16_t aCode, + const nsAString& aReason) + : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID) + , mWasClean(aWasClean) + , mCode(aCode) + , mReason(aReason) + {} + +private: + virtual void DoWork(nsIWebSocketEventListener* aListener) override + { + nsresult rv = aListener->WebSocketClosed(mWebSocketSerialID, + mWasClean, mCode, mReason); + NS_WARN_IF(NS_FAILED(rv)); + } + + bool mWasClean; + uint16_t mCode; + const nsString mReason; +}; + /* static */ already_AddRefed WebSocketEventService::GetOrCreate() { @@ -124,6 +215,62 @@ WebSocketEventService::~WebSocketEventService() MOZ_ASSERT(NS_IsMainThread()); } +void +WebSocketEventService::WebSocketCreated(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsAString& aURI, + const nsACString& aProtocols) +{ + // Let's continue only if we have some listeners. + if (!HasListeners()) { + return; + } + + RefPtr runnable = + new WebSocketCreatedRunnable(aWebSocketSerialID, aInnerWindowID, + aURI, aProtocols); + nsresult rv = NS_DispatchToMainThread(runnable); + NS_WARN_IF(NS_FAILED(rv)); +} + +void +WebSocketEventService::WebSocketOpened(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsAString& aEffectiveURI, + const nsACString& aProtocols, + const nsACString& aExtensions) +{ + // Let's continue only if we have some listeners. + if (!HasListeners()) { + return; + } + + RefPtr runnable = + new WebSocketOpenedRunnable(aWebSocketSerialID, aInnerWindowID, + aEffectiveURI, aProtocols, aExtensions); + nsresult rv = NS_DispatchToMainThread(runnable); + NS_WARN_IF(NS_FAILED(rv)); +} + +void +WebSocketEventService::WebSocketClosed(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + bool aWasClean, + uint16_t aCode, + const nsAString& aReason) +{ + // Let's continue only if we have some listeners. + if (!HasListeners()) { + return; + } + + RefPtr runnable = + new WebSocketClosedRunnable(aWebSocketSerialID, aInnerWindowID, + aWasClean, aCode, aReason); + nsresult rv = NS_DispatchToMainThread(runnable); + NS_WARN_IF(NS_FAILED(rv)); +} + void WebSocketEventService::FrameReceived(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID, @@ -290,11 +437,18 @@ WebSocketEventService::HasListeners() const return !!mCountListeners; } -WebSocketEventService::WindowListeners* -WebSocketEventService::GetListeners(uint64_t aInnerWindowID) const +void +WebSocketEventService::GetListeners(uint64_t aInnerWindowID, + WebSocketEventService::WindowListeners& aListeners) const { + aListeners.Clear(); + WindowListener* listener = mWindows.Get(aInnerWindowID); - return listener ? &listener->mListeners : nullptr; + if (!listener) { + return; + } + + aListeners.AppendElements(listener->mListeners); } void diff --git a/netwerk/protocol/websocket/WebSocketEventService.h b/netwerk/protocol/websocket/WebSocketEventService.h index 09ddf710062..571da96614d 100644 --- a/netwerk/protocol/websocket/WebSocketEventService.h +++ b/netwerk/protocol/websocket/WebSocketEventService.h @@ -15,7 +15,7 @@ #include "nsHashKeys.h" #include "nsIObserver.h" #include "nsISupportsImpl.h" -#include "nsTObserverArray.h" +#include "nsTArray.h" namespace mozilla { namespace net { @@ -26,7 +26,7 @@ class WebSocketEventListenerChild; class WebSocketEventService final : public nsIWebSocketEventService , public nsIObserver { - friend class WebSocketFrameRunnable; + friend class WebSocketBaseRunnable; public: NS_DECL_ISUPPORTS @@ -35,6 +35,23 @@ public: static already_AddRefed GetOrCreate(); + void WebSocketCreated(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsAString& aURI, + const nsACString& aProtocols); + + void WebSocketOpened(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsAString& aEffectiveURI, + const nsACString& aProtocols, + const nsACString& aExtensions); + + void WebSocketClosed(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + bool aWasClean, + uint16_t aCode, + const nsAString& aReason); + void FrameReceived(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID, WebSocketFrame* aFrame); @@ -66,7 +83,7 @@ private: bool HasListeners() const; void Shutdown(); - typedef nsTObserverArray> WindowListeners; + typedef nsTArray> WindowListeners; struct WindowListener { @@ -74,7 +91,9 @@ private: RefPtr mActor; }; - WindowListeners* GetListeners(uint64_t aInnerWindowID) const; + void GetListeners(uint64_t aInnerWindowID, + WindowListeners& aListeners) const; + void ShutdownActorListener(WindowListener* aListener); // Used only on the main-thread. diff --git a/netwerk/protocol/websocket/nsIWebSocketChannel.idl b/netwerk/protocol/websocket/nsIWebSocketChannel.idl index 10d446bd4d5..dd6fd46de71 100644 --- a/netwerk/protocol/websocket/nsIWebSocketChannel.idl +++ b/netwerk/protocol/websocket/nsIWebSocketChannel.idl @@ -22,7 +22,7 @@ interface nsIPrincipal; * We are also making it scriptable for now, but this may change once we have * WebSockets for Workers. */ -[scriptable, uuid(1bfc252b-ad46-413c-860b-2079bf1399c7)] +[scriptable, uuid(ce71d028-322a-4105-a947-a894689b52bf)] interface nsIWebSocketChannel : nsISupports { /** @@ -228,4 +228,16 @@ interface nsIWebSocketChannel : nsISupports * created via IPC, the serial number is received from the child process. */ attribute unsigned long serial; + +%{C++ + inline uint32_t Serial() + { + uint32_t serial; + nsresult rv = GetSerial(&serial); + if (NS_WARN_IF(NS_FAILED(rv))) { + return 0; + } + return serial; + } +%} }; diff --git a/netwerk/protocol/websocket/nsIWebSocketEventService.idl b/netwerk/protocol/websocket/nsIWebSocketEventService.idl index 0642fada9d1..f9f07402604 100644 --- a/netwerk/protocol/websocket/nsIWebSocketEventService.idl +++ b/netwerk/protocol/websocket/nsIWebSocketEventService.idl @@ -36,9 +36,23 @@ interface nsIWebSocketFrame : nsISupports const long OPCODE_PONG = 0xA; }; -[scriptable, uuid(f6a7ec44-23b2-4c77-bb94-f11a8df5a874)] +[scriptable, uuid(ccbd96ae-2b7d-42fc-9ee5-116fa8e1723a)] interface nsIWebSocketEventListener : nsISupports { + void webSocketCreated(in unsigned long aWebSocketSerialID, + in AString aURI, + in ACString aProtocols); + + void webSocketOpened(in unsigned long aWebSocketSerialID, + in AString aEffectiveURI, + in ACString aProtocols, + in ACString aExtensions); + + void webSocketClosed(in unsigned long aWebSocketSerialID, + in boolean aWasClean, + in unsigned short aCode, + in AString aReason); + void frameReceived(in unsigned long aWebSocketSerialID, in nsIWebSocketFrame aFrame); From 69adf98a7169914c6530518758e76bc6b32989d9 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 28 Oct 2015 19:11:25 +0000 Subject: [PATCH 27/95] Bug 1215092 - WebSocketEventService and WebSocket discovering - part 4 - MessageAvailable event, r=michal --- dom/base/WebSocket.cpp | 10 +++++ dom/base/test/test_websocket_frame.html | 44 +++++++++---------- .../websocket/PWebSocketEventListener.ipdl | 4 ++ .../websocket/WebSocketEventListenerChild.cpp | 13 ++++++ .../websocket/WebSocketEventListenerChild.h | 4 ++ .../WebSocketEventListenerParent.cpp | 10 +++++ .../websocket/WebSocketEventService.cpp | 42 ++++++++++++++++++ .../websocket/WebSocketEventService.h | 5 +++ .../websocket/nsIWebSocketEventService.idl | 24 ++++++---- 9 files changed, 125 insertions(+), 31 deletions(-) diff --git a/dom/base/WebSocket.cpp b/dom/base/WebSocket.cpp index 56f5a39cc2b..0b233615a2f 100644 --- a/dom/base/WebSocket.cpp +++ b/dom/base/WebSocket.cpp @@ -1852,14 +1852,20 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx, return NS_OK; } + uint16_t messageType = nsIWebSocketEventListener::TYPE_STRING; + // Create appropriate JS object for message JS::Rooted jsData(aCx); if (aIsBinary) { if (mBinaryType == dom::BinaryType::Blob) { + messageType = nsIWebSocketEventListener::TYPE_BLOB; + nsresult rv = nsContentUtils::CreateBlobBuffer(aCx, GetOwner(), aData, &jsData); NS_ENSURE_SUCCESS(rv, rv); } else if (mBinaryType == dom::BinaryType::Arraybuffer) { + messageType = nsIWebSocketEventListener::TYPE_ARRAYBUFFER; + JS::Rooted arrayBuf(aCx); nsresult rv = nsContentUtils::CreateArrayBuffer(aCx, aData, arrayBuf.address()); @@ -1879,6 +1885,10 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx, jsData.setString(jsString); } + mImpl->mService->WebSocketMessageAvailable(mImpl->mChannel->Serial(), + mImpl->mInnerWindowID, + aData, messageType); + // create an event that uses the MessageEvent interface, // which does not bubble, is not cancelable, and has no default action diff --git a/dom/base/test/test_websocket_frame.html b/dom/base/test/test_websocket_frame.html index 78c12bd236f..59ab8590778 100644 --- a/dom/base/test/test_websocket_frame.html +++ b/dom/base/test/test_websocket_frame.html @@ -18,6 +18,7 @@ var frameReceivedCounter = 0; var frameSentCounter = 0; var webSocketCreatedCounter = 0; var webSocketOpenedCounter = 0; +var webSocketMessageAvailableCounter = 0; var webSocketClosedCounter = 0; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -25,7 +26,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); var tests = [ { payload: "Hello world!" }, { payload: (function() { var buffer = ""; for (var i = 0; i < 120; ++i) buffer += i; return buffer; }()) }, - { payload: "end" }, ] var innerId = @@ -59,6 +59,24 @@ var listener = { webSocketOpenedCounter++; }, + webSocketMessageAvailable: function(aWebSocketSerialID, aData, aMessageType) { + info("WebSocketMessageAvailable"); + + if (tests.length) { + is(aData, tests[0].payload, "Message matches!"); + is(aMessageType, Ci.nsIWebSocketEventListener.TYPE_STRING, "The type is 'string'"); + + webSocketMessageAvailableCounter++; + + tests.shift(); + if (tests.length) { + ws.send(tests[0].payload); + } else { + ws.send("end"); + } + } + }, + webSocketClosed: function(aWebSocketSerialID, aWasClean, aCode, aReason) { info("WebSocketClosed"); @@ -84,15 +102,6 @@ var listener = { is(aFrame.maskBit, false, "Checking maskBit"); is(aFrame.mask, 0, "Checking mask"); is(aFrame.payload, tests[0].payload, "Checking payload: " + aFrame.payload); - } else { - ok(aFrame.timeStamp, "Checking timeStamp: " + aFrame.timeStamp); - is(aFrame.finBit, true, "Checking finBit"); - is(aFrame.rsvBit1, false, "Checking rsvBit1"); - is(aFrame.rsvBit2, false, "Checking rsvBit2"); - is(aFrame.rsvBit3, false, "Checking rsvBit3"); - is(aFrame.opCode, aFrame.OPCODE_CLOSE, "Checking opCode"); - is(aFrame.maskBit, false, "Checking maskBit"); - is(aFrame.mask, 0, "Checking mask"); } frameReceivedCounter++; @@ -111,15 +120,6 @@ var listener = { is(aFrame.maskBit, true, "Checking maskBit"); ok(!!aFrame.mask, "Checking mask: " + aFrame.mask); is(aFrame.payload, tests[0].payload, "Checking payload: " + aFrame.payload); - } else { - ok(aFrame.timeStamp, "Checking timeStamp: " + aFrame.timeStamp); - is(aFrame.finBit, true, "Checking finBit"); - is(aFrame.rsvBit1, false, "Checking rsvBit1"); - is(aFrame.rsvBit2, false, "Checking rsvBit2"); - is(aFrame.rsvBit3, false, "Checking rsvBit3"); - is(aFrame.opCode, aFrame.OPCODE_CLOSE, "Checking opCode"); - is(aFrame.maskBit, true, "Checking maskBit"); - ok(!!aFrame.mask, "Checking mask: " + aFrame.mask); } frameSentCounter++; @@ -136,6 +136,7 @@ function checkListener() { ok(frameSentCounter, "We sent some frames!"); ok(webSocketCreatedCounter, "We have a create notification"); ok(webSocketOpenedCounter, "We have a open notification"); + ok(webSocketMessageAvailableCounter, "We have a messageAvailable notification"); ok(webSocketClosedCounter, "We have a close notification"); SimpleTest.finish(); } @@ -153,11 +154,8 @@ ws.onclose = function(e) { ws.onmessage = function(e) { info("onmessage"); - - is(e.data, tests[0].payload, "Wrong data"); - tests.shift(); if (tests.length) { - ws.send(tests[0].payload); + is(e.data, tests[0].payload, "Wrong data"); } } diff --git a/netwerk/protocol/websocket/PWebSocketEventListener.ipdl b/netwerk/protocol/websocket/PWebSocketEventListener.ipdl index 20e16fa9fd3..ef0310d7cb7 100644 --- a/netwerk/protocol/websocket/PWebSocketEventListener.ipdl +++ b/netwerk/protocol/websocket/PWebSocketEventListener.ipdl @@ -26,6 +26,10 @@ child: nsCString aProtocols, nsCString aExtensions); + WebSocketMessageAvailable(uint32_t awebSocketSerialID, + nsCString aData, + uint16_t aMessageType); + WebSocketClosed(uint32_t awebSocketSerialID, bool aWasClean, uint16_t aCode, diff --git a/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp b/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp index 691d0fb1dd3..08a57b817b8 100644 --- a/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp +++ b/netwerk/protocol/websocket/WebSocketEventListenerChild.cpp @@ -49,6 +49,19 @@ WebSocketEventListenerChild::RecvWebSocketOpened(const uint32_t& aWebSocketSeria return true; } +bool +WebSocketEventListenerChild::RecvWebSocketMessageAvailable(const uint32_t& aWebSocketSerialID, + const nsCString& aData, + const uint16_t& aMessageType) +{ + if (mService) { + mService->WebSocketMessageAvailable(aWebSocketSerialID, mInnerWindowID, + aData, aMessageType); + } + + return true; +} + bool WebSocketEventListenerChild::RecvWebSocketClosed(const uint32_t& aWebSocketSerialID, const bool& aWasClean, diff --git a/netwerk/protocol/websocket/WebSocketEventListenerChild.h b/netwerk/protocol/websocket/WebSocketEventListenerChild.h index c8b5ecd3cfe..8a42abac2bd 100644 --- a/netwerk/protocol/websocket/WebSocketEventListenerChild.h +++ b/netwerk/protocol/websocket/WebSocketEventListenerChild.h @@ -30,6 +30,10 @@ public: const nsCString& aProtocols, const nsCString& aExtensions) override; + bool RecvWebSocketMessageAvailable(const uint32_t& aWebSocketSerialID, + const nsCString& aData, + const uint16_t& aMessageType) override; + bool RecvWebSocketClosed(const uint32_t& aWebSocketSerialID, const bool& aWasClean, const uint16_t& aCode, diff --git a/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp b/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp index 79647ef28ef..ef1d57188ee 100644 --- a/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp +++ b/netwerk/protocol/websocket/WebSocketEventListenerParent.cpp @@ -88,6 +88,16 @@ WebSocketEventListenerParent::WebSocketClosed(uint32_t aWebSocketSerialID, return NS_OK; } +NS_IMETHODIMP +WebSocketEventListenerParent::WebSocketMessageAvailable(uint32_t aWebSocketSerialID, + const nsACString& aData, + uint16_t aMessageType) +{ + unused << SendWebSocketMessageAvailable(aWebSocketSerialID, nsCString(aData), + aMessageType); + return NS_OK; +} + NS_IMETHODIMP WebSocketEventListenerParent::FrameReceived(uint32_t aWebSocketSerialID, nsIWebSocketFrame* aFrame) diff --git a/netwerk/protocol/websocket/WebSocketEventService.cpp b/netwerk/protocol/websocket/WebSocketEventService.cpp index 8eb55c7872b..06984e75ef3 100644 --- a/netwerk/protocol/websocket/WebSocketEventService.cpp +++ b/netwerk/protocol/websocket/WebSocketEventService.cpp @@ -149,6 +149,30 @@ private: const nsCString mExtensions; }; +class WebSocketMessageAvailableRunnable final : public WebSocketBaseRunnable +{ +public: + WebSocketMessageAvailableRunnable(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsACString& aData, + uint16_t aMessageType) + : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID) + , mData(aData) + , mMessageType(aMessageType) + {} + +private: + virtual void DoWork(nsIWebSocketEventListener* aListener) override + { + nsresult rv = aListener->WebSocketMessageAvailable(mWebSocketSerialID, + mData, mMessageType); + NS_WARN_IF(NS_FAILED(rv)); + } + + const nsCString mData; + uint16_t mMessageType; +}; + class WebSocketClosedRunnable final : public WebSocketBaseRunnable { public: @@ -252,6 +276,24 @@ WebSocketEventService::WebSocketOpened(uint32_t aWebSocketSerialID, NS_WARN_IF(NS_FAILED(rv)); } +void +WebSocketEventService::WebSocketMessageAvailable(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsACString& aData, + uint16_t aMessageType) +{ + // Let's continue only if we have some listeners. + if (!HasListeners()) { + return; + } + + RefPtr runnable = + new WebSocketMessageAvailableRunnable(aWebSocketSerialID, aInnerWindowID, + aData, aMessageType); + nsresult rv = NS_DispatchToMainThread(runnable); + NS_WARN_IF(NS_FAILED(rv)); +} + void WebSocketEventService::WebSocketClosed(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID, diff --git a/netwerk/protocol/websocket/WebSocketEventService.h b/netwerk/protocol/websocket/WebSocketEventService.h index 571da96614d..2515c05ebf3 100644 --- a/netwerk/protocol/websocket/WebSocketEventService.h +++ b/netwerk/protocol/websocket/WebSocketEventService.h @@ -46,6 +46,11 @@ public: const nsACString& aProtocols, const nsACString& aExtensions); + void WebSocketMessageAvailable(uint32_t aWebSocketSerialID, + uint64_t aInnerWindowID, + const nsACString& aData, + uint16_t aMessageType); + void WebSocketClosed(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID, bool aWasClean, diff --git a/netwerk/protocol/websocket/nsIWebSocketEventService.idl b/netwerk/protocol/websocket/nsIWebSocketEventService.idl index f9f07402604..c2986dc2f05 100644 --- a/netwerk/protocol/websocket/nsIWebSocketEventService.idl +++ b/netwerk/protocol/websocket/nsIWebSocketEventService.idl @@ -6,7 +6,7 @@ #include "domstubs.idl" #include "nsISupports.idl" -[scriptable, builtinclass, uuid(470133f3-a04f-48a9-82bd-8d1bc7eb6f9c)] +[scriptable, builtinclass, uuid(6714a6be-2265-4f73-a988-d78a12416037)] interface nsIWebSocketFrame : nsISupports { readonly attribute DOMHighResTimeStamp timeStamp; @@ -26,17 +26,17 @@ interface nsIWebSocketFrame : nsISupports readonly attribute ACString payload; // Non-Control opCode values: - const long OPCODE_CONTINUATION = 0x0; - const long OPCODE_TEXT = 0x1; - const long OPCODE_BINARY = 0x2; + const unsigned short OPCODE_CONTINUATION = 0x0; + const unsigned short OPCODE_TEXT = 0x1; + const unsigned short OPCODE_BINARY = 0x2; // Control opCode values: - const long OPCODE_CLOSE = 0x8; - const long OPCODE_PING = 0x9; - const long OPCODE_PONG = 0xA; + const unsigned short OPCODE_CLOSE = 0x8; + const unsigned short OPCODE_PING = 0x9; + const unsigned short OPCODE_PONG = 0xA; }; -[scriptable, uuid(ccbd96ae-2b7d-42fc-9ee5-116fa8e1723a)] +[scriptable, uuid(e7c005ab-e694-489b-b741-96db43ffb16f)] interface nsIWebSocketEventListener : nsISupports { void webSocketCreated(in unsigned long aWebSocketSerialID, @@ -48,6 +48,14 @@ interface nsIWebSocketEventListener : nsISupports in ACString aProtocols, in ACString aExtensions); + const unsigned short TYPE_STRING = 0x0; + const unsigned short TYPE_BLOB = 0x1; + const unsigned short TYPE_ARRAYBUFFER = 0x2; + + void webSocketMessageAvailable(in unsigned long aWebSocketSerialID, + in ACString aMessage, + in unsigned short aType); + void webSocketClosed(in unsigned long aWebSocketSerialID, in boolean aWasClean, in unsigned short aCode, From c364b921351b761e26351d8130dcec9ef11ff72b Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Wed, 28 Oct 2015 15:27:35 -0400 Subject: [PATCH 28/95] Bug 1218618 - Assert that the hit-testing tree's root node doesn't have siblings. r=kats --- gfx/layers/apz/src/APZCTreeManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 276ed3f5289..9344942925e 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -190,6 +190,9 @@ APZCTreeManager::UpdateHitTestingTree(CompositorParent* aCompositor, mApzcTreeLog << "[end]\n"; } + // We do not support tree structures where the root node has siblings. + MOZ_ASSERT(!(mRootNode && mRootNode->GetPrevSibling())); + for (size_t i = 0; i < state.mNodesToDestroy.Length(); i++) { APZCTM_LOG("Destroying node at %p with APZC %p\n", state.mNodesToDestroy[i].get(), From f12f90789bb250dba53291cef5b7db6a90a88ecb Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 28 Oct 2015 15:39:13 -0400 Subject: [PATCH 29/95] Bug 1219391 - Request snapping for the entire handoff chain when ending the fling animation. r=botond --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 38f7ecf1c5e..64cf4d6326d 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1318,7 +1318,6 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) // previous overscroll pan. Make sure to snap back in this situation. if (!SnapBackIfOverscrolled()) { SetState(NOTHING); - RequestSnap(); } return nsEventStatus_eIgnore; @@ -2687,6 +2686,9 @@ bool AsyncPanZoomController::SnapBackIfOverscrolled() { StartOverscrollAnimation(ParentLayerPoint(0, 0)); return true; } + // If we don't kick off an overscroll animation, we still need to ask the + // main thread to snap to any nearby snap points. + RequestSnap(); return false; } From 91289ce9212f2dc9adf137a14b0bcfe74879bfdb Mon Sep 17 00:00:00 2001 From: Eric Faust Date: Wed, 28 Oct 2015 13:01:06 -0700 Subject: [PATCH 30/95] Bug 1215889 - Fix tests for uplift. (r=jorendorff) --- .../ecma_6/Class/derivedConstructorInlining.js | 7 +++++++ .../Class/derivedConstructorReturnPrimitive.js | 7 +++++++ .../Class/derivedConstructorTDZExplicitThis.js | 13 +++++++------ .../ecma_6/Class/derivedConstructorTDZOffEdge.js | 7 +++++++ .../Class/derivedConstructorTDZReturnObject.js | 7 +++++++ .../Class/derivedConstructorTDZReturnUndefined.js | 7 +++++++ 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/js/src/tests/ecma_6/Class/derivedConstructorInlining.js b/js/src/tests/ecma_6/Class/derivedConstructorInlining.js index 387ea1d6936..f0c35d334d8 100644 --- a/js/src/tests/ecma_6/Class/derivedConstructorInlining.js +++ b/js/src/tests/ecma_6/Class/derivedConstructorInlining.js @@ -1,3 +1,5 @@ +var test = ` + // Since we (for now!) can't emit jitcode for derived class statements. Make // sure we can correctly invoke derived class constructors. @@ -15,5 +17,10 @@ function intermediate() { for (let i = 0; i < 1100; i++) assertThrownErrorContains(intermediate, "|this|"); +`; + +if (classesEnabled()) + eval(test); + if (typeof reportCompare === 'function') reportCompare(0,0,"OK"); diff --git a/js/src/tests/ecma_6/Class/derivedConstructorReturnPrimitive.js b/js/src/tests/ecma_6/Class/derivedConstructorReturnPrimitive.js index 8b1594fa812..2b16333883e 100644 --- a/js/src/tests/ecma_6/Class/derivedConstructorReturnPrimitive.js +++ b/js/src/tests/ecma_6/Class/derivedConstructorReturnPrimitive.js @@ -1,3 +1,5 @@ +var test = ` + class foo extends null { constructor() { // Returning a primitive is a TypeError in derived constructors. This @@ -11,5 +13,10 @@ class foo extends null { for (let i = 0; i < 1100; i++) assertThrownErrorContains(() => new foo(), "return"); +`; + +if (classesEnabled()) + eval(test); + if (typeof reportCompare === 'function') reportCompare(0,0,"OK"); diff --git a/js/src/tests/ecma_6/Class/derivedConstructorTDZExplicitThis.js b/js/src/tests/ecma_6/Class/derivedConstructorTDZExplicitThis.js index 8ef9e48eea4..eb1ffa48df6 100644 --- a/js/src/tests/ecma_6/Class/derivedConstructorTDZExplicitThis.js +++ b/js/src/tests/ecma_6/Class/derivedConstructorTDZExplicitThis.js @@ -1,12 +1,8 @@ -function pleaseRunMyCode() { } +var test = ` class foo extends null { constructor() { - // Just bareword |this| is DCEd by the BytecodeEmitter. Your guess as - // to why we think this is a good idea is as good as mine. In order to - // combat this inanity, make it a function arg, so we have to compute - // it. - pleaseRunMyCode(this); + this; assertEq(false, true); } } @@ -14,5 +10,10 @@ class foo extends null { for (let i = 0; i < 1100; i++) assertThrownErrorContains(() => new foo(), "|this|"); +`; + +if (classesEnabled()) + eval(test); + if (typeof reportCompare === 'function') reportCompare(0,0,"OK"); diff --git a/js/src/tests/ecma_6/Class/derivedConstructorTDZOffEdge.js b/js/src/tests/ecma_6/Class/derivedConstructorTDZOffEdge.js index 145b12d2a11..20835cb29ab 100644 --- a/js/src/tests/ecma_6/Class/derivedConstructorTDZOffEdge.js +++ b/js/src/tests/ecma_6/Class/derivedConstructorTDZOffEdge.js @@ -1,3 +1,5 @@ +var test = ` + class foo extends null { constructor() { // Let it fall off the edge and throw. @@ -7,5 +9,10 @@ class foo extends null { for (let i = 0; i < 1100; i++) assertThrownErrorContains(() => new foo(), "|this|"); +`; + +if (classesEnabled()) + eval(test); + if (typeof reportCompare === 'function') reportCompare(0,0,"OK"); diff --git a/js/src/tests/ecma_6/Class/derivedConstructorTDZReturnObject.js b/js/src/tests/ecma_6/Class/derivedConstructorTDZReturnObject.js index 48206a881e1..ab60cb3ce07 100644 --- a/js/src/tests/ecma_6/Class/derivedConstructorTDZReturnObject.js +++ b/js/src/tests/ecma_6/Class/derivedConstructorTDZReturnObject.js @@ -1,3 +1,5 @@ +var test = ` + class foo extends null { constructor() { // If you return an object, we don't care that |this| went @@ -9,5 +11,10 @@ class foo extends null { for (let i = 0; i < 1100; i++) new foo(); +`; + +if (classesEnabled()) + eval(test); + if (typeof reportCompare === 'function') reportCompare(0,0,"OK"); diff --git a/js/src/tests/ecma_6/Class/derivedConstructorTDZReturnUndefined.js b/js/src/tests/ecma_6/Class/derivedConstructorTDZReturnUndefined.js index ab31b7aedd2..de94f7010ce 100644 --- a/js/src/tests/ecma_6/Class/derivedConstructorTDZReturnUndefined.js +++ b/js/src/tests/ecma_6/Class/derivedConstructorTDZReturnUndefined.js @@ -1,3 +1,5 @@ +var test = ` + class foo extends null { constructor() { // Explicit returns of undefined should act the same as falling off the @@ -9,5 +11,10 @@ class foo extends null { for (let i = 0; i < 1100; i++) assertThrownErrorContains(() => new foo(), "|this|"); +`; + +if (classesEnabled()) + eval(test); + if (typeof reportCompare === 'function') reportCompare(0,0,"OK"); From 04d3e9e653ed688f65b03dc418c286b312489c50 Mon Sep 17 00:00:00 2001 From: Eric Faust Date: Wed, 28 Oct 2015 13:01:07 -0700 Subject: [PATCH 31/95] Bug 1201460 - Follow up: Ensure added classes tests are safe for uplift. (rs=jorendorff) --- js/src/jit-test/tests/asm.js/testBasic.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/js/src/jit-test/tests/asm.js/testBasic.js b/js/src/jit-test/tests/asm.js/testBasic.js index e1656d2da41..d3a09522139 100644 --- a/js/src/jit-test/tests/asm.js/testBasic.js +++ b/js/src/jit-test/tests/asm.js/testBasic.js @@ -1,6 +1,7 @@ // |jit-test| test-also-noasmjs load(libdir + "asm.js"); load(libdir + "asserts.js"); +load(libdir + "class.js"); assertAsmTypeFail(USE_ASM); assertAsmTypeFail(USE_ASM + 'return'); @@ -131,10 +132,12 @@ assertTypeFailInEval('function f(global, {imports}) { "use asm"; function g() {} assertTypeFailInEval('function f(g = 2) { "use asm"; function g() {} return g }'); assertTypeFailInEval('function *f() { "use asm"; function g() {} return g }'); assertTypeFailInEval('f => { "use asm"; function g() {} return g }'); -assertTypeFailInEval('class f { constructor() {"use asm"; return {}} }'); assertTypeFailInEval('var f = { method() {"use asm"; return {}} }'); -assertAsmTypeFail(USE_ASM + 'class c { constructor() {}}; return c;'); assertAsmTypeFail(USE_ASM + 'return {m() {}};'); +if (classesEnabled()) { + assertTypeFailInEval('class f { constructor() {"use asm"; return {}} }'); + assertAsmTypeFail(USE_ASM + 'class c { constructor() {}}; return c;'); +} assertAsmTypeFail(USE_ASM + 'function f(i) {i=i|0; (i for (x in [1,2,3])) } return f'); assertAsmTypeFail(USE_ASM + 'function f(i) {i=i|0; [i for (x in [1,2,3])] } return f'); From 2e6dc50cd9da8ba8ce1433074eaa48b1605aa247 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 28 Oct 2015 13:42:16 -0700 Subject: [PATCH 32/95] Bug 1219419 - Keep DefaultTracer simple for now; r=fitzgen --- js/public/TracingAPI.h | 21 +++++++++------------ js/src/ds/TraceableFifo.h | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/js/public/TracingAPI.h b/js/public/TracingAPI.h index 1484f530727..c18d2552914 100644 --- a/js/public/TracingAPI.h +++ b/js/public/TracingAPI.h @@ -370,22 +370,15 @@ JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc, namespace js { // Automates static dispatch for tracing for TraceableContainers. -template struct DefaultTracer; - -// The default for POD, non-pointer types is to do nothing. -template -struct DefaultTracer::value && - mozilla::IsPod::value>::Type> { - static void trace(JSTracer* trc, T* t, const char* name) { - MOZ_ASSERT(mozilla::IsPod::value); - MOZ_ASSERT(!mozilla::IsPointer::value); - } -}; +template struct DefaultTracer; // The default for non-pod (e.g. struct) types is to call the trace method. template -struct DefaultTracer::value>::Type> { +struct DefaultTracer { static void trace(JSTracer* trc, T* t, const char* name) { + // If your build is failing here, it means you either need an + // implementation of DefaultTracer for your type or, for container + // and structure types that contain GC pointers, a trace method. t->trace(trc); } }; @@ -398,6 +391,10 @@ struct DefaultTracer } }; +template <> struct DefaultTracer { + static void trace(JSTracer* trc, uint32_t* id, const char* name) {} +}; + } // namespace js #endif /* js_TracingAPI_h */ diff --git a/js/src/ds/TraceableFifo.h b/js/src/ds/TraceableFifo.h index 7edcf2975fe..2ac1390e977 100644 --- a/js/src/ds/TraceableFifo.h +++ b/js/src/ds/TraceableFifo.h @@ -12,7 +12,7 @@ namespace js { -template struct DefaultTracer; +template struct DefaultTracer; // A TraceableFifo is a Fifo with an additional trace method that knows how to // visit all of the items stored in the Fifo. For Fifos that contain GC things, From 3cb4578dbb431f6e7d413f3d8f54757004a94cf6 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Wed, 28 Oct 2015 13:43:59 -0700 Subject: [PATCH 33/95] Backed out changeset 71cb0cec8da0 (bug 1219085) for wpt orange --- .../web-platform/mozilla/meta/MANIFEST.json | 6 - .../fetch-request-redirect.https.html | 175 ------------------ .../service-worker/resources/dummy.html | 2 - .../fetch-request-redirect-iframe.html | 35 ---- .../service-worker/resources/silence.oga | Bin 12983 -> 0 bytes .../service-worker/resources/square.png | Bin 18299 -> 0 bytes 6 files changed, 218 deletions(-) delete mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-request-redirect.https.html delete mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.html delete mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html delete mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/silence.oga delete mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/square.png diff --git a/testing/web-platform/mozilla/meta/MANIFEST.json b/testing/web-platform/mozilla/meta/MANIFEST.json index 8560b3788cf..66b89e3add3 100644 --- a/testing/web-platform/mozilla/meta/MANIFEST.json +++ b/testing/web-platform/mozilla/meta/MANIFEST.json @@ -211,12 +211,6 @@ "url": "/_mozilla/service-workers/service-worker/fetch-request-no-freshness-headers.https.html" } ], - "service-workers/service-worker/fetch-request-redirect.https.html": [ - { - "path": "service-workers/service-worker/fetch-request-redirect.https.html", - "url": "/_mozilla/service-workers/service-worker/fetch-request-redirect.https.html" - } - ], "service-workers/service-worker/fetch-request-resources.https.html": [ { "path": "service-workers/service-worker/fetch-request-resources.https.html", diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-request-redirect.https.html b/testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-request-redirect.https.html deleted file mode 100644 index bda8f4f4a45..00000000000 --- a/testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-request-redirect.https.html +++ /dev/null @@ -1,175 +0,0 @@ - -Service Worker: FetchEvent for resources - - - - - diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.html b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.html deleted file mode 100644 index 12a179980df..00000000000 --- a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.html +++ /dev/null @@ -1,2 +0,0 @@ - -Hello world diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html deleted file mode 100644 index ffd76bfc499..00000000000 --- a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/fetch-request-redirect-iframe.html +++ /dev/null @@ -1,35 +0,0 @@ - diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/silence.oga b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/silence.oga deleted file mode 100644 index af591880436af43abb4cee59fde320081bcac7ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12983 zcmaiabzD?!*Y1Fl0wR(MNOw01(%nOMHzP3vNaF({-8sO}AVWzDNJw``w{(L@mz<5y z`+e^@f1Ufc_nte}UbEu5*IsMSsM*?Tf>1&KY2$DI?WE+oG^0?WcsRRR*h3$tP^3%$ zT`}AJ_wy@?+QXgy+aB&j0Y>fzZtrlF?*H5R9{tOO0$9|ucd_G8bF-y#vbWIr%bQAp ziie9!h?|>7@Zs(kz$v3Dr6w%{7PYZ~xLDir!0fD@-OSm!IC%I_(EerhN>WM(phf|a zT52)Nrh$JbhLJ%NxnYDM-2`sMFsJIK##MTqF0%sX@%o06^Q?m0It9Xf!bUM z72*i{D(RGduqlm8YiRpT3TSJeyBkkG98`Q(L=RlW<%`k^UQo5;Sdn7l>Z5_E0OQFr zwc|hfAM=1Ln1n+aYBqhL(LpxCb}U_+Fc+H1O@((Xo0}QXVPVE}Xt&T-1~lBwhT9IH z%YYID*)adxLv(IRI3geBx`m5^TxCfCI(W^dgoD5oFh^WdDD1$|1@ve(HWeTolR$4+ z7$Et3L6Q_fT~r@9=bmpGyptpWdT+^!e4vsKbN{9L*F1o}5~Knlu0>SxS$Q8wWkT(H z^D!3lI_T_h+^~z~^77)qyHtr<-3rW^|7wm20#OGOg5{|{{^t@(9YSi+%UqQ44>n72 zer`BVKU?)6&%ncF?@RUY>wT_Hd?}o=8UiJi+DSdjvWBe;N4y^f_GPtGip&Lomzn?C zFA#7KCYe>NgzN+7Q0l@Aw|?f&*{FZb2`oPB5|KWrv>fceM-Nm)E>T(mIBJv!CY05P zv?r5{4X3OZ&mra{9*Y<5%NOoz(;v(?6V z*Fk2dAg0NXu{&|tD-yzv@IW=7;J)nsxJWnWkO+KDZ zAvs?Gv7w)9<4|bpjr@%Imqh%5WGtqpPu9m<)~tM(ep|9=O^ zUx3GgK%;TweR1Rfz!iWF%3tdOdjS>Xg3}WVfF3~ne{@tk1q^CDhW39u00iQq>j1OK zLHQICwUlbLRBE-9h_uzT|9_2NWt>k1Ff2W=>p*Q5QQtSHsOjl9mhjv06A;`C)U_tm zkK^K(xY3D%5Ing!ZcCDD_(7C_(Vl^%0nNLqdhnsW!g9q41j1XNVTmuc$P1#uw#;3r z7DG%)GvLxFXf#-^EHBZ5jol*=997&6paqp2IN5>$@gIXUK%ii5dFFgVi%8+345>)w ztyE|T_a-?sT6ilP24>mHfT=2Wk^;k`3@G?DV-i$Vkue9r2M7Z=pX7|j5}}A^fC44r zMbv)tX(aNg5z1)7j5YX-r+VBFzv-;$oz$|A+d*sHe^xDcwSI@`rLT-+)sbX-SW4H_L=gyyXZK~deR+Y z=x%I$p{$v#GM!{S?hctxvNra#p1t57hZ&D+ThGFbXFaTS>y7o#{l?utE+<)=>RRiQ zdKh1PG@MS_fEh39TI&kx0IP=6A6KT_&C^8Gv;oe>BYeiX?#8CN#?w>$N2Wd=H%G1&no*A2{nKyD!23Vr%_NZQXNs{pqBYDaeYT@$`kZ{`p5>^?`GP zyD{lo?K3}3kB=)b>*eW>%lhw(g_6hI{mhdfD|*)Y!u~6I$%_|B)&MI#$SkRjK5>ZY zW#-1Y-`ab3W3qRPTZ4^9I6X)CH~r(25X&^bMSUAn&*&A>*R8+SijfuR<*YbGY)@Jb z_PVQYTB;(;_im8DkY&ETa_J>oGrZ&*`K_Xh6Fh8h9MmPa(0+Q+QT0>v!@rb z43tA|TK4*@-XW1r0O!32A)N+Vj{1>@e-->IMiu*f)zLsz>CImSAH+a%3{*j0Ry*A^ z+QI)L70Y}T`%NPt)lq-Ba|yC^?_qd&UGB2i$n~wt=>}PP-N-uM=)A`>f9@v@Kv0t( zG7sz%0D|Y%z|PpA_U!H#Gk5TOtdw`Q`L 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 diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/square.png b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/square.png deleted file mode 100644 index 01c9666a8de9d5535615aff830810e5df4b2156f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18299 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 bDgs((CoOJ&@$4~l+kmsZyIqm(x-I_(KvUo& From d02d49de975e469c0ac08c397eb82bad922ac884 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 28 Oct 2015 14:37:54 -0700 Subject: [PATCH 34/95] Bug 932517 - Followup: remove let-block logic in sloppy mode ES6 let declaration check. (rs=evilpie) --- js/src/frontend/Parser.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 00eff936681..8e1438d3d4a 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -6678,18 +6678,10 @@ Parser::shouldParseLetDeclaration(bool* parseDeclOut) case TOK_LC: case TOK_LB: - // A following name is always a declaration. - // // |let {| and |let [| are destructuring declarations. *parseDeclOut = true; break; - case TOK_LP: - // Only parse let blocks for 1.7 and 1.8. Do not expose deprecated let - // blocks to content. - *parseDeclOut = versionNumber() == JSVERSION_1_7 || versionNumber() == JSVERSION_1_8; - break; - default: break; } From cf8a49f17d9a56ce352d0b0ae11aac6a2f54526e Mon Sep 17 00:00:00 2001 From: Sean Stangl Date: Mon, 26 Oct 2015 15:11:40 -0700 Subject: [PATCH 35/95] Bug 1218587 - Add -G option for running jit-tests under rr. r=terrence --- js/src/jit-test/jit_test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/js/src/jit-test/jit_test.py b/js/src/jit-test/jit_test.py index 15da4c4e3fd..c2f9f7f421b 100755 --- a/js/src/jit-test/jit_test.py +++ b/js/src/jit-test/jit_test.py @@ -81,6 +81,8 @@ def main(argv): help='Retest using test list file [FILE]') op.add_option('-g', '--debug', action='store_const', const='gdb', dest='debugger', help='Run a single test under the gdb debugger') + op.add_option('-G', '--debug-rr', action='store_const', const='rr', dest='debugger', + help='Run a single test under the rr debugger') op.add_option('--debugger', type='string', help='Run a single test under the specified debugger') op.add_option('--valgrind', dest='valgrind', action='store_true', @@ -266,11 +268,15 @@ def main(argv): debug_cmd = ['gdb', '--args'] elif options.debugger == 'lldb': debug_cmd = ['lldb', '--'] + elif options.debugger == 'rr': + debug_cmd = ['rr', 'record'] else: debug_cmd = options.debugger.split() with change_env(test_environment): subprocess.call(debug_cmd + tc.command(prefix, jittests.LIB_DIR)) + if options.debugger == 'rr': + subprocess.call(['rr', 'replay']) sys.exit() try: From e37869515f137af63ae190669b90014db4f1ac13 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Thu, 15 Oct 2015 16:59:11 -0700 Subject: [PATCH 36/95] Bug 1215752 - Weakmap refactoring, r=terrence --- js/src/gc/Marking.cpp | 39 ++++----- js/src/gc/Marking.h | 4 +- js/src/jsweakmap.cpp | 31 +------ js/src/jsweakmap.h | 188 +++++++++++++++++++++--------------------- 4 files changed, 118 insertions(+), 144 deletions(-) diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index fdc3cc4375d..2d3d5ef4c3d 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -580,23 +580,23 @@ DispatchToTracer(JSTracer* trc, T* thingp, const char* name) namespace js { -typedef bool DoNothingMarkingType; +typedef bool HasNoImplicitEdgesType; template -struct LinearlyMarkedEphemeronKeyType { - typedef DoNothingMarkingType Type; +struct ImplicitEdgeHolderType { + typedef HasNoImplicitEdgesType Type; }; -// For now, we only handle JSObject* keys, but the linear time algorithm can be -// easily extended by adding in more types here, then making +// For now, we only handle JSObject* and JSScript* keys, but the linear time +// algorithm can be easily extended by adding in more types here, then making // GCMarker::traverse call markPotentialEphemeronKey. template <> -struct LinearlyMarkedEphemeronKeyType { +struct ImplicitEdgeHolderType { typedef JSObject* Type; }; template <> -struct LinearlyMarkedEphemeronKeyType { +struct ImplicitEdgeHolderType { typedef JSScript* Type; }; @@ -605,7 +605,7 @@ GCMarker::markEphemeronValues(gc::Cell* markedCell, WeakEntryVector& values) { size_t initialLen = values.length(); for (size_t i = 0; i < initialLen; i++) - values[i].weakmap->maybeMarkEntry(this, markedCell, values[i].key); + values[i].weakmap->traceEntry(this, markedCell, values[i].key); // The vector should not be appended to during iteration because the key is // already marked, and even in cases where we have a multipart key, we @@ -615,7 +615,7 @@ GCMarker::markEphemeronValues(gc::Cell* markedCell, WeakEntryVector& values) template void -GCMarker::markPotentialEphemeronKeyHelper(T markedThing) +GCMarker::markImplicitEdgesHelper(T markedThing) { if (!isWeakMarkingTracer()) return; @@ -623,25 +623,26 @@ GCMarker::markPotentialEphemeronKeyHelper(T markedThing) MOZ_ASSERT(gc::TenuredCell::fromPointer(markedThing)->zone()->isGCMarking()); MOZ_ASSERT(!gc::TenuredCell::fromPointer(markedThing)->zone()->isGCSweeping()); - auto weakValues = weakKeys.get(JS::GCCellPtr(markedThing)); - if (!weakValues) + auto p = weakKeys.get(JS::GCCellPtr(markedThing)); + if (!p) return; + WeakEntryVector& markables = p->value; - markEphemeronValues(markedThing, weakValues->value); - weakValues->value.clear(); // If key address is reused, it should do nothing + markEphemeronValues(markedThing, markables); + markables.clear(); // If key address is reused, it should do nothing } template <> void -GCMarker::markPotentialEphemeronKeyHelper(bool) +GCMarker::markImplicitEdgesHelper(HasNoImplicitEdgesType) { } template void -GCMarker::markPotentialEphemeronKey(T* thing) +GCMarker::markImplicitEdges(T* thing) { - markPotentialEphemeronKeyHelper::Type>(thing); + markImplicitEdgesHelper::Type>(thing); } } // namespace js @@ -810,7 +811,7 @@ js::GCMarker::markAndPush(StackTag tag, T* thing) if (!mark(thing)) return; pushTaggedPtr(tag, thing); - markPotentialEphemeronKey(thing); + markImplicitEdges(thing); } namespace js { template <> void GCMarker::traverse(JSObject* thing) { markAndPush(ObjectTag, thing); } @@ -1425,7 +1426,7 @@ GCMarker::processMarkStackTop(SliceBudget& budget) return; } - markPotentialEphemeronKey(obj); + markImplicitEdges(obj); ObjectGroup* group = obj->groupFromGC(); traverseEdge(obj, group); @@ -1777,7 +1778,7 @@ GCMarker::enterWeakMarkingMode() for (GCZoneGroupIter zone(runtime()); !zone.done(); zone.next()) { for (WeakMapBase* m : zone->gcWeakMapList) { if (m->marked) - m->markEphemeronEntries(this); + (void) m->traceEntries(this); } } } diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index be698e36fe6..1dbe7513698 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -291,8 +291,8 @@ class GCMarker : public JSTracer template void markAndTraceChildren(T* thing); template void markAndPush(StackTag tag, T* thing); template void markAndScan(T* thing); - template void markPotentialEphemeronKeyHelper(T oldThing); - template void markPotentialEphemeronKey(T* oldThing); + template void markImplicitEdgesHelper(T oldThing); + template void markImplicitEdges(T* oldThing); void eagerlyMarkChildren(JSLinearString* str); void eagerlyMarkChildren(JSRope* rope); void eagerlyMarkChildren(JSString* str); diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp index 6cfc8a6f65e..20859a628be 100644 --- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -35,35 +35,6 @@ WeakMapBase::~WeakMapBase() MOZ_ASSERT(CurrentThreadIsGCSweeping() || CurrentThreadIsHandlingInitFailure()); } -void -WeakMapBase::trace(JSTracer* tracer) -{ - MOZ_ASSERT(isInList()); - if (tracer->isMarkingTracer()) { - marked = true; - if (tracer->weakMapAction() == DoNotTraceWeakMaps) { - // Do not trace any WeakMap entries at this time. Just record the - // fact that the WeakMap has been marked. Entries are marked in the - // iterative marking phase by markAllIteratively(), after as many - // keys as possible have been marked already. - } else { - MOZ_ASSERT(tracer->weakMapAction() == ExpandWeakMaps); - markEphemeronEntries(tracer); - } - } else { - // If we're not actually doing garbage collection, the keys won't be marked - // nicely as needed by the true ephemeral marking algorithm --- custom tracers - // such as the cycle collector must use their own means for cycle detection. - // So here we do a conservative approximation: pretend all keys are live. - if (tracer->weakMapAction() == DoNotTraceWeakMaps) - return; - - nonMarkingTraceValues(tracer); - if (tracer->weakMapAction() == TraceWeakMapKeysValues) - nonMarkingTraceKeys(tracer); - } -} - void WeakMapBase::unmarkZone(JS::Zone* zone) { @@ -87,7 +58,7 @@ WeakMapBase::markZoneIteratively(JS::Zone* zone, JSTracer* tracer) { bool markedAny = false; for (WeakMapBase* m : zone->gcWeakMapList) { - if (m->marked && m->markIteratively(tracer)) + if (m->marked && m->traceEntries(tracer)) markedAny = true; } return markedAny; diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index fa33e3cca1b..1b9a2dcada1 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -27,29 +27,27 @@ class WeakMapBase; // // More precisely: // -// A WeakMap entry is collected if and only if either the WeakMap or the entry's key -// is collected. If an entry is not collected, it remains in the WeakMap and it has a -// strong reference to the value. +// A WeakMap entry is live if and only if both the WeakMap and the entry's key +// are live. An entry holds a strong reference to its value. // -// You must call this table's 'trace' method when the object of which it is a part is -// reached by the garbage collection tracer. Once a table is known to be live, the -// implementation takes care of the iterative marking needed for weak tables and removing -// table entries when collection is complete. +// You must call this table's 'trace' method when its owning object is reached +// by the garbage collection tracer. Once a table is known to be live, the +// implementation takes care of the special weak marking (ie, marking through +// the implicit edges stored in the map) and of removing (sweeping) table +// entries when collection is complete. typedef HashSet, SystemAllocPolicy> WeakMapSet; -// Common base class for all WeakMap specializations. The collector uses this to call -// their markIteratively and sweep methods. +// Common base class for all WeakMap specializations, used for calling +// subclasses' GC-related methods. class WeakMapBase : public mozilla::LinkedListElement { - friend void js::GCMarker::enterWeakMarkingMode(); + friend class js::GCMarker; public: WeakMapBase(JSObject* memOf, JS::Zone* zone); virtual ~WeakMapBase(); - void trace(JSTracer* tracer); - // Garbage collector entry points. // Unmark all weak maps in a zone. @@ -80,23 +78,22 @@ class WeakMapBase : public mozilla::LinkedListElement // Restore information about which weak maps are marked for many zones. static void restoreMarkedWeakMaps(WeakMapSet& markedWeakMaps); - // Any weakmap key types that want to participate in the non-iterative - // ephemeron marking must override this method. - virtual void maybeMarkEntry(JSTracer* trc, gc::Cell* markedCell, JS::GCCellPtr l) = 0; - - virtual void markEphemeronEntries(JSTracer* trc) = 0; - protected: // Instance member functions called by the above. Instantiations of WeakMap override // these with definitions appropriate for their Key and Value types. - virtual void nonMarkingTraceKeys(JSTracer* tracer) = 0; - virtual void nonMarkingTraceValues(JSTracer* tracer) = 0; - virtual bool markIteratively(JSTracer* tracer) = 0; + virtual void trace(JSTracer* tracer) = 0; virtual bool findZoneEdges() = 0; virtual void sweep() = 0; virtual void traceMappings(WeakMapTracer* tracer) = 0; virtual void finish() = 0; + // Any weakmap key types that want to participate in the non-iterative + // ephemeron marking must override this method. + virtual void traceEntry(JSTracer* trc, gc::Cell* markedCell, JS::GCCellPtr l) = 0; + + virtual bool traceEntries(JSTracer* trc) = 0; + + protected: // Object that this weak map is part of, if any. HeapPtrObject memberOf; @@ -120,12 +117,14 @@ static T* extractUnbarriered(T* v) template > -class WeakMap : public HashMap, public WeakMapBase +class WeakMap : public HashMap, + public WeakMapBase { public: typedef HashMap Base; typedef typename Base::Enum Enum; typedef typename Base::Lookup Lookup; + typedef typename Base::Entry Entry; typedef typename Base::Range Range; typedef typename Base::Ptr Ptr; typedef typename Base::AddPtr AddPtr; @@ -142,8 +141,8 @@ class WeakMap : public HashMap, publ } // Overwritten to add a read barrier to prevent an incorrectly gray value - // from escaping the weak map. See the comment before UnmarkGrayChildren in - // gc/Marking.cpp + // from escaping the weak map. See the UnmarkGrayTracer::onChild comment in + // gc/Marking.cpp. Ptr lookup(const Lookup& l) const { Ptr p = Base::lookup(l); if (p) @@ -168,11 +167,14 @@ class WeakMap : public HashMap, publ // Resolve ambiguity with LinkedListElement<>::remove. using Base::remove; - // The WeakMap and some part of the key are marked. If the entry is marked - // according to the exact semantics of this WeakMap, then mark the value. - // (For a standard WeakMap, the entry is marked if either the key its - // delegate is marked.) - void maybeMarkEntry(JSTracer* trc, gc::Cell* markedCell, JS::GCCellPtr origKey) override + // Trace a WeakMap entry based on 'markedCell' getting marked, where + // 'origKey' is the key in the weakmap. These will probably be the same, + // but can be different eg when markedCell is a delegate for origKey. + // + // This implementation does not use 'markedCell'; it looks up origKey and + // checks the mark bits on everything it cares about, one of which will be + // markedCell. But a subclass might use it to optimize the liveness check. + void traceEntry(JSTracer* trc, gc::Cell* markedCell, JS::GCCellPtr origKey) override { MOZ_ASSERT(marked); @@ -181,6 +183,7 @@ class WeakMap : public HashMap, publ MOZ_ASSERT(p.found()); Key key(p->key()); + MOZ_ASSERT((markedCell == extractUnbarriered(key)) || (markedCell == getDelegate(key))); if (gc::IsMarked(&key)) { TraceEdge(trc, &p->value(), "ephemeron value"); } else if (keyNeedsMark(key)) { @@ -191,6 +194,39 @@ class WeakMap : public HashMap, publ key.unsafeSet(nullptr); // Prevent destructor from running barriers. } + void trace(JSTracer* trc) override { + MOZ_ASSERT(isInList()); + + if (trc->isMarkingTracer()) + marked = true; + + if (trc->weakMapAction() == DoNotTraceWeakMaps) + return; + + if (!trc->isMarkingTracer()) { + // Trace keys only if weakMapAction() says to. + if (trc->weakMapAction() == TraceWeakMapKeysValues) { + for (Enum e(*this); !e.empty(); e.popFront()) { + Key key(e.front().key()); + TraceEdge(trc, &key, "WeakMap entry key"); + if (key != e.front().key()) + e.rekeyFront(key); + } + } + + // Always trace all values (unless weakMapAction() is + // DoNotTraceWeakMaps). + for (Range r = Base::all(); !r.empty(); r.popFront()) + TraceEdge(trc, &r.front().value(), "WeakMap entry value"); + + return; + } + + // Marking tracer + MOZ_ASSERT(trc->weakMapAction() == ExpandWeakMaps); + (void) traceEntries(trc); + } + protected: static void addWeakEntry(JSTracer* trc, JS::GCCellPtr key, gc::WeakMarkable markable) { @@ -209,62 +245,55 @@ class WeakMap : public HashMap, publ } } - void markEphemeronEntries(JSTracer* trc) override { + bool traceEntries(JSTracer* trc) override { MOZ_ASSERT(marked); + + bool markedAny = false; + for (Enum e(*this); !e.empty(); e.popFront()) { - Key key(e.front().key()); + Entry& entry(e.front()); + Key key(entry.key()); // If the entry is live, ensure its key and value are marked. - if (gc::IsMarked(&key)) { - (void) markValue(trc, &e.front().value()); - MOZ_ASSERT(key == e.front().key()); // No moving - } else if (keyNeedsMark(key)) { - TraceEdge(trc, &e.front().value(), "WeakMap entry value"); + + bool keyIsMarked = gc::IsMarked(&key); + if (!keyIsMarked && keyNeedsMark(key)) { TraceEdge(trc, &key, "proxy-preserved WeakMap entry key"); - MOZ_ASSERT(key == e.front().key()); // No moving + keyIsMarked = true; + markedAny = true; + } + + if (keyIsMarked) { + if (!gc::IsMarked(&entry.value())) { + TraceEdge(trc, &entry.value(), "WeakMap entry value"); + markedAny = true; + } + + if (e.front().key() != key) + e.rekeyFront(key); } else if (trc->isWeakMarkingTracer()) { - // Entry is not yet known to be live. Record it in the list of - // weak keys. Or rather, record this weakmap and the lookup key - // so we can repeat the lookup when we need to (to allow - // incremental weak marking, we can't just store a pointer to - // the entry.) Also record the delegate, if any, because - // marking the delegate must also mark the entry. + // Entry is not yet known to be live. Record this weakmap and + // the lookup key in the list of weak keys. Also record the + // delegate, if any, because marking the delegate also marks + // the entry. JS::GCCellPtr weakKey(extractUnbarriered(key)); gc::WeakMarkable markable(this, weakKey); addWeakEntry(trc, weakKey, markable); if (JSObject* delegate = getDelegate(key)) addWeakEntry(trc, JS::GCCellPtr(delegate), markable); + MOZ_ASSERT(key == e.front().key()); // No moving } + key.unsafeSet(nullptr); // Prevent destructor from running barriers. } + + return markedAny; } private: void exposeGCThingToActiveJS(const JS::Value& v) const { JS::ExposeValueToActiveJS(v); } void exposeGCThingToActiveJS(JSObject* obj) const { JS::ExposeObjectToActiveJS(obj); } - bool markValue(JSTracer* trc, Value* x) { - if (gc::IsMarked(x)) - return false; - TraceEdge(trc, x, "WeakMap entry value"); - MOZ_ASSERT(gc::IsMarked(x)); - return true; - } - - void nonMarkingTraceKeys(JSTracer* trc) override { - for (Enum e(*this); !e.empty(); e.popFront()) { - Key key(e.front().key()); - TraceEdge(trc, &key, "WeakMap entry key"); - if (key != e.front().key()) - entryMoved(e, key); - } - } - - void nonMarkingTraceValues(JSTracer* trc) override { - for (Range r = Base::all(); !r.empty(); r.popFront()) - TraceEdge(trc, &r.front().value(), "WeakMap entry value"); - } - JSObject* getDelegate(JSObject* key) const { JSWeakmapKeyDelegateOp op = key->getClass()->ext.weakmapKeyDelegateOp; return op ? op(key) : nullptr; @@ -287,28 +316,6 @@ class WeakMap : public HashMap, publ return false; } - bool markIteratively(JSTracer* trc) override { - bool markedAny = false; - for (Enum e(*this); !e.empty(); e.popFront()) { - /* If the entry is live, ensure its key and value are marked. */ - Key key(e.front().key()); - if (gc::IsMarked(const_cast(&key))) { - if (markValue(trc, &e.front().value())) - markedAny = true; - if (e.front().key() != key) - entryMoved(e, key); - } else if (keyNeedsMark(key)) { - TraceEdge(trc, &e.front().value(), "WeakMap entry value"); - TraceEdge(trc, &key, "proxy-preserved WeakMap entry key"); - if (e.front().key() != key) - entryMoved(e, key); - markedAny = true; - } - key.unsafeSet(nullptr); // Prevent destructor from running barriers. - } - return markedAny; - } - bool findZoneEdges() override { // This is overridden by ObjectValueMap. return true; @@ -321,7 +328,7 @@ class WeakMap : public HashMap, publ if (gc::IsAboutToBeFinalized(&k)) e.removeFront(); else if (k != e.front().key()) - entryMoved(e, k); + e.rekeyFront(k); } /* * Once we've swept, all remaining edges should stay within the @@ -347,11 +354,6 @@ class WeakMap : public HashMap, publ } } - /* Rekey an entry when moved, ensuring we do not trigger barriers. */ - void entryMoved(Enum& e, const Key& k) { - e.rekeyFront(k); - } - protected: void assertEntriesNotAboutToBeFinalized() { #if DEBUG From a058cb9c71b396fe2c1fb77056c4b0405b271637 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Oct 2015 22:19:59 -0700 Subject: [PATCH 37/95] Bug 1187782 (part 1) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --- dom/base/nsHostObjectProtocolHandler.cpp | 254 +++++++++++------------ 1 file changed, 118 insertions(+), 136 deletions(-) diff --git a/dom/base/nsHostObjectProtocolHandler.cpp b/dom/base/nsHostObjectProtocolHandler.cpp index 07286ddfd76..82074572b1d 100644 --- a/dom/base/nsHostObjectProtocolHandler.cpp +++ b/dom/base/nsHostObjectProtocolHandler.cpp @@ -66,15 +66,125 @@ class BlobURLsReporter final : public nsIMemoryReporter NS_IMETHOD CollectReports(nsIHandleReportCallback* aCallback, nsISupports* aData, bool aAnonymize) override { - EnumArg env; - env.mCallback = aCallback; - env.mData = aData; - env.mAnonymize = aAnonymize; - - if (gDataTable) { - gDataTable->EnumerateRead(CountCallback, &env); - gDataTable->EnumerateRead(ReportCallback, &env); + if (!gDataTable) { + return NS_OK; } + + nsDataHashtable, uint32_t> refCounts; + + // Determine number of URLs per blob, to handle the case where it's > 1. + for (auto iter = gDataTable->Iter(); !iter.Done(); iter.Next()) { + nsCOMPtr blob = + do_QueryInterface(iter.UserData()->mObject); + if (blob) { + refCounts.Put(blob, refCounts.Get(blob) + 1); + } + } + + for (auto iter = gDataTable->Iter(); !iter.Done(); iter.Next()) { + nsCStringHashKey::KeyType key = iter.Key(); + DataInfo* info = iter.UserData(); + + nsCOMPtr tmp = do_QueryInterface(info->mObject); + RefPtr blob = + static_cast(tmp.get()); + + if (blob) { + NS_NAMED_LITERAL_CSTRING(desc, + "A blob URL allocated with URL.createObjectURL; the referenced " + "blob cannot be freed until all URLs for it have been explicitly " + "invalidated with URL.revokeObjectURL."); + nsAutoCString path, url, owner, specialDesc; + nsCOMPtr principalURI; + uint64_t size = 0; + uint32_t refCount = 1; + DebugOnly blobWasCounted; + + blobWasCounted = refCounts.Get(blob, &refCount); + MOZ_ASSERT(blobWasCounted); + MOZ_ASSERT(refCount > 0); + + bool isMemoryFile = blob->IsMemoryFile(); + + if (isMemoryFile) { + ErrorResult rv; + size = blob->GetSize(rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + size = 0; + } + } + + path = isMemoryFile ? "memory-blob-urls/" : "file-blob-urls/"; + BuildPath(path, key, info, aAnonymize); + + if (refCount > 1) { + nsAutoCString addrStr; + + addrStr = "0x"; + addrStr.AppendInt((uint64_t)(nsIDOMBlob*)blob, 16); + + path += " "; + path.AppendInt(refCount); + path += "@"; + path += addrStr; + + specialDesc = desc; + specialDesc += "\n\nNOTE: This blob (address "; + specialDesc += addrStr; + specialDesc += ") has "; + specialDesc.AppendInt(refCount); + specialDesc += " URLs."; + if (isMemoryFile) { + specialDesc += " Its size is divided "; + specialDesc += refCount > 2 ? "among" : "between"; + specialDesc += " them in this report."; + } + } + + const nsACString& descString = specialDesc.IsEmpty() + ? static_cast(desc) + : static_cast(specialDesc); + if (isMemoryFile) { + aCallback->Callback(EmptyCString(), + path, + KIND_OTHER, + UNITS_BYTES, + size / refCount, + descString, + aData); + } else { + aCallback->Callback(EmptyCString(), + path, + KIND_OTHER, + UNITS_COUNT, + 1, + descString, + aData); + } + } else { + // Just report the path for the DOMMediaStream or MediaSource. + nsCOMPtr + ms(do_QueryInterface(info->mObject)); + nsAutoCString path; + path = ms ? "media-source-urls/" : "dom-media-stream-urls/"; + BuildPath(path, key, info, aAnonymize); + + NS_NAMED_LITERAL_CSTRING(desc, + "An object URL allocated with URL.createObjectURL; the referenced " + "data cannot be freed until all URLs for it have been explicitly " + "invalidated with URL.revokeObjectURL."); + + aCallback->Callback(EmptyCString(), + path, + KIND_OTHER, + UNITS_COUNT, + 1, + desc, + aData); + } + } + return NS_OK; } @@ -143,28 +253,6 @@ class BlobURLsReporter final : public nsIMemoryReporter private: ~BlobURLsReporter() {} - struct EnumArg { - nsIHandleReportCallback* mCallback; - nsISupports* mData; - bool mAnonymize; - nsDataHashtable, uint32_t> mRefCounts; - }; - - // Determine number of URLs per blob, to handle the case where it's > 1. - static PLDHashOperator CountCallback(nsCStringHashKey::KeyType aKey, - DataInfo* aInfo, - void* aUserArg) - { - EnumArg* envp = static_cast(aUserArg); - nsCOMPtr blob; - - blob = do_QueryInterface(aInfo->mObject); - if (blob) { - envp->mRefCounts.Put(blob, envp->mRefCounts.Get(blob) + 1); - } - return PL_DHASH_NEXT; - } - static void BuildPath(nsAutoCString& path, nsCStringHashKey::KeyType aKey, DataInfo* aInfo, @@ -201,112 +289,6 @@ class BlobURLsReporter final : public nsIMemoryReporter path += url; } } - - static PLDHashOperator ReportCallback(nsCStringHashKey::KeyType aKey, - DataInfo* aInfo, - void* aUserArg) - { - EnumArg* envp = static_cast(aUserArg); - nsCOMPtr tmp = do_QueryInterface(aInfo->mObject); - RefPtr blob = static_cast(tmp.get()); - - if (blob) { - NS_NAMED_LITERAL_CSTRING - (desc, "A blob URL allocated with URL.createObjectURL; the referenced " - "blob cannot be freed until all URLs for it have been explicitly " - "invalidated with URL.revokeObjectURL."); - nsAutoCString path, url, owner, specialDesc; - nsCOMPtr principalURI; - uint64_t size = 0; - uint32_t refCount = 1; - DebugOnly blobWasCounted; - - blobWasCounted = envp->mRefCounts.Get(blob, &refCount); - MOZ_ASSERT(blobWasCounted); - MOZ_ASSERT(refCount > 0); - - bool isMemoryFile = blob->IsMemoryFile(); - - if (isMemoryFile) { - ErrorResult rv; - size = blob->GetSize(rv); - if (NS_WARN_IF(rv.Failed())) { - rv.SuppressException(); - size = 0; - } - } - - path = isMemoryFile ? "memory-blob-urls/" : "file-blob-urls/"; - BuildPath(path, aKey, aInfo, envp->mAnonymize); - - if (refCount > 1) { - nsAutoCString addrStr; - - addrStr = "0x"; - addrStr.AppendInt((uint64_t)(nsIDOMBlob*)blob, 16); - - path += " "; - path.AppendInt(refCount); - path += "@"; - path += addrStr; - - specialDesc = desc; - specialDesc += "\n\nNOTE: This blob (address "; - specialDesc += addrStr; - specialDesc += ") has "; - specialDesc.AppendInt(refCount); - specialDesc += " URLs."; - if (isMemoryFile) { - specialDesc += " Its size is divided "; - specialDesc += refCount > 2 ? "among" : "between"; - specialDesc += " them in this report."; - } - } - - const nsACString& descString = specialDesc.IsEmpty() - ? static_cast(desc) - : static_cast(specialDesc); - if (isMemoryFile) { - envp->mCallback->Callback(EmptyCString(), - path, - KIND_OTHER, - UNITS_BYTES, - size / refCount, - descString, - envp->mData); - } - else { - envp->mCallback->Callback(EmptyCString(), - path, - KIND_OTHER, - UNITS_COUNT, - 1, - descString, - envp->mData); - } - } else { - // Just report the path for the DOMMediaStream or MediaSource. - nsCOMPtr ms(do_QueryInterface(aInfo->mObject)); - nsAutoCString path; - path = ms ? "media-source-urls/" : "dom-media-stream-urls/"; - BuildPath(path, aKey, aInfo, envp->mAnonymize); - - NS_NAMED_LITERAL_CSTRING - (desc, "An object URL allocated with URL.createObjectURL; the referenced " - "data cannot be freed until all URLs for it have been explicitly " - "invalidated with URL.revokeObjectURL."); - - envp->mCallback->Callback(EmptyCString(), - path, - KIND_OTHER, - UNITS_COUNT, - 1, - desc, - envp->mData); - } - - return PL_DHASH_NEXT; - } }; NS_IMPL_ISUPPORTS(BlobURLsReporter, nsIMemoryReporter) From 5805477aa5de67a164df1dfe6d6759469521ef8f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Oct 2015 22:21:51 -0700 Subject: [PATCH 38/95] Bug 1187782 (part 2) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --- dom/base/nsGlobalWindow.cpp | 4 +--- dom/base/nsGlobalWindow.h | 17 ++++++++--------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 3d182d71fb2..e43a0c3cc20 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -12976,9 +12976,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow, tmp->mMessageManager.get())->Disconnect(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager) } - - tmp->mGroupMessageManagers.EnumerateRead(DisconnectGroupMessageManager, nullptr); - tmp->mGroupMessageManagers.Clear(); + tmp->DisconnectAndClearGroupMessageManagers(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroupMessageManagers) NS_IMPL_CYCLE_COLLECTION_UNLINK_END diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 8ce4d5beea3..aefc7da0990 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1906,15 +1906,15 @@ public: static already_AddRefed Create(nsGlobalWindow *aOuterWindow); - static PLDHashOperator - DisconnectGroupMessageManager(const nsAString& aKey, - nsIMessageBroadcaster* aMM, - void* aUserArg) + void DisconnectAndClearGroupMessageManagers() { - if (aMM) { - static_cast(aMM)->Disconnect(); + for (auto iter = mGroupMessageManagers.Iter(); !iter.Done(); iter.Next()) { + nsIMessageBroadcaster* mm = iter.UserData(); + if (mm) { + static_cast(mm)->Disconnect(); + } } - return PL_DHASH_NEXT; + mGroupMessageManagers.Clear(); } protected: @@ -1931,8 +1931,7 @@ protected: MOZ_ASSERT(mCleanMessageManager, "chrome windows may always disconnect the msg manager"); - mGroupMessageManagers.EnumerateRead(DisconnectGroupMessageManager, nullptr); - mGroupMessageManagers.Clear(); + DisconnectAndClearGroupMessageManagers(); if (mMessageManager) { static_cast( From 4398d7b8f4901548942b981c03713c4d2ca91e5e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Oct 2015 22:22:10 -0700 Subject: [PATCH 39/95] Bug 1187782 (part 3) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --- dom/base/nsWindowMemoryReporter.cpp | 51 +++++++++-------------------- 1 file changed, 16 insertions(+), 35 deletions(-) diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index 7026716a180..93e27810ee7 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -789,37 +789,6 @@ CheckForGhostWindowsEnumerator(nsISupports *aKey, TimeStamp& aTimeStamp, return PL_DHASH_NEXT; } -struct GetNonDetachedWindowDomainsEnumeratorData -{ - nsTHashtable *nonDetachedDomains; - nsIEffectiveTLDService *tldService; -}; - -static PLDHashOperator -GetNonDetachedWindowDomainsEnumerator(const uint64_t& aId, nsGlobalWindow* aWindow, - void* aClosure) -{ - GetNonDetachedWindowDomainsEnumeratorData *data = - static_cast(aClosure); - - // Null outer window implies null top, but calling GetTop() when there's no - // outer window causes us to spew debug warnings. - if (!aWindow->GetOuterWindow() || !aWindow->GetTopInternal()) { - // This window is detached, so we don't care about its domain. - return PL_DHASH_NEXT; - } - - nsCOMPtr uri = GetWindowURI(aWindow); - - nsAutoCString domain; - if (uri) { - data->tldService->GetBaseDomain(uri, 0, domain); - } - - data->nonDetachedDomains->PutEntry(domain); - return PL_DHASH_NEXT; -} - /** * Iterate over mDetachedWindows and update it to reflect the current state of * the world. In particular: @@ -861,10 +830,22 @@ nsWindowMemoryReporter::CheckForGhostWindows( nsTHashtable nonDetachedWindowDomains; // Populate nonDetachedWindowDomains. - GetNonDetachedWindowDomainsEnumeratorData nonDetachedEnumData = - { &nonDetachedWindowDomains, tldService }; - windowsById->EnumerateRead(GetNonDetachedWindowDomainsEnumerator, - &nonDetachedEnumData); + for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) { + // Null outer window implies null top, but calling GetTop() when there's no + // outer window causes us to spew debug warnings. + nsGlobalWindow* window = iter.UserData(); + if (!window->GetOuterWindow() || !window->GetTopInternal()) { + // This window is detached, so we don't care about its domain. + continue; + } + + nsCOMPtr uri = GetWindowURI(window); + nsAutoCString domain; + if (uri) { + tldService->GetBaseDomain(uri, 0, domain); + } + nonDetachedWindowDomains.PutEntry(domain); + } // Update mDetachedWindows and write the ghost window IDs into aOutGhostIDs, // if it's not null. From 685046e077f1d5f3289b506b062a7172a1fd5bae Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Oct 2015 22:22:31 -0700 Subject: [PATCH 40/95] Bug 1187782 (part 4) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --- dom/base/nsGlobalWindow.cpp | 33 +++++++++------------------------ dom/base/nsGlobalWindow.h | 6 ------ 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index e43a0c3cc20..6ff2b855a0a 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -12869,18 +12869,6 @@ nsGlobalWindow::RemoveGamepad(uint32_t aIndex) mGamepads.Remove(aIndex); } -// static -PLDHashOperator -nsGlobalWindow::EnumGamepadsForGet(const uint32_t& aKey, Gamepad* aData, - void* aUserArg) -{ - nsTArray >* array = - static_cast >*>(aUserArg); - array->EnsureLengthAtLeast(aData->Index() + 1); - (*array)[aData->Index()] = aData; - return PL_DHASH_NEXT; -} - void nsGlobalWindow::GetGamepads(nsTArray >& aGamepads) { @@ -12888,7 +12876,11 @@ nsGlobalWindow::GetGamepads(nsTArray >& aGamepads) aGamepads.Clear(); // mGamepads.Count() may not be sufficient, but it's not harmful. aGamepads.SetCapacity(mGamepads.Count()); - mGamepads.EnumerateRead(EnumGamepadsForGet, &aGamepads); + for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) { + Gamepad* gamepad = iter.UserData(); + aGamepads.EnsureLengthAtLeast(gamepad->Index() + 1); + aGamepads[gamepad->Index()] = gamepad; + } } already_AddRefed @@ -12918,22 +12910,15 @@ nsGlobalWindow::HasSeenGamepadInput() return mHasSeenGamepadInput; } -// static -PLDHashOperator -nsGlobalWindow::EnumGamepadsForSync(const uint32_t& aKey, Gamepad* aData, - void* aUserArg) -{ - RefPtr gamepadsvc(GamepadService::GetService()); - gamepadsvc->SyncGamepadState(aKey, aData); - return PL_DHASH_NEXT; -} - void nsGlobalWindow::SyncGamepadState() { MOZ_ASSERT(IsInnerWindow()); if (mHasSeenGamepadInput) { - mGamepads.EnumerateRead(EnumGamepadsForSync, nullptr); + RefPtr gamepadsvc(GamepadService::GetService()); + for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) { + gamepadsvc->SyncGamepadState(iter.Key(), iter.UserData()); + } } } #endif // MOZ_GAMEPAD diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index aefc7da0990..39fa536cf81 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -763,12 +763,6 @@ public: void SetHasSeenGamepadInput(bool aHasSeen); bool HasSeenGamepadInput(); void SyncGamepadState(); - static PLDHashOperator EnumGamepadsForSync(const uint32_t& aKey, - mozilla::dom::Gamepad* aData, - void* aUserArg); - static PLDHashOperator EnumGamepadsForGet(const uint32_t& aKey, - mozilla::dom::Gamepad* aData, - void* aUserArg); #endif // Inner windows only. From be9909dcbe240824954d308285c28dee457696b7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 Oct 2015 15:13:04 -0700 Subject: [PATCH 41/95] Bug 1187782 (part 5) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --- dom/base/nsDOMAttributeMap.cpp | 7 ------ dom/base/nsDOMAttributeMap.h | 8 +------ dom/base/nsDocument.cpp | 44 +++++++++++++++------------------- 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/dom/base/nsDOMAttributeMap.cpp b/dom/base/nsDOMAttributeMap.cpp index 87e58627be1..93e686da0d2 100644 --- a/dom/base/nsDOMAttributeMap.cpp +++ b/dom/base/nsDOMAttributeMap.cpp @@ -557,13 +557,6 @@ nsDOMAttributeMap::Count() const return mAttributeCache.Count(); } -uint32_t -nsDOMAttributeMap::Enumerate(AttrCache::EnumReadFunction aFunc, - void *aUserArg) const -{ - return mAttributeCache.EnumerateRead(aFunc, aUserArg); -} - size_t nsDOMAttributeMap::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { diff --git a/dom/base/nsDOMAttributeMap.h b/dom/base/nsDOMAttributeMap.h index c52ee1f5b0a..9fb4a30a6b4 100644 --- a/dom/base/nsDOMAttributeMap.h +++ b/dom/base/nsDOMAttributeMap.h @@ -128,13 +128,7 @@ public: typedef nsRefPtrHashtable AttrCache; - /** - * Enumerates over the attribute nodess in the map and calls aFunc for each - * one. If aFunc returns PL_DHASH_STOP we'll stop enumerating at that point. - * - * @return The number of attribute nodes that aFunc was called for. - */ - uint32_t Enumerate(AttrCache::EnumReadFunction aFunc, void *aUserArg) const; + static void BlastSubtreeToPieces(nsINode *aNode); Element* GetParentObject() const { diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 7bc7d63a1b2..c836aa1e810 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -7633,42 +7633,36 @@ nsIDocument::GetCompatMode(nsString& aCompatMode) const } } -static void BlastSubtreeToPieces(nsINode *aNode); - -PLDHashOperator -BlastFunc(nsAttrHashKey::KeyType aKey, Attr *aData, void* aUserArg) -{ - nsCOMPtr *attr = - static_cast*>(aUserArg); - - *attr = aData; - - NS_ASSERTION(attr->get(), - "non-nsIAttribute somehow made it into the hashmap?!"); - - return PL_DHASH_STOP; -} - -static void -BlastSubtreeToPieces(nsINode *aNode) +void +nsDOMAttributeMap::BlastSubtreeToPieces(nsINode *aNode) { if (aNode->IsElement()) { Element *element = aNode->AsElement(); const nsDOMAttributeMap *map = element->GetAttributeMap(); if (map) { nsCOMPtr attr; - while (map->Enumerate(BlastFunc, &attr) > 0) { + + // This non-standard style of iteration is presumably used because some + // of the code in the loop body can trigger element removal, which + // invalidates the iterator. + while (true) { + auto iter = map->mAttributeCache.ConstIter(); + if (iter.Done()) { + break; + } + nsCOMPtr attr = iter.UserData(); + NS_ASSERTION(attr.get(), + "non-nsIAttribute somehow made it into the hashmap?!"); + BlastSubtreeToPieces(attr); -#ifdef DEBUG - nsresult rv = -#endif + DebugOnly rv = element->UnsetAttr(attr->NodeInfo()->NamespaceID(), attr->NodeInfo()->NameAtom(), false); // XXX Should we abort here? - NS_ASSERTION(NS_SUCCEEDED(rv), "Uhoh, UnsetAttr shouldn't fail!"); + NS_ASSERTION(NS_SUCCEEDED(rv), "Uh-oh, UnsetAttr shouldn't fail!"); } } } @@ -7835,7 +7829,7 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv) if (rv.Failed()) { // Disconnect all nodes from their parents, since some have the old document // as their ownerDocument and some have this as their ownerDocument. - BlastSubtreeToPieces(adoptedNode); + nsDOMAttributeMap::BlastSubtreeToPieces(adoptedNode); if (!sameDocument && oldDocument) { uint32_t count = nodesWithProperties.Count(); @@ -7864,7 +7858,7 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv) if (rv.Failed()) { // Disconnect all nodes from their parents. - BlastSubtreeToPieces(adoptedNode); + nsDOMAttributeMap::BlastSubtreeToPieces(adoptedNode); return nullptr; } From ce6db513afaf5a9ec5752b871869fe092692d417 Mon Sep 17 00:00:00 2001 From: Mason Chang Date: Wed, 28 Oct 2015 14:54:54 -0700 Subject: [PATCH 42/95] Bug 842894 - Support DirectWrite using the Skia backend. r=bas --- gfx/2d/2D.h | 9 ++++++++ gfx/2d/DrawTargetSkia.cpp | 3 ++- gfx/2d/Factory.cpp | 9 ++++++++ gfx/2d/ScaledFontDWrite.cpp | 24 ++++++++++++++++++++ gfx/2d/ScaledFontDWrite.h | 23 +++++++++++++------ gfx/skia/skia/include/ports/SkTypeface_win.h | 11 +++++++++ gfx/skia/skia/src/ports/SkFontHost_win.cpp | 13 +++++++++++ gfx/thebes/gfxDWriteFontList.cpp | 18 +++++++++++++++ gfx/thebes/gfxDWriteFontList.h | 5 ++++ gfx/thebes/gfxDWriteFonts.cpp | 21 ++++++++++++++++- gfx/thebes/gfxDWriteFonts.h | 2 ++ gfx/thebes/gfxWindowsPlatform.cpp | 4 +--- 12 files changed, 130 insertions(+), 12 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 6ede3d18ed4..86dbe86fbf6 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -42,6 +42,9 @@ struct ID3D11Texture2D; struct ID3D11Device; struct ID2D1Device; struct IDWriteRenderingParams; +struct IDWriteFont; +struct IDWriteFontFamily; +struct IDWriteFontFace; class GrContext; @@ -1278,6 +1281,12 @@ public: static uint64_t GetD2DVRAMUsageSourceSurface(); static void D2DCleanup(); + static already_AddRefed + CreateScaledFontForDWriteFont(IDWriteFont* aFont, + IDWriteFontFamily* aFontFamily, + IDWriteFontFace* aFontFace, + Float aSize); + private: static ID2D1Device *mD2D1Device; static ID3D10Device1 *mD3D10Device; diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index 1554094ace7..96498a85cd2 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -573,7 +573,8 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont, { if (aFont->GetType() != FontType::MAC && aFont->GetType() != FontType::SKIA && - aFont->GetType() != FontType::GDI) { + aFont->GetType() != FontType::GDI && + aFont->GetType() != FontType::DWRITE) { return; } diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index 5446b58f9fb..2d39e7865ed 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -736,6 +736,15 @@ Factory::D2DCleanup() DrawTargetD2D::CleanupD2D(); } +already_AddRefed +Factory::CreateScaledFontForDWriteFont(IDWriteFont* aFont, + IDWriteFontFamily* aFontFamily, + IDWriteFontFace* aFontFace, + float aSize) +{ + return MakeAndAddRef(aFont, aFontFamily, aFontFace, aSize); +} + #endif // XP_WIN #ifdef USE_SKIA_GPU diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp index 885140be417..b1b5b087b43 100644 --- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -8,6 +8,13 @@ #include "DrawTargetD2D.h" #include "Logging.h" +#ifdef USE_SKIA +#include "PathSkia.h" +#include "skia/include/core/SkPaint.h" +#include "skia/include/core/SkPath.h" +#include "skia/include/ports/SkTypeface_win.h" +#endif + #include namespace mozilla { @@ -287,6 +294,8 @@ DWriteFontFileStream::ReleaseFileFragment(void *fragmentContext) ScaledFontDWrite::ScaledFontDWrite(uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize) : ScaledFontBase(aGlyphSize) + , mFont(nullptr) + , mFontFamily(nullptr) { IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory(); @@ -323,6 +332,21 @@ ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget return pathBuilder->Finish(); } + +#ifdef USE_SKIA +SkTypeface* +ScaledFontDWrite::GetSkTypeface() +{ + MOZ_ASSERT(mFont); + if (!mTypeface) { + IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory(); + // What to do if no font? How to create a font just with a font face? + mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily); + } + return mTypeface; +} +#endif + void ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint) { diff --git a/gfx/2d/ScaledFontDWrite.h b/gfx/2d/ScaledFontDWrite.h index a517ab55db0..1210a9e6832 100644 --- a/gfx/2d/ScaledFontDWrite.h +++ b/gfx/2d/ScaledFontDWrite.h @@ -19,11 +19,22 @@ class ScaledFontDWrite final : public ScaledFontBase public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDwrite) ScaledFontDWrite(IDWriteFontFace *aFont, Float aSize) - : mFontFace(aFont) - , ScaledFontBase(aSize) + : ScaledFontBase(aSize) + , mFont(nullptr) + , mFontFamily(nullptr) + , mFontFace(aFont) {} + ScaledFontDWrite(uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize); + ScaledFontDWrite(IDWriteFont* aFont, IDWriteFontFamily* aFontFamily, + IDWriteFontFace* aFontFace, Float aSize) + : ScaledFontBase(aSize) + , mFont(aFont) + , mFontFamily(aFontFamily) + , mFontFace(aFontFace) + {} + virtual FontType GetType() const { return FontType::DWRITE; } virtual already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); @@ -36,13 +47,11 @@ public: virtual AntialiasMode GetDefaultAAMode(); #ifdef USE_SKIA - virtual SkTypeface* GetSkTypeface() - { - MOZ_ASSERT(false, "Skia and DirectWrite do not mix"); - return nullptr; - } + virtual SkTypeface* GetSkTypeface(); #endif + RefPtr mFont; + RefPtr mFontFamily; RefPtr mFontFace; }; diff --git a/gfx/skia/skia/include/ports/SkTypeface_win.h b/gfx/skia/skia/include/ports/SkTypeface_win.h index 07752d82f9b..d032d6dc6ca 100644 --- a/gfx/skia/skia/include/ports/SkTypeface_win.h +++ b/gfx/skia/skia/include/ports/SkTypeface_win.h @@ -9,6 +9,7 @@ #define SkTypeface_win_DEFINED #include "SkTypeface.h" +#include /** * Like the other Typeface create methods, this returns a new reference to the @@ -39,6 +40,16 @@ class SkFontMgr; class SkRemotableFontMgr; struct IDWriteFactory; +/** + * Like the other Typeface create methods, this returns a new reference to the + * corresponding typeface for the specified dwrite font. The caller is responsible + * for calling unref() when it is finished. + */ +SK_API SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFactory* aFactory, + IDWriteFontFace* aFontFace, + IDWriteFont* aFont, + IDWriteFontFamily* aFontFamily); + SK_API SkFontMgr* SkFontMgr_New_GDI(); SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory = NULL); diff --git a/gfx/skia/skia/src/ports/SkFontHost_win.cpp b/gfx/skia/skia/src/ports/SkFontHost_win.cpp index e4aab81b150..0bee788015b 100755 --- a/gfx/skia/skia/src/ports/SkFontHost_win.cpp +++ b/gfx/skia/skia/src/ports/SkFontHost_win.cpp @@ -27,6 +27,7 @@ #include "SkTemplates.h" #include "SkThread.h" #include "SkTypeface_win.h" +#include "SkTypeface_win_dw.h" #include "SkTypefaceCache.h" #include "SkUtils.h" @@ -342,6 +343,18 @@ SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) { return face; } +/*** + * This guy is public. + */ + +SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFactory* aFactory, + IDWriteFontFace* aFontFace, + IDWriteFont* aFont, + IDWriteFontFamily* aFontFamily) +{ + return DWriteFontTypeface::Create(aFactory, aFontFace, aFont, aFontFamily); +} + /** * The created SkTypeface takes ownership of fontMemResource. */ diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index 50c3d6d2f08..65fbf23b8d0 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -342,6 +342,24 @@ gfxDWriteFontFamily::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, AddSizeOfExcludingThis(aMallocSizeOf, aSizes); } +already_AddRefed +gfxDWriteFontFamily::GetDefaultFont() +{ + RefPtr font; + for (UINT32 i = 0; i < mDWFamily->GetFontCount(); i++) { + HRESULT hr = mDWFamily->GetFont(i, getter_AddRefs(font)); + if (FAILED(hr)) { + NS_WARNING("Failed to get default font from existing family"); + continue; + } + + return font.forget(); + } + + NS_WARNING("No available DWrite fonts. Returning null"); + return nullptr; +} + //////////////////////////////////////////////////////////////////////////////// // gfxDWriteFontEntry diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h index 9ce33613647..1cd7d8eee64 100644 --- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -57,6 +57,7 @@ public: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; + already_AddRefed GetDefaultFont(); protected: /** This font family's directwrite fontfamily object */ RefPtr mDWFamily; @@ -163,6 +164,10 @@ public: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; + already_AddRefed GetFont() { + return mFont.forget(); + } + protected: friend class gfxDWriteFont; friend class gfxDWriteFontList; diff --git a/gfx/thebes/gfxDWriteFonts.cpp b/gfx/thebes/gfxDWriteFonts.cpp index 72a5c1f45bb..ce61314dac6 100644 --- a/gfx/thebes/gfxDWriteFonts.cpp +++ b/gfx/thebes/gfxDWriteFonts.cpp @@ -82,7 +82,7 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry, , mAllowManualShowGlyphs(true) { gfxDWriteFontEntry *fe = - static_cast(aFontEntry); + static_cast(aFontEntry); nsresult rv; DWRITE_FONT_SIMULATIONS sims = DWRITE_FONT_SIMULATIONS_NONE; if ((GetStyle()->style != NS_FONT_STYLE_NORMAL) && @@ -103,6 +103,21 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry, return; } + mFont = fe->GetFont(); + if (!mFont) { + gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList(); + gfxDWriteFontFamily* defaultFontFamily = + static_cast(fontList->GetDefaultFont(aFontStyle)); + + mFont = defaultFontFamily->GetDefaultFont(); + NS_WARNING("Using default font"); + } + + HRESULT hr = mFont->GetFontFamily(getter_AddRefs(mFontFamily)); + if (FAILED(hr)) { + MOZ_ASSERT(false); + } + ComputeMetrics(anAAOption); } @@ -687,6 +702,10 @@ gfxDWriteFont::GetScaledFont(mozilla::gfx::DrawTarget *aTarget) mAzureScaledFont = Factory::CreateScaledFontWithCairo(nativeFont, GetAdjustedSize(), GetCairoScaledFont()); + } else if (aTarget->GetBackendType() == BackendType::SKIA) { + mAzureScaledFont = + Factory::CreateScaledFontForDWriteFont(mFont, mFontFamily, + mFontFace, GetAdjustedSize()); } else { mAzureScaledFont = Factory::CreateScaledFontForNativeFont(nativeFont, GetAdjustedSize()); diff --git a/gfx/thebes/gfxDWriteFonts.h b/gfx/thebes/gfxDWriteFonts.h index 89c085e6d64..525d16a415c 100644 --- a/gfx/thebes/gfxDWriteFonts.h +++ b/gfx/thebes/gfxDWriteFonts.h @@ -91,6 +91,8 @@ protected: bool GetForceGDIClassic(); RefPtr mFontFace; + RefPtr mFont; + RefPtr mFontFamily; cairo_font_face_t *mCairoFontFace; Metrics *mMetrics; diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 645bbefdb95..0b37a1043ee 100755 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -690,9 +690,7 @@ gfxWindowsPlatform::CreatePlatformFontList() #ifdef CAIRO_HAS_DWRITE_FONT // bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd // crashers so blacklist them altogether - if (IsNotWin7PreRTM() && GetDWriteFactory() && - // Skia doesn't support DirectWrite fonts yet. - (gfxPlatform::GetDefaultContentBackend() != BackendType::SKIA)) { + if (IsNotWin7PreRTM() && GetDWriteFactory()) { pfl = new gfxDWriteFontList(); if (NS_SUCCEEDED(pfl->InitFontList())) { return pfl; From 450dc59dc607494dd7ccc6edca2806e9dcf01e59 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Oct 2015 14:47:29 -0700 Subject: [PATCH 43/95] Bug 1214476 - Remove unused code for encoding BMPv2 files. r=seth. nsBMPEncoder produces either BMPv3 or BMPv5 files. (See the Version enum which only has VERSION_3 and VERSION_5 values, and ParseOptions()'s handling of the |version| parameter. Nonetheless, there is some code to handle encoding of BMPv2 files. This patch removes this. --- image/encoders/bmp/nsBMPEncoder.cpp | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/image/encoders/bmp/nsBMPEncoder.cpp b/image/encoders/bmp/nsBMPEncoder.cpp index a92e3f667b5..8f02ef564bc 100644 --- a/image/encoders/bmp/nsBMPEncoder.cpp +++ b/image/encoders/bmp/nsBMPEncoder.cpp @@ -615,28 +615,16 @@ nsBMPEncoder::EncodeInfoHeader() NativeEndian::swapToLittleEndianInPlace(&littleEndianmBIH.profile_size, 1); ENCODE(&mImageBufferCurr, littleEndianmBIH.bihsize); - - if (mBMPInfoHeader.bihsize == InfoHeaderLength::WIN_V2) { - uint16_t width = (uint16_t) littleEndianmBIH.width; - ENCODE(&mImageBufferCurr, width); - uint16_t height = (uint16_t) littleEndianmBIH.width; - ENCODE(&mImageBufferCurr, height); - } else { - ENCODE(&mImageBufferCurr, littleEndianmBIH.width); - ENCODE(&mImageBufferCurr, littleEndianmBIH.height); - } - + ENCODE(&mImageBufferCurr, littleEndianmBIH.width); + ENCODE(&mImageBufferCurr, littleEndianmBIH.height); ENCODE(&mImageBufferCurr, littleEndianmBIH.planes); ENCODE(&mImageBufferCurr, littleEndianmBIH.bpp); - - if (mBMPInfoHeader.bihsize > InfoHeaderLength::WIN_V2) { - ENCODE(&mImageBufferCurr, littleEndianmBIH.compression); - ENCODE(&mImageBufferCurr, littleEndianmBIH.image_size); - ENCODE(&mImageBufferCurr, littleEndianmBIH.xppm); - ENCODE(&mImageBufferCurr, littleEndianmBIH.yppm); - ENCODE(&mImageBufferCurr, littleEndianmBIH.colors); - ENCODE(&mImageBufferCurr, littleEndianmBIH.important_colors); - } + ENCODE(&mImageBufferCurr, littleEndianmBIH.compression); + ENCODE(&mImageBufferCurr, littleEndianmBIH.image_size); + ENCODE(&mImageBufferCurr, littleEndianmBIH.xppm); + ENCODE(&mImageBufferCurr, littleEndianmBIH.yppm); + ENCODE(&mImageBufferCurr, littleEndianmBIH.colors); + ENCODE(&mImageBufferCurr, littleEndianmBIH.important_colors); if (mBMPInfoHeader.bihsize > InfoHeaderLength::WIN_V3) { ENCODE(&mImageBufferCurr, littleEndianmBIH.red_mask); From f62a7895a02a7f3691f238801f5ea127906a7bbf Mon Sep 17 00:00:00 2001 From: Mason Chang Date: Wed, 28 Oct 2015 15:17:04 -0700 Subject: [PATCH 44/95] Backout bug 842894 for lack of skia documentation. r=me --- gfx/2d/2D.h | 9 -------- gfx/2d/DrawTargetSkia.cpp | 3 +-- gfx/2d/Factory.cpp | 9 -------- gfx/2d/ScaledFontDWrite.cpp | 24 -------------------- gfx/2d/ScaledFontDWrite.h | 23 ++++++------------- gfx/skia/skia/include/ports/SkTypeface_win.h | 11 --------- gfx/skia/skia/src/ports/SkFontHost_win.cpp | 13 ----------- gfx/thebes/gfxDWriteFontList.cpp | 18 --------------- gfx/thebes/gfxDWriteFontList.h | 5 ---- gfx/thebes/gfxDWriteFonts.cpp | 21 +---------------- gfx/thebes/gfxDWriteFonts.h | 2 -- gfx/thebes/gfxWindowsPlatform.cpp | 4 +++- 12 files changed, 12 insertions(+), 130 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 86dbe86fbf6..6ede3d18ed4 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -42,9 +42,6 @@ struct ID3D11Texture2D; struct ID3D11Device; struct ID2D1Device; struct IDWriteRenderingParams; -struct IDWriteFont; -struct IDWriteFontFamily; -struct IDWriteFontFace; class GrContext; @@ -1281,12 +1278,6 @@ public: static uint64_t GetD2DVRAMUsageSourceSurface(); static void D2DCleanup(); - static already_AddRefed - CreateScaledFontForDWriteFont(IDWriteFont* aFont, - IDWriteFontFamily* aFontFamily, - IDWriteFontFace* aFontFace, - Float aSize); - private: static ID2D1Device *mD2D1Device; static ID3D10Device1 *mD3D10Device; diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index 96498a85cd2..1554094ace7 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -573,8 +573,7 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont, { if (aFont->GetType() != FontType::MAC && aFont->GetType() != FontType::SKIA && - aFont->GetType() != FontType::GDI && - aFont->GetType() != FontType::DWRITE) { + aFont->GetType() != FontType::GDI) { return; } diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index 2d39e7865ed..5446b58f9fb 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -736,15 +736,6 @@ Factory::D2DCleanup() DrawTargetD2D::CleanupD2D(); } -already_AddRefed -Factory::CreateScaledFontForDWriteFont(IDWriteFont* aFont, - IDWriteFontFamily* aFontFamily, - IDWriteFontFace* aFontFace, - float aSize) -{ - return MakeAndAddRef(aFont, aFontFamily, aFontFace, aSize); -} - #endif // XP_WIN #ifdef USE_SKIA_GPU diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp index b1b5b087b43..885140be417 100644 --- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -8,13 +8,6 @@ #include "DrawTargetD2D.h" #include "Logging.h" -#ifdef USE_SKIA -#include "PathSkia.h" -#include "skia/include/core/SkPaint.h" -#include "skia/include/core/SkPath.h" -#include "skia/include/ports/SkTypeface_win.h" -#endif - #include namespace mozilla { @@ -294,8 +287,6 @@ DWriteFontFileStream::ReleaseFileFragment(void *fragmentContext) ScaledFontDWrite::ScaledFontDWrite(uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize) : ScaledFontBase(aGlyphSize) - , mFont(nullptr) - , mFontFamily(nullptr) { IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory(); @@ -332,21 +323,6 @@ ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget return pathBuilder->Finish(); } - -#ifdef USE_SKIA -SkTypeface* -ScaledFontDWrite::GetSkTypeface() -{ - MOZ_ASSERT(mFont); - if (!mTypeface) { - IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory(); - // What to do if no font? How to create a font just with a font face? - mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily); - } - return mTypeface; -} -#endif - void ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint) { diff --git a/gfx/2d/ScaledFontDWrite.h b/gfx/2d/ScaledFontDWrite.h index 1210a9e6832..a517ab55db0 100644 --- a/gfx/2d/ScaledFontDWrite.h +++ b/gfx/2d/ScaledFontDWrite.h @@ -19,22 +19,11 @@ class ScaledFontDWrite final : public ScaledFontBase public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDwrite) ScaledFontDWrite(IDWriteFontFace *aFont, Float aSize) - : ScaledFontBase(aSize) - , mFont(nullptr) - , mFontFamily(nullptr) - , mFontFace(aFont) + : mFontFace(aFont) + , ScaledFontBase(aSize) {} - ScaledFontDWrite(uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize); - ScaledFontDWrite(IDWriteFont* aFont, IDWriteFontFamily* aFontFamily, - IDWriteFontFace* aFontFace, Float aSize) - : ScaledFontBase(aSize) - , mFont(aFont) - , mFontFamily(aFontFamily) - , mFontFace(aFontFace) - {} - virtual FontType GetType() const { return FontType::DWRITE; } virtual already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); @@ -47,11 +36,13 @@ public: virtual AntialiasMode GetDefaultAAMode(); #ifdef USE_SKIA - virtual SkTypeface* GetSkTypeface(); + virtual SkTypeface* GetSkTypeface() + { + MOZ_ASSERT(false, "Skia and DirectWrite do not mix"); + return nullptr; + } #endif - RefPtr mFont; - RefPtr mFontFamily; RefPtr mFontFace; }; diff --git a/gfx/skia/skia/include/ports/SkTypeface_win.h b/gfx/skia/skia/include/ports/SkTypeface_win.h index d032d6dc6ca..07752d82f9b 100644 --- a/gfx/skia/skia/include/ports/SkTypeface_win.h +++ b/gfx/skia/skia/include/ports/SkTypeface_win.h @@ -9,7 +9,6 @@ #define SkTypeface_win_DEFINED #include "SkTypeface.h" -#include /** * Like the other Typeface create methods, this returns a new reference to the @@ -40,16 +39,6 @@ class SkFontMgr; class SkRemotableFontMgr; struct IDWriteFactory; -/** - * Like the other Typeface create methods, this returns a new reference to the - * corresponding typeface for the specified dwrite font. The caller is responsible - * for calling unref() when it is finished. - */ -SK_API SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFactory* aFactory, - IDWriteFontFace* aFontFace, - IDWriteFont* aFont, - IDWriteFontFamily* aFontFamily); - SK_API SkFontMgr* SkFontMgr_New_GDI(); SK_API SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory = NULL); diff --git a/gfx/skia/skia/src/ports/SkFontHost_win.cpp b/gfx/skia/skia/src/ports/SkFontHost_win.cpp index 0bee788015b..e4aab81b150 100755 --- a/gfx/skia/skia/src/ports/SkFontHost_win.cpp +++ b/gfx/skia/skia/src/ports/SkFontHost_win.cpp @@ -27,7 +27,6 @@ #include "SkTemplates.h" #include "SkThread.h" #include "SkTypeface_win.h" -#include "SkTypeface_win_dw.h" #include "SkTypefaceCache.h" #include "SkUtils.h" @@ -343,18 +342,6 @@ SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) { return face; } -/*** - * This guy is public. - */ - -SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFactory* aFactory, - IDWriteFontFace* aFontFace, - IDWriteFont* aFont, - IDWriteFontFamily* aFontFamily) -{ - return DWriteFontTypeface::Create(aFactory, aFontFace, aFont, aFontFamily); -} - /** * The created SkTypeface takes ownership of fontMemResource. */ diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index 65fbf23b8d0..50c3d6d2f08 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -342,24 +342,6 @@ gfxDWriteFontFamily::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, AddSizeOfExcludingThis(aMallocSizeOf, aSizes); } -already_AddRefed -gfxDWriteFontFamily::GetDefaultFont() -{ - RefPtr font; - for (UINT32 i = 0; i < mDWFamily->GetFontCount(); i++) { - HRESULT hr = mDWFamily->GetFont(i, getter_AddRefs(font)); - if (FAILED(hr)) { - NS_WARNING("Failed to get default font from existing family"); - continue; - } - - return font.forget(); - } - - NS_WARNING("No available DWrite fonts. Returning null"); - return nullptr; -} - //////////////////////////////////////////////////////////////////////////////// // gfxDWriteFontEntry diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h index 1cd7d8eee64..9ce33613647 100644 --- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -57,7 +57,6 @@ public: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; - already_AddRefed GetDefaultFont(); protected: /** This font family's directwrite fontfamily object */ RefPtr mDWFamily; @@ -164,10 +163,6 @@ public: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; - already_AddRefed GetFont() { - return mFont.forget(); - } - protected: friend class gfxDWriteFont; friend class gfxDWriteFontList; diff --git a/gfx/thebes/gfxDWriteFonts.cpp b/gfx/thebes/gfxDWriteFonts.cpp index ce61314dac6..72a5c1f45bb 100644 --- a/gfx/thebes/gfxDWriteFonts.cpp +++ b/gfx/thebes/gfxDWriteFonts.cpp @@ -82,7 +82,7 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry, , mAllowManualShowGlyphs(true) { gfxDWriteFontEntry *fe = - static_cast(aFontEntry); + static_cast(aFontEntry); nsresult rv; DWRITE_FONT_SIMULATIONS sims = DWRITE_FONT_SIMULATIONS_NONE; if ((GetStyle()->style != NS_FONT_STYLE_NORMAL) && @@ -103,21 +103,6 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry, return; } - mFont = fe->GetFont(); - if (!mFont) { - gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList(); - gfxDWriteFontFamily* defaultFontFamily = - static_cast(fontList->GetDefaultFont(aFontStyle)); - - mFont = defaultFontFamily->GetDefaultFont(); - NS_WARNING("Using default font"); - } - - HRESULT hr = mFont->GetFontFamily(getter_AddRefs(mFontFamily)); - if (FAILED(hr)) { - MOZ_ASSERT(false); - } - ComputeMetrics(anAAOption); } @@ -702,10 +687,6 @@ gfxDWriteFont::GetScaledFont(mozilla::gfx::DrawTarget *aTarget) mAzureScaledFont = Factory::CreateScaledFontWithCairo(nativeFont, GetAdjustedSize(), GetCairoScaledFont()); - } else if (aTarget->GetBackendType() == BackendType::SKIA) { - mAzureScaledFont = - Factory::CreateScaledFontForDWriteFont(mFont, mFontFamily, - mFontFace, GetAdjustedSize()); } else { mAzureScaledFont = Factory::CreateScaledFontForNativeFont(nativeFont, GetAdjustedSize()); diff --git a/gfx/thebes/gfxDWriteFonts.h b/gfx/thebes/gfxDWriteFonts.h index 525d16a415c..89c085e6d64 100644 --- a/gfx/thebes/gfxDWriteFonts.h +++ b/gfx/thebes/gfxDWriteFonts.h @@ -91,8 +91,6 @@ protected: bool GetForceGDIClassic(); RefPtr mFontFace; - RefPtr mFont; - RefPtr mFontFamily; cairo_font_face_t *mCairoFontFace; Metrics *mMetrics; diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 0b37a1043ee..645bbefdb95 100755 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -690,7 +690,9 @@ gfxWindowsPlatform::CreatePlatformFontList() #ifdef CAIRO_HAS_DWRITE_FONT // bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd // crashers so blacklist them altogether - if (IsNotWin7PreRTM() && GetDWriteFactory()) { + if (IsNotWin7PreRTM() && GetDWriteFactory() && + // Skia doesn't support DirectWrite fonts yet. + (gfxPlatform::GetDefaultContentBackend() != BackendType::SKIA)) { pfl = new gfxDWriteFontList(); if (NS_SUCCEEDED(pfl->InitFontList())) { return pfl; From 3e7c85024b70909bf38aef5ba428f23605690564 Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Wed, 28 Oct 2015 14:55:45 -0700 Subject: [PATCH 45/95] Bug 1219452 - Update script for rust mp4parser. r=kinetik Automate update and patching of the rust mp4 parser from the upstream repo. A rev for mp4parse-rust can be passed on the command line, but the byteorder crate's version is hardcoded. Differences to adapt to the gecko build system are applied as patches like we do for other media code. Unfortunately cargo isn't much help here. It can download crates for us, and we can set CARGO_HOME to force it to use a specific directory, but it doesn't return enough information to get the versions, etc. without some guessing/scraping to find the packaged source. --- .../binding/byteorder-mod.patch | 37 +++++++++++++++++++ .../libstagefright/binding/mp4parse-mod.patch | 13 +++++++ media/libstagefright/binding/update-rust.sh | 37 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 media/libstagefright/binding/byteorder-mod.patch create mode 100644 media/libstagefright/binding/mp4parse-mod.patch create mode 100755 media/libstagefright/binding/update-rust.sh diff --git a/media/libstagefright/binding/byteorder-mod.patch b/media/libstagefright/binding/byteorder-mod.patch new file mode 100644 index 00000000000..cce9208bbb7 --- /dev/null +++ b/media/libstagefright/binding/byteorder-mod.patch @@ -0,0 +1,37 @@ +diff --git a/media/libstagefright/binding/byteorder/mod.rs b/media/libstagefright/binding/byteorder/mod.rs +index 59ba692..9d2d1d5 100644 +--- a/media/libstagefright/binding/byteorder/mod.rs ++++ b/media/libstagefright/binding/byteorder/mod.rs +@@ -36,16 +36,16 @@ assert_eq!(wtr, vec![5, 2, 0, 3]); + ``` + */ + +-#![crate_name = "byteorder"] + #![doc(html_root_url = "http://burntsushi.net/rustdoc/byteorder")] + + #![deny(missing_docs)] + + use std::mem::transmute; + +-pub use new::{ReadBytesExt, WriteBytesExt, Error, Result}; ++pub use byteorder::new::{ReadBytesExt, WriteBytesExt, Error, Result}; + +-mod new; ++// Re-export new so gecko can build us as a mod intead of a crate. ++pub mod new; + + #[inline] + fn extend_sign(val: u64, nbytes: usize) -> i64 { +diff --git a/media/libstagefright/binding/byteorder/new.rs b/media/libstagefright/binding/byteorder/new.rs +index bbef0cd..a2e5393 100644 +--- a/media/libstagefright/binding/byteorder/new.rs ++++ b/media/libstagefright/binding/byteorder/new.rs +@@ -3,7 +3,7 @@ use std::fmt; + use std::io; + use std::result; + +-use ByteOrder; ++use byteorder::ByteOrder; + + /// A short-hand for `result::Result`. + pub type Result = result::Result; diff --git a/media/libstagefright/binding/mp4parse-mod.patch b/media/libstagefright/binding/mp4parse-mod.patch new file mode 100644 index 00000000000..d122f9f9440 --- /dev/null +++ b/media/libstagefright/binding/mp4parse-mod.patch @@ -0,0 +1,13 @@ +diff --git a/media/libstagefright/binding/MP4Metadata.rs b/media/libstagefright/binding/MP4Metadata.rs +index a9ab567..b746f15 100644 +--- a/media/libstagefright/binding/MP4Metadata.rs ++++ b/media/libstagefright/binding/MP4Metadata.rs +@@ -214,7 +214,7 @@ pub struct Track { + track_type: TrackType, + } + +-extern crate byteorder; ++mod byteorder; // 'extern crate' upstream. + use byteorder::{BigEndian, ReadBytesExt}; + use std::io::{Read, BufRead, Take}; + use std::io::Cursor; diff --git a/media/libstagefright/binding/update-rust.sh b/media/libstagefright/binding/update-rust.sh new file mode 100755 index 00000000000..dbd08dbf840 --- /dev/null +++ b/media/libstagefright/binding/update-rust.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Script to update mp4parse-rust sources to latest upstream + +# Default version. +VER=v0.1.2 + +# Accept version or commit from the command line. +if test -n "$1"; then + VER=$1 +fi + +echo "Fetching sources..." +rm -rf _upstream +git clone https://github.com/mozilla/mp4parse-rust _upstream/mp4parse +pushd _upstream/mp4parse +git checkout ${VER} +popd +cp _upstream/mp4parse/src/lib.rs MP4Metadata.rs +cp _upstream/mp4parse/src/capi.rs . + +# TODO: download deps from crates.io. + +git clone https://github.com/BurntSushi/byteorder _upstream/byteorder +pushd _upstream/byteorder +git checkout 0.3.13 +popd +cp _upstream/byteorder/src/lib.rs byteorder/mod.rs +cp _upstream/byteorder/src/new.rs byteorder/new.rs + +echo "Applying patches..." +patch -p4 < byteorder-mod.patch +patch -p4 < mp4parse-mod.patch + +echo "Cleaning up..." +rm -rf _upstream + +echo "Updated to ${VER}." From 574f0890a6b9b559383acff794bee676aa631d4b Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Wed, 28 Oct 2015 15:00:49 -0700 Subject: [PATCH 46/95] Bug 1219452 - Fix unused attribute warning. r=kinetik Results of running the new update-rust script. - Include some #[inline] directives missed in bug 1215234. - Remove #[crate-name] directive to silence a warning caused by our building byteorder as a submodule instead of a crate. --- media/libstagefright/binding/byteorder/mod.rs | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/media/libstagefright/binding/byteorder/mod.rs b/media/libstagefright/binding/byteorder/mod.rs index 17d429d6865..9d2d1d532b1 100644 --- a/media/libstagefright/binding/byteorder/mod.rs +++ b/media/libstagefright/binding/byteorder/mod.rs @@ -36,7 +36,6 @@ assert_eq!(wtr, vec![5, 2, 0, 3]); ``` */ -#![crate_name = "byteorder"] #![doc(html_root_url = "http://burntsushi.net/rustdoc/byteorder")] #![deny(missing_docs)] @@ -45,9 +44,10 @@ use std::mem::transmute; pub use byteorder::new::{ReadBytesExt, WriteBytesExt, Error, Result}; -// Re-export new so gecko and build us as a mod intead of a crate. +// Re-export new so gecko can build us as a mod intead of a crate. pub mod new; +#[inline] fn extend_sign(val: u64, nbytes: usize) -> i64 { let shift = (8 - nbytes) * 8; (val << shift) as i64 >> shift @@ -123,6 +123,7 @@ pub trait ByteOrder { /// Reads a signed 16 bit integer from `buf`. /// /// Panics when `buf.len() < 2`. + #[inline] fn read_i16(buf: &[u8]) -> i16 { Self::read_u16(buf) as i16 } @@ -130,6 +131,7 @@ pub trait ByteOrder { /// Reads a signed 32 bit integer from `buf`. /// /// Panics when `buf.len() < 4`. + #[inline] fn read_i32(buf: &[u8]) -> i32 { Self::read_u32(buf) as i32 } @@ -137,6 +139,7 @@ pub trait ByteOrder { /// Reads a signed 64 bit integer from `buf`. /// /// Panics when `buf.len() < 8`. + #[inline] fn read_i64(buf: &[u8]) -> i64 { Self::read_u64(buf) as i64 } @@ -145,6 +148,7 @@ pub trait ByteOrder { /// /// Panics when `nbytes < 1` or `nbytes > 8` or /// `buf.len() < nbytes` + #[inline] fn read_int(buf: &[u8], nbytes: usize) -> i64 { extend_sign(Self::read_uint(buf, nbytes), nbytes) } @@ -152,6 +156,7 @@ pub trait ByteOrder { /// Reads a IEEE754 single-precision (4 bytes) floating point number. /// /// Panics when `buf.len() < 4`. + #[inline] fn read_f32(buf: &[u8]) -> f32 { unsafe { transmute(Self::read_u32(buf)) } } @@ -159,6 +164,7 @@ pub trait ByteOrder { /// Reads a IEEE754 double-precision (8 bytes) floating point number. /// /// Panics when `buf.len() < 8`. + #[inline] fn read_f64(buf: &[u8]) -> f64 { unsafe { transmute(Self::read_u64(buf)) } } @@ -166,6 +172,7 @@ pub trait ByteOrder { /// Writes a signed 16 bit integer `n` to `buf`. /// /// Panics when `buf.len() < 2`. + #[inline] fn write_i16(buf: &mut [u8], n: i16) { Self::write_u16(buf, n as u16) } @@ -173,6 +180,7 @@ pub trait ByteOrder { /// Writes a signed 32 bit integer `n` to `buf`. /// /// Panics when `buf.len() < 4`. + #[inline] fn write_i32(buf: &mut [u8], n: i32) { Self::write_u32(buf, n as u32) } @@ -180,6 +188,7 @@ pub trait ByteOrder { /// Writes a signed 64 bit integer `n` to `buf`. /// /// Panics when `buf.len() < 8`. + #[inline] fn write_i64(buf: &mut [u8], n: i64) { Self::write_u64(buf, n as u64) } @@ -187,6 +196,7 @@ pub trait ByteOrder { /// Writes a IEEE754 single-precision (4 bytes) floating point number. /// /// Panics when `buf.len() < 4`. + #[inline] fn write_f32(buf: &mut [u8], n: f32) { Self::write_u32(buf, unsafe { transmute(n) }) } @@ -194,6 +204,7 @@ pub trait ByteOrder { /// Writes a IEEE754 double-precision (8 bytes) floating point number. /// /// Panics when `buf.len() < 8`. + #[inline] fn write_f64(buf: &mut [u8], n: f64) { Self::write_u64(buf, unsafe { transmute(n) }) } @@ -271,60 +282,74 @@ macro_rules! write_num_bytes { } impl ByteOrder for BigEndian { + #[inline] fn read_u16(buf: &[u8]) -> u16 { read_num_bytes!(u16, 2, buf, to_be) } + #[inline] fn read_u32(buf: &[u8]) -> u32 { read_num_bytes!(u32, 4, buf, to_be) } + #[inline] fn read_u64(buf: &[u8]) -> u64 { read_num_bytes!(u64, 8, buf, to_be) } + #[inline] fn read_uint(buf: &[u8], nbytes: usize) -> u64 { read_num_bytes!(u64, 8, be nbytes, buf, to_be) } + #[inline] fn write_u16(buf: &mut [u8], n: u16) { write_num_bytes!(u16, 2, n, buf, to_be); } + #[inline] fn write_u32(buf: &mut [u8], n: u32) { write_num_bytes!(u32, 4, n, buf, to_be); } + #[inline] fn write_u64(buf: &mut [u8], n: u64) { write_num_bytes!(u64, 8, n, buf, to_be); } } impl ByteOrder for LittleEndian { + #[inline] fn read_u16(buf: &[u8]) -> u16 { read_num_bytes!(u16, 2, buf, to_le) } + #[inline] fn read_u32(buf: &[u8]) -> u32 { read_num_bytes!(u32, 4, buf, to_le) } + #[inline] fn read_u64(buf: &[u8]) -> u64 { read_num_bytes!(u64, 8, buf, to_le) } + #[inline] fn read_uint(buf: &[u8], nbytes: usize) -> u64 { read_num_bytes!(u64, 8, le nbytes, buf, to_le) } + #[inline] fn write_u16(buf: &mut [u8], n: u16) { write_num_bytes!(u16, 2, n, buf, to_le); } + #[inline] fn write_u32(buf: &mut [u8], n: u32) { write_num_bytes!(u32, 4, n, buf, to_le); } + #[inline] fn write_u64(buf: &mut [u8], n: u64) { write_num_bytes!(u64, 8, n, buf, to_le); } From 6149ddc123a4e3177354b1154627f71e5d6807f5 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 29 Oct 2015 00:04:05 +0100 Subject: [PATCH 47/95] Bug 1219411: Correctly use RGBA instead of RGB for the background color in background-blending-moz-element reftest. r=mstange --- .../css-blending/background-blending-moz-element-ref.html | 2 +- .../reftests/css-blending/background-blending-moz-element.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/reftests/css-blending/background-blending-moz-element-ref.html b/layout/reftests/css-blending/background-blending-moz-element-ref.html index 285d30194ef..70298325c45 100644 --- a/layout/reftests/css-blending/background-blending-moz-element-ref.html +++ b/layout/reftests/css-blending/background-blending-moz-element-ref.html @@ -9,7 +9,7 @@ .c { height: 10px; - background: rgb(0,255,0,.5); + background: rgba(0,255,0,.5); } diff --git a/layout/reftests/css-blending/background-blending-moz-element.html b/layout/reftests/css-blending/background-blending-moz-element.html index be0e93726e3..11272a70f69 100644 --- a/layout/reftests/css-blending/background-blending-moz-element.html +++ b/layout/reftests/css-blending/background-blending-moz-element.html @@ -12,7 +12,7 @@ div { } #b { - background: rgb(0,255,0,.5); + background: rgba(0,255,0,.5); } #c { background: -moz-element(#b); From 7d88d7d188cb5a282434119bdd13880a0b461b97 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 28 Oct 2015 19:16:13 -0400 Subject: [PATCH 48/95] Fix the help string for ./mach web-platform-tests --e10s, no bug, DONTBUILD --- testing/web-platform/harness/wptrunner/wptcommandline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/web-platform/harness/wptrunner/wptcommandline.py b/testing/web-platform/harness/wptrunner/wptcommandline.py index e9e42a0b01f..19be4c0be72 100644 --- a/testing/web-platform/harness/wptrunner/wptcommandline.py +++ b/testing/web-platform/harness/wptrunner/wptcommandline.py @@ -155,7 +155,7 @@ def create_parser(product_choices=None): gecko_group.add_argument("--prefs-root", dest="prefs_root", action="store", type=abs_path, help="Path to the folder containing browser prefs") gecko_group.add_argument("--e10s", dest="gecko_e10s", action="store_true", - help="Path to the folder containing browser prefs") + help="Run tests with electrolysis preferences") b2g_group = parser.add_argument_group("B2G-specific") b2g_group.add_argument("--b2g-no-backup", action="store_true", default=False, From 0b347434ba4196c2c5b974cc21da4f38648df707 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 28 Oct 2015 11:28:21 +1100 Subject: [PATCH 49/95] Bug 1218157: Only ever read from cached data in NotifyDataArrived. r=cpearce The logic of queuing NotifyDataArrived and read data there was fundamentally flawed as we would continually perform reads from the same MediaResource at two different ends. This would cause repetitive seeks and data being removed from the media cache. Worse, a read in NotifyDataArrived would cause another NotifyDataArrived to be scheduled. As range-request are extremely slow, it would result in stutters and constant interruptions. --- dom/media/apple/AppleMP3Reader.cpp | 29 ++++++++++++++++------- dom/media/directshow/DirectShowReader.cpp | 28 +++++++++++++++------- dom/media/gstreamer/GStreamerReader.cpp | 28 +++++++++++++++------- dom/media/omx/MediaCodecReader.cpp | 15 ++++++++++-- dom/media/omx/MediaOmxReader.cpp | 26 +++++++++++++------- dom/media/webm/WebMReader.cpp | 18 ++++++++++---- 6 files changed, 103 insertions(+), 41 deletions(-) diff --git a/dom/media/apple/AppleMP3Reader.cpp b/dom/media/apple/AppleMP3Reader.cpp index f38f530aa65..d477ff22fb3 100644 --- a/dom/media/apple/AppleMP3Reader.cpp +++ b/dom/media/apple/AppleMP3Reader.cpp @@ -507,23 +507,34 @@ AppleMP3Reader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) return; } - IntervalSet intervals = mFilter.NotifyDataArrived(aLength, aOffset); + AutoPinned resource(mResource.GetResource()); + nsTArray byteRanges; + nsresult rv = resource->GetCachedRanges(byteRanges); + + if (NS_FAILED(rv)) { + return; + } + + IntervalSet intervals; + for (auto& range : byteRanges) { + intervals += mFilter.NotifyDataArrived(range.Length(), range.mStart); + } for (const auto& interval : intervals) { RefPtr bytes = - mResource.MediaReadAt(interval.mStart, interval.Length()); + resource->MediaReadAt(interval.mStart, interval.Length()); NS_ENSURE_TRUE_VOID(bytes); mMP3FrameParser.Parse(bytes->Elements(), interval.Length(), interval.mStart); if (!mMP3FrameParser.IsMP3()) { return; } + } - uint64_t duration = mMP3FrameParser.GetDuration(); - if (duration != mDuration) { - LOGD("Updating media duration to %lluus\n", duration); - MOZ_ASSERT(mDecoder); - mDuration = duration; - mDecoder->DispatchUpdateEstimatedMediaDuration(duration); - } + uint64_t duration = mMP3FrameParser.GetDuration(); + if (duration != mDuration) { + LOGD("Updating media duration to %lluus\n", duration); + MOZ_ASSERT(mDecoder); + mDuration = duration; + mDecoder->DispatchUpdateEstimatedMediaDuration(duration); } } diff --git a/dom/media/directshow/DirectShowReader.cpp b/dom/media/directshow/DirectShowReader.cpp index 7d493b0a079..1dbc57e4381 100644 --- a/dom/media/directshow/DirectShowReader.cpp +++ b/dom/media/directshow/DirectShowReader.cpp @@ -387,22 +387,32 @@ DirectShowReader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) return; } - IntervalSet intervals = mFilter.NotifyDataArrived(aLength, aOffset); + AutoPinned resource(mDecoder->GetResource()); + nsTArray byteRanges; + nsresult rv = resource->GetCachedRanges(byteRanges); + + if (NS_FAILED(rv)) { + return; + } + + IntervalSet intervals; + for (auto& range : byteRanges) { + intervals += mFilter.NotifyDataArrived(range.Length(), range.mStart); + } for (const auto& interval : intervals) { RefPtr bytes = - mDecoder->GetResource()->MediaReadAt(interval.mStart, interval.Length()); + resource->MediaReadAt(interval.mStart, interval.Length()); NS_ENSURE_TRUE_VOID(bytes); mMP3FrameParser.Parse(bytes->Elements(), interval.Length(), interval.mStart); if (!mMP3FrameParser.IsMP3()) { return; } - - int64_t duration = mMP3FrameParser.GetDuration(); - if (duration != mDuration) { - MOZ_ASSERT(mDecoder); - mDuration = duration; - mDecoder->DispatchUpdateEstimatedMediaDuration(mDuration); - } + } + int64_t duration = mMP3FrameParser.GetDuration(); + if (duration != mDuration) { + MOZ_ASSERT(mDecoder); + mDuration = duration; + mDecoder->DispatchUpdateEstimatedMediaDuration(mDuration); } } diff --git a/dom/media/gstreamer/GStreamerReader.cpp b/dom/media/gstreamer/GStreamerReader.cpp index 2a68059903b..41e0d97eca6 100644 --- a/dom/media/gstreamer/GStreamerReader.cpp +++ b/dom/media/gstreamer/GStreamerReader.cpp @@ -1286,22 +1286,32 @@ void GStreamerReader::NotifyDataArrivedInternal(uint32_t aLength, return; } - IntervalSet intervals = mFilter.NotifyDataArrived(aLength, aOffset); + AutoPinned resource(mResource.GetResource()); + nsTArray byteRanges; + nsresult rv = resource->GetCachedRanges(byteRanges); + + if (NS_FAILED(rv)) { + return; + } + + IntervalSet intervals; + for (auto& range : byteRanges) { + intervals += mFilter.NotifyDataArrived(range.Length(), range.mStart); + } for (const auto& interval : intervals) { RefPtr bytes = - mResource.MediaReadAt(interval.mStart, interval.Length()); + resource->MediaReadAt(interval.mStart, interval.Length()); NS_ENSURE_TRUE_VOID(bytes); mMP3FrameParser.Parse(bytes->Elements(), interval.Length(), interval.mStart); if (!mMP3FrameParser.IsMP3()) { return; } - - int64_t duration = mMP3FrameParser.GetDuration(); - if (duration != mLastParserDuration && mUseParserDuration) { - MOZ_ASSERT(mDecoder); - mLastParserDuration = duration; - mDecoder->DispatchUpdateEstimatedMediaDuration(mLastParserDuration); - } + } + int64_t duration = mMP3FrameParser.GetDuration(); + if (duration != mLastParserDuration && mUseParserDuration) { + MOZ_ASSERT(mDecoder); + mLastParserDuration = duration; + mDecoder->DispatchUpdateEstimatedMediaDuration(mLastParserDuration); } } diff --git a/dom/media/omx/MediaCodecReader.cpp b/dom/media/omx/MediaCodecReader.cpp index 90fc29be8a3..a33b45285dd 100644 --- a/dom/media/omx/MediaCodecReader.cpp +++ b/dom/media/omx/MediaCodecReader.cpp @@ -520,10 +520,21 @@ void MediaCodecReader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) { - IntervalSet intervals = mFilter.NotifyDataArrived(aLength, aOffset); + AutoPinned resource(mDecoder->GetResource()); + nsTArray byteRanges; + nsresult rv = resource->GetCachedRanges(byteRanges); + + if (NS_FAILED(rv)) { + return; + } + + IntervalSet intervals; + for (auto& range : byteRanges) { + intervals += mFilter.NotifyDataArrived(range.Length(), range.mStart); + } for (const auto& interval : intervals) { RefPtr bytes = - mDecoder->GetResource()->MediaReadAt(interval.mStart, interval.Length()); + resource->MediaReadAt(interval.mStart, interval.Length()); MonitorAutoLock monLock(mParserMonitor); if (mNextParserPosition == mParsedDataLength && mNextParserPosition >= interval.mStart && diff --git a/dom/media/omx/MediaOmxReader.cpp b/dom/media/omx/MediaOmxReader.cpp index cc38da6889f..77096a83f61 100644 --- a/dom/media/omx/MediaOmxReader.cpp +++ b/dom/media/omx/MediaOmxReader.cpp @@ -463,21 +463,31 @@ void MediaOmxReader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset return; } - IntervalSet intervals = mFilter.NotifyDataArrived(aLength, aOffset); + AutoPinned resource(mDecoder->GetResource()); + nsTArray byteRanges; + nsresult rv = resource->GetCachedRanges(byteRanges); + + if (NS_FAILED(rv)) { + return; + } + + IntervalSet intervals; + for (auto& range : byteRanges) { + intervals += mFilter.NotifyDataArrived(range.Length(), range.mStart); + } for (const auto& interval : intervals) { RefPtr bytes = - mDecoder->GetResource()->MediaReadAt(interval.mStart, interval.Length()); + resource->MediaReadAt(interval.mStart, interval.Length()); NS_ENSURE_TRUE_VOID(bytes); mMP3FrameParser.Parse(bytes->Elements(), interval.Length(), interval.mStart); if (!mMP3FrameParser.IsMP3()) { return; } - - int64_t duration = mMP3FrameParser.GetDuration(); - if (duration != mLastParserDuration) { - mLastParserDuration = duration; - decoder->DispatchUpdateEstimatedMediaDuration(mLastParserDuration); - } + } + int64_t duration = mMP3FrameParser.GetDuration(); + if (duration != mLastParserDuration) { + mLastParserDuration = duration; + decoder->DispatchUpdateEstimatedMediaDuration(mLastParserDuration); } } diff --git a/dom/media/webm/WebMReader.cpp b/dom/media/webm/WebMReader.cpp index 8797eda15ce..d8c7272c176 100644 --- a/dom/media/webm/WebMReader.cpp +++ b/dom/media/webm/WebMReader.cpp @@ -790,10 +790,20 @@ media::TimeIntervals WebMReader::GetBuffered() void WebMReader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) { MOZ_ASSERT(OnTaskQueue()); - RefPtr bytes = - mDecoder->GetResource()->MediaReadAt(aOffset, aLength); - NS_ENSURE_TRUE_VOID(bytes); - mBufferedState->NotifyDataArrived(bytes->Elements(), aLength, aOffset); + AutoPinned resource(mDecoder->GetResource()); + nsTArray byteRanges; + nsresult rv = resource->GetCachedRanges(byteRanges); + + if (NS_FAILED(rv)) { + return; + } + + for (auto& range : byteRanges) { + RefPtr bytes = + resource->MediaReadAt(range.mStart, range.Length()); + NS_ENSURE_TRUE_VOID(bytes); + mBufferedState->NotifyDataArrived(bytes->Elements(), aLength, aOffset); + } } int WebMReader::GetVideoCodec() From 4b58755cd675fc9ec9d1c31a7376fd573bbcbdcf Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 28 Oct 2015 14:14:11 +1100 Subject: [PATCH 50/95] Bug 1213177: Enable WebM on machines where H264 HW decoding is disabled. r=kentuckyfriedtakahe --- dom/media/mediasource/MediaSource.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dom/media/mediasource/MediaSource.cpp b/dom/media/mediasource/MediaSource.cpp index 7d0f11b1327..ac3ebe99d19 100644 --- a/dom/media/mediasource/MediaSource.cpp +++ b/dom/media/mediasource/MediaSource.cpp @@ -27,6 +27,7 @@ #include "nsThreadUtils.h" #include "mozilla/Logging.h" #include "nsServiceManagerUtils.h" +#include "gfxPlatform.h" #ifdef MOZ_WIDGET_ANDROID #include "AndroidBridge.h" @@ -75,13 +76,14 @@ static const char* const gMediaSourceTypes[6] = { // * Windows Vista and Server 2008 without the optional "Platform Update Supplement" // * N/KN editions (Europe and Korea) of Windows 7/8/8.1/10 without the // optional "Windows Media Feature Pack" - +// 2. If H264 hardware acceleration is not available. static bool IsWebMForced() { bool mp4supported = DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4")); - return !mp4supported; + bool hwsupported = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding(); + return !mp4supported || !hwsupported; } static nsresult From 10226182f682518a111ddfb79fe7e397e3ffb6f4 Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Wed, 28 Oct 2015 08:58:35 +0900 Subject: [PATCH 51/95] Bug 1219057 - Do not show "Unable to print stack trace" for exception thrown while compiling top-level script. r=jandem --- js/src/shell/js.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 126dace94dd..99de6308e6a 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -5239,9 +5239,10 @@ PrintStackTrace(JSContext* cx, HandleValue exn) if (!exnObj->is()) return true; + // Exceptions thrown while compiling top-level script have no stack. RootedObject stackObj(cx, exnObj->as().stack()); if (!stackObj) - return false; + return true; RootedString stackStr(cx); if (!BuildStackString(cx, stackObj, &stackStr, 2)) From 115bf7eb696b195e0d8ab0d619a00a27cb6878e3 Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Wed, 28 Oct 2015 03:41:04 +0900 Subject: [PATCH 52/95] Bug 819125 - Reset return value before executing catch/finally block. r=jandem --- js/src/frontend/BytecodeEmitter.cpp | 35 +- .../tests/ecma_6/Statements/try-completion.js | 482 ++++++++++++++++++ js/src/vm/Xdr.h | 2 +- 3 files changed, 511 insertions(+), 8 deletions(-) create mode 100644 js/src/tests/ecma_6/Statements/try-completion.js diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 111b1a9f549..f7ef1959822 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4984,6 +4984,15 @@ BytecodeEmitter::emitTry(ParseNode* pn) for (ParseNode* pn3 = catchList->pn_head; pn3; pn3 = pn3->pn_next) { MOZ_ASSERT(this->stackDepth == depth); + // Clear the frame's return value that might have been set by the + // try block: + // + // eval("try { 1; throw 2 } catch(e) {}"); // undefined, not 1 + if (!emit1(JSOP_UNDEFINED)) + return false; + if (!emit1(JSOP_SETRVAL)) + return false; + // Emit the lexical scope and catch body. MOZ_ASSERT(pn3->isKind(PNK_LEXICALSCOPE)); if (!emitTree(pn3)) @@ -5034,14 +5043,26 @@ BytecodeEmitter::emitTry(ParseNode* pn) stmtInfo.type = StmtType::SUBROUTINE; if (!updateSourceCoordNotes(pn->pn_kid3->pn_pos.begin)) return false; - if (!emit1(JSOP_FINALLY) || - !emit1(JSOP_GETRVAL) || - !emitTree(pn->pn_kid3) || - !emit1(JSOP_SETRVAL) || - !emit1(JSOP_RETSUB)) - { + if (!emit1(JSOP_FINALLY)) + return false; + if (!emit1(JSOP_GETRVAL)) + return false; + + // Clear the frame's return value to make break/continue return + // correct value even if there's no other statement before them: + // + // eval("x: try { 1 } finally { break x; }"); // undefined, not 1 + if (!emit1(JSOP_UNDEFINED)) + return false; + if (!emit1(JSOP_SETRVAL)) + return false; + + if (!emitTree(pn->pn_kid3)) + return false; + if (!emit1(JSOP_SETRVAL)) + return false; + if (!emit1(JSOP_RETSUB)) return false; - } hasTryFinally = true; MOZ_ASSERT(this->stackDepth == depth); } diff --git a/js/src/tests/ecma_6/Statements/try-completion.js b/js/src/tests/ecma_6/Statements/try-completion.js new file mode 100644 index 00000000000..f9bd1e14963 --- /dev/null +++ b/js/src/tests/ecma_6/Statements/try-completion.js @@ -0,0 +1,482 @@ +var BUGNUMBER = 819125; +var summary = "try block should return try value if finally returned normally"; + +print(BUGNUMBER + ": " + summary); + +function expectTryValue(code, isUndefined) { + assertEq(eval(code), isUndefined ? undefined : 'try'); +} + +function expectCatchValue(code, isUndefined) { + assertEq(eval(code), isUndefined ? undefined : 'catch'); +} + +function expectFinallyValue(code, isUndefined) { + assertEq(eval(code), isUndefined ? undefined : 'finally'); +} + +// ==== finally: normal ==== + +// try: normal +// finally: normal +expectTryValue(` +try { + 'try'; +} finally { + 'finally'; +} +`); + +// try: normal without value +// finally: normal +expectTryValue(` +try { +} finally { + 'finally'; +} +`, true); + +// try: break +// finally: normal +expectTryValue(` +while (true) { + try { + 'try'; + break; + } finally { + 'finally'; + } +} +`); + +// try: break without value +// finally: normal +expectTryValue(` +while (true) { + try { + break; + } finally { + 'finally'; + } +} +`, true); + +// try: continue +// finally: normal +expectTryValue(` +do { + try { + 'try'; + continue; + } finally { + 'finally'; + } +} while (false); +`); + +// try: continue without value +// finally: normal +expectTryValue(` +do { + try { + continue; + } finally { + 'finally'; + } +} while (false); +`, true); + +// try: throw +// catch: normal +// finally: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { + 'catch'; +} finally { + 'finally'; +} +`); + +// try: throw +// catch: normal +// finally: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { + 'catch'; +} finally { + 'finally'; +} +`); + +// try: throw +// catch: normal without value +// finally: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { +} finally { + 'finally'; +} +`, true); + +// try: throw +// catch: normal without value +// finally: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { +} finally { + 'finally'; +} +`, true); + +// try: throw +// catch: break +// finally: normal +expectCatchValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + break; + } finally { + 'finally'; + } +} +`); + +// try: throw +// catch: break without value +// finally: normal +expectCatchValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + break; + } finally { + 'finally'; + } +} +`, true); + +// try: throw +// catch: continue +// finally: normal +expectCatchValue(` +do { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + continue; + } finally { + 'finally'; + } +} while (false); +`); + +// try: throw +// catch: continue without value +// finally: normal +expectCatchValue(` +do { + try { + 'try'; + throw 'exception'; + } catch (e) { + continue; + } finally { + 'finally'; + } +} while (false); +`, true); + +// ==== finally: break ==== + +// try: normal +// finally: break +expectFinallyValue(` +while (true) { + try { + 'try'; + } finally { + 'finally'; + break; + } +} +`); + +// try: normal +// finally: break without value +expectFinallyValue(` +while (true) { + try { + 'try'; + } finally { + break; + } +} +`, true); + +// try: break +// finally: break +expectFinallyValue(` +while (true) { + try { + 'try'; + break; + } finally { + 'finally'; + break; + } +} +`); + +// try: break +// finally: break without value +expectFinallyValue(` +while (true) { + try { + 'try'; + break; + } finally { + break; + } +} +`, true); + +// try: continue +// finally: break +expectFinallyValue(` +do { + try { + 'try'; + continue; + } finally { + 'finally'; + break; + } +} while (false); +`); + +// try: continue +// finally: break without value +expectFinallyValue(` +do { + try { + 'try'; + continue; + } finally { + break; + } +} while (false); +`, true); + +// try: throw +// catch: normal +// finally: break +expectFinallyValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + } finally { + 'finally'; + break; + } +} +`, false); + +// try: throw +// catch: normal +// finally: break without value +expectFinallyValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + } finally { + break; + } +} +`, true); + +// ==== finally: continue ==== + +// try: normal +// finally: continue +expectFinallyValue(` +do { + try { + 'try'; + } finally { + 'finally'; + continue; + } +} while (false); +`); + +// try: normal +// finally: continue without value +expectFinallyValue(` +do { + try { + 'try'; + } finally { + continue; + } +} while (false); +`, true); + +// try: break +// finally: continue +expectFinallyValue(` +do { + try { + 'try'; + break; + } finally { + 'finally'; + continue; + } +} while (false); +`); + +// try: break +// finally: continue without value +expectFinallyValue(` +do { + try { + 'try'; + break; + } finally { + continue; + } +} while (false); +`, true); + +// try: continue +// finally: continue +expectFinallyValue(` +do { + try { + 'try'; + continue; + } finally { + 'finally'; + continue; + } +} while (false); +`); + +// try: continue +// finally: continue without value +expectFinallyValue(` +do { + try { + 'try'; + continue; + } finally { + continue; + } +} while (false); +`, true); + +// ==== without finally ==== + +// try: throw +// catch: normal +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { + 'catch'; +} +`); + +// try: throw +// catch: normal without value +expectCatchValue(` +try { + 'try'; + throw 'exception'; +} catch (e) { +} +`, true); + +// try: throw +// catch: break +expectCatchValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + break; + } +} +`); + +// try: throw +// catch: break without value +expectCatchValue(` +while (true) { + try { + 'try'; + throw 'exception'; + } catch (e) { + break; + } +} +`, true); + +// try: throw +// catch: continue +expectCatchValue(` +do { + try { + 'try'; + throw 'exception'; + } catch (e) { + 'catch'; + continue; + } +} while (false); +`); + +// try: throw +// catch: continue without value +expectCatchValue(` +do { + try { + 'try'; + throw 'exception'; + } catch (e) { + continue; + } +} while (false); +`, true); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index 510097d36b6..051b10f38e9 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -29,7 +29,7 @@ namespace js { * * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode */ -static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 317; +static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 318; static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND); From 8ed3f7bb89726797dd738c9a1716669885a7ffbb Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Mon, 19 Oct 2015 03:53:14 +0900 Subject: [PATCH 53/95] Bug 1217982 - Remove for-each from storage/. r=mak --- storage/test/unit/test_js_helpers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/test/unit/test_js_helpers.js b/storage/test/unit/test_js_helpers.js index 185240c6a23..727c2aeebea 100644 --- a/storage/test/unit/test_js_helpers.js +++ b/storage/test/unit/test_js_helpers.js @@ -70,7 +70,7 @@ function test_params_gets_sync() // Make sure we do not assert in getting the value. let originalCount = Object.getOwnPropertyNames(stmt.params).length; let expected = ["a", "b", "c"]; - for each (let name in expected) { + for (let name of expected) { stmt.params[name]; } @@ -91,7 +91,7 @@ function test_params_gets_async() // Make sure we do not assert in getting the value. let originalCount = Object.getOwnPropertyNames(stmt.params).length; let expected = ["a", "b", "c"]; - for each (let name in expected) { + for (let name of expected) { stmt.params[name]; } From d23da6e1a56e3dfb8ef51ae2c1282edd9264786c Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Tue, 27 Oct 2015 08:49:03 +1100 Subject: [PATCH 54/95] Bug 1218577: Use only Blank PDM if enabled. r=kamidphish --- dom/media/platforms/PDMFactory.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index 1499697d4cb..6838c08dcab 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -241,6 +241,15 @@ PDMFactory::CreatePDMs() { RefPtr m; + if (sUseBlankDecoder) { + m = CreateBlankDecoderModule(); + StartupPDM(m); + // The Blank PDM SupportsMimeType reports true for all codecs; the creation + // of its decoder is infallible. As such it will be used for all media, we + // can stop creating more PDM from this point. + return; + } + if (sGMPDecoderEnabled) { m = new GMPDecoderModule(); StartupPDM(m); @@ -282,11 +291,6 @@ PDMFactory::CreatePDMs() m = new AgnosticDecoderModule(); StartupPDM(m); - - if (sUseBlankDecoder) { - m = CreateBlankDecoderModule(); - StartupPDM(m); - } } bool From cef55f867e102106fff83785158b1234996d3eaf Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:42 -0700 Subject: [PATCH 55/95] Bug 1207355 (Part 1) - Stop requesting decodes in nsDocument. r=tn --- b2g/app/b2g.js | 1 - dom/base/nsDocument.cpp | 17 ++--------------- layout/base/nsPresShell.cpp | 19 ++++++++++++++++++- layout/generic/nsImageFrame.h | 1 + modules/libpref/init/all.js | 3 --- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index d74046a0429..a32cc42a829 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -343,7 +343,6 @@ pref("image.mem.surfacecache.max_size_kb", 131072); // 128MB pref("image.mem.surfacecache.size_factor", 8); // 1/8 of main memory pref("image.mem.surfacecache.discard_factor", 2); // Discard 1/2 of the surface cache at a time. pref("image.mem.surfacecache.min_expiration_ms", 86400000); // 24h, we rely on the out of memory hook -pref("image.onload.decode.limit", 24); /* don't decode more than 24 images eagerly */ // XXX this isn't a good check for "are touch events supported", but // we don't really have a better one at the moment. diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index c836aa1e810..bd4939a9cbf 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -2117,9 +2117,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument) tmp->mInUnlinkOrDeletion = false; NS_IMPL_CYCLE_COLLECTION_UNLINK_END -static bool sPrefsInitialized = false; -static uint32_t sOnloadDecodeLimit = 0; - nsresult nsDocument::Init() { @@ -2127,11 +2124,6 @@ nsDocument::Init() return NS_ERROR_ALREADY_INITIALIZED; } - if (!sPrefsInitialized) { - sPrefsInitialized = true; - Preferences::AddUintVarCache(&sOnloadDecodeLimit, "image.onload.decode.limit", 0); - } - // Force initialization. nsINode::nsSlots* slots = Slots(); @@ -10522,12 +10514,8 @@ nsDocument::AddImage(imgIRequest* aImage) // If this is the first insertion and we're locking images, lock this image // too. - if (oldCount == 0) { - if (mLockingImages) - rv = aImage->LockImage(); - if (NS_SUCCEEDED(rv) && (!sOnloadDecodeLimit || - mImageTracker.Count() < sOnloadDecodeLimit)) - rv = aImage->StartDecoding(); + if (oldCount == 0 && mLockingImages) { + rv = aImage->LockImage(); } // If this is the first insertion and we're animating images, request @@ -10658,7 +10646,6 @@ PLDHashOperator LockEnumerator(imgIRequest* aKey, void* userArg) { aKey->LockImage(); - aKey->RequestDecode(); return PL_DHASH_NEXT; } diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index d0c70289dfa..b1a2d7152e8 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -168,6 +168,7 @@ #include "mozilla/Telemetry.h" #include "nsCanvasFrame.h" #include "nsIImageLoadingContent.h" +#include "nsImageFrame.h" #include "nsIScreen.h" #include "nsIScreenManager.h" #include "nsPlaceholderFrame.h" @@ -10701,7 +10702,23 @@ nsresult PresShell::UpdateImageLockingState() { // We're locked if we're both thawed and active. - return mDocument->SetImageLockingState(!mFrozen && mIsActive); + bool locked = !mFrozen && mIsActive; + + nsresult rv = mDocument->SetImageLockingState(locked); + + if (locked) { + // Request decodes for visible images; we want to start decoding as + // quickly as possible when we get foregrounded to minimize flashing. + for (auto iter = mVisibleImages.Iter(); !iter.Done(); iter.Next()) { + nsCOMPtr content = do_QueryInterface(iter.Get()->GetKey()); + nsImageFrame* imageFrame = do_QueryFrame(content->GetPrimaryFrame()); + if (imageFrame) { + imageFrame->MaybeDecodeForPredictedSize(); + } + } + } + + return rv; } PresShell* diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 4f43e35215d..a2b7190d0ea 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -230,6 +230,7 @@ protected: protected: friend class nsImageListener; friend class nsImageLoadingContent; + friend class PresShell; nsresult OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage); nsresult OnFrameUpdate(imgIRequest* aRequest, const nsIntRect* aRect); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 73a04990355..2b27904ae63 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4152,9 +4152,6 @@ pref("image.multithreaded_decoding.limit", -1); // cache. pref("canvas.image.cache.limit", 0); -// How many images to eagerly decode on a given page. 0 means "no limit". -pref("image.onload.decode.limit", 0); - // WebGL prefs #ifdef ANDROID // Disable MSAA on mobile. From 96eaaa17c41dd75164aa9d785421d2c1c786aede Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 56/95] Bug 1207355 (Part 2) - Stop requesting decodes in nsImageLoadingContent. r=tn --- dom/base/nsImageLoadingContent.cpp | 47 ------------------------------ 1 file changed, 47 deletions(-) diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index 75ba3f347c5..fcd1aaa54b5 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -229,53 +229,6 @@ nsImageLoadingContent::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus) MOZ_ASSERT(aRequest == mCurrentRequest, "One way or another, we should be current by now"); - // We just loaded all the data we're going to get. If we're visible and - // haven't done an initial paint (*), we want to make sure the image starts - // decoding immediately, for two reasons: - // - // 1) This image is sitting idle but might need to be decoded as soon as we - // start painting, in which case we've wasted time. - // - // 2) We want to block onload until all visible images are decoded. We do this - // by blocking onload until all in-progress decodes get at least one frame - // decoded. However, if all the data comes in while painting is suppressed - // (ie, before the initial paint delay is finished), we fire onload without - // doing a paint first. This means that decode-on-draw images don't start - // decoding, so we can't wait for them to finish. See bug 512435. - // - // (*) IsPaintingSuppressed returns false if we haven't gotten the initial - // reflow yet, so we have to test !DidInitialize || IsPaintingSuppressed. - // It's possible for painting to be suppressed for reasons other than the - // initial paint delay (for example, being in the bfcache), but we probably - // aren't loading images in those situations. - - // XXXkhuey should this be GetOurCurrentDoc? Decoding if we're not in - // the document seems silly. - nsIDocument* doc = GetOurOwnerDoc(); - nsIPresShell* shell = doc ? doc->GetShell() : nullptr; - if (shell && shell->IsVisible() && - (!shell->DidInitialize() || shell->IsPaintingSuppressed())) { - - nsIFrame* f = GetOurPrimaryFrame(); - // If we haven't gotten a frame yet either we aren't going to (so don't - // bother kicking off a decode), or we will get very soon on the next - // refresh driver tick when it flushes. And it will most likely be a - // specific image type frame (we only create generic (ie inline) type - // frames for images that don't have a size, and since we have all the data - // we should have the size) which will check its own visibility on its - // first reflow. - if (f) { - // If we've gotten a frame and that frame has called FrameCreate and that - // frame has been reflowed then we know that it checked it's own visibility - // so we can trust our visible count and we don't start decode if we are not - // visible. - if (!mFrameCreateCalled || (f->GetStateBits() & NS_FRAME_FIRST_REFLOW) || - mVisibleCount > 0 || shell->AssumeAllImagesVisible()) { - mCurrentRequest->StartDecoding(); - } - } - } - // Fire the appropriate DOM event. if (NS_SUCCEEDED(aStatus)) { FireEvent(NS_LITERAL_STRING("load")); From a96fd4ed25614c35dd9d01ac975537c826a7bb43 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 57/95] Bug 1207355 (Part 3) - Request decodes intelligently in nsImageFrame. r=tn --- layout/generic/nsImageFrame.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index f2a6dbc413a..a0411b6a1d1 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1814,7 +1814,11 @@ nsImageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, // decoded yet. And we are not going to ask the image to draw, so this // may be the only chance to tell it that it should decode. if (currentRequest) { - currentRequest->RequestDecode(); + uint32_t status = 0; + currentRequest->GetImageStatus(&status); + if (!(status & imgIRequest::STATUS_DECODE_COMPLETE)) { + MaybeDecodeForPredictedSize(); + } } } else { aLists.Content()->AppendNewToTop(new (aBuilder) @@ -2295,7 +2299,6 @@ nsresult nsImageFrame::LoadIcons(nsPresContext *aPresContext) if (NS_FAILED(rv)) { return rv; } - gIconLoad->mLoadingImage->RequestDecode(); rv = LoadIcon(brokenSrc, aPresContext, @@ -2303,7 +2306,6 @@ nsresult nsImageFrame::LoadIcons(nsPresContext *aPresContext) if (NS_FAILED(rv)) { return rv; } - gIconLoad->mBrokenImage->RequestDecode(); return rv; } @@ -2373,13 +2375,35 @@ void nsImageFrame::IconLoad::GetPrefs() } NS_IMETHODIMP -nsImageFrame::IconLoad::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) +nsImageFrame::IconLoad::Notify(imgIRequest* aRequest, + int32_t aType, + const nsIntRect* aData) { + MOZ_ASSERT(aRequest); + if (aType != imgINotificationObserver::LOAD_COMPLETE && aType != imgINotificationObserver::FRAME_UPDATE) { return NS_OK; } + if (aType == imgINotificationObserver::LOAD_COMPLETE) { + nsCOMPtr image; + aRequest->GetImage(getter_AddRefs(image)); + if (!image) { + return NS_ERROR_FAILURE; + } + + // Retrieve the image's intrinsic size. + int32_t width = 0; + int32_t height = 0; + image->GetWidth(&width); + image->GetHeight(&height); + + // Request a decode at that size. + image->RequestDecodeForSize(IntSize(width, height), + imgIContainer::DECODE_FLAGS_DEFAULT); + } + nsTObserverArray::ForwardIterator iter(mIconObservers); nsImageFrame *frame; while (iter.HasMore()) { From e71bb162dc12414c058a0e00ac4eaa47c4dd5f8f Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 58/95] Bug 1207355 (Part 4) - Request decodes intelligently in nsBulletFrame. r=tn --- layout/generic/nsBulletFrame.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/layout/generic/nsBulletFrame.cpp b/layout/generic/nsBulletFrame.cpp index 25c1f6dfcd8..f7472d2259c 100644 --- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -712,9 +712,20 @@ nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aDa // Unconditionally start decoding for now. // XXX(seth): We eventually want to decide whether to do this based on // visibility. We should get that for free from bug 1091236. - if (aRequest == mImageRequest) { - mImageRequest->RequestDecode(); + nsCOMPtr container; + aRequest->GetImage(getter_AddRefs(container)); + if (container) { + // Retrieve the intrinsic size of the image. + int32_t width = 0; + int32_t height = 0; + container->GetWidth(&width); + container->GetHeight(&height); + + // Request a decode at that size. + container->RequestDecodeForSize(IntSize(width, height), + imgIContainer::DECODE_FLAGS_DEFAULT); } + InvalidateFrame(); } From c82be0d745b0f34a3e8a4571819cb3b83b7f158b Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 59/95] Bug 1207355 (Part 5) - Request decodes intelligently in MultipartImage. r=tn --- image/MultipartImage.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/image/MultipartImage.cpp b/image/MultipartImage.cpp index 4950e7699c8..4eb34bf716f 100644 --- a/image/MultipartImage.cpp +++ b/image/MultipartImage.cpp @@ -70,6 +70,16 @@ public: return; } + // Retrieve the image's intrinsic size. + int32_t width = 0; + int32_t height = 0; + mImage->GetWidth(&width); + mImage->GetHeight(&height); + + // Request decoding at the intrinsic size. + mImage->RequestDecodeForSize(IntSize(width, height), + imgIContainer::DECODE_FLAGS_DEFAULT); + // If there's already an error, we may never get a FRAME_COMPLETE // notification, so go ahead and notify our owner right away. RefPtr tracker = mImage->GetProgressTracker(); @@ -125,7 +135,6 @@ MultipartImage::Init() RefPtr firstPartTracker = InnerImage()->GetProgressTracker(); firstPartTracker->AddObserver(this); - InnerImage()->RequestDecode(); InnerImage()->IncrementAnimationConsumers(); } @@ -154,7 +163,6 @@ MultipartImage::BeginTransitionToPart(Image* aNextPart) // Start observing the next part; we'll complete the transition when // NextPartObserver calls FinishTransition. mNextPartObserver->BeginObserving(mNextPart); - mNextPart->RequestDecode(); mNextPart->IncrementAnimationConsumers(); } From 62d0653212c9b2d4770f37eec419469aa7a04579 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 60/95] Bug 1207355 (Part 6) - Only respect StartDecoding() in imgRequest/imgRequestProxy. r=tn --- image/imgRequest.cpp | 2 +- image/imgRequestProxy.cpp | 27 +++------------------------ 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/image/imgRequest.cpp b/image/imgRequest.cpp index f6862039e38..1d850dc1ad5 100644 --- a/image/imgRequest.cpp +++ b/image/imgRequest.cpp @@ -1053,7 +1053,7 @@ imgRequest::FinishPreparingForNewPart(const NewPartResult& aResult) } if (IsDecodeRequested()) { - aResult.mImage->RequestDecode(); + aResult.mImage->StartDecoding(); } } diff --git a/image/imgRequestProxy.cpp b/image/imgRequestProxy.cpp index bf912ae2fbe..155de9a9544 100644 --- a/image/imgRequestProxy.cpp +++ b/image/imgRequestProxy.cpp @@ -208,15 +208,6 @@ imgRequestProxy::ChangeOwner(imgRequest* aNewOwner) uint32_t oldAnimationConsumers = mAnimationConsumers; ClearAnimationConsumers(); - // Were we decoded before? - bool wasDecoded = false; - RefPtr progressTracker = GetProgressTracker(); - if (progressTracker->HasImage() && - progressTracker->GetImageStatus() & - imgIRequest::STATUS_FRAME_COMPLETE) { - wasDecoded = true; - } - GetOwner()->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER); mBehaviour->SetOwner(aNewOwner); @@ -235,9 +226,9 @@ imgRequestProxy::ChangeOwner(imgRequest* aNewOwner) GetOwner()->AddProxy(this); - // If we were decoded, or if we'd previously requested a decode, request a - // decode on the new image - if (wasDecoded || mDecodeRequested) { + // If we'd previously requested a synchronous decode, request a decode on the + // new image. + if (mDecodeRequested) { StartDecoding(); } @@ -389,18 +380,6 @@ imgRequestProxy::StartDecoding() NS_IMETHODIMP imgRequestProxy::RequestDecode() { - // Flag this, so we know to transfer the request if our owner changes - mDecodeRequested = true; - - RefPtr image = GetImage(); - if (image) { - return image->RequestDecode(); - } - - if (GetOwner()) { - GetOwner()->RequestDecode(); - } - return NS_OK; } From 9b952ac16adac6f9f73874c78ee981ba82b2be44 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 61/95] Bug 1207355 (Part 7) - Only trigger intrinsic size decode in FinalizeDecoder() if StartDecoding() was called. r=tn --- image/RasterImage.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index c4642321528..d9ad6f76545 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -319,6 +319,9 @@ RasterImage::LookupFrame(uint32_t aFrameNum, IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags) ? aSize : mSize; + if (requestedSize.IsEmpty()) { + return DrawableFrameRef(); // Can't decode to a surface of zero size. + } LookupResult result = LookupFrameInternal(aFrameNum, requestedSize, aFlags); @@ -1175,6 +1178,15 @@ RasterImage::RequestDecode() NS_IMETHODIMP RasterImage::StartDecoding() { + if (mError) { + return NS_ERROR_FAILURE; + } + + if (!mHasSize) { + mWantFullDecode = true; + return NS_OK; + } + return RequestDecodeForSize(mSize, FLAG_SYNC_DECODE_IF_FAST); } @@ -1188,7 +1200,6 @@ RasterImage::RequestDecodeForSize(const IntSize& aSize, uint32_t aFlags) } if (!mHasSize) { - mWantFullDecode = true; return NS_OK; } From 7a98a9dcaa8703c51d2e4687e61ea69e6b94b64b Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 62/95] Bug 1207355 (Part 8) - Remove imgIContainer::RequestDecode() and imgIRequest::RequestDecode(). r=tn --- image/DynamicImage.cpp | 6 ------ image/ImageWrapper.cpp | 6 ------ image/RasterImage.cpp | 11 +---------- image/VectorImage.cpp | 9 --------- image/imgIContainer.idl | 20 +++++++------------- image/imgIRequest.idl | 13 ++++++------- image/imgLoader.cpp | 4 ++-- image/imgRequest.cpp | 2 +- image/imgRequest.h | 4 ++-- image/imgRequestProxy.cpp | 9 +-------- image/test/unit/image_load_helpers.js | 6 ------ layout/style/nsStyleStruct.h | 3 --- 12 files changed, 20 insertions(+), 73 deletions(-) diff --git a/image/DynamicImage.cpp b/image/DynamicImage.cpp index cf8d5555658..4fdf836080b 100644 --- a/image/DynamicImage.cpp +++ b/image/DynamicImage.cpp @@ -246,12 +246,6 @@ DynamicImage::Draw(gfxContext* aContext, return DrawResult::SUCCESS; } -NS_IMETHODIMP -DynamicImage::RequestDecode() -{ - return NS_OK; -} - NS_IMETHODIMP DynamicImage::StartDecoding() { diff --git a/image/ImageWrapper.cpp b/image/ImageWrapper.cpp index 3289678669e..44cc8fe0e8a 100644 --- a/image/ImageWrapper.cpp +++ b/image/ImageWrapper.cpp @@ -214,12 +214,6 @@ ImageWrapper::Draw(gfxContext* aContext, aFilter, aSVGContext, aFlags); } -NS_IMETHODIMP -ImageWrapper::RequestDecode() -{ - return mInnerImage->RequestDecode(); -} - NS_IMETHODIMP ImageWrapper::StartDecoding() { diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index d9ad6f76545..ba054ac8496 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -1166,15 +1166,6 @@ RasterImage::CanDiscard() { !mAnim; // Can never discard animated images } -//****************************************************************************** - -NS_IMETHODIMP -RasterImage::RequestDecode() -{ - return RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT); -} - - NS_IMETHODIMP RasterImage::StartDecoding() { @@ -1799,7 +1790,7 @@ RasterImage::FinalizeDecoder(Decoder* aDecoder) // If we were a metadata decode and a full decode was requested, do it. if (done && wasMetadata && mWantFullDecode) { mWantFullDecode = false; - RequestDecode(); + RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT); } } diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp index 0bcd4f46326..0703f18c298 100644 --- a/image/VectorImage.cpp +++ b/image/VectorImage.cpp @@ -964,15 +964,6 @@ VectorImage::RecoverFromLossOfSurfaces() SurfaceCache::RemoveImage(ImageKey(this)); } -//****************************************************************************** - -NS_IMETHODIMP -VectorImage::RequestDecode() -{ - // Nothing to do for SVG images - return NS_OK; -} - NS_IMETHODIMP VectorImage::StartDecoding() { diff --git a/image/imgIContainer.idl b/image/imgIContainer.idl index c190494ca6a..950ab0cda66 100644 --- a/image/imgIContainer.idl +++ b/image/imgIContainer.idl @@ -75,7 +75,7 @@ native nsIntSizeByVal(nsIntSize); * * Internally, imgIContainer also manages animation of images. */ -[scriptable, builtinclass, uuid(7c795421-a79c-43ac-9e20-6d4e8a9dfb76)] +[scriptable, builtinclass, uuid(a8dbee24-ff86-4755-b40e-51175caf31af)] interface imgIContainer : nsISupports { /** @@ -383,22 +383,16 @@ interface imgIContainer : nsISupports /* * Ensures that an image is decoding. Calling this function guarantees that - * the image will at some point fire off decode notifications. Calling draw() - * or getFrame() triggers the same mechanism internally. Thus, if you want to - * be sure that the image will be decoded but don't want to access it until - * then, you must call requestDecode(). - */ - void requestDecode(); - - /* - * This is equivalent to requestDecode() but it also synchronously decodes - * images that can be decoded "quickly" according to some heuristic. + * the image will at some point fire off decode notifications. Images that + * can be decoded "quickly" according to some heuristic will be decoded + * synchronously. */ [noscript] void startDecoding(); /* - * This method is equivalent to requestDecode(), but enables the caller to - * provide more detailed information about the decode request. + * This method triggers decoding for an image, but unlike startDecoding() it + * enables the caller to provide more detailed information about the decode + * request. * * @param aSize The size to which the image should be scaled while decoding, * if possible. If the image cannot be scaled to this size while diff --git a/image/imgIRequest.idl b/image/imgIRequest.idl index ef31511e7eb..680bd6e3ac6 100644 --- a/image/imgIRequest.idl +++ b/image/imgIRequest.idl @@ -19,7 +19,7 @@ interface nsIPrincipal; * @version 0.1 * @see imagelib2 */ -[scriptable, builtinclass, uuid(4cb01f0a-ef94-4345-a8d7-1a93f15ff548)] +[scriptable, builtinclass, uuid(db0a945c-3883-424a-98d0-2ee0523b0255)] interface imgIRequest : nsIRequest { /** @@ -145,15 +145,14 @@ interface imgIRequest : nsIRequest void cancelAndForgetObserver(in nsresult aStatus); /** - * Requests a decode for the image. + * Requests a synchronous decode for the image. * - * imgIContainer has a requestDecode() method, but callers may want to request + * imgIContainer has a startDecoding() method, but callers may want to request * a decode before the container has necessarily been instantiated. Calling - * requestDecode() on the imgIRequest simply forwards along the request if the - * container already exists, or calls it once it gets OnStartContainer if the - * container does not yet exist. + * startDecoding() on the imgIRequest simply forwards along the request if the + * container already exists, or calls it once the container becomes available + * if it does not yet exist. */ - void requestDecode(); void startDecoding(); /** diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index 33a5f0b86cc..aa298291dd2 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -1590,7 +1590,7 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request, // We will send notifications from imgCacheValidator::OnStartRequest(). // In the mean time, we must defer notifications because we are added to // the imgRequest's proxy list, and we can get extra notifications - // resulting from methods such as RequestDecode(). See bug 579122. + // resulting from methods such as StartDecoding(). See bug 579122. proxy->SetNotificationsDeferred(true); // Attach the proxy without notifying @@ -1666,7 +1666,7 @@ imgLoader::ValidateRequestWithNewChannel(imgRequest* request, // We will send notifications from imgCacheValidator::OnStartRequest(). // In the mean time, we must defer notifications because we are added to // the imgRequest's proxy list, and we can get extra notifications - // resulting from methods such as RequestDecode(). See bug 579122. + // resulting from methods such as StartDecoding(). See bug 579122. req->SetNotificationsDeferred(true); // Add the proxy without notifying diff --git a/image/imgRequest.cpp b/image/imgRequest.cpp index 1d850dc1ad5..62b6f1770a4 100644 --- a/image/imgRequest.cpp +++ b/image/imgRequest.cpp @@ -413,7 +413,7 @@ imgRequest::ContinueEvict() } void -imgRequest::RequestDecode() +imgRequest::StartDecoding() { MutexAutoLock lock(mMutex); mDecodeRequested = true; diff --git a/image/imgRequest.h b/image/imgRequest.h index 4abf009108c..520ca16f59b 100644 --- a/image/imgRequest.h +++ b/image/imgRequest.h @@ -95,7 +95,7 @@ public: void ContinueEvict(); // Request that we start decoding the image as soon as data becomes available. - void RequestDecode(); + void StartDecoding(); inline uint64_t InnerWindowID() const { return mInnerWindowId; @@ -220,7 +220,7 @@ private: // Update the cache entry size based on the image container. void UpdateCacheEntrySize(); - /// Returns true if RequestDecode() was called. + /// Returns true if StartDecoding() was called. bool IsDecodeRequested() const; // Weak reference to parent loader; this request cannot outlive its owner. diff --git a/image/imgRequestProxy.cpp b/image/imgRequestProxy.cpp index 155de9a9544..ecec7d58845 100644 --- a/image/imgRequestProxy.cpp +++ b/image/imgRequestProxy.cpp @@ -371,19 +371,12 @@ imgRequestProxy::StartDecoding() } if (GetOwner()) { - GetOwner()->RequestDecode(); + GetOwner()->StartDecoding(); } return NS_OK; } -NS_IMETHODIMP -imgRequestProxy::RequestDecode() -{ - return NS_OK; -} - - NS_IMETHODIMP imgRequestProxy::LockImage() { diff --git a/image/test/unit/image_load_helpers.js b/image/test/unit/image_load_helpers.js index 5fc59658439..e8d9a29f860 100644 --- a/image/test/unit/image_load_helpers.js +++ b/image/test/unit/image_load_helpers.js @@ -48,12 +48,6 @@ function ImageListener(start_callback, stop_callback) { do_check_false(this.synchronous); - try { - aRequest.requestDecode(); - } catch (e) { - do_print("requestDecode threw " + e); - } - this.state |= LOAD_COMPLETE; if (this.stop_callback) diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 6f831876e07..c33c3016f86 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -962,9 +962,6 @@ struct nsStyleBorder { return mBorderImageSource.IsLoaded(); } - // Defined in nsStyleStructInlines.h - inline nsresult RequestDecode(); - void GetBorderColor(mozilla::css::Side aSide, nscolor& aColor, bool& aForeground) const { From 37d10a152650006889846117ea2cef959475b761 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 13 Oct 2015 20:51:47 -0500 Subject: [PATCH 63/95] Bug 1216966 - Part 1: Splurge and use separate error messages for generator comprehensions that need more parentheses and yield expressions that need more parentheses. r=efaust. --- js/src/frontend/Parser.cpp | 19 +++++++------------ js/src/js.msg | 3 ++- js/src/vm/Xdr.h | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 8e1438d3d4a..d384c194e10 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -6927,7 +6927,7 @@ Parser::expr(InHandling inHandling, YieldHandling yieldHandling, return null(); while (true) { if (handler.isUnparenthesizedYieldExpression(pn)) { - report(ParseError, false, pn, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str); + report(ParseError, false, pn, JSMSG_BAD_YIELD_SYNTAX); return null(); } @@ -8227,8 +8227,6 @@ Parser::legacyGeneratorExpr(Node kid) return SyntaxParseHandler::NodeFailure; } -static const char js_generator_str[] = "generator"; - #endif /* JS_HAS_GENERATOR_EXPRS */ template @@ -8493,7 +8491,7 @@ Parser::argumentList(YieldHandling yieldHandling, Node listNode, b if (!tokenStream.peekToken(&tt)) return false; if (tt == TOK_COMMA) { - report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str); + report(ParseError, false, argNode, JSMSG_BAD_YIELD_SYNTAX); return false; } } @@ -8511,14 +8509,14 @@ Parser::argumentList(YieldHandling yieldHandling, Node listNode, b if (!argNode) return false; if (!arg0) { - report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str); + report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX); return false; } TokenKind tt; if (!tokenStream.peekToken(&tt)) return false; if (tt == TOK_COMMA) { - report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str); + report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX); return false; } } @@ -9501,8 +9499,7 @@ Parser::parenExprOrGeneratorComprehension(YieldHandling yieldHandl return null(); } if (handler.isUnparenthesizedCommaExpression(pn)) { - report(ParseError, false, null(), - JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str); + report(ParseError, false, null(), JSMSG_BAD_GENERATOR_SYNTAX); return null(); } pn = legacyGeneratorExpr(pn); @@ -9513,8 +9510,7 @@ Parser::parenExprOrGeneratorComprehension(YieldHandling yieldHandl if (!tokenStream.getToken(&tt)) return null(); if (tt != TOK_RP) { - report(ParseError, false, null(), - JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str); + report(ParseError, false, null(), JSMSG_BAD_GENERATOR_SYNTAX); return null(); } handler.setEndPosition(pn, pos().end); @@ -9570,8 +9566,7 @@ Parser::exprInParens(InHandling inHandling, YieldHandling yieldHan return null(); } if (handler.isUnparenthesizedCommaExpression(pn)) { - report(ParseError, false, null(), - JSMSG_BAD_GENERATOR_SYNTAX, js_generator_str); + report(ParseError, false, null(), JSMSG_BAD_GENERATOR_SYNTAX); return null(); } pn = legacyGeneratorExpr(pn); diff --git a/js/src/js.msg b/js/src/js.msg index cffa1e7c06e..b5da63f30f3 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -201,7 +201,8 @@ MSG_DEF(JSMSG_BAD_DUP_ARGS, 0, JSEXN_SYNTAXERR, "duplicate argument n MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 0, JSEXN_SYNTAXERR, "invalid for each loop") MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side") MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 1, JSEXN_TYPEERR, "generator function {0} returns a value") -MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized") +MSG_DEF(JSMSG_BAD_YIELD_SYNTAX, 0, JSEXN_SYNTAXERR, "yield expression must be parenthesized") +MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 0, JSEXN_SYNTAXERR, "generator expression must be parenthesized") MSG_DEF(JSMSG_BAD_GENEXP_BODY, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression") MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_REFERENCEERR, "invalid increment/decrement operand") MSG_DEF(JSMSG_BAD_METHOD_DEF, 0, JSEXN_SYNTAXERR, "bad method definition") diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index 051b10f38e9..ac41d49ebfb 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -33,7 +33,7 @@ static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 318; static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND); -static_assert(JSErr_Limit == 418, +static_assert(JSErr_Limit == 419, "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or " "removed MSG_DEFs from js.msg, you should increment " "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's " From 2681104370495ddac4232c6c0ec13856937a4740 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 13 Oct 2015 20:55:10 -0500 Subject: [PATCH 64/95] Bug 1216966 - Part 2: Tweak a comment about comprehension syntax. r=efaust. --- js/src/frontend/Parser.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index d384c194e10..2b96334ca53 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -9525,24 +9525,23 @@ Parser::parenExprOrGeneratorComprehension(YieldHandling yieldHandl return pn; } -// Legacy generator comprehensions can sometimes appear without parentheses. -// For example: -// -// foo(x for (x in bar)) -// -// In this case the parens are part of the call, and not part of the generator -// comprehension. This can happen in these contexts: +// Legacy generator comprehensions can appear anywhere an expression is +// enclosed in parentheses, even if those parentheses are part of statement +// syntax or a function call: // // if (_) // while (_) {} // do {} while (_) // switch (_) {} // with (_) {} -// foo(_) // must be first and only argument +// foo(_) // must be first and only argument +// +// This is not the case for also-nonstandard ES6-era generator comprehensions. +// Those must be enclosed in PrimaryExpression parentheses. +// +// sum(x*x for (x in y)); // ok +// sum(for (x of y) x*x); // SyntaxError: needs more parens // -// This is not the case for ES6 generator comprehensions; they must always be in -// parentheses. - template typename ParseHandler::Node Parser::exprInParens(InHandling inHandling, YieldHandling yieldHandling) From a66effc56164f7f568961785e9e7c7829524a021 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 13 Oct 2015 20:57:17 -0500 Subject: [PATCH 65/95] Bug 1216966 - Part 3: Remove redundant method Parser::parenExprOrGeneratorComprehension. r=efaust. --- js/src/frontend/Parser.cpp | 108 ++++++++++++------------------------- js/src/frontend/Parser.h | 4 +- 2 files changed, 36 insertions(+), 76 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 2b96334ca53..1bd1de52bff 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3246,7 +3246,7 @@ typename ParseHandler::Node Parser::condition(InHandling inHandling, YieldHandling yieldHandling) { MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND); - Node pn = exprInParens(inHandling, yieldHandling); + Node pn = exprInParens(inHandling, yieldHandling, TripledotProhibited); if (!pn) return null(); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND); @@ -5689,7 +5689,7 @@ Parser::switchStatement(YieldHandling yieldHandling) MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH); - Node discriminant = exprInParens(InAllowed, yieldHandling); + Node discriminant = exprInParens(InAllowed, yieldHandling, TripledotProhibited); if (!discriminant) return null(); @@ -6104,7 +6104,7 @@ Parser::withStatement(YieldHandling yieldHandling) return null(); MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH); - Node objectExpr = exprInParens(InAllowed, yieldHandling); + Node objectExpr = exprInParens(InAllowed, yieldHandling, TripledotProhibited); if (!objectExpr) return null(); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH); @@ -9361,25 +9361,38 @@ Parser::primaryExpr(YieldHandling yieldHandling, TripledotHandling TokenKind next; if (!tokenStream.peekToken(&next, TokenStream::Operand)) return null(); - if (next != TOK_RP) - return parenExprOrGeneratorComprehension(yieldHandling); - // Not valid expression syntax, but this is valid in an arrow function - // with no params: `() => body`. - tokenStream.consumeKnownToken(next, TokenStream::Operand); + if (next == TOK_RP) { + // Not valid expression syntax, but this is valid in an arrow function + // with no params: `() => body`. + tokenStream.consumeKnownToken(next, TokenStream::Operand); - if (!tokenStream.peekToken(&next)) - return null(); - if (next != TOK_ARROW) { - report(ParseError, false, null(), JSMSG_UNEXPECTED_TOKEN, - "expression", TokenKindToDesc(TOK_RP)); - return null(); + if (!tokenStream.peekToken(&next)) + return null(); + if (next != TOK_ARROW) { + report(ParseError, false, null(), JSMSG_UNEXPECTED_TOKEN, + "expression", TokenKindToDesc(TOK_RP)); + return null(); + } + + // Now just return something that will allow parsing to continue. + // It doesn't matter what; when we reach the =>, we will rewind and + // reparse the whole arrow function. See Parser::assignExpr. + return handler.newNullLiteral(pos()); } - // Now just return something that will allow parsing to continue. - // It doesn't matter what; when we reach the =>, we will rewind and - // reparse the whole arrow function. See Parser::assignExpr. - return handler.newNullLiteral(pos()); + if (next == TOK_FOR) { + uint32_t begin = pos().begin; + tokenStream.consumeKnownToken(next, TokenStream::Operand); + return generatorComprehension(begin); + } + + Node expr = exprInParens(InAllowed, yieldHandling, TripledotAllowed); + if (!expr) + return null(); + MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN); + handler.setEndPosition(expr, pos().end); + return handler.parenthesize(expr); } case TOK_TEMPLATE_HEAD: @@ -9471,60 +9484,6 @@ Parser::primaryExpr(YieldHandling yieldHandling, TripledotHandling } } -template -typename ParseHandler::Node -Parser::parenExprOrGeneratorComprehension(YieldHandling yieldHandling) -{ - MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP)); - uint32_t begin = pos().begin; - uint32_t startYieldOffset = pc->lastYieldOffset; - - bool matched; - if (!tokenStream.matchToken(&matched, TOK_FOR, TokenStream::Operand)) - return null(); - if (matched) - return generatorComprehension(begin); - - Node pn = expr(InAllowed, yieldHandling, TripledotAllowed, PredictInvoked); - if (!pn) - return null(); - -#if JS_HAS_GENERATOR_EXPRS - if (!tokenStream.matchToken(&matched, TOK_FOR)) - return null(); - if (matched) { - if (pc->lastYieldOffset != startYieldOffset) { - reportWithOffset(ParseError, false, pc->lastYieldOffset, - JSMSG_BAD_GENEXP_BODY, js_yield_str); - return null(); - } - if (handler.isUnparenthesizedCommaExpression(pn)) { - report(ParseError, false, null(), JSMSG_BAD_GENERATOR_SYNTAX); - return null(); - } - pn = legacyGeneratorExpr(pn); - if (!pn) - return null(); - handler.setBeginPosition(pn, begin); - TokenKind tt; - if (!tokenStream.getToken(&tt)) - return null(); - if (tt != TOK_RP) { - report(ParseError, false, null(), JSMSG_BAD_GENERATOR_SYNTAX); - return null(); - } - handler.setEndPosition(pn, pos().end); - return handler.parenthesize(pn); - } -#endif /* JS_HAS_GENERATOR_EXPRS */ - - pn = handler.parenthesize(pn); - - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN); - - return pn; -} - // Legacy generator comprehensions can appear anywhere an expression is // enclosed in parentheses, even if those parentheses are part of statement // syntax or a function call: @@ -9544,13 +9503,14 @@ Parser::parenExprOrGeneratorComprehension(YieldHandling yieldHandl // template typename ParseHandler::Node -Parser::exprInParens(InHandling inHandling, YieldHandling yieldHandling) +Parser::exprInParens(InHandling inHandling, YieldHandling yieldHandling, + TripledotHandling tripledotHandling) { MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP)); uint32_t begin = pos().begin; uint32_t startYieldOffset = pc->lastYieldOffset; - Node pn = expr(inHandling, yieldHandling, TripledotProhibited, PredictInvoked); + Node pn = expr(inHandling, yieldHandling, tripledotHandling, PredictInvoked); if (!pn) return null(); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 9f545af7cc1..b15929967cb 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -711,8 +711,8 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter bool allowCallSyntax, InvokedPrediction invoked = PredictUninvoked); Node primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt, InvokedPrediction invoked = PredictUninvoked); - Node parenExprOrGeneratorComprehension(YieldHandling yieldHandling); - Node exprInParens(InHandling inHandling, YieldHandling yieldHandling); + Node exprInParens(InHandling inHandling, YieldHandling yieldHandling, + TripledotHandling tripledotHandling); bool tryNewTarget(Node& newTarget); bool checkAndMarkSuperScope(); From 521757bb504251f0e407fce320cc2da042839725 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 08:58:11 -0500 Subject: [PATCH 66/95] Bug 1216966 - Part 4: Update a big comment about for-loops in Parser.cpp. r=efaust. --- js/src/frontend/Parser.cpp | 55 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 1bd1de52bff..e7c051602d3 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -5273,43 +5273,44 @@ Parser::forStatement(YieldHandling yieldHandling) MOZ_ASSERT_IF(isForDecl, pn1->isArity(PN_LIST)); MOZ_ASSERT(!!blockObj == (isForDecl && (pn1->isOp(JSOP_DEFLET) || pn1->isOp(JSOP_DEFCONST)))); - // All forms of for-loop (for(;;), for-in, for-of) generate an implicit - // block to store any lexical variables declared by the loop-head. We - // implement this by desugaring such loops. These: + // If the head of a for-loop declares any lexical variables, we generate an + // implicit block to store them. We implement this by desugaring. These: // - // for (let/const ; ; ) - // for (let in ) - // for (let of ) + // for (let/const ; ; ) + // for (let in ) + // for (let of ) // - // transform into almost these desugarings: + // transform into roughly the same parse trees as these (using deprecated + // let-block syntax): // - // let () { for (; ; ) } - // let () { for ( in ) } - // let () { for ( of ) } + // let () { for (; ; ) } + // let () { for ( in ) } + // let () { for ( of ) } // - // This desugaring is not *quite* correct. Assignments in the head of a - // let-block are evaluated *outside* the scope of the variables declared by - // the let-block-head. But ES6 mandates that they be evaluated in the same - // scope, triggering used-before-initialization temporal dead zone errors - // as necessary. Bug 1069480 will fix this. + // This desugaring is not ES6 compliant. Initializers in the head of a + // let-block are evaluated *outside* the scope of the variables being + // initialized. ES6 mandates that they be evaluated in the same scope, + // triggering used-before-initialization temporal dead zone errors as + // necessary. See bug 1216623 on scoping and bug 1069480 on TDZ. // - // Additionally, ES6 mandates that *each iteration* of a for-loop create a - // fresh binding of loop variables. For example: + // Additionally, in ES6, each iteration of a for-loop creates a fresh + // binding of the loop variables. For example: // - // var funcs = []; - // for (let i = 0; i < 2; i++) - // funcs.push(function() { return i; }); - // assertEq(funcs[0](), 0); - // assertEq(funcs[1](), 1); + // var funcs = []; + // for (let i = 0; i < 2; i++) + // funcs.push(function() { return i; }); + // assertEq(funcs[0](), 0); // the two closures capture... + // assertEq(funcs[1](), 1); // ...two different `i` bindings // // These semantics are implemented by "freshening" the implicit block -- // changing the scope chain to a fresh clone of the instantaneous block // object -- each iteration, just before evaluating the "update" in - // for(;;) loops. (We don't implement this freshening for for-in/of loops, - // but soon: bug 449811.) No freshening occurs in for (const ...;;) as - // there's no point (you can't reassign consts), and moreover the spec - // requires it (which fact isn't exposed in-language but can be observed - // through the Debugger API). + // for(;;) loops. We don't implement this freshening for for-in/of loops + // yet: bug 449811. + // + // No freshening occurs in `for (const ...;;)` as there's no point: you + // can't reassign consts. This is observable through the Debugger API. (The + // ES6 spec also skips cloning the environment in this case.) // // If the for-loop head includes a lexical declaration, then we create an // implicit block scope, and: From 26680235f295f09e4d53a2726a2845861337d7e9 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 12:05:22 -0500 Subject: [PATCH 67/95] Bug 1216966 - Part 5: Code organization and comments around parsing comprehensions. r=efaust. --- js/src/frontend/Parser.cpp | 42 +++++++++++++++++++++++++++++--------- js/src/frontend/Parser.h | 11 +++++----- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index e7c051602d3..2ddc7f39c7e 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -5779,7 +5779,7 @@ Parser::switchStatement(YieldHandling yieldHandling) handler.addList(body, stmt); } - // In ES6, lexical bindings canot be accessed until initialized. If + // In ES6, lexical bindings cannot be accessed until initialized. If // there was a 'let' declaration in the case we just parsed, remember // the slot starting at which new lexical bindings will be // assigned. Since lexical bindings from previous cases will not @@ -7550,6 +7550,25 @@ Parser::unaryExpr(YieldHandling yieldHandling, TripledotHandling t } } + +/*** Comprehensions ******************************************************************************* + * + * We currently support four flavors of comprehensions, all deprecated: + * + * [EXPR for (V in OBJ) if (COND)] // legacy array comprehension + * (EXPR for (V in OBJ) if (COND)) // legacy generator expression + * [for (V of OBJ) if (COND) EXPR] // ES6-era array comprehension + * (for (V of OBJ) if (COND) EXPR) // ES6-era generator expression + * + * (The last two flavors are called "ES6-era" because they were in ES6 draft + * specifications for a while. Shortly after this syntax was implemented in SM, + * TC39 decided to drop it.) + * + * Legacy generator expressions evaluate to legacy generators (using the + * StopIteration protocol); ES6-era generator expressions evaluate to ES6 + * generators (using the `{done:, value:}` protocol). + */ + /* * A dedicated helper for transplanting the legacy comprehension expression E in * @@ -8191,18 +8210,18 @@ Parser::generatorComprehensionLambda(GeneratorKind comprehensionKi /* * Starting from a |for| keyword after an expression, parse the comprehension - * tail completing this generator expression. Wrap the expression at kid in a + * tail completing this generator expression. Wrap the expression |expr| in a * generator function that is immediately called to evaluate to the generator * iterator that is the value of this legacy generator expression. * - * |kid| must be the expression before the |for| keyword; we return an + * |expr| must be the expression before the |for| keyword; we return an * application of a generator function that includes the |for| loops and - * |if| guards, with |kid| as the operand of a |yield| expression as the + * |if| guards, with |expr| as the operand of a |yield| expression as the * innermost loop body. * - * Note how unlike Python, we do not evaluate the expression to the right of - * the first |in| in the chain of |for| heads. Instead, a generator expression - * is merely sugar for a generator function expression and its application. + * Unlike Python, we do not evaluate the expression to the right of the first + * |in| in the chain of |for| heads. Instead, a generator expression is merely + * sugar for a generator function expression and its application. */ template <> ParseNode* @@ -8369,8 +8388,8 @@ Parser::comprehensionTail(GeneratorKind comprehensionKind) return handler.newExprStatement(yieldExpr, pos().end); } -// Parse an ES6 generator or array comprehension, starting at the first 'for'. -// The caller is responsible for matching the ending TOK_RP or TOK_RB. +// Parse an ES6-era generator or array comprehension, starting at the first +// `for`. The caller is responsible for matching the ending TOK_RP or TOK_RB. template typename ParseHandler::Node Parser::comprehension(GeneratorKind comprehensionKind) @@ -8438,6 +8457,9 @@ Parser::generatorComprehension(uint32_t begin) return result; } + +/* * */ + template typename ParseHandler::Node Parser::assignExprWithoutYield(YieldHandling yieldHandling, unsigned msg) @@ -8849,7 +8871,7 @@ Parser::arrayInitializer(YieldHandling yieldHandling) if (!tokenStream.getToken(&tt, TokenStream::Operand)) return null(); - // Handle an ES7 array comprehension first. + // Handle an ES6-era array comprehension first. if (tt == TOK_FOR) return arrayComprehension(begin); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index b15929967cb..391ec334e20 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -737,18 +737,17 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter Node condition(InHandling inHandling, YieldHandling yieldHandling); - Node generatorComprehensionLambda(GeneratorKind comprehensionKind, unsigned begin, - Node innerStmt); - + /* comprehensions */ Node legacyComprehensionTail(Node kid, unsigned blockid, GeneratorKind comprehensionKind, ParseContext* outerpc, unsigned innerBlockScopeDepth); Node legacyArrayComprehension(Node array); + Node generatorComprehensionLambda(GeneratorKind comprehensionKind, unsigned begin, + Node innerStmt); Node legacyGeneratorExpr(Node kid); - - Node comprehensionTail(GeneratorKind comprehensionKind); - Node comprehensionIf(GeneratorKind comprehensionKind); Node comprehensionFor(GeneratorKind comprehensionKind); + Node comprehensionIf(GeneratorKind comprehensionKind); + Node comprehensionTail(GeneratorKind comprehensionKind); Node comprehension(GeneratorKind comprehensionKind); Node arrayComprehension(uint32_t begin); Node generatorComprehension(uint32_t begin); From 5d891019cb5ac0806a404266d86370888bc8d61c Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 14:08:51 -0500 Subject: [PATCH 68/95] Bug 1217001 - Refactor BytecodeEmitter::variables. Part 1: preliminaries. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 30 ++++++++++++----------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index f7ef1959822..af7460a6aab 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4222,7 +4222,7 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL MOZ_ASSERT(isLetExpr == (emitOption == PushInitialValues)); ParseNode* next; - for (ParseNode* pn2 = pn->pn_head; ; pn2 = next) { + for (ParseNode* pn2 = pn->pn_head; pn2; pn2 = next) { if (!updateSourceCoordNotes(pn2->pn_pos.begin)) return false; next = pn2->pn_next; @@ -4259,7 +4259,7 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (!emitInitializeDestructuringDecls(pn->getOp(), pn2)) return false; } - break; + continue; } /* @@ -4294,12 +4294,9 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL return false; /* If we are not initializing, nothing to pop. */ - if (emitOption != InitializeVars) { - if (next) - continue; - break; - } - goto emit_note_pop; + if (emitOption != InitializeVars) + continue; + goto emit_pop; } /* @@ -4360,11 +4357,8 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL // If we are not initializing, nothing to pop. If we are initializing // lets, we must emit the pops. - if (emitOption != InitializeVars) { - if (next) - continue; - break; - } + if (emitOption != InitializeVars) + continue; MOZ_ASSERT_IF(pn2->isDefn(), pn3 == pn2->pn_expr); if (!pn2->pn_scopecoord.isFree()) { @@ -4375,11 +4369,11 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL return false; } - emit_note_pop: - if (!next) - break; - if (!emit1(JSOP_POP)) - return false; + emit_pop: + if (next) { + if (!emit1(JSOP_POP)) + return false; + } } if (pn->pn_xflags & PNX_POPVAR) { From 2525488ee00b14c7e3f70718cb1147eaf965de35 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 14:26:15 -0500 Subject: [PATCH 69/95] Bug 1217001 - Part 2: Rename two local variables and improve some old comments. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 91 +++++++++++++++-------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index af7460a6aab..d4082d53bb9 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4222,41 +4222,44 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL MOZ_ASSERT(isLetExpr == (emitOption == PushInitialValues)); ParseNode* next; - for (ParseNode* pn2 = pn->pn_head; pn2; pn2 = next) { - if (!updateSourceCoordNotes(pn2->pn_pos.begin)) + for (ParseNode* binding = pn->pn_head; binding; binding = next) { + if (!updateSourceCoordNotes(binding->pn_pos.begin)) return false; - next = pn2->pn_next; + next = binding->pn_next; - ParseNode* pn3; - if (!pn2->isKind(PNK_NAME)) { - if (pn2->isKind(PNK_ARRAY) || pn2->isKind(PNK_OBJECT)) { - // If the emit option is DefineVars, emit variable binding - // ops, but not destructuring ops. The parser (see - // Parser::variables) has ensured that our caller will be the - // PNK_FOR/PNK_FORIN/PNK_FOROF case in emitTree (we don't have - // to worry about this being a variable declaration, as - // destructuring declarations without initializers, e.g., |var - // [x]|, are not legal syntax), and that case will emit the - // destructuring code only after emitting an enumerating - // opcode and a branch that tests whether the enumeration - // ended. Thus, each iteration's assignment is responsible for - // initializing, and nothing needs to be done here. + ParseNode* initializer; + if (!binding->isKind(PNK_NAME)) { + if (binding->isKind(PNK_ARRAY) || binding->isKind(PNK_OBJECT)) { + // Destructuring BindingPattern in a `for` loop head: + // for (let [x, y] of pts) ...; + // or in a deprecated comprehension: + // a = [x*y for (let [x, y] of pts)]; // - // Otherwise this is emitting destructuring let binding - // initialization for a legacy comprehension expression. See - // emitForInOrOfVariables. + // (ES6 calls this a ForDeclaration. When emitting code for a + // plain LexicalDeclaration, like `let [x, y] = pt;`, + // binding will be a PNK_ASSIGN node, not a PNK_ARRAY node. + // `let [x, y];` without an initializer is a SyntaxError.) + MOZ_ASSERT(pn->pn_count == 1); if (emitOption == DefineVars) { - if (!emitDestructuringDecls(pn->getOp(), pn2)) + // Emit JSOP_DEFVAR instructions if needed, but not + // destructuring ops. Each iteration of the for-loop is + // responsible for initializing these variables, so it's + // the caller's responsibility. + if (!emitDestructuringDecls(pn->getOp(), binding)) return false; } else { + // We're emitting destructuring let binding initialization + // for a legacy comprehension expression. See + // emitForInOrOfVariables. + // Lexical bindings cannot be used before they are // initialized. Similar to the JSOP_INITLEXICAL case below. MOZ_ASSERT(emitOption != DefineVars); MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); if (!emit1(JSOP_UNDEFINED)) return false; - if (!emitInitializeDestructuringDecls(pn->getOp(), pn2)) + if (!emitInitializeDestructuringDecls(pn->getOp(), binding)) return false; } continue; @@ -4268,8 +4271,8 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL * (var x = i in o)...', this will cause the entire 'var [a, b] = * i' to be hoisted out of the loop. */ - MOZ_ASSERT(pn2->isKind(PNK_ASSIGN)); - MOZ_ASSERT(pn2->isOp(JSOP_NOP)); + MOZ_ASSERT(binding->isKind(PNK_ASSIGN)); + MOZ_ASSERT(binding->isOp(JSOP_NOP)); MOZ_ASSERT(emitOption != DefineVars); /* @@ -4277,20 +4280,20 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL * function f(){} precedes the var, detect simple name assignment * here and initialize the name. */ - if (pn2->pn_left->isKind(PNK_NAME)) { - pn3 = pn2->pn_right; - pn2 = pn2->pn_left; + if (binding->pn_left->isKind(PNK_NAME)) { + initializer = binding->pn_right; + binding = binding->pn_left; goto do_name; } - pn3 = pn2->pn_left; - if (!emitDestructuringDecls(pn->getOp(), pn3)) + initializer = binding->pn_left; + if (!emitDestructuringDecls(pn->getOp(), initializer)) return false; - if (!emitTree(pn2->pn_right)) + if (!emitTree(binding->pn_right)) return false; - if (!emitDestructuringOps(pn3, isLetExpr)) + if (!emitDestructuringOps(initializer, isLetExpr)) return false; /* If we are not initializing, nothing to pop. */ @@ -4301,27 +4304,27 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL /* * Load initializer early to share code above that jumps to do_name. - * NB: if this var redeclares an existing binding, then pn2 is linked - * on its definition's use-chain and pn_expr has been overlayed with - * pn_lexdef. + * NB: if this var redeclares an existing binding, then `binding` is + * linked on its definition's use-chain and pn_expr has been overlayed + * with pn_lexdef. */ - pn3 = pn2->maybeExpr(); + initializer = binding->maybeExpr(); do_name: - if (!bindNameToSlot(pn2)) + if (!bindNameToSlot(binding)) return false; JSOp op; - op = pn2->getOp(); + op = binding->getOp(); MOZ_ASSERT(op != JSOP_CALLEE); - MOZ_ASSERT(!pn2->pn_scopecoord.isFree() || !pn->isOp(JSOP_NOP)); + MOZ_ASSERT(!binding->pn_scopecoord.isFree() || !pn->isOp(JSOP_NOP)); jsatomid atomIndex; - if (!maybeEmitVarDecl(pn->getOp(), pn2, &atomIndex)) + if (!maybeEmitVarDecl(pn->getOp(), binding, &atomIndex)) return false; - if (pn3) { + if (initializer) { MOZ_ASSERT(emitOption != DefineVars); if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME || @@ -4343,7 +4346,7 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL bool oldEmittingForInit = emittingForInit; emittingForInit = false; - if (!emitTree(pn3)) + if (!emitTree(initializer)) return false; emittingForInit = oldEmittingForInit; } else if (op == JSOP_INITLEXICAL || op == JSOP_INITGLEXICAL || isLetExpr) { @@ -4360,9 +4363,9 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (emitOption != InitializeVars) continue; - MOZ_ASSERT_IF(pn2->isDefn(), pn3 == pn2->pn_expr); - if (!pn2->pn_scopecoord.isFree()) { - if (!emitVarOp(pn2, op)) + MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); + if (!binding->pn_scopecoord.isFree()) { + if (!emitVarOp(binding, op)) return false; } else { if (!emitIndexOp(op, atomIndex)) From 0a65c6cdd5d5d25f95c6ef44a595c970842cd237 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 14:26:46 -0500 Subject: [PATCH 70/95] Bug 1217001 - Part 3: Remove one goto statement. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 124 ++++++++++++++-------------- 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index d4082d53bb9..15f8b20f442 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4299,80 +4299,78 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL /* If we are not initializing, nothing to pop. */ if (emitOption != InitializeVars) continue; - goto emit_pop; - } + } else { - /* - * Load initializer early to share code above that jumps to do_name. - * NB: if this var redeclares an existing binding, then `binding` is - * linked on its definition's use-chain and pn_expr has been overlayed - * with pn_lexdef. - */ - initializer = binding->maybeExpr(); + /* + * Load initializer early to share code above that jumps to + * do_name. NB: if this var redeclares an existing binding, then + * `binding` is linked on its definition's use-chain and pn_expr + * has been overlayed with pn_lexdef. + */ + initializer = binding->maybeExpr(); - do_name: - if (!bindNameToSlot(binding)) - return false; + do_name: + if (!bindNameToSlot(binding)) + return false; + JSOp op; + op = binding->getOp(); + MOZ_ASSERT(op != JSOP_CALLEE); + MOZ_ASSERT(!binding->pn_scopecoord.isFree() || !pn->isOp(JSOP_NOP)); - JSOp op; - op = binding->getOp(); - MOZ_ASSERT(op != JSOP_CALLEE); - MOZ_ASSERT(!binding->pn_scopecoord.isFree() || !pn->isOp(JSOP_NOP)); + jsatomid atomIndex; + if (!maybeEmitVarDecl(pn->getOp(), binding, &atomIndex)) + return false; - jsatomid atomIndex; - if (!maybeEmitVarDecl(pn->getOp(), binding, &atomIndex)) - return false; + if (initializer) { + MOZ_ASSERT(emitOption != DefineVars); + if (op == JSOP_SETNAME || + op == JSOP_STRICTSETNAME || + op == JSOP_SETGNAME || + op == JSOP_STRICTSETGNAME || + op == JSOP_SETINTRINSIC) + { + MOZ_ASSERT(emitOption != PushInitialValues); + JSOp bindOp; + if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME) + bindOp = JSOP_BINDNAME; + else if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME) + bindOp = JSOP_BINDGNAME; + else + bindOp = JSOP_BINDINTRINSIC; + if (!emitIndex32(bindOp, atomIndex)) + return false; + } - if (initializer) { - MOZ_ASSERT(emitOption != DefineVars); - if (op == JSOP_SETNAME || - op == JSOP_STRICTSETNAME || - op == JSOP_SETGNAME || - op == JSOP_STRICTSETGNAME || - op == JSOP_SETINTRINSIC) - { - MOZ_ASSERT(emitOption != PushInitialValues); - JSOp bindOp; - if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME) - bindOp = JSOP_BINDNAME; - else if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME) - bindOp = JSOP_BINDGNAME; - else - bindOp = JSOP_BINDINTRINSIC; - if (!emitIndex32(bindOp, atomIndex)) + bool oldEmittingForInit = emittingForInit; + emittingForInit = false; + if (!emitTree(initializer)) + return false; + emittingForInit = oldEmittingForInit; + } else if (op == JSOP_INITLEXICAL || op == JSOP_INITGLEXICAL || isLetExpr) { + // 'let' bindings cannot be used before they are + // initialized. JSOP_INITLEXICAL distinguishes the binding site. + MOZ_ASSERT(emitOption != DefineVars); + MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); + if (!emit1(JSOP_UNDEFINED)) return false; } - bool oldEmittingForInit = emittingForInit; - emittingForInit = false; - if (!emitTree(initializer)) - return false; - emittingForInit = oldEmittingForInit; - } else if (op == JSOP_INITLEXICAL || op == JSOP_INITGLEXICAL || isLetExpr) { - // 'let' bindings cannot be used before they are - // initialized. JSOP_INITLEXICAL distinguishes the binding site. - MOZ_ASSERT(emitOption != DefineVars); - MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); - if (!emit1(JSOP_UNDEFINED)) - return false; + // If we are not initializing, nothing to pop. If we are initializing + // lets, we must emit the pops. + if (emitOption != InitializeVars) + continue; + + MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); + if (!binding->pn_scopecoord.isFree()) { + if (!emitVarOp(binding, op)) + return false; + } else { + if (!emitIndexOp(op, atomIndex)) + return false; + } } - // If we are not initializing, nothing to pop. If we are initializing - // lets, we must emit the pops. - if (emitOption != InitializeVars) - continue; - - MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); - if (!binding->pn_scopecoord.isFree()) { - if (!emitVarOp(binding, op)) - return false; - } else { - if (!emitIndexOp(op, atomIndex)) - return false; - } - - emit_pop: if (next) { if (!emit1(JSOP_POP)) return false; From 513671097a22b122f62178453a7f74cf54ab0306 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 14:38:07 -0500 Subject: [PATCH 71/95] Bug 1217001 - Part 4: Improve the comments on VarEmitOption. r=shu. --- js/src/frontend/BytecodeEmitter.h | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index 23c6807d7c6..c335aa1b67e 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -104,16 +104,24 @@ struct StmtInfoBCE; typedef Vector BytecodeVector; typedef Vector SrcNotesVector; -// This enum tells EmitVariables and the destructuring functions how emit the -// given Parser::variables parse tree. In the base case, DefineVars, the caller -// only wants variables to be defined in the prologue (if necessary). For -// PushInitialValues, variable initializer expressions are evaluated and left -// on the stack. For InitializeVars, the initializer expressions values are -// assigned (to local variables) and popped. +// This enum tells BytecodeEmitter::emitVariables and the destructuring +// methods how emit the given Parser::variables parse tree. enum VarEmitOption { - DefineVars = 0, - PushInitialValues = 1, - InitializeVars = 2 + // The normal case. Emit code to evaluate initializer expressions and + // assign them to local variables. Also emit JSOP_DEF{VAR,LET,CONST} + // opcodes in the prologue if the declaration occurs at toplevel. + InitializeVars, + + // Emit only JSOP_DEFVAR opcodes, in the prologue, if necessary. This is + // used in one case: `for (var $BindingPattern in/of obj)`. If we're at + // toplevel, the variable(s) must be defined with JSOP_DEFVAR, but they're + // populated inside the loop, via emitAssignment. + DefineVars, + + // Emit code to evaluate initializer expressions and leave those values on + // the stack. This is used to implement `for (let/const ...;;)` and + // deprecated `let` blocks. + PushInitialValues }; struct BytecodeEmitter From c048f1f73553e40c531d28526df648b89419019b Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 16:07:03 -0500 Subject: [PATCH 72/95] Bug 1217001 - Part 5: Further revise control structure in BytecodeEmitter::emitVariables(). r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 68 ++++++++++++++--------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 15f8b20f442..e6d8393e0d6 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4228,50 +4228,46 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL next = binding->pn_next; ParseNode* initializer; - if (!binding->isKind(PNK_NAME)) { - if (binding->isKind(PNK_ARRAY) || binding->isKind(PNK_OBJECT)) { - // Destructuring BindingPattern in a `for` loop head: - // for (let [x, y] of pts) ...; - // or in a deprecated comprehension: - // a = [x*y for (let [x, y] of pts)]; - // - // (ES6 calls this a ForDeclaration. When emitting code for a - // plain LexicalDeclaration, like `let [x, y] = pt;`, - // binding will be a PNK_ASSIGN node, not a PNK_ARRAY node. - // `let [x, y];` without an initializer is a SyntaxError.) + if (binding->isKind(PNK_ARRAY) || binding->isKind(PNK_OBJECT)) { + // Destructuring BindingPattern in a `for` loop head: + // for (let [x, y] of pts) ...; + // or in a deprecated comprehension: + // a = [x*y for (let [x, y] of pts)]; + // + // (ES6 calls this a ForDeclaration. When emitting code for a plain + // LexicalDeclaration, like `let [x, y] = pt;`, binding will be a + // PNK_ASSIGN node, not a PNK_ARRAY node. `let [x, y];` without an + // initializer is a SyntaxError.) - MOZ_ASSERT(pn->pn_count == 1); - if (emitOption == DefineVars) { - // Emit JSOP_DEFVAR instructions if needed, but not - // destructuring ops. Each iteration of the for-loop is - // responsible for initializing these variables, so it's - // the caller's responsibility. - if (!emitDestructuringDecls(pn->getOp(), binding)) - return false; - } else { - // We're emitting destructuring let binding initialization - // for a legacy comprehension expression. See - // emitForInOrOfVariables. + MOZ_ASSERT(pn->pn_count == 1); + if (emitOption == DefineVars) { + // Emit JSOP_DEFVAR instructions if needed, but not + // destructuring ops. Each iteration of the for-loop is + // responsible for initializing these variables, so it's + // the caller's responsibility. + if (!emitDestructuringDecls(pn->getOp(), binding)) + return false; + } else { + // We're emitting destructuring let binding initialization + // for a legacy comprehension expression. See + // emitForInOrOfVariables. - // Lexical bindings cannot be used before they are - // initialized. Similar to the JSOP_INITLEXICAL case below. - MOZ_ASSERT(emitOption != DefineVars); - MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); - if (!emit1(JSOP_UNDEFINED)) - return false; - if (!emitInitializeDestructuringDecls(pn->getOp(), binding)) - return false; - } - continue; + // Lexical bindings cannot be used before they are + // initialized. Similar to the JSOP_INITLEXICAL case below. + MOZ_ASSERT(emitOption != DefineVars); + MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); + if (!emit1(JSOP_UNDEFINED)) + return false; + if (!emitInitializeDestructuringDecls(pn->getOp(), binding)) + return false; } - + } else if (binding->isKind(PNK_ASSIGN)) { /* * A destructuring initialiser assignment preceded by var will * never occur to the left of 'in' in a for-in loop. As with 'for * (var x = i in o)...', this will cause the entire 'var [a, b] = * i' to be hoisted out of the loop. */ - MOZ_ASSERT(binding->isKind(PNK_ASSIGN)); MOZ_ASSERT(binding->isOp(JSOP_NOP)); MOZ_ASSERT(emitOption != DefineVars); @@ -4300,7 +4296,6 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (emitOption != InitializeVars) continue; } else { - /* * Load initializer early to share code above that jumps to * do_name. NB: if this var redeclares an existing binding, then @@ -4310,6 +4305,7 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL initializer = binding->maybeExpr(); do_name: + MOZ_ASSERT(binding->isKind(PNK_NAME)); if (!bindNameToSlot(binding)) return false; From bad049288777c78c74e40b7244cd6163924c43fa Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 16:47:22 -0500 Subject: [PATCH 73/95] Bug 1217001 - Part 6: Eliminate some `continue` statements. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index e6d8393e0d6..2f7df135725 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4291,10 +4291,6 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (!emitDestructuringOps(initializer, isLetExpr)) return false; - - /* If we are not initializing, nothing to pop. */ - if (emitOption != InitializeVars) - continue; } else { /* * Load initializer early to share code above that jumps to @@ -4354,20 +4350,19 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL // If we are not initializing, nothing to pop. If we are initializing // lets, we must emit the pops. - if (emitOption != InitializeVars) - continue; - - MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); - if (!binding->pn_scopecoord.isFree()) { - if (!emitVarOp(binding, op)) - return false; - } else { - if (!emitIndexOp(op, atomIndex)) - return false; + if (emitOption == InitializeVars) { + MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); + if (!binding->pn_scopecoord.isFree()) { + if (!emitVarOp(binding, op)) + return false; + } else { + if (!emitIndexOp(op, atomIndex)) + return false; + } } } - if (next) { + if (next && emitOption == InitializeVars) { if (!emit1(JSOP_POP)) return false; } From 8f6b63e5b3623178097a3bb2bf43e330d802a6a2 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 17:22:52 -0500 Subject: [PATCH 74/95] Bug 1217001 - Part 7: Change BytecodeEmitter::emitNormalFor() to decouple it from weird expectations about BytecodeEmitter::emitVariables(). r=shu. In particular, before this patch, emitNormalFor expected `emitTree(|var x = 3;|)` to leave the value `3` on the operand stack. This is totally weird and must die. --- js/src/frontend/BytecodeEmitter.cpp | 62 +++++++++++++---------------- js/src/jit/IonBuilder.cpp | 4 +- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 2f7df135725..8324d96e170 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4362,6 +4362,7 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL } } + MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); if (next && emitOption == InitializeVars) { if (!emit1(JSOP_POP)) return false; @@ -5600,33 +5601,32 @@ BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top) /* C-style for (init; cond; update) ... loop. */ bool forLoopRequiresFreshening = false; - JSOp op; - ParseNode* init = forHead->pn_kid1; - if (!init) { - // If there's no init, emit a nop so that there's somewhere to put the - // SRC_FOR annotation that IonBuilder will look for. - op = JSOP_NOP; - } else if (init->isKind(PNK_FRESHENBLOCK)) { - // Also emit a nop, as above. - op = JSOP_NOP; - - // The loop's init declaration was hoisted into an enclosing lexical - // scope node. Note that the block scope must be freshened each - // iteration. - forLoopRequiresFreshening = true; - } else { - emittingForInit = true; - if (!updateSourceCoordNotes(init->pn_pos.begin)) - return false; - if (!emitTree(init)) - return false; - emittingForInit = false; - - op = JSOP_POP; + if (ParseNode* init = forHead->pn_kid1) { + if (init->isKind(PNK_FRESHENBLOCK)) { + // The loop's init declaration was hoisted into an enclosing lexical + // scope node. Note that the block scope must be freshened each + // iteration. + forLoopRequiresFreshening = true; + } else { + emittingForInit = true; + if (!updateSourceCoordNotes(init->pn_pos.begin)) + return false; + if (init->isKind(PNK_VAR) || init->isKind(PNK_LET) || init->isKind(PNK_CONST)) { + init->pn_xflags |= PNX_POPVAR; // Momentary hack, removed later in this patch stack. + if (!emitTree(init)) + return false; + } else { + if (!emitTree(init)) + return false; + if (!emit1(JSOP_POP)) + return false; + } + emittingForInit = false; + } } /* - * NB: the SRC_FOR note has offsetBias 1 (JSOP_{NOP,POP}_LENGTH). + * NB: the SRC_FOR note has offsetBias 1 (JSOP_NOP_LENGTH). * Use tmp to hold the biased srcnote "top" offset, which differs * from the top local variable by the length of the JSOP_GOTO * emitted in between tmp and top if this loop has a condition. @@ -5634,7 +5634,7 @@ BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top) unsigned noteIndex; if (!newSrcNote(SRC_FOR, ¬eIndex)) return false; - if (!emit1(op)) + if (!emit1(JSOP_NOP)) return false; ptrdiff_t tmp = offset(); @@ -5643,9 +5643,6 @@ BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top) /* Goto the loop condition, which branches back to iterate. */ if (!emitJump(JSOP_GOTO, 0, &jmp)) return false; - } else { - if (op != JSOP_NOP && !emit1(JSOP_NOP)) - return false; } top = offset(); @@ -5692,12 +5689,9 @@ BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top) if (ParseNode* update = forHead->pn_kid3) { if (!updateSourceCoordNotes(update->pn_pos.begin)) return false; - op = JSOP_POP; if (!emitTree(update)) return false; - - /* Always emit the POP or NOP to help IonBuilder. */ - if (!emit1(op)) + if (!emit1(JSOP_POP)) return false; /* Restore the absolute line number for source note readers. */ @@ -5728,13 +5722,13 @@ BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top) return false; if (!setSrcNoteOffset(noteIndex, 1, tmp2 - tmp)) return false; + /* The third note offset helps us find the loop-closing jump. */ if (!setSrcNoteOffset(noteIndex, 2, offset() - tmp)) return false; /* If no loop condition, just emit a loop-closing jump. */ - op = forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO; - if (!emitJump(op, top - offset())) + if (!emitJump(forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO, top - offset())) return false; if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top, offset())) diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index ca57ad2fe3f..74cfab1bb06 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -3241,8 +3241,8 @@ IonBuilder::whileOrForInLoop(jssrcnote* sn) IonBuilder::ControlStatus IonBuilder::forLoop(JSOp op, jssrcnote* sn) { - // Skip the NOP or POP. - MOZ_ASSERT(op == JSOP_POP || op == JSOP_NOP); + // Skip the NOP. + MOZ_ASSERT(op == JSOP_NOP); pc = GetNextPc(pc); jsbytecode* condpc = pc + GetSrcNoteOffset(sn, 0); From 2fc5c62ae4d63038cedbcfe99fcdd79e484cc9d6 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 18:47:02 -0500 Subject: [PATCH 75/95] Bug 1217001 - Part 8: Eliminate all uses of PNX_POPVAR. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 8324d96e170..3c682ac31db 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4254,12 +4254,14 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL // Lexical bindings cannot be used before they are // initialized. Similar to the JSOP_INITLEXICAL case below. - MOZ_ASSERT(emitOption != DefineVars); - MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); + MOZ_ASSERT(emitOption == InitializeVars); + MOZ_ASSERT(pn->pn_xflags & PNX_POPVAR); if (!emit1(JSOP_UNDEFINED)) return false; if (!emitInitializeDestructuringDecls(pn->getOp(), binding)) return false; + if (!emit1(JSOP_POP)) + return false; } } else if (binding->isKind(PNK_ASSIGN)) { /* @@ -4291,6 +4293,13 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (!emitDestructuringOps(initializer, isLetExpr)) return false; + + MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); + MOZ_ASSERT_IF(pn->pn_xflags & PNX_POPVAR, emitOption == InitializeVars); + if (emitOption == InitializeVars) { + if (!emit1(JSOP_POP)) + return false; + } } else { /* * Load initializer early to share code above that jumps to @@ -4350,6 +4359,8 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL // If we are not initializing, nothing to pop. If we are initializing // lets, we must emit the pops. + MOZ_ASSERT_IF(emitOption == InitializeVars, (pn->pn_xflags & PNX_POPVAR) != 0); + MOZ_ASSERT_IF((pn->pn_xflags & PNX_POPVAR) != 0, emitOption == InitializeVars); if (emitOption == InitializeVars) { MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); if (!binding->pn_scopecoord.isFree()) { @@ -4359,21 +4370,11 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (!emitIndexOp(op, atomIndex)) return false; } + if (!emit1(JSOP_POP)) + return false; } } - - MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); - if (next && emitOption == InitializeVars) { - if (!emit1(JSOP_POP)) - return false; - } } - - if (pn->pn_xflags & PNX_POPVAR) { - if (!emit1(JSOP_POP)) - return false; - } - return true; } From cb2a09a6f2593f0a52291b1a398c8afea121260a Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 17:26:16 -0500 Subject: [PATCH 76/95] Bug 1217001 - Part 9: Remove PNX_POPVAR. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 21 +++++++-------------- js/src/frontend/ParseNode.h | 17 ++++++----------- js/src/frontend/Parser.cpp | 11 +---------- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 3c682ac31db..d26911b615b 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4255,7 +4255,6 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL // Lexical bindings cannot be used before they are // initialized. Similar to the JSOP_INITLEXICAL case below. MOZ_ASSERT(emitOption == InitializeVars); - MOZ_ASSERT(pn->pn_xflags & PNX_POPVAR); if (!emit1(JSOP_UNDEFINED)) return false; if (!emitInitializeDestructuringDecls(pn->getOp(), binding)) @@ -4294,8 +4293,6 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (!emitDestructuringOps(initializer, isLetExpr)) return false; - MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); - MOZ_ASSERT_IF(pn->pn_xflags & PNX_POPVAR, emitOption == InitializeVars); if (emitOption == InitializeVars) { if (!emit1(JSOP_POP)) return false; @@ -4352,15 +4349,12 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL // 'let' bindings cannot be used before they are // initialized. JSOP_INITLEXICAL distinguishes the binding site. MOZ_ASSERT(emitOption != DefineVars); - MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR); if (!emit1(JSOP_UNDEFINED)) return false; } // If we are not initializing, nothing to pop. If we are initializing // lets, we must emit the pops. - MOZ_ASSERT_IF(emitOption == InitializeVars, (pn->pn_xflags & PNX_POPVAR) != 0); - MOZ_ASSERT_IF((pn->pn_xflags & PNX_POPVAR) != 0, emitOption == InitializeVars); if (emitOption == InitializeVars) { MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); if (!binding->pn_scopecoord.isFree()) { @@ -5612,17 +5606,16 @@ BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top) emittingForInit = true; if (!updateSourceCoordNotes(init->pn_pos.begin)) return false; - if (init->isKind(PNK_VAR) || init->isKind(PNK_LET) || init->isKind(PNK_CONST)) { - init->pn_xflags |= PNX_POPVAR; // Momentary hack, removed later in this patch stack. - if (!emitTree(init)) - return false; - } else { - if (!emitTree(init)) - return false; + if (!emitTree(init)) + return false; + emittingForInit = false; + + if (!init->isKind(PNK_VAR) && !init->isKind(PNK_LET) && !init->isKind(PNK_CONST)) { + // 'init' is an expression, not a declaration. emitTree left + // its value on the stack. if (!emit1(JSOP_POP)) return false; } - emittingForInit = false; } } diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 0b2da5f2818..2785f3e2a28 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -314,14 +314,12 @@ IsDeleteKind(ParseNodeKind kind) * PNK_FOR binary pn_left: either PNK_FORIN (for-in statement), * PNK_FOROF (for-of) or PNK_FORHEAD (for(;;)) * pn_right: body - * PNK_FORIN ternary pn_kid1: PNK_VAR to left of 'in', or nullptr - * its pn_xflags may have PNX_POPVAR bit set + * PNK_FORIN ternary pn_kid1: PNK_VAR to left of 'in', or nullptr * pn_kid2: PNK_NAME or destructuring expr * to left of 'in'; if pn_kid1, then this * is a clone of pn_kid1->pn_head * pn_kid3: object expr to right of 'in' - * PNK_FOROF ternary pn_kid1: PNK_VAR to left of 'of', or nullptr - * its pn_xflags may have PNX_POPVAR bit set + * PNK_FOROF ternary pn_kid1: PNK_VAR to left of 'of', or nullptr * pn_kid2: PNK_NAME or destructuring expr * to left of 'of'; if pn_kid1, then this * is a clone of pn_kid1->pn_head @@ -757,15 +755,12 @@ class ParseNode #define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED) /* PN_LIST pn_xflags bits. */ -#define PNX_POPVAR 0x01 /* PNK_VAR or PNK_CONST last result - needs popping */ -#define PNX_FUNCDEFS 0x02 /* contains top-level function statements */ -#define PNX_SETCALL 0x04 /* call expression in lvalue context */ -/* 0x08 is available */ -#define PNX_ARRAYHOLESPREAD 0x10 /* one or more of +#define PNX_FUNCDEFS 0x01 /* contains top-level function statements */ +#define PNX_SETCALL 0x02 /* call expression in lvalue context */ +#define PNX_ARRAYHOLESPREAD 0x04 /* one or more of 1. array initialiser has holes 2. array initializer has spread node */ -#define PNX_NONCONST 0x20 /* initialiser has non-constants */ +#define PNX_NONCONST 0x08 /* initialiser has non-constants */ static_assert(PNX_NONCONST < (1 << NumListFlagBits), "Not enough bits"); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 2ddc7f39c7e..da147b82752 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4468,7 +4468,6 @@ Parser::lexicalDeclaration(YieldHandling yieldHandling, bool i nullptr, CurrentLexicalStaticBlock(pc), HoistVars); if (!pn) return null(); - pn->pn_xflags = PNX_POPVAR; return MatchOrInsertSemicolonAfterExpression(tokenStream) ? pn : nullptr; } @@ -4915,10 +4914,7 @@ Parser::exportDeclaration() kid = variables(YieldIsName, PNK_VAR, NotInForInit); if (!kid) return null(); - kid->pn_xflags = PNX_POPVAR; - - kid = MatchOrInsertSemicolonAfterExpression(tokenStream) ? kid : nullptr; - if (!kid) + if (!MatchOrInsertSemicolonAfterExpression(tokenStream)) return null(); MOZ_ASSERT(kid->isArity(PN_LIST)); @@ -6737,10 +6733,6 @@ Parser::statement(YieldHandling yieldHandling, bool canHaveDirecti Node pn = variables(yieldHandling, PNK_VAR, NotInForInit); if (!pn) return null(); - - // Tell js_EmitTree to generate a final POP. - handler.setListFlag(pn, PNX_POPVAR); - if (!MatchOrInsertSemicolonAfterExpression(tokenStream)) return null(); return pn; @@ -7986,7 +7978,6 @@ Parser::legacyComprehensionTail(ParseNode* bodyExpr, unsigned ParseNode* lets = handler.newDeclarationList(PNK_LET, pn3, JSOP_DEFLET); if (!lets) return null(); - lets->pn_xflags |= PNX_POPVAR; /* Definitions can't be passed directly to EmitAssignment as lhs. */ pn3 = cloneLeftHandSide(pn3); From 0e9993095f3a16a4aafd410b4aaa271cdba403d4 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 18:54:19 -0500 Subject: [PATCH 77/95] Bug 1217001 - Part 10: Delete redundant boolean argument. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 12 +++++++----- js/src/frontend/BytecodeEmitter.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index d26911b615b..4461a02f547 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4216,10 +4216,9 @@ BytecodeEmitter::emitTemplateString(ParseNode* pn) } bool -BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isLetExpr) +BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption) { MOZ_ASSERT(pn->isArity(PN_LIST)); - MOZ_ASSERT(isLetExpr == (emitOption == PushInitialValues)); ParseNode* next; for (ParseNode* binding = pn->pn_head; binding; binding = next) { @@ -4290,7 +4289,7 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (!emitTree(binding->pn_right)) return false; - if (!emitDestructuringOps(initializer, isLetExpr)) + if (!emitDestructuringOpsHelper(initializer, emitOption)) return false; if (emitOption == InitializeVars) { @@ -4345,7 +4344,10 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isL if (!emitTree(initializer)) return false; emittingForInit = oldEmittingForInit; - } else if (op == JSOP_INITLEXICAL || op == JSOP_INITGLEXICAL || isLetExpr) { + } else if (op == JSOP_INITLEXICAL || + op == JSOP_INITGLEXICAL || + emitOption == PushInitialValues) + { // 'let' bindings cannot be used before they are // initialized. JSOP_INITLEXICAL distinguishes the binding site. MOZ_ASSERT(emitOption != DefineVars); @@ -5173,7 +5175,7 @@ BytecodeEmitter::emitLetBlock(ParseNode* pnLet) int letHeadDepth = this->stackDepth; - if (!emitVariables(varList, PushInitialValues, true)) + if (!emitVariables(varList, PushInitialValues)) return false; /* Push storage for hoisted let decls (e.g. 'let (x) { let y }'). */ diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index c335aa1b67e..f72cc84af0b 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -469,7 +469,7 @@ struct BytecodeEmitter bool emitNameIncDec(ParseNode* pn); bool maybeEmitVarDecl(JSOp prologueOp, ParseNode* pn, jsatomid* result); - bool emitVariables(ParseNode* pn, VarEmitOption emitOption, bool isLetExpr = false); + bool emitVariables(ParseNode* pn, VarEmitOption emitOption); bool emitNewInit(JSProtoKey key); bool emitSingletonInitialiser(ParseNode* pn); From 70e9b57234a0eaa0eba75c872f4500919a26129f Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 18:59:36 -0500 Subject: [PATCH 78/95] Bug 1217001 - Part 11: Get rid of the last goto in BytecodeEmitter::emitVariables(). r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 179 ++++++++++++++-------------- js/src/frontend/BytecodeEmitter.h | 2 + 2 files changed, 92 insertions(+), 89 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 4461a02f547..ed2842a99a6 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4226,7 +4226,6 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption) return false; next = binding->pn_next; - ParseNode* initializer; if (binding->isKind(PNK_ARRAY) || binding->isKind(PNK_OBJECT)) { // Destructuring BindingPattern in a `for` loop head: // for (let [x, y] of pts) ...; @@ -4277,103 +4276,105 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption) * here and initialize the name. */ if (binding->pn_left->isKind(PNK_NAME)) { - initializer = binding->pn_right; - binding = binding->pn_left; - goto do_name; - } - - initializer = binding->pn_left; - if (!emitDestructuringDecls(pn->getOp(), initializer)) - return false; - - if (!emitTree(binding->pn_right)) - return false; - - if (!emitDestructuringOpsHelper(initializer, emitOption)) - return false; - - if (emitOption == InitializeVars) { - if (!emit1(JSOP_POP)) + if (!emitSingleVariable(pn, binding->pn_left, binding->pn_right, emitOption)) return false; + } else { + ParseNode* initializer = binding->pn_left; + if (!emitDestructuringDecls(pn->getOp(), initializer)) + return false; + + if (!emitTree(binding->pn_right)) + return false; + + if (!emitDestructuringOpsHelper(initializer, emitOption)) + return false; + + if (emitOption == InitializeVars) { + if (!emit1(JSOP_POP)) + return false; + } } } else { - /* - * Load initializer early to share code above that jumps to - * do_name. NB: if this var redeclares an existing binding, then - * `binding` is linked on its definition's use-chain and pn_expr - * has been overlayed with pn_lexdef. - */ - initializer = binding->maybeExpr(); - - do_name: - MOZ_ASSERT(binding->isKind(PNK_NAME)); - if (!bindNameToSlot(binding)) + if (!emitSingleVariable(pn, binding, binding->maybeExpr(), emitOption)) return false; - - JSOp op; - op = binding->getOp(); - MOZ_ASSERT(op != JSOP_CALLEE); - MOZ_ASSERT(!binding->pn_scopecoord.isFree() || !pn->isOp(JSOP_NOP)); - - jsatomid atomIndex; - if (!maybeEmitVarDecl(pn->getOp(), binding, &atomIndex)) - return false; - - if (initializer) { - MOZ_ASSERT(emitOption != DefineVars); - if (op == JSOP_SETNAME || - op == JSOP_STRICTSETNAME || - op == JSOP_SETGNAME || - op == JSOP_STRICTSETGNAME || - op == JSOP_SETINTRINSIC) - { - MOZ_ASSERT(emitOption != PushInitialValues); - JSOp bindOp; - if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME) - bindOp = JSOP_BINDNAME; - else if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME) - bindOp = JSOP_BINDGNAME; - else - bindOp = JSOP_BINDINTRINSIC; - if (!emitIndex32(bindOp, atomIndex)) - return false; - } - - bool oldEmittingForInit = emittingForInit; - emittingForInit = false; - if (!emitTree(initializer)) - return false; - emittingForInit = oldEmittingForInit; - } else if (op == JSOP_INITLEXICAL || - op == JSOP_INITGLEXICAL || - emitOption == PushInitialValues) - { - // 'let' bindings cannot be used before they are - // initialized. JSOP_INITLEXICAL distinguishes the binding site. - MOZ_ASSERT(emitOption != DefineVars); - if (!emit1(JSOP_UNDEFINED)) - return false; - } - - // If we are not initializing, nothing to pop. If we are initializing - // lets, we must emit the pops. - if (emitOption == InitializeVars) { - MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); - if (!binding->pn_scopecoord.isFree()) { - if (!emitVarOp(binding, op)) - return false; - } else { - if (!emitIndexOp(op, atomIndex)) - return false; - } - if (!emit1(JSOP_POP)) - return false; - } } } return true; } +bool +BytecodeEmitter::emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode* initializer, + VarEmitOption emitOption) +{ + // NB: if this var redeclares an existing binding, then `binding` is linked + // on its definition's use-chain and pn_expr has been overlayed with + // pn_lexdef. + MOZ_ASSERT(binding->isKind(PNK_NAME)); + if (!bindNameToSlot(binding)) + return false; + + JSOp op = binding->getOp(); + MOZ_ASSERT(op != JSOP_CALLEE); + MOZ_ASSERT(!binding->pn_scopecoord.isFree() || !pn->isOp(JSOP_NOP)); + + jsatomid atomIndex; + if (!maybeEmitVarDecl(pn->getOp(), binding, &atomIndex)) + return false; + + if (initializer) { + MOZ_ASSERT(emitOption != DefineVars); + if (op == JSOP_SETNAME || + op == JSOP_STRICTSETNAME || + op == JSOP_SETGNAME || + op == JSOP_STRICTSETGNAME || + op == JSOP_SETINTRINSIC) + { + MOZ_ASSERT(emitOption != PushInitialValues); + JSOp bindOp; + if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME) + bindOp = JSOP_BINDNAME; + else if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME) + bindOp = JSOP_BINDGNAME; + else + bindOp = JSOP_BINDINTRINSIC; + if (!emitIndex32(bindOp, atomIndex)) + return false; + } + + bool oldEmittingForInit = emittingForInit; + emittingForInit = false; + if (!emitTree(initializer)) + return false; + emittingForInit = oldEmittingForInit; + } else if (op == JSOP_INITLEXICAL || + op == JSOP_INITGLEXICAL || + emitOption == PushInitialValues) + { + // 'let' bindings cannot be used before they are + // initialized. JSOP_INITLEXICAL distinguishes the binding site. + MOZ_ASSERT(emitOption != DefineVars); + if (!emit1(JSOP_UNDEFINED)) + return false; + } + + // If we are not initializing, nothing to pop. If we are initializing + // lets, we must emit the pops. + if (emitOption == InitializeVars) { + MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr); + if (!binding->pn_scopecoord.isFree()) { + if (!emitVarOp(binding, op)) + return false; + } else { + if (!emitIndexOp(op, atomIndex)) + return false; + } + if (!emit1(JSOP_POP)) + return false; + } + + return true; +} + bool BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) { diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index f72cc84af0b..2ce95dbb5ba 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -470,6 +470,8 @@ struct BytecodeEmitter bool maybeEmitVarDecl(JSOp prologueOp, ParseNode* pn, jsatomid* result); bool emitVariables(ParseNode* pn, VarEmitOption emitOption); + bool emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode* initializer, + VarEmitOption emitOption); bool emitNewInit(JSProtoKey key); bool emitSingletonInitialiser(ParseNode* pn); From d6f3808f53c2d3a3e56cd13ab23d27f8113c1c59 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 19 Oct 2015 15:58:19 -0500 Subject: [PATCH 79/95] Bug 1217099 - Stop emitting pointless JSOP_GETLOCAL; JSOP_POP bytecode sequence for `var x;`. r=shu. --- .../tests/unit/test_get-executable-lines.js | 2 +- js/src/frontend/BytecodeEmitter.cpp | 3 +++ .../tests/debug/Script-getAllColumnOffsets-02.js | 2 +- js/src/tests/ecma_5/Global/bug-320887.js | 15 +++++++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 js/src/tests/ecma_5/Global/bug-320887.js diff --git a/devtools/server/tests/unit/test_get-executable-lines.js b/devtools/server/tests/unit/test_get-executable-lines.js index a593a64f143..2228fa5259f 100644 --- a/devtools/server/tests/unit/test_get-executable-lines.js +++ b/devtools/server/tests/unit/test_get-executable-lines.js @@ -38,7 +38,7 @@ function test_executable_lines() { do_check_true(!error); let source = gThreadClient.source(sources[0]); source.getExecutableLines(function(lines){ - do_check_true(arrays_equal([2, 3, 5, 6, 7, 8, 12, 14, 16], lines)); + do_check_true(arrays_equal([2, 5, 7, 8, 12, 14, 16], lines)); finishClient(gClient); }); }); diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index ed2842a99a6..b93d0a1ae97 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4355,6 +4355,9 @@ BytecodeEmitter::emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode MOZ_ASSERT(emitOption != DefineVars); if (!emit1(JSOP_UNDEFINED)) return false; + } else { + // The declaration is like `var x;`. Nothing to do. + return true; } // If we are not initializing, nothing to pop. If we are initializing diff --git a/js/src/jit-test/tests/debug/Script-getAllColumnOffsets-02.js b/js/src/jit-test/tests/debug/Script-getAllColumnOffsets-02.js index 145643d3b63..405b13d629b 100644 --- a/js/src/jit-test/tests/debug/Script-getAllColumnOffsets-02.js +++ b/js/src/jit-test/tests/debug/Script-getAllColumnOffsets-02.js @@ -18,4 +18,4 @@ global.eval("function f(n){var w0,x1=3,y2=4,z3=9} debugger;"); global.f(3); // Should have hit each variable declared. -assertEq(global.log, "18 21 26 31 35 "); +assertEq(global.log, "21 26 31 35 "); diff --git a/js/src/tests/ecma_5/Global/bug-320887.js b/js/src/tests/ecma_5/Global/bug-320887.js new file mode 100644 index 00000000000..5e8d3445abd --- /dev/null +++ b/js/src/tests/ecma_5/Global/bug-320887.js @@ -0,0 +1,15 @@ +// `var x` should not call the getter of an existing global property. + +var hit = 0; +Object.defineProperty(this, "x", { + get: function () { return ++hit; }, + configurable: true +}); +eval("var x;"); +assertEq(hit, 0); + +// The declaration should not have redefined the global x, either. +assertEq(x, 1); +assertEq(x, 2); + +reportCompare(0, 0); From f3d6c3ed1e08c76156252ed533a9acf6e8902d94 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 19 Oct 2015 17:08:28 -0500 Subject: [PATCH 80/95] Bug 1217110 - Remove unnecessary opcode JSOP_BINDINTRINSIC. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 18 +++++++++--------- js/src/vm/Interpreter.cpp | 14 +------------- js/src/vm/Opcodes.h | 18 ++++-------------- 3 files changed, 14 insertions(+), 36 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index b93d0a1ae97..81f0eab44e7 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4326,17 +4326,14 @@ BytecodeEmitter::emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME || op == JSOP_SETGNAME || - op == JSOP_STRICTSETGNAME || - op == JSOP_SETINTRINSIC) + op == JSOP_STRICTSETGNAME) { MOZ_ASSERT(emitOption != PushInitialValues); JSOp bindOp; if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME) bindOp = JSOP_BINDNAME; - else if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME) - bindOp = JSOP_BINDGNAME; else - bindOp = JSOP_BINDINTRINSIC; + bindOp = JSOP_BINDGNAME; if (!emitIndex32(bindOp, atomIndex)) return false; } @@ -4396,13 +4393,16 @@ BytecodeEmitter::emitAssignment(ParseNode* lhs, JSOp op, ParseNode* rhs) if (lhs->pn_scopecoord.isFree()) { if (!makeAtomIndex(lhs->pn_atom, &atomIndex)) return false; + JSOp bindOp; - if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME)) + if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME)) { bindOp = JSOP_BINDNAME; - else if (lhs->isOp(JSOP_SETGNAME) || lhs->isOp(JSOP_STRICTSETGNAME)) + } else if (lhs->isOp(JSOP_SETGNAME) || lhs->isOp(JSOP_STRICTSETGNAME)) { bindOp = JSOP_BINDGNAME; - else - bindOp = JSOP_BINDINTRINSIC; + } else { + MOZ_ASSERT(lhs->isOp(JSOP_SETINTRINSIC)); + break; + } if (!emitIndex32(bindOp, atomIndex)) return false; offset++; diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index fb99a95d8d2..ae2fc6048b1 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1799,6 +1799,7 @@ CASE(EnableInterruptsPseudoOpcode) CASE(JSOP_NOP) CASE(JSOP_UNUSED14) CASE(JSOP_BACKPATCH) +CASE(JSOP_UNUSED145) CASE(JSOP_UNUSED171) CASE(JSOP_UNUSED172) CASE(JSOP_UNUSED173) @@ -2139,16 +2140,6 @@ CASE(JSOP_PICK) } END_CASE(JSOP_PICK) -CASE(JSOP_BINDINTRINSIC) -{ - NativeObject* holder = GlobalObject::getIntrinsicsHolder(cx, cx->global()); - if (!holder) - goto error; - - PUSH_OBJECT(*holder); -} -END_CASE(JSOP_BINDINTRINSIC) - CASE(JSOP_BINDGNAME) CASE(JSOP_BINDNAME) { @@ -2572,9 +2563,6 @@ CASE(JSOP_SETINTRINSIC) if (!SetIntrinsicOperation(cx, script, REGS.pc, value)) goto error; - - REGS.sp[-2] = REGS.sp[-1]; - REGS.sp--; } END_CASE(JSOP_SETINTRINSIC) diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index 32b14d2732c..19832563f42 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -1474,24 +1474,14 @@ */ \ macro(JSOP_GETINTRINSIC, 143, "getintrinsic", NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_TYPESET) \ /* - * Pops the top two values on the stack as 'val' and 'scope', sets intrinsic - * as 'val', and pushes 'val' onto the stack. - * - * 'scope' is not used. + * Stores the top stack value in the specified intrinsic. * Category: Variables and Scopes * Type: Intrinsics * Operands: uint32_t nameIndex - * Stack: scope, val => val + * Stack: val => val */ \ - macro(JSOP_SETINTRINSIC, 144, "setintrinsic", NULL, 5, 2, 1, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING) \ - /* - * Pushes 'intrinsicHolder' onto the stack. - * Category: Variables and Scopes - * Type: Intrinsics - * Operands: uint32_t nameIndex - * Stack: => intrinsicHolder - */ \ - macro(JSOP_BINDINTRINSIC, 145, "bindintrinsic", NULL, 5, 0, 1, JOF_ATOM|JOF_NAME|JOF_SET) \ + macro(JSOP_SETINTRINSIC, 144, "setintrinsic", NULL, 5, 1, 1, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING) \ + macro(JSOP_UNUSED145, 145, "unused145", NULL, 1, 0, 0, JOF_BYTE) \ /* * Initialize a non-configurable, non-writable, non-enumerable data-property on an object. * From e3b452e30f1a45d0eafdb2b5ba46fdaef308e50b Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Wed, 28 Oct 2015 17:07:11 -0700 Subject: [PATCH 81/95] Bug 1218591 - Reset the WebSocket retry counter when the server replies. r=dragana --- dom/push/PushServiceWebSocket.jsm | 13 ++--- dom/push/test/xpcshell/head.js | 6 ++- dom/push/test/xpcshell/test_retry_ws.js | 71 +++++++++++++++++++++++++ dom/push/test/xpcshell/xpcshell.ini | 1 + 4 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 dom/push/test/xpcshell/test_retry_ws.js diff --git a/dom/push/PushServiceWebSocket.jsm b/dom/push/PushServiceWebSocket.jsm index fa7747c6452..10e72cfbe5f 100644 --- a/dom/push/PushServiceWebSocket.jsm +++ b/dom/push/PushServiceWebSocket.jsm @@ -1127,9 +1127,6 @@ this.PushServiceWebSocket = { return; } - // Since we've had a successful connection reset the retry fail count. - this._retryFailCount = 0; - let data = { messageType: "hello", use_webpush: true, @@ -1196,12 +1193,10 @@ this.PushServiceWebSocket = { return; } - // If we are not waiting for a hello message, reset the retry fail count - if (this._currentState != STATE_WAITING_FOR_HELLO) { - debug('Reseting _retryFailCount and _pingIntervalRetryTimes'); - this._retryFailCount = 0; - this._pingIntervalRetryTimes = {}; - } + // If we receive a message, we know the connection succeeded. Reset the + // connection attempt and ping interval counters. + this._retryFailCount = 0; + this._pingIntervalRetryTimes = {}; let doNotHandle = false; if ((message === '{}') || diff --git a/dom/push/test/xpcshell/head.js b/dom/push/test/xpcshell/head.js index ae12eb9c92c..791370f78b2 100644 --- a/dom/push/test/xpcshell/head.js +++ b/dom/push/test/xpcshell/head.js @@ -378,7 +378,11 @@ MockWebSocket.prototype = { () => this._listener.onServerClose(this._context, statusCode, reason), () => this._listener.onStop(this._context, Cr.NS_BASE_STREAM_CLOSED) ); - } + }, + + serverInterrupt(result = Cr.NS_ERROR_NET_RESET) { + waterfall(() => this._listener.onStop(this._context, result)); + }, }; /** diff --git a/dom/push/test/xpcshell/test_retry_ws.js b/dom/push/test/xpcshell/test_retry_ws.js new file mode 100644 index 00000000000..9287bd2ebb4 --- /dev/null +++ b/dom/push/test/xpcshell/test_retry_ws.js @@ -0,0 +1,71 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +'use strict'; + +const {PushDB, PushService, PushServiceWebSocket} = serviceExports; + +const userAgentID = '05f7b940-51b6-4b6f-8032-b83ebb577ded'; + +function run_test() { + do_get_profile(); + setPrefs({ + userAgentID: userAgentID, + pingInterval: 10000, + retryBaseInterval: 25, + }); + run_next_test(); +} + +add_task(function* test_ws_retry() { + let db = PushServiceWebSocket.newPushDB(); + do_register_cleanup(() => {return db.drop().then(_ => db.close());}); + + yield db.put({ + channelID: '61770ba9-2d57-4134-b949-d40404630d5b', + pushEndpoint: 'https://example.org/push/1', + scope: 'https://example.net/push/1', + version: 1, + originAttributes: '', + quota: Infinity, + }); + + let alarmDelays = []; + let setAlarm = PushService.setAlarm; + PushService.setAlarm = function(delay) { + alarmDelays.push(delay); + setAlarm.apply(this, arguments); + }; + + let handshakeDone; + let handshakePromise = new Promise(resolve => handshakeDone = resolve); + PushService.init({ + serverURI: "wss://push.example.org/", + networkInfo: new MockDesktopNetworkInfo(), + makeWebSocket(uri) { + return new MockWebSocket(uri, { + onHello(request) { + if (alarmDelays.length == 10) { + PushService.setAlarm = setAlarm; + this.serverSendMsg(JSON.stringify({ + messageType: 'hello', + status: 200, + uaid: userAgentID, + })); + handshakeDone(); + return; + } + this.serverInterrupt(); + }, + }); + }, + }); + + yield waitForPromise( + handshakePromise, + 45000, + 'Timed out waiting for successful handshake' + ); + deepEqual(alarmDelays, [25, 50, 100, 200, 400, 800, 1600, 3200, 6400, 10000], + 'Wrong reconnect alarm delays'); +}); diff --git a/dom/push/test/xpcshell/xpcshell.ini b/dom/push/test/xpcshell/xpcshell.ini index 650aa92455e..79e002a01b9 100644 --- a/dom/push/test/xpcshell/xpcshell.ini +++ b/dom/push/test/xpcshell/xpcshell.ini @@ -40,6 +40,7 @@ run-sequentially = This will delete all existing push subscriptions. [test_webapps_cleardata.js] [test_updateRecordNoEncryptionKeys_ws.js] [test_reconnect_retry.js] +[test_retry_ws.js] #http2 test [test_resubscribe_4xxCode_http2.js] [test_resubscribe_5xxCode_http2.js] From bbea36ac579c2c7565465ea6c95b714501f0acd5 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Wed, 28 Oct 2015 17:13:12 -0700 Subject: [PATCH 82/95] Bug 1194534 - Disable two failing tests. r=billm --- dom/plugins/test/mochitest/mochitest.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochitest/mochitest.ini index 447b4530b63..23169e82070 100644 --- a/dom/plugins/test/mochitest/mochitest.ini +++ b/dom/plugins/test/mochitest/mochitest.ini @@ -43,10 +43,10 @@ support-files = [test_bug1092842.html] skip-if = e10s [test_cocoa_focus.html] -skip-if = toolkit != "cocoa" +skip-if = toolkit != "cocoa" || e10s # Bug 1194534 support-files = cocoa_focus.html [test_cocoa_window_focus.html] -skip-if = toolkit != "cocoa" +skip-if = toolkit != "cocoa" || e10s # Bug 1194534 support-files = cocoa_window_focus.html [test_cookies.html] [test_copyText.html] From 85703d7ba814d495f1795d4e0409a702fc531054 Mon Sep 17 00:00:00 2001 From: Rail Aliiev Date: Wed, 28 Oct 2015 20:28:07 -0400 Subject: [PATCH 83/95] Bug 1218763 - Antivirus should retry on SSLError. r=nthomas DONTBUILD --- testing/mozharness/scripts/release/antivirus.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testing/mozharness/scripts/release/antivirus.py b/testing/mozharness/scripts/release/antivirus.py index 5c81e67d7f7..949fc123aa1 100644 --- a/testing/mozharness/scripts/release/antivirus.py +++ b/testing/mozharness/scripts/release/antivirus.py @@ -132,6 +132,7 @@ class AntivirusScan(BaseScript, VirtualenvMixin): from boto.s3.connection import S3Connection from boto.exception import S3CopyError, S3ResponseError from redo import retry + from httplib import HTTPException # suppress boto debug logging, it's too verbose with --loglevel=debug import logging @@ -156,7 +157,7 @@ class AntivirusScan(BaseScript, VirtualenvMixin): args=(destination, ), sleeptime=5, max_sleeptime=60, retry_exceptions=(S3CopyError, S3ResponseError, - IOError)) + IOError, HTTPException)) def find_release_files(): candidates_prefix = self._get_candidates_prefix() From b22afffd548fc58bf08473a46f5fef1a11029077 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 29 Oct 2015 09:35:10 +0900 Subject: [PATCH 84/95] Bug 962249 followup - Fix the bug of Window.scroll{Max,Min}{X,Y} that they incorrectly return app units instead of css pixels. r=roc --- dom/base/nsGlobalWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 6ff2b855a0a..fe14eb24c44 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -5507,7 +5507,8 @@ nsGlobalWindow::GetScrollBoundaryOuter(Side aSide) FlushPendingNotifications(Flush_Layout); if (nsIScrollableFrame *sf = GetScrollFrame()) { - return sf->GetScrollRange().Edge(aSide); + return nsPresContext:: + AppUnitsToIntCSSPixels(sf->GetScrollRange().Edge(aSide)); } return 0; } From 25cc2483ee220141e6cf9571cfaa64026e117991 Mon Sep 17 00:00:00 2001 From: Tanvi Vyas Date: Wed, 28 Oct 2015 17:53:02 -0700 Subject: [PATCH 85/95] Bug 1219454 - Replace 'show' with 'receive' for consistent messaging around notifications and to account for new Push permission in about:preferences. r=MattN --- browser/components/preferences/in-content/content.js | 2 +- browser/components/preferences/in-content/content.xul | 2 +- browser/locales/en-US/chrome/browser/preferences/content.dtd | 2 +- .../en-US/chrome/browser/preferences/preferences.properties | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/browser/components/preferences/in-content/content.js b/browser/components/preferences/in-content/content.js index 50f33edd86c..15c28ec4b0d 100644 --- a/browser/components/preferences/in-content/content.js +++ b/browser/components/preferences/in-content/content.js @@ -123,7 +123,7 @@ var gContentPane = { let bundlePreferences = document.getElementById("bundlePreferences"); let params = { permissionType: "desktop-notification" }; params.windowTitle = bundlePreferences.getString("notificationspermissionstitle"); - params.introText = bundlePreferences.getString("notificationspermissionstext2"); + params.introText = bundlePreferences.getString("notificationspermissionstext3"); gSubDialog.open("chrome://browser/content/preferences/permissions.xul", "resizable=yes", params); diff --git a/browser/components/preferences/in-content/content.xul b/browser/components/preferences/in-content/content.xul index 5fe1364e18d..5bb587413ae 100644 --- a/browser/components/preferences/in-content/content.xul +++ b/browser/components/preferences/in-content/content.xul @@ -70,7 +70,7 @@ - +