 core/modules/editor/editor.services.yml          |  2 +-
 core/modules/editor/src/Plugin/EditorManager.php | 46 +++++++++++++++++++++---
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/core/modules/editor/editor.services.yml b/core/modules/editor/editor.services.yml
index 731215c..f9ac2a1 100644
--- a/core/modules/editor/editor.services.yml
+++ b/core/modules/editor/editor.services.yml
@@ -1,7 +1,7 @@
 services:
   plugin.manager.editor:
     class: Drupal\editor\Plugin\EditorManager
-    parent: default_plugin_manager
+    arguments: ['@container.namespaces', '@cache.discovery', '@module_handler', '@cache.data']
   element.editor:
     class: Drupal\editor\Element
     arguments: ['@plugin.manager.editor']
diff --git a/core/modules/editor/src/Plugin/EditorManager.php b/core/modules/editor/src/Plugin/EditorManager.php
index 6fc04d0..37eeeee 100644
--- a/core/modules/editor/src/Plugin/EditorManager.php
+++ b/core/modules/editor/src/Plugin/EditorManager.php
@@ -7,9 +7,11 @@
 
 namespace Drupal\editor\Plugin;
 
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Plugin\DefaultPluginManager;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\editor\Entity\Editor;
 
 /**
  * Configurable text editor manager.
@@ -22,20 +24,30 @@
 class EditorManager extends DefaultPluginManager {
 
   /**
+   * The attachments cache.
+   *
+   * @var \Drupal\Core\Cache\CacheBackendInterface
+   */
+  protected $attachmentsCache;
+
+  /**
    * Constructs an EditorManager object.
    *
    * @param \Traversable $namespaces
    *   An object that implements \Traversable which contains the root paths
    *   keyed by the corresponding namespace to look for plugin implementations.
-   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
-   *   Cache backend instance to use.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $discovery_cache
+   *   Cache backend instance to use for plugin discovery.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler to invoke the alter hook with.
+   * @param \Drupal\Core\Cache\CacheBackendInterface $attachments_cache
+   *   Cache backend instance to use for editor attachment caching.
    */
-  public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
+  public function __construct(\Traversable $namespaces, CacheBackendInterface $discovery_cache, ModuleHandlerInterface $module_handler, CacheBackendInterface $attachments_cache) {
     parent::__construct('Plugin/Editor', $namespaces, $module_handler, 'Drupal\editor\Plugin\EditorPluginInterface', 'Drupal\editor\Annotation\Editor');
     $this->alterInfo('editor_info');
-    $this->setCacheBackend($cache_backend, 'editor_plugins');
+    $this->setCacheBackend($discovery_cache, 'editor_plugins');
+    $this->attachmentsCache = $attachments_cache;
   }
 
   /**
@@ -64,6 +76,32 @@ public function listOptions() {
    * @see drupal_process_attached()
    */
   public function getAttachments(array $format_ids) {
+    $cid = 'editor_attachments:' . implode($format_ids);
+    $cached = $this->attachmentsCache->get($cid);
+    if (!$cached) {
+      $attachments = $this->doGetAttachments($format_ids);
+      $tags = ['editor_list'];
+      foreach ($format_ids as $format_id) {
+        $editor = editor_load($format_id);
+        if (!$editor) {
+          continue;
+        }
+      }
+      $this->attachmentsCache->set($cid, $attachments, Cache::PERMANENT, $tags);
+    }
+    return $cached->data;
+  }
+
+  /**
+   * Helper for ::getAttachments().
+   *
+   * @param array $format_ids
+   *   An array of format IDs as returned by array_keys(filter_formats()).
+   *
+   * @return array
+   *   An array of attachments, for use with #attached.
+   */
+  public function doGetAttachments(array $format_ids) {
     $attachments = array('library' => array());
 
     $settings = array();
