Index: src/js/_enqueues/wp/shortcode.js
===================================================================
--- src/js/_enqueues/wp/shortcode.js	(revision 43384)
+++ src/js/_enqueues/wp/shortcode.js	(working copy)
@@ -77,9 +77,12 @@
 				// Create the match object and pass it through the callback.
 				var result = callback( wp.shortcode.fromMatch( arguments ) );
 
-				// Make sure to return any of the extra brackets if they
-				// weren't used to escape the shortcode.
-				return result ? left + result + right : match;
+				// Matches the `do_shortcode` implementation in php.
+				if ( _.isString( result ) || _.isNumber( result ) || result ) {
+					return left + result + right;
+				} else {
+					return left + right;
+				}
 			});
 		},
 
Index: tests/qunit/wp-includes/js/shortcode.js
===================================================================
--- tests/qunit/wp-includes/js/shortcode.js	(revision 43384)
+++ tests/qunit/wp-includes/js/shortcode.js	(working copy)
@@ -164,6 +164,46 @@
 		equal( result, 'this has the [foo] shortcode', 'stub not replaced' );
 	});
 
+	test( 'replace() replaces the shortcode with `0` when the callback returns `0`', function() {
+		var result = wp.shortcode.replace( 'foo', 'this has the [foo]shortcode[/foo]', function() {
+			return 0;
+		} );
+
+		equal( result, 'this has the 0', 'shortcode not replaced with `0`' );
+	});
+
+	test( 'replace() removes the shortcode and shortcode content when the callback returns `null`', function() {
+		var result = wp.shortcode.replace( 'foo', 'this has the [foo]shortcode[/foo]', function() {
+			return null;
+		} );
+
+		equal( result, 'this has the ', 'shortcode and shortcode content not removed' );
+	});
+
+	test( 'replace() removes the shortcode and shortcode content when the callback returns `false`', function() {
+		var result = wp.shortcode.replace( 'foo', 'this has the [foo]shortcode[/foo]', function() {
+			return false;
+		} );
+
+		equal( result, 'this has the ', 'shortcode and shortcode content not removed' );
+	});
+
+	test( 'replace() removes the shortcode and shortcode content when the callback returns `undefined`', function() {
+		var result = wp.shortcode.replace( 'foo', 'this has the [foo]shortcode[/foo]', function() {
+			return undefined;
+		} );
+
+		equal( result, 'this has the ', 'shortcode and shortcode content not removed' );
+	});
+
+	test( 'replace() removes the shortcode and shortcode content when the callback returns an empty string', function() {
+		var result = wp.shortcode.replace( 'foo', 'this has the [foo]shortcode[/foo]', function() {
+			return '';
+		} );
+
+		equal( result, 'this has the ', 'shortcode and shortcode content not removed' );
+	});
+
     // A callback function for the replace tests
 	function shortcodeReplaceCallback( ) {
 		return 'bar';
@@ -204,7 +244,7 @@
 
 		deepEqual( wp.shortcode.attrs('foo "bar" \'baz\''), expected, 'attr parsed numeric attributes');
 	});
-	
+
 	test( 'attrs() should return mixed attributes created with single, double, and no quotes', function() {
 		var expected = {
 			'named': { a: 'foo', b: 'bar', c: 'baz' }, 'numeric' : ['foo', 'bar', 'baz']
