From 0a8c03ba8e214bf38a49d183e351e8cd56c5380e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 28 Oct 2015 10:50:36 -0700 Subject: [PATCH 001/108] 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 5802dc3cd675..f1dc7e893e76 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 7b41c377283f..eabae22f74aa 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 a6930c746b5f..9e1ee08faded 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 d9bcfea50a05..32a0ef5d860d 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 b09d9c398891..178bd25baa02 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 a3a0a9b30447..82121d1ac2c4 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 08bb04a0dbd1..88f00bd7668f 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 ab2544736ed4..3490326c29aa 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 cf8a4f242629..69f59cc0f587 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 489a63378fca68371eaa196da5a7908418e22190 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 28 Oct 2015 10:50:41 -0700 Subject: [PATCH 002/108] 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 69f59cc0f587..23ed1f86f8bb 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 bfa112caf5997edc0a4f039d29b0d5bbd52f9e2f Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 28 Oct 2015 10:50:45 -0700 Subject: [PATCH 003/108] 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 2b423d2fe18e..fb30d7fa3ab9 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 b05cf7fd062c..31d2dfb88cfc 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 23ed1f86f8bb..377c25aa756a 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 2e67a4792c32deec6bfb184de17a1ddff94e91b5 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 28 Oct 2015 10:50:53 -0700 Subject: [PATCH 004/108] 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 377c25aa756a..e32ba3107164 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 731d7a9cdfc4b0953bf9a38619f74ea6aa420584 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 28 Oct 2015 14:02:33 -0400 Subject: [PATCH 005/108] Bug 1190469 - Refactor some code to have a general-purpose snap function available in APZC. r=botond --HG-- extra : commitid : FuJ8LNkJWKv --- 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 be055132c58d..57465e78001f 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 c36db4e124a5..a4d46d450e5a 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 e9975e4779af343b969b3f614e31d75c4c90c93f Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 28 Oct 2015 14:02:36 -0400 Subject: [PATCH 006/108] Bug 1190469 - Request scroll snapping in a few places that animations are cancelled so that we don't leave things unsnapped. r=botond --HG-- extra : commitid : E2vwH6RDvR5 --- 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 ad8d157371b1..a85fddc03ee7 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 57465e78001f..38f7ecf1c5ef 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 9936a2b37fb5fb8583d48e8f30d020f3c1ba22ff Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 28 Oct 2015 11:16:06 -0700 Subject: [PATCH 007/108] 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 a68a68207477..c766960f3d07 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 6d48040fc9e30401ed9f0cc5193bdc15435327d7 Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Wed, 28 Oct 2015 19:25:26 +0100 Subject: [PATCH 008/108] 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 0b869c1e6ac7..8b024eb8f045 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 d8e38493d30bce9b49c45119c040b7bae7366af9 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 27 Oct 2015 20:13:45 -0400 Subject: [PATCH 009/108] 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 66b89e3add3d..8560b3788cfd 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 000000000000..bda8f4f4a45b --- /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 000000000000..12a179980df2 --- /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 000000000000..ffd76bfc4990 --- /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 867a147a46c5228d86796ecb3b17e1f154d1edd7 Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Wed, 28 Oct 2015 18:51:59 +0000 Subject: [PATCH 010/108] 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 000000000000..780ef55dc6a3 --- /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 a236ac67a953..126dace94dd7 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 b7738102b447638ac7f6d6714abc5d44b40fd309 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 23 Oct 2015 15:37:19 -0400 Subject: [PATCH 011/108] 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 e3144266530a..881e4e376b31 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 fc136257e3ae36c9ef3f8f4d2ef0043244cf35f4 Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Fri, 12 Jun 2015 08:48:42 -0400 Subject: [PATCH 012/108] 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 f2433b12d8b9..6ede3d18ed4c 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 477ec9d12da1..0b5612ad8efc 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 d315400107a1..a45d63f5f49c 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 30e901bd6b63..50c13818003f 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 f8eeacfdd173..a5234326b985 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 adfb66969c57..5446b58f9fb7 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 dc2d773e508e..737affceabce 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 e627ab706a04..0c8e571e2e04 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 7c68b90d9931..75180b913fbf 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 7862a0a497f5..982b5f7c527b 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 b2627b44036c..fdfde62d8cd0 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 5d8655d503a5..e365c93e0ae5 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 58165d3b3d24..e82182604e9c 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 435adc1361d4a74caaef7ef93dc9d6cf19f8fa83 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 28 Sep 2015 17:09:56 -0500 Subject: [PATCH 013/108] 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 000000000000..83f3687b42a8 --- /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 8b4175a96217..ac83e3e6fca3 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 000000000000..3b80f062e877 --- /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 a9225e2d8300..c99c03ec15b7 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 6e062730aa38..6a0b78e62f9e 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 faa1a44adb34953f6b9c1cf17ad284c9c88bd9f8 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Thu, 24 Sep 2015 09:11:53 -0500 Subject: [PATCH 014/108] 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 e0fb75cb7fde..37f8702f3c36 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 5aa7d2cb3bfe..7969686dfef0 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 be3ccecfb5c6..eb13d141cb58 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 f4507291cd44..b3b9a127ac4d 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 a47e37e881f0..d2f625fe2b4c 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 03f305c86729..3a07984ed701 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 e8f7d56409d1..b0bff91adfdc 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 d028cad8e62a..92bc5b517569 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 9665b9e0c3cd309cc03cb8d4648a7d4de4f21aaa Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Fri, 25 Sep 2015 09:29:53 -0500 Subject: [PATCH 015/108] 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 6caf6623137c..13484e7c20a2 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 e86d7551a969..44eede53076a 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 780a9950169a..63a15a35dc95 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 b78a021b1b16..efed07959d8b 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 37f8702f3c36..b3cde76a0f5a 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 46227afc4da9..a70c53137a34 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 7d70fe180b710ec1d0b22ef5336d8932354e6169 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 28 Sep 2015 09:41:08 -0500 Subject: [PATCH 016/108] 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 13484e7c20a2..f00fff1fdbe7 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 44eede53076a..b9391eea13ed 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 63a15a35dc95..8234374f56c2 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 7969686dfef0..f050ec9246c0 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 7fa8522446abae50faa9e444640fce769e8a2972 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 28 Sep 2015 17:09:00 -0500 Subject: [PATCH 017/108] 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 e4cd7687ce2c..2141347e9513 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 d9a03441977d..cd33e3d31dd5 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 cc9ddd0bbfa9..b006eadf78a6 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 7a528d20d4d7cf1bdd173c9a78a40ec6a01f58ec Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 12 Oct 2015 12:04:09 -0500 Subject: [PATCH 018/108] 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 231565e1d9c4..e2f1b386d725 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 d51dcbce99bde3fa0c41ccca042351697d1167a7 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 14 Oct 2015 09:38:21 -0500 Subject: [PATCH 019/108] 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 d8ce5bad7446..a93ab3235aa1 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 c5c7a6b006da..f38f530aa656 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 d4a97536f173..d1df024c62c8 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 ce97e7fd8bd7..d32119ba9068 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 4bd5f1562055..1851852ec1a2 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 121d1cb87dac..73a049903554 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 d77269ffa23389783c7ee496445f043a84cbfef6 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Fri, 23 Oct 2015 12:50:26 -0500 Subject: [PATCH 020/108] 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 7a561e3af671..cd8d177c8638 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 d5915db3a44baa4daa3b4cbe8d6cd2b67cd8e25a Mon Sep 17 00:00:00 2001 From: James Willcox Date: Mon, 26 Oct 2015 12:44:21 -0500 Subject: [PATCH 021/108] 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 b45c31e3ec5c..e3cc76986fc5 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 6ab6121caae997fed4729e584cc7711d7e101a1d Mon Sep 17 00:00:00 2001 From: James Willcox Date: Tue, 27 Oct 2015 16:03:49 -0500 Subject: [PATCH 022/108] 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 f28cb81ca12b..4bf7df7a007e 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 f4d0be67dfc4..647c7bcfed87 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 1c5b794be3b0f8639a0951f49257cc226c3845c0 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Tue, 27 Oct 2015 16:07:51 -0500 Subject: [PATCH 023/108] 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 f84f0438559e..794fb8b8ad38 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 b121e7da05486b4cb25757341eeb44a7678e032f Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 28 Oct 2015 19:10:20 +0000 Subject: [PATCH 024/108] Bug 1215092 - WebSocketEventService and WebSocket discovering - part 1 - Renaming WebSocketFrameService, r=michal --HG-- rename : netwerk/protocol/websocket/PWebSocketFrameListener.ipdl => netwerk/protocol/websocket/PWebSocketEventListener.ipdl rename : netwerk/protocol/websocket/WebSocketFrameListenerChild.cpp => netwerk/protocol/websocket/WebSocketEventListenerChild.cpp rename : netwerk/protocol/websocket/WebSocketFrameListenerChild.h => netwerk/protocol/websocket/WebSocketEventListenerChild.h rename : netwerk/protocol/websocket/WebSocketFrameListenerParent.cpp => netwerk/protocol/websocket/WebSocketEventListenerParent.cpp rename : netwerk/protocol/websocket/WebSocketFrameListenerParent.h => netwerk/protocol/websocket/WebSocketEventListenerParent.h rename : netwerk/protocol/websocket/WebSocketFrameService.cpp => netwerk/protocol/websocket/WebSocketEventService.cpp rename : netwerk/protocol/websocket/WebSocketFrameService.h => netwerk/protocol/websocket/WebSocketEventService.h rename : netwerk/protocol/websocket/nsIWebSocketFrameService.idl => netwerk/protocol/websocket/nsIWebSocketEventService.idl --- 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 a0a2bed27cf9..03db0ecaa558 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 e2543f729d64..9185e4be8375 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 b327e04d7df8..3809d637703f 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 b7bcaf757f63..37f035502694 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 9beef791f002..1bf8c4a26777 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 4309cab594c1..dbbc525cfd48 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 655963183705..5ea25d72c5de 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 b4355ba1b45d..dfe2a6c7e518 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 48d2f3660fff..0158be5328ec 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 6e6218a49360..3fdb1ca0ecd7 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 80c549420385..6644b75f2aa3 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 3cfbdb610129..529c87ab02b7 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 0cc1fcd224b3..c13d6f3ff100 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 e02bb13032b0..5b5b10d73451 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 f5b2f8f7d796..057e3fd677b4 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 5e7cd7a3fa6c..09ddf7100622 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 315eb43a3ceb..56f1a27e9a7e 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 c80e399809de..86848c368ed6 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 d32c493da5ec..0642fada9d1e 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 73c08ab4136ed435ad0f2b2be5f94888f4c438ab Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 28 Oct 2015 19:10:42 +0000 Subject: [PATCH 025/108] 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 3809d637703f..3ceb8bea589e 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 37f035502694..19f481dfe1f8 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 1bf8c4a26777..85d3eba66a01 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 dbbc525cfd48..c548b1b6e04c 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 5ea25d72c5de..2e1f2f518297 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 91eb34f2cbc9..dd9136b93aa4 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 d9f52864e64b..34757d85bbef 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 0158be5328ec..ca850695d8af 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 3fdb1ca0ecd7..de9fed7064ca 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 fafbcc23fae6..34f87a9868aa 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 d04b0c7509cd..2354703b0fd6 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 239e99d74c56..293223f8a67e 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 0adae64404ab..10d446bd4d5b 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 419e0606331f27bc6651ceb282aadab145ae286a Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 28 Oct 2015 19:11:05 +0000 Subject: [PATCH 026/108] 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 bd3c045abba2..56f5a39cc2bf 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 03db0ecaa558..78c12bd236f5 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 dfe2a6c7e518..20e16fa9fd36 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 6644b75f2aa3..691d0fb1dd38 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 529c87ab02b7..c8b5ecd3cfe7 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 c13d6f3ff100..79647ef28efe 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 057e3fd677b4..8eb55c7872bb 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 09ddf7100622..571da96614d5 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 10d446bd4d5b..dd6fd46de715 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 0642fada9d1e..f9f074026044 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 cee356be8ec0557f4a68a772615e700d62901039 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 28 Oct 2015 19:11:25 +0000 Subject: [PATCH 027/108] 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 56f5a39cc2bf..0b233615a2f7 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 78c12bd236f5..59ab85907788 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 20e16fa9fd36..ef0310d7cb7a 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 691d0fb1dd38..08a57b817b8c 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 c8b5ecd3cfe7..8a42abac2bd3 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 79647ef28efe..ef1d57188ee7 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 8eb55c7872bb..06984e75ef32 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 571da96614d5..2515c05ebf3e 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 f9f074026044..c2986dc2f059 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 4797e62ace68913909541142210492dcc7beeffd Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Wed, 28 Oct 2015 15:27:35 -0400 Subject: [PATCH 028/108] Bug 1218618 - Assert that the hit-testing tree's root node doesn't have siblings. r=kats --HG-- extra : source : 94dc564a7dd0b93e22e60395391b4b951b09c002 --- 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 276ed3f5289b..9344942925e6 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 c65eaafded99a63baf4d8f83ccd7193372d1f6f7 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 28 Oct 2015 15:39:13 -0400 Subject: [PATCH 029/108] Bug 1219391 - Request snapping for the entire handoff chain when ending the fling animation. r=botond --HG-- extra : commitid : 6yaFBO8ZuY --- 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 38f7ecf1c5ef..64cf4d6326d0 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 ac8e914c48cb0a4290114e0b176fb23be2b77308 Mon Sep 17 00:00:00 2001 From: Eric Faust Date: Wed, 28 Oct 2015 13:01:06 -0700 Subject: [PATCH 030/108] 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 387ea1d6936e..f0c35d334d8f 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 8b1594fa812b..2b16333883e6 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 8ef9e48eea40..eb1ffa48df66 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 145b12d2a113..20835cb29ab1 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 48206a881e1a..ab60cb3ce07b 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 ab31b7aedd2a..de94f7010ce0 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 681b839a18b52c03ba128679615a860983affbec Mon Sep 17 00:00:00 2001 From: Eric Faust Date: Wed, 28 Oct 2015 13:01:07 -0700 Subject: [PATCH 031/108] 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 e1656d2da41e..d3a09522139e 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 2ee6159bdb737ce7d9f134345a75ff958361a73f Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 28 Oct 2015 13:42:16 -0700 Subject: [PATCH 032/108] Bug 1219419 - Keep DefaultTracer simple for now; r=fitzgen --HG-- extra : rebase_source : e9d040a6d574f5fa60158ff8521cde1cab08e14c --- 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 1484f5307279..c18d25529140 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 7edcf2975fe2..2ac1390e9770 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 38f032ac874cf2e9cd8ae53f2c2556001f6f1b9c Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Wed, 28 Oct 2015 13:43:59 -0700 Subject: [PATCH 033/108] Backed out changeset 71cb0cec8da0 (bug 1219085) for wpt orange --HG-- extra : commitid : IjFlJwi7sAo --- .../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 8560b3788cfd..66b89e3add3d 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 bda8f4f4a45b..000000000000 --- 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 12a179980df2..000000000000 --- 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 ffd76bfc4990..000000000000 --- 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 54b7ac24f451d1fa7f90a90db7d4cb1564446eee Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 28 Oct 2015 14:37:54 -0700 Subject: [PATCH 034/108] 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 00eff936681b..8e1438d3d4a3 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 1c8b35cef0eee3f3ae948dad7a075811800c7263 Mon Sep 17 00:00:00 2001 From: Sean Stangl Date: Mon, 26 Oct 2015 15:11:40 -0700 Subject: [PATCH 035/108] 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 15da4c4e3fd6..c2f9f7f421b8 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 1ab1e39ec567584cc20bec8ec81939b39ff4c080 Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Thu, 15 Oct 2015 16:59:11 -0700 Subject: [PATCH 036/108] Bug 1215752 - Weakmap refactoring, r=terrence --HG-- extra : rebase_source : d912254e42d12f90c8f5fea5eeee750021668433 --- 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 fdc3cc4375d6..2d3d5ef4c3db 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 be698e36fe63..1dbe7513698e 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 6cfc8a6f65e0..20859a628bec 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 fa33e3cca1b8..1b9a2dcada12 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 2e6272c4e50ecea352ed3b33b6c93ba3315360a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Oct 2015 22:19:59 -0700 Subject: [PATCH 037/108] Bug 1187782 (part 1) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --HG-- extra : rebase_source : d051f883dc42d5f31806fb1aef46e97b147bf78e --- 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 07286ddfd76b..82074572b1d0 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 499c07231c6c3657fce3f19dfd4d8fbe328c4c11 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Oct 2015 22:21:51 -0700 Subject: [PATCH 038/108] Bug 1187782 (part 2) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --HG-- extra : rebase_source : e731e832371a92b40b1dd2591dffae1c5a682b3b --- 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 3d182d71fb23..e43a0c3cc207 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 8ce4d5beea37..aefc7da0990d 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 d4891260a725c9294c9fdf176bdf697a8559e6b6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Oct 2015 22:22:10 -0700 Subject: [PATCH 039/108] Bug 1187782 (part 3) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --HG-- extra : rebase_source : 2011a2b7432d217470da2651a9184fc76776b3f7 --- 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 7026716a1805..93e27810ee7c 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 b6011893da2944f3c15a576c7d5c9ae3381438fe Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 26 Oct 2015 22:22:31 -0700 Subject: [PATCH 040/108] Bug 1187782 (part 4) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --HG-- extra : rebase_source : 01299d13b755c9abf6706cd8b44448e980ff431f --- 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 e43a0c3cc207..6ff2b855a0a7 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 aefc7da0990d..39fa536cf814 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 4ea9c77760196e960d340b1766f5777ca5773139 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 Oct 2015 15:13:04 -0700 Subject: [PATCH 041/108] Bug 1187782 (part 5) - Replace nsBaseHashtable::EnumerateRead() calls in dom/base/ with iterators. r=khuey. --HG-- extra : rebase_source : 127ca38615a41d92b492b73b693e0ff781f29b86 --- 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 87e58627be16..93e686da0d2a 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 c52ee1f5b0af..9fb4a30a6b45 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 7bc7d63a1b2f..c836aa1e8107 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 f9083bce99d6a36948aaf3b01edf0ed27a2766b4 Mon Sep 17 00:00:00 2001 From: Mason Chang Date: Wed, 28 Oct 2015 14:54:54 -0700 Subject: [PATCH 042/108] 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 6ede3d18ed4c..86dbe86fbf6e 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 1554094ace7d..96498a85cd26 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 5446b58f9fb7..2d39e7865ed8 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 885140be417c..b1b5b087b431 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 a517ab55db0b..1210a9e6832a 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 07752d82f9b6..d032d6dc6ca2 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 e4aab81b150a..0bee788015b0 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 50c3d6d2f08c..65fbf23b8d0a 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 9ce336136471..1cd7d8eee649 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 72a5c1f45bb9..ce61314dac62 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 89c085e6d646..525d16a415c4 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 645bbefdb953..0b37a1043ee6 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 1d2927bcb69721122869ee7bd4fdd87b8d999d59 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Oct 2015 14:47:29 -0700 Subject: [PATCH 043/108] 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. --HG-- extra : rebase_source : eaa1ddd801872c14860e3bd81645bc99d56d8e4b --- 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 a92e3f667b51..8f02ef564bca 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 9e9747858c5ebd6e2759d5c0685069761c237edc Mon Sep 17 00:00:00 2001 From: Mason Chang Date: Wed, 28 Oct 2015 15:17:04 -0700 Subject: [PATCH 044/108] 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 86dbe86fbf6e..6ede3d18ed4c 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 96498a85cd26..1554094ace7d 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 2d39e7865ed8..5446b58f9fb7 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 b1b5b087b431..885140be417c 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 1210a9e6832a..a517ab55db0b 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 d032d6dc6ca2..07752d82f9b6 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 0bee788015b0..e4aab81b150a 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 65fbf23b8d0a..50c3d6d2f08c 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 1cd7d8eee649..9ce336136471 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 ce61314dac62..72a5c1f45bb9 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 525d16a415c4..89c085e6d646 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 0b37a1043ee6..645bbefdb953 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 5ffe01b5a7040ca43a0267ee77968a3f38d1f127 Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Wed, 28 Oct 2015 14:55:45 -0700 Subject: [PATCH 045/108] 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 000000000000..cce9208bbb7c --- /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 000000000000..d122f9f94409 --- /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 000000000000..dbd08dbf840c --- /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 a370569334c7fae23d20d13ca066220ad3a11378 Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Wed, 28 Oct 2015 15:00:49 -0700 Subject: [PATCH 046/108] 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 17d429d68659..9d2d1d532b13 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 7d3ed22660438c8358437df3e70a3966622c132f Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Thu, 29 Oct 2015 00:04:05 +0100 Subject: [PATCH 047/108] 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 285d30194efd..70298325c45a 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 be0e93726e3b..11272a70f692 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 b14199f1cd7e3959b4d6c8192e9eab5e9745197e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 28 Oct 2015 19:16:13 -0400 Subject: [PATCH 048/108] 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 e9e42a0b01fd..19be4c0be72f 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 fd8146966c8c1ae0f4c4d278cf81d6cec3e2f7de Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 28 Oct 2015 11:28:21 +1100 Subject: [PATCH 049/108] 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 f38f530aa656..d477ff22fb3d 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 7d493b0a079c..1dbc57e43815 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 2a68059903b7..41e0d97eca65 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 90fc29be8a3f..a33b45285dd3 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 cc38da6889fa..77096a83f617 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 8797eda15ce5..d8c7272c176e 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 3c3b1f1353cc219d8fb079ffeb32773f62743620 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 28 Oct 2015 14:14:11 +1100 Subject: [PATCH 050/108] 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 7d0f11b1327a..ac3ebe99d19e 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 e38179386aec808050ac7615f256df9fdf475022 Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Wed, 28 Oct 2015 08:58:35 +0900 Subject: [PATCH 051/108] Bug 1219057 - Do not show "Unable to print stack trace" for exception thrown while compiling top-level script. r=jandem --HG-- extra : commitid : 4am0S9Z4gxO extra : rebase_source : cbe8a5c98a833ea750940470d4fb178ba7562d35 --- 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 126dace94dd7..99de6308e6a4 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 236fae84bb05fbef86db8dd194bcfaa58bdb2a8e Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Wed, 28 Oct 2015 03:41:04 +0900 Subject: [PATCH 052/108] Bug 819125 - Reset return value before executing catch/finally block. r=jandem --HG-- extra : commitid : GB7mCyiMYBH extra : rebase_source : 318b043d58577320e98858d48040cfeedc9f3781 extra : amend_source : 5152ea756c727f1c4a43fc24b5a094a7c7246f7a --- 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 111b1a9f5498..f7ef1959822f 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 000000000000..f9bd1e149639 --- /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 510097d36b67..051b10f38e9b 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 6fc0b6a5761a7a9b6a2fb1999e8f948acfc7c390 Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Mon, 19 Oct 2015 03:53:14 +0900 Subject: [PATCH 053/108] Bug 1217982 - Remove for-each from storage/. r=mak --HG-- extra : commitid : JkK4BJvCHax extra : rebase_source : add04bcdd5f6400e8d20f9fdcd3ce57f48fabae1 --- 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 185240c6a23b..727c2aeebeab 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 7dcba4750b3097605fa92c8dd7e2b2b3f43aa69d Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Tue, 27 Oct 2015 08:49:03 +1100 Subject: [PATCH 054/108] 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 1499697d4cb7..6838c08dcab6 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 68cc239e9da4639aecde250ff6eff68206184edb Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:42 -0700 Subject: [PATCH 055/108] 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 d74046a04294..a32cc42a829e 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 c836aa1e8107..bd4939a9cbf6 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 d0c70289dfad..b1a2d7152e82 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 4f43e35215d9..a2b7190d0ea0 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 73a049903554..2b27904ae638 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 0f6a340e580e90fc30339cee62b69d3e16045e19 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 056/108] 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 75ba3f347c50..fcd1aaa54b5a 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 90c6fe8bde3c6acb578c94e258d7d240ad8c585a Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 057/108] 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 f2a6dbc413aa..a0411b6a1d13 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 485e5ae23bb750e6da96c641601625ea21a5f67c Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 058/108] 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 25c1f6dfcd8f..f7472d2259c4 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 eb5b7a1afa1a72769d21c9f5aa5c7ca549f8b86a Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 059/108] 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 4950e7699c82..4eb34bf716f3 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 3dca063a5f56cfc34a3b2c57e8a161288b1eda20 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 060/108] 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 f6862039e38b..1d850dc1ad56 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 bf912ae2fbec..155de9a9544f 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 698cb76c02890ad9d492521cd58708ef2cb6d662 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 061/108] 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 c4642321528f..d9ad6f765451 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 0fa74a123c9af26c431fb5204bf74c51284223c2 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 28 Oct 2015 16:40:43 -0700 Subject: [PATCH 062/108] 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 cf8d5555658d..4fdf836080bc 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 3289678669ec..44cc8fe0e8a4 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 d9ad6f765451..ba054ac84962 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 0bcd4f463265..0703f18c2988 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 c190494ca6a1..950ab0cda66f 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 ef31511e7eb1..680bd6e3ac65 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 33a5f0b86cc8..aa298291dd26 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 1d850dc1ad56..62b6f1770a48 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 4abf009108cc..520ca16f59b4 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 155de9a9544f..ecec7d588451 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 5fc596584395..e8d9a29f860d 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 6f831876e075..c33c3016f867 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 81046417ef4ce239c9298819166c59a824856804 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 13 Oct 2015 20:51:47 -0500 Subject: [PATCH 063/108] 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. --HG-- extra : commitid : IPM20a3EZYh extra : rebase_source : 1092460266c2213da5367ce24998952ee85f9c19 --- 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 8e1438d3d4a3..d384c194e107 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 cffa1e7c06e8..b5da63f30f35 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 051b10f38e9b..ac41d49ebfbf 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 6591a938a6f84d8e95c8243a6641aa9686acb255 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 13 Oct 2015 20:55:10 -0500 Subject: [PATCH 064/108] Bug 1216966 - Part 2: Tweak a comment about comprehension syntax. r=efaust. --HG-- extra : commitid : CSXoptkZYCm extra : rebase_source : 2fa85d4984790aa8d3367409a5b03924b4755b8d --- 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 d384c194e107..2b96334ca53c 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 dad2eee82141e8632c35e269ef99ed8091fee92e Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 13 Oct 2015 20:57:17 -0500 Subject: [PATCH 065/108] Bug 1216966 - Part 3: Remove redundant method Parser::parenExprOrGeneratorComprehension. r=efaust. --HG-- extra : commitid : KQVHggIqNe0 extra : rebase_source : 2ed7960dc3132ee3da9a9ba717950bdc7dbb24f1 --- 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 2b96334ca53c..1bd1de52bffb 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 9f545af7cc16..b15929967cb2 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 92007f69a8780bbdc0496a48bb469c69da291027 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 08:58:11 -0500 Subject: [PATCH 066/108] Bug 1216966 - Part 4: Update a big comment about for-loops in Parser.cpp. r=efaust. --HG-- extra : commitid : Fh2dnLkYJTF extra : rebase_source : 914501ee34ec25e548fbc12c7889252f32a1c800 --- 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 1bd1de52bffb..e7c051602d37 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 bf34b5b7e70b0042f81a60371f45211f0f280786 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 12:05:22 -0500 Subject: [PATCH 067/108] Bug 1216966 - Part 5: Code organization and comments around parsing comprehensions. r=efaust. --HG-- extra : commitid : 9UZpM2OMfLB extra : rebase_source : f32a22c398c9429817e42f0d8b38c5db873e69c7 --- 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 e7c051602d37..2ddc7f39c7ee 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 b15929967cb2..391ec334e20e 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 763594faa4fc4301829bb2730778b4aa726efbd2 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 14:08:51 -0500 Subject: [PATCH 068/108] Bug 1217001 - Refactor BytecodeEmitter::variables. Part 1: preliminaries. r=shu. --HG-- extra : commitid : 3gVlpKVM1gf extra : rebase_source : 49faabfc198de36911a1d45b761cfe8e0d7563b9 --- 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 f7ef1959822f..af7460a6aabb 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 4b39d8d3852b4fde2c84897afe14718929d1efab Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 14:26:15 -0500 Subject: [PATCH 069/108] Bug 1217001 - Part 2: Rename two local variables and improve some old comments. r=shu. --HG-- extra : commitid : 9asVWnOZ54g extra : rebase_source : 651ca8e9a9654b645ff09aa189474ee50e6c1796 --- 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 af7460a6aabb..d4082d53bb95 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 f55551c9d0c8701422f4aadfc31e8edba84b53f7 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 14:26:46 -0500 Subject: [PATCH 070/108] Bug 1217001 - Part 3: Remove one goto statement. r=shu. --HG-- extra : commitid : 9SxNl4NzWY5 extra : rebase_source : b1552c15130d60202a77f29e44ec65a1aece7717 --- 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 d4082d53bb95..15f8b20f4429 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 aea3d1a5b4f52326a0aee8f2e2c5f451f1b65e41 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 14:38:07 -0500 Subject: [PATCH 071/108] Bug 1217001 - Part 4: Improve the comments on VarEmitOption. r=shu. --HG-- extra : commitid : 7Noyvd57pmn extra : rebase_source : 013f400cc0658deae9312224ddefa5bf820cbb58 --- 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 23c6807d7c6b..c335aa1b67e1 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 153d73e7ab51710fc66956a58f8e5757abc30621 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 16:07:03 -0500 Subject: [PATCH 072/108] Bug 1217001 - Part 5: Further revise control structure in BytecodeEmitter::emitVariables(). r=shu. --HG-- extra : commitid : 3XjXKWS7MNk extra : rebase_source : d6a5b43a44f7ca95c123705a055c2db0ade5dfbd --- 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 15f8b20f4429..e6d8393e0d69 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 264bd1bc9d00e19d126c84b16731abe83b6e7a96 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 16:47:22 -0500 Subject: [PATCH 073/108] Bug 1217001 - Part 6: Eliminate some `continue` statements. r=shu. --HG-- extra : commitid : AjSauVCC2uI extra : rebase_source : feda21c817e7cd8aaed0e7d3b22e61391e8be782 --- 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 e6d8393e0d69..2f7df1357254 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 993969eefd1eafa5430822242bb2215da4ec6b43 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 17:22:52 -0500 Subject: [PATCH 074/108] 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. --HG-- extra : commitid : H3z2cyYZdyB extra : rebase_source : d5e262b25a56ca95d1a36289c7b7a9be0c760154 --- 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 2f7df1357254..8324d96e170d 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 ca57ad2fe3f8..74cfab1bb064 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 3faca8dcbc15f8f97c8515ce14be7f76147d8950 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 18:47:02 -0500 Subject: [PATCH 075/108] Bug 1217001 - Part 8: Eliminate all uses of PNX_POPVAR. r=shu. --HG-- extra : commitid : JlsGVMYs2Jl extra : rebase_source : edcd1890a258e5aa8f7e0779192db471cef4e8e1 --- 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 8324d96e170d..3c682ac31dbd 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 73010d67b4777c98d6ffbc9f5dfbc6273b27ea8a Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 17:26:16 -0500 Subject: [PATCH 076/108] Bug 1217001 - Part 9: Remove PNX_POPVAR. r=shu. --HG-- extra : commitid : HZuhuYI77ri extra : rebase_source : 7a9a0d138e77f495b63ad535e545610813d13b29 --- 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 3c682ac31dbd..d26911b615bd 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 0b2da5f2818f..2785f3e2a284 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 2ddc7f39c7ee..da147b827520 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 c1ac383a91d0c1c5c95d3f340317f64154ec1fa5 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 18:54:19 -0500 Subject: [PATCH 077/108] Bug 1217001 - Part 10: Delete redundant boolean argument. r=shu. --HG-- extra : commitid : Gz8Tfr7ZQ1j extra : rebase_source : 34c0e5ec50d708c93bd5c0aa89bf121cb81e1093 --- 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 d26911b615bd..4461a02f5470 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 c335aa1b67e1..f72cc84af0bf 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 536ae59cee71b7991bf71f00ad71a604e0d3bd19 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 14 Oct 2015 18:59:36 -0500 Subject: [PATCH 078/108] Bug 1217001 - Part 11: Get rid of the last goto in BytecodeEmitter::emitVariables(). r=shu. --HG-- extra : commitid : 4CPmLmrWL1l extra : rebase_source : a44f203eb9d6dd35aa6914bc68c9ee7a285674de --- 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 4461a02f5470..ed2842a99a61 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 f72cc84af0bf..2ce95dbb5ba5 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 3a39cf480637c5207b34f7a810dbecdda86d19d9 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 19 Oct 2015 15:58:19 -0500 Subject: [PATCH 079/108] Bug 1217099 - Stop emitting pointless JSOP_GETLOCAL; JSOP_POP bytecode sequence for `var x;`. r=shu. --HG-- extra : commitid : CZL288j5vAL extra : rebase_source : c5b484323f9a17d7794e23b863a77a9bd7b739ce --- .../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 a593a64f1433..2228fa5259f5 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 ed2842a99a61..b93d0a1ae972 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 145643d3b635..405b13d629bf 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 000000000000..5e8d3445abd8 --- /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 021332a53b2b6881fa505d20f0990f909104345a Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 19 Oct 2015 17:08:28 -0500 Subject: [PATCH 080/108] Bug 1217110 - Remove unnecessary opcode JSOP_BINDINTRINSIC. r=shu. --HG-- extra : commitid : KvPvP0Ki9Dv extra : rebase_source : 5e789e5a02817b45976313aea0f21b050ce91ff8 --- 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 b93d0a1ae972..81f0eab44e75 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 fb99a95d8d2a..ae2fc6048b1c 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 32b14d2732c0..19832563f420 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 4792069b33219fe92bd5df264d48d769bb3192ff Mon Sep 17 00:00:00 2001 From: Kit Cambridge Date: Wed, 28 Oct 2015 17:07:11 -0700 Subject: [PATCH 081/108] Bug 1218591 - Reset the WebSocket retry counter when the server replies. r=dragana --HG-- extra : commitid : L8bN4lFe50x --- 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 fa7747c64524..10e72cfbe5f2 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 ae12eb9c92c0..791370f78b28 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 000000000000..9287bd2ebb4b --- /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 650aa92455e1..79e002a01b96 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 ec55a186c75682e436104437138d1c89852fc9db Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Wed, 28 Oct 2015 17:13:12 -0700 Subject: [PATCH 082/108] 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 447b4530b63d..23169e820705 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 59f83538199cceff374dc498c0c9043cbf745f0f Mon Sep 17 00:00:00 2001 From: Rail Aliiev Date: Wed, 28 Oct 2015 20:28:07 -0400 Subject: [PATCH 083/108] 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 5c81e67d7f79..949fc123aa1a 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 c5789b066ea2916bb226157d4543658e373c7752 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Thu, 29 Oct 2015 09:35:10 +0900 Subject: [PATCH 084/108] 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 --HG-- extra : source : 6e8a9147cab01c95c57f979c7831122c3c6cef19 --- 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 6ff2b855a0a7..fe14eb24c44e 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 ab940c53e83f66f5c247ec1c740d8a5080ecacbf Mon Sep 17 00:00:00 2001 From: Tanvi Vyas Date: Wed, 28 Oct 2015 17:53:02 -0700 Subject: [PATCH 085/108] 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 50f33edd86c2..15c28ec4b0dd 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 5fe1364e18d6..5bb587413ae6 100644 --- a/browser/components/preferences/in-content/content.xul +++ b/browser/components/preferences/in-content/content.xul @@ -70,7 +70,7 @@ - +