From 748c0d8b108b251dae1bb3605b1fe67bf083ef82 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Tue, 8 Jun 2021 16:03:39 +0900 Subject: [PATCH] Do not remove placeholder for data URL (#24704) --- packages/next/client/image.tsx | 6 ++- .../default/pages/blurry-placeholder.js | 11 +++++ .../default/test/index.test.js | 46 ++++++++++++++++--- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/packages/next/client/image.tsx b/packages/next/client/image.tsx index 1a3e507e59e88..56f3edbabebba 100644 --- a/packages/next/client/image.tsx +++ b/packages/next/client/image.tsx @@ -269,14 +269,16 @@ function removePlaceholder( placeholder: PlaceholderValue ) { if (placeholder === 'blur' && element) { - if (element.complete) { + if (element.complete && !element.src.startsWith('data:')) { // If the real image fails to load, this will still remove the placeholder. // This is the desired behavior for now, and will be revisited when error // handling is worked on for the image component itself. element.style.backgroundImage = 'none' } else { element.onload = () => { - element.style.backgroundImage = 'none' + if (!element.src.startsWith('data:')) { + element.style.backgroundImage = 'none' + } } } } diff --git a/test/integration/image-component/default/pages/blurry-placeholder.js b/test/integration/image-component/default/pages/blurry-placeholder.js index d23c21799cd4c..6d3dd34f031ab 100644 --- a/test/integration/image-component/default/pages/blurry-placeholder.js +++ b/test/integration/image-component/default/pages/blurry-placeholder.js @@ -14,6 +14,17 @@ export default function Page() { placeholder="blur" blurDataURL="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cfilter id='blur' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20' edgeMode='duplicate' /%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1' /%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter='url(%23blur)' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMDAwMDAwQEBAQFBQUFBQcHBgYHBwsICQgJCAsRCwwLCwwLEQ8SDw4PEg8bFRMTFRsfGhkaHyYiIiYwLTA+PlT/wAALCAAKAAoBAREA/8QAMwABAQEAAAAAAAAAAAAAAAAAAAcJEAABAwUAAwAAAAAAAAAAAAAFAAYRAQMEEyEVMlH/2gAIAQEAAD8Az1bLPaxhiuk0QdeCOLDtHixN2dmd2bsc5FPX7VTREX//2Q==' x='0' y='0' height='100%25' width='100%25'/%3E%3C/svg%3E" /> + +
+ +
) } diff --git a/test/integration/image-component/default/test/index.test.js b/test/integration/image-component/default/test/index.test.js index 80ad254302995..42d3e1b197539 100644 --- a/test/integration/image-component/default/test/index.test.js +++ b/test/integration/image-component/default/test/index.test.js @@ -51,6 +51,12 @@ async function getComputed(browser, id, prop) { return null } +async function getComputedStyle(browser, id, prop) { + return browser.eval( + `window.getComputedStyle(document.getElementById('${id}')).getPropertyValue('${prop}')` + ) +} + async function getSrc(browser, id) { const src = await browser.elementById(id).getAttribute('src') if (src) { @@ -586,8 +592,14 @@ describe('Image Component Tests', () => { it('should have blurry placeholder when enabled', async () => { const html = await renderViaHTTP(appPort, '/blurry-placeholder') - expect(html).toContain( - 'background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cfilter id='blur' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20' edgeMode='duplicate' /%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1' /%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter='url(%23blur)' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMDAwMDAwQEBAQFBQUFBQcHBgYHBwsICQgJCAsRCwwLCwwLEQ8SDw4PEg8bFRMTFRsfGhkaHyYiIiYwLTA+PlT/wAALCAAKAAoBAREA/8QAMwABAQEAAAAAAAAAAAAAAAAAAAcJEAABAwUAAwAAAAAAAAAAAAAFAAYRAQMEEyEVMlH/2gAIAQEAAD8Az1bLPaxhiuk0QdeCOLDtHixN2dmd2bsc5FPX7VTREX//2Q==' x='0' y='0' height='100%25' width='100%25'/%3E%3C/svg%3E")' + const $html = cheerio.load(html) + + expect($html('#blurry-placeholder')[0].attribs.style).toContain( + `background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cfilter id='blur' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20' edgeMode='duplicate' /%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1' /%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter='url(%23blur)' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMDAwMDAwQEBAQFBQUFBQcHBgYHBwsICQgJCAsRCwwLCwwLEQ8SDw4PEg8bFRMTFRsfGhkaHyYiIiYwLTA+PlT/wAALCAAKAAoBAREA/8QAMwABAQEAAAAAAAAAAAAAAAAAAAcJEAABAwUAAwAAAAAAAAAAAAAFAAYRAQMEEyEVMlH/2gAIAQEAAD8Az1bLPaxhiuk0QdeCOLDtHixN2dmd2bsc5FPX7VTREX//2Q==' x='0' y='0' height='100%25' width='100%25'/%3E%3C/svg%3E")` + ) + + expect($html('#blurry-placeholder-with-lazy')[0].attribs.style).toContain( + `background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cfilter id='blur' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20' edgeMode='duplicate' /%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1' /%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter='url(%23blur)' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMDAwMDAwQEBAQFBQUFBQcHBgYHBwsICQgJCAsRCwwLCwwLEQ8SDw4PEg8bFRMTFRsfGhkaHyYiIiYwLTA+PlT/wAALCAAKAAoBAREA/8QAMwABAQEAAAAAAAAAAAAAAAAAAAcJEAABAwUAAwAAAAAAAAAAAAAFAAYRAQMEEyEVMlH/2gAIAQEAAD8Az1bLPaxhiuk0QdeCOLDtHixN2dmd2bsc5FPX7VTREX//2Q==' x='0' y='0' height='100%25' width='100%25'/%3E%3C/svg%3E")` ) }) @@ -595,11 +607,33 @@ describe('Image Component Tests', () => { let browser try { browser = await webdriver(appPort, '/blurry-placeholder') - const id = 'blurry-placeholder' - const backgroundImage = await browser.eval( - `window.getComputedStyle(document.getElementById('${id}')).getPropertyValue('background-image')` + + expect( + await getComputedStyle( + browser, + 'blurry-placeholder', + 'background-image' + ) + ).toBe('none') + expect( + await getComputedStyle( + browser, + 'blurry-placeholder-with-lazy', + 'background-image' + ) + ).toBe( + `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cfilter id='blur' filterUnits='userSpaceOnUse' color-interpolation-filters='sRGB'%3E%3CfeGaussianBlur stdDeviation='20' edgeMode='duplicate' /%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='1 1' /%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter='url(%23blur)' href='data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMDAwMDAwQEBAQFBQUFBQcHBgYHBwsICQgJCAsRCwwLCwwLEQ8SDw4PEg8bFRMTFRsfGhkaHyYiIiYwLTA+PlT/wAALCAAKAAoBAREA/8QAMwABAQEAAAAAAAAAAAAAAAAAAAcJEAABAwUAAwAAAAAAAAAAAAAFAAYRAQMEEyEVMlH/2gAIAQEAAD8Az1bLPaxhiuk0QdeCOLDtHixN2dmd2bsc5FPX7VTREX//2Q==' x='0' y='0' height='100%25' width='100%25'/%3E%3C/svg%3E")` ) - expect(backgroundImage).toBe('none') + + await browser.eval('document.getElementById("spacer").remove()') + + expect( + await getComputedStyle( + browser, + 'blurry-placeholder-with-lazy', + 'background-image' + ) + ).toBe('none') } finally { if (browser) { await browser.close()