diff --git a/core/modules/filter/src/Entity/FilterFormat.php b/core/modules/filter/src/Entity/FilterFormat.php
index 4b00af1..59acedb 100644
--- a/core/modules/filter/src/Entity/FilterFormat.php
+++ b/core/modules/filter/src/Entity/FilterFormat.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\filter\Entity;
 
+use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
@@ -387,4 +388,42 @@ public function getHtmlRestrictions() {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function removeFilter($instance_id) {
+    unset($this->filters[$instance_id]);
+    $this->filterCollection->removeInstanceId($instance_id);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function onDependencyRemoval(array $dependencies) {
+    $changed = FALSE;
+    $filters = $this->filters();
+    foreach ($filters as $filter) {
+      if (in_array($filter->provider, $dependencies['module'])) {
+        $this->removeFilter($filter->getPluginId());
+        $changed = TRUE;
+      }
+    }
+    if ($changed) {
+      $this->save();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function calculatePluginDependencies(PluginInspectionInterface $instance) {
+    // Only add dependencies for plugins that are actually configured. This is
+    // necessary because the filter plugin collection will return all available
+    // filter plugins.
+    // @see \Drupal\filter\FilterPluginCollection::getConfiguration()
+    if (isset($this->filters[$instance->getPluginId()])) {
+      parent::calculatePluginDependencies($instance);
+    }
+  }
+
 }
diff --git a/core/modules/filter/src/FilterFormatInterface.php b/core/modules/filter/src/FilterFormatInterface.php
index b5e75ce..b9c558b 100644
--- a/core/modules/filter/src/FilterFormatInterface.php
+++ b/core/modules/filter/src/FilterFormatInterface.php
@@ -84,4 +84,12 @@ public function getFilterTypes();
    */
   public function getHtmlRestrictions();
 
+  /**
+   * Removes a filter.
+   *
+   * @param string $instance_id
+   *   The ID of a filter plugin to be removed.
+   */
+  public function removeFilter($instance_id);
+
 }
diff --git a/core/modules/filter/src/Tests/FilterAPITest.php b/core/modules/filter/src/Tests/FilterAPITest.php
index 588546e..786bfc0 100644
--- a/core/modules/filter/src/Tests/FilterAPITest.php
+++ b/core/modules/filter/src/Tests/FilterAPITest.php
@@ -386,4 +386,27 @@ public function assertFilterFormatViolation(ConstraintViolationListInterface $vi
     }
     $this->assertTrue($filter_format_violation_found, format_string('Validation violation for invalid value "%invalid_value" found', array('%invalid_value' => $invalid_value)));
   }
+
+  /**
+   * Tests that dependency removal works.
+   *
+   * Uninstalling a module that provides a filter should not remove a filter
+   * format that uses the filter.
+   */
+  public function testDependencyRemoval() {
+    $this->installSchema('user', array('users_data'));
+    $filter_format = \Drupal\filter\Entity\FilterFormat::load('filtered_html');
+    $filter_config = [
+      'weight' => 10,
+      'status' => 1,
+    ];
+    $filter_format->setFilterConfig('filter_test_restrict_tags_and_attributes', $filter_config)->save();
+    $this->assertEqual(['module' => ['filter_test']], $filter_format->getDependencies());
+    \Drupal::moduleHandler()->uninstall(array('filter_test'));
+
+    \Drupal::entityManager()->getStorage('filter_format')->resetCache();
+    $filter_format = \Drupal\filter\Entity\FilterFormat::load('filtered_html');
+    $this->assertEqual([], $filter_format->getDependencies());
+  }
+
 }
