Index: src/wp-includes/media.php
===================================================================
--- src/wp-includes/media.php	(revision 40891)
+++ src/wp-includes/media.php	(working copy)
@@ -2556,7 +2556,11 @@
 		} elseif ( $is_vimeo ) {
 			// Remove all query arguments and force SSL - see #40866.
 			$parsed_vimeo_url = wp_parse_url( $atts['src'] );
-			$atts['src'] = 'https://' . $parsed_vimeo_url['host'] . $parsed_vimeo_url['path'];
+			$vimeo_src = 'https://' . $parsed_vimeo_url['host'] . $parsed_vimeo_url['path'];
+
+			// Add loop param for mejs bug - see #40977, not needed after #39686.
+			$loop = $atts['loop'] ? '1' : '0';
+			$atts['src'] = add_query_arg( 'loop', $loop, $vimeo_src );
 		}
 	}
 
Index: src/wp-includes/widgets/class-wp-widget-media-video.php
===================================================================
--- src/wp-includes/widgets/class-wp-widget-media-video.php	(revision 40891)
+++ src/wp-includes/widgets/class-wp-widget-media-video.php	(working copy)
@@ -115,13 +115,9 @@
 			$attachment = get_post( $instance['attachment_id'] );
 		}
 
+		$src = $instance['url'];
 		if ( $attachment ) {
 			$src = wp_get_attachment_url( $attachment->ID );
-		} else {
-
-			// Manually add the loop query argument.
-			$loop = $instance['loop'] ? '1' : '0';
-			$src = empty( $instance['url'] ) ? $instance['url'] : add_query_arg( 'loop', $loop, $instance['url'] );
 		}
 
 		if ( empty( $src ) ) {
Index: tests/phpunit/tests/media.php
===================================================================
--- tests/phpunit/tests/media.php	(revision 40891)
+++ tests/phpunit/tests/media.php	(working copy)
@@ -761,6 +761,31 @@
 	}
 
 	/**
+	 * @ticket 40977
+	 * @depends test_video_shortcode_body
+	 */
+	function test_wp_video_shortcode_vimeo_adds_loop() {
+		$actual = wp_video_shortcode( array(
+			'src' => 'http://vimeo.com/190372437',
+		) );
+
+		$this->assertContains( 'src="https://vimeo.com/190372437?loop=0', $actual );
+	}
+
+	/**
+	 * @ticket 40977
+	 * @depends test_video_shortcode_body
+	 */
+	function test_wp_video_shortcode_vimeo_force_adds_loop_true() {
+		$actual = wp_video_shortcode( array(
+			'src' => 'http://vimeo.com/190372437',
+			'loop' => true,
+		) );
+
+		$this->assertContains( 'src="https://vimeo.com/190372437?loop=1', $actual );
+	}
+
+	/**
 	 * Test [video] shortcode processing
 	 *
 	 */
