diff --git a/core/modules/node/src/Tests/Views/BulkFormTest.php b/core/modules/node/src/Tests/Views/BulkFormTest.php
index 42dc34a..3ab918a 100644
--- a/core/modules/node/src/Tests/Views/BulkFormTest.php
+++ b/core/modules/node/src/Tests/Views/BulkFormTest.php
@@ -62,18 +62,15 @@ public function testBulkForm() {
     $this->assertTrue($node->isPublished(), 'Node has been published');
 
     // Make sticky action.
-    $node->setPublished(FALSE);
-    $node->save();
     $this->assertFalse($node->isSticky(), 'Node is not sticky');
     $edit = array(
       'node_bulk_form[0]' => TRUE,
       'action' => 'node_make_sticky_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-    // Re-load the node and check the status and sticky flag.
+    // Re-load the node and check the sticky flag.
     $node_storage->resetCache(array($node->id()));
     $node = $node_storage->load($node->id());
-    $this->assertTrue($node->isPublished(), 'Node has been published');
     $this->assertTrue($node->isSticky(), 'Node has been made sticky');
 
     // Make unsticky action.
@@ -88,18 +85,15 @@ public function testBulkForm() {
     $this->assertFalse($node->isSticky(), 'Node is not sticky anymore');
 
     // Promote to front page.
-    $node->setPublished(FALSE);
-    $node->save();
     $this->assertFalse($node->isPromoted(), 'Node is not promoted to the front page');
     $edit = array(
       'node_bulk_form[0]' => TRUE,
       'action' => 'node_promote_action',
     );
     $this->drupalPostForm(NULL, $edit, t('Apply'));
-    // Re-load the node and check the status and promoted flag.
+    // Re-load the node and check the promoted flag.
     $node_storage->resetCache(array($node->id()));
     $node = $node_storage->load($node->id());
-    $this->assertTrue($node->isPublished(), 'Node has been published');
     $this->assertTrue($node->isPromoted(), 'Node has been promoted to the front page');
 
     // Demote from front page.
diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php
index ecd541e..63d3ba1 100644
--- a/core/modules/views/src/Entity/View.php
+++ b/core/modules/views/src/Entity/View.php
@@ -433,4 +433,13 @@ public function isInstallable() {
     return (bool) \Drupal::service('views.views_data')->get($this->base_table);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function __sleep() {
+    $keys = parent::__sleep();
+    unset($keys[array_search('executable', $keys)]);
+    return $keys;
+  }
+
 }
diff --git a/core/modules/views/src/Form/ViewsExposedForm.php b/core/modules/views/src/Form/ViewsExposedForm.php
index 1b1aa35..c87113c 100644
--- a/core/modules/views/src/Form/ViewsExposedForm.php
+++ b/core/modules/views/src/Form/ViewsExposedForm.php
@@ -121,7 +121,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $form['#id'] = Html::cleanCssIdentifier('views_exposed_form-' . String::checkPlain($view->storage->id()) . '-' . String::checkPlain($display['id']));
 
     /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
-    $exposed_form_plugin = $form_state->get('exposed_form_plugin');
+    $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
     $exposed_form_plugin->exposedFormAlter($form, $form_state);
 
     // Save the form.
@@ -134,15 +134,17 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function validateForm(array &$form, FormStateInterface $form_state) {
+    $view = $form_state->get('view');
+
     foreach (array('field', 'filter') as $type) {
       /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */
-      $handlers = &$form_state->get('view')->$type;
+      $handlers = &$view->$type;
       foreach ($handlers as $key => $handler) {
         $handlers[$key]->validateExposed($form, $form_state);
       }
     }
     /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
-    $exposed_form_plugin = $form_state->get('exposed_form_plugin');
+    $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
     $exposed_form_plugin->exposedFormValidate($form, $form_state);
   }
 
@@ -157,13 +159,14 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         $handlers[$key]->submitExposed($form, $form_state);
       }
     }
+
     $view = $form_state->get('view');
     $view->exposed_data = $form_state->getValues();
     $view->exposed_raw_input = [];
 
-    $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', '', 'reset');
+    $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset');
     /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
-    $exposed_form_plugin = $form_state->get('exposed_form_plugin');
+    $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
     $exposed_form_plugin->exposedFormSubmit($form, $form_state, $exclude);
 
     foreach ($form_state->getValues() as $key => $value) {
diff --git a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
index f9ba904..7f0caa9 100644
--- a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
+++ b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
@@ -150,7 +150,6 @@ public function renderExposedForm($block = FALSE) {
       $form_state->set('ajax', TRUE);
     }
 
-    $form_state->set('exposed_form_plugin', $this);
     $form = \Drupal::formBuilder()->buildForm('\Drupal\views\Form\ViewsExposedForm', $form_state);
 
     if (!$this->view->display_handler->displaysExposed() || (!$block && $this->view->display_handler->getOption('exposed_block'))) {
diff --git a/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php b/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
index bb6b803..34a2a9a 100644
--- a/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
+++ b/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
@@ -55,6 +55,13 @@
 abstract class RelationshipPluginBase extends HandlerBase {
 
   /**
+   * The relationship alias.
+   *
+   * @var string
+   */
+  public $alias;
+
+  /**
    * Overrides \Drupal\views\Plugin\views\HandlerBase::init().
    *
    * Init handler to let relationships live on tables other than
diff --git a/core/modules/views/src/Tests/ViewExecutableTest.php b/core/modules/views/src/Tests/ViewExecutableTest.php
index ecbe857..ed1b47a 100644
--- a/core/modules/views/src/Tests/ViewExecutableTest.php
+++ b/core/modules/views/src/Tests/ViewExecutableTest.php
@@ -449,6 +449,7 @@ public function testValidateNestedLoops() {
     $errors = $executable->validate();
     $total_error_count = array_reduce($errors, function ($carry, $item) {
       $carry += count($item);
+
       return $carry;
     });
     // Assert that there were 9 total errors across 3 displays.
@@ -456,4 +457,29 @@ public function testValidateNestedLoops() {
     $this->assertIdentical(3, count($errors));
   }
 
+  /**
+   * Tests serialization of the ViewExecutable object.
+   */
+  public function testSerialization() {
+    $view = Views::getView('test_executable_displays');
+    $view->setDisplay('page_1');
+    $view->setArguments(['test']);
+    $view->setCurrentPage(2);
+
+    $serialized = serialize($view);
+
+    // Test the view storage object is not present in the actual serialized
+    // string.
+    $this->assertIdentical(strpos($serialized, '"Drupal\views\Entity\View"'), FALSE, 'The Drupal\views\Entity\View class was not found in the serialized string.');
+
+    /** @var \Drupal\views\ViewExecutable $unserialized */
+    $unserialized = unserialize($serialized);
+
+    $this->assertTrue($unserialized instanceof ViewExecutable);
+    $this->assertIdentical($view->storage->id(), $unserialized->storage->id(), 'The expected storage entity was loaded on the unserialized view.');
+    $this->assertIdentical($unserialized->current_display, 'page_1', 'The expected display was set on the unserialized view.');
+    $this->assertIdentical($unserialized->args, ['test'], 'The expected argument was set on the unserialized view.');
+    $this->assertIdentical($unserialized->getCurrentPage(), 2, 'The expected current page was set on the unserialized view.');
+  }
+
 }
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index d74fe31..0eb445d 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -26,7 +26,7 @@
  * An object to contain all of the data to generate a view, plus the member
  * functions to build the view query, execute the query and render the output.
  */
-class ViewExecutable {
+class ViewExecutable implements \Serializable {
   use DependencySerializationTrait;
 
   /**
@@ -2295,4 +2295,49 @@ public function calculateDependencies() {
     return $this->storage->calculateDependencies();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function serialize() {
+    return serialize([
+      // Only serialize the storage entity ID.
+      $this->storage->id(),
+      $this->current_display,
+      $this->args,
+      $this->current_page,
+      $this->exposed_input,
+      $this->exposed_raw_input,
+      $this->exposed_data,
+      $this->dom_id,
+      $this->executed,
+    ]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function unserialize($serialized) {
+    list($storage, $current_display, $args, $current_page, $exposed_input, $exposed_raw_input, $exposed_data, $dom_id, $executed) = unserialize($serialized);
+
+    $this->setRequest(\Drupal::request());
+    $this->user = \Drupal::currentUser();
+
+    $this->storage = \Drupal::entityManager()->getStorage('view')->load($storage);
+
+    $this->setDisplay($current_display);
+    $this->setArguments($args);
+    $this->setCurrentPage($current_page);
+    $this->setExposedInput($exposed_input);
+    $this->exposed_data = $exposed_data;
+    $this->exposed_raw_input = $exposed_raw_input;
+    $this->dom_id = $dom_id;
+
+    $this->initHandlers();
+
+    // If the display was previously executed, execute it now.
+    if ($executed) {
+      $this->execute($this->current_display);
+    }
+  }
+
 }
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index 5d27d30..28b1175 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -266,6 +266,7 @@ public function validate(array $form, FormStateInterface $form_state) {
   public function save(array $form, FormStateInterface $form_state) {
     $view = $this->entity;
     $executable = $view->getExecutable();
+    $executable->initDisplay();
 
     // Go through and remove displayed scheduled for removal.
     $displays = $view->get('display');
diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php
index 68eb0e8..3dcb45b 100644
--- a/core/modules/views_ui/src/ViewUI.php
+++ b/core/modules/views_ui/src/ViewUI.php
@@ -173,10 +173,10 @@ class ViewUI implements ViewEntityInterface {
   public function __construct(ViewEntityInterface $storage, ViewExecutable $executable = NULL) {
     $this->entityType = 'view';
     $this->storage = $storage;
-    if (!isset($executable)) {
-      $executable = Views::executableFactory()->get($this);
+
+    if (isset($executable)) {
+      $this->executable = $executable;
     }
-    $this->executable = $executable;
   }
 
   /**
@@ -259,7 +259,7 @@ public function standardSubmit($form, FormStateInterface $form_state) {
     $display_id = $form_state->get('display_id');
     if ($revert) {
       // If it's revert just change the override and return.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       $display->optionsOverride($form, $form_state);
 
       // Don't execute the normal submit handling but still store the changed view into cache.
@@ -273,7 +273,7 @@ public function standardSubmit($form, FormStateInterface $form_state) {
     elseif ($was_defaulted && !$is_defaulted) {
       // We were using the default display's values, but we're now overriding
       // the default display and saving values specific to this display.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       // optionsOverride toggles the override of this section.
       $display->optionsOverride($form, $form_state);
       $display->submitOptionsForm($form, $form_state);
@@ -283,7 +283,7 @@ public function standardSubmit($form, FormStateInterface $form_state) {
       // to go back to the default display.
       // Overwrite the default display with the current form values, and make
       // the current display use the new default values.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       // optionsOverride toggles the override of this section.
       $display->optionsOverride($form, $form_state);
       $display->submitOptionsForm($form, $form_state);
@@ -481,7 +481,7 @@ public function submitItemAdd($form, FormStateInterface $form_state) {
     if ($was_defaulted && !$is_defaulted) {
       // We were using the default display's values, but we're now overriding
       // the default display and saving values specific to this display.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       // setOverride toggles the override of this section.
       $display->setOverride($section);
     }
@@ -490,7 +490,7 @@ public function submitItemAdd($form, FormStateInterface $form_state) {
       // to go back to the default display.
       // Overwrite the default display with the current form values, and make
       // the current display use the new default values.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       // optionsOverride toggles the override of this section.
       $display->setOverride($section);
     }
@@ -503,7 +503,7 @@ public function submitItemAdd($form, FormStateInterface $form_state) {
         if ($cut = strpos($field, '$')) {
           $field = substr($field, 0, $cut);
         }
-        $id = $this->executable->addHandler($display_id, $type, $table, $field);
+        $id = $this->getExecutable()->addHandler($display_id, $type, $table, $field);
 
         // check to see if we have group by settings
         $key = $type;
@@ -516,7 +516,7 @@ public function submitItemAdd($form, FormStateInterface $form_state) {
           'field' => $field,
         );
         $handler = Views::handlerManager($key)->getHandler($item);
-        if ($this->executable->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) {
+        if ($this->getExecutable()->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) {
           $this->addFormToStack('handler-group', $display_id, $type, $id);
         }
 
@@ -580,11 +580,11 @@ public function renderPreview($display_id, $args = array()) {
 
     $rows = array('query' => array(), 'statistics' => array());
 
-    $errors = $this->executable->validate();
-    $this->executable->destroy();
+    $errors = $this->getExecutable()->validate();
+    $this->getExecutable()->destroy();
     if (empty($errors)) {
       $this->ajax = TRUE;
-      $this->executable->live_preview = TRUE;
+      $this->getExecutable()->live_preview = TRUE;
 
       // AJAX happens via HTTP POST but everything expects exposed data to
       // be in GET. Copy stuff but remove ajax-framework specific keys.
@@ -597,19 +597,19 @@ public function renderPreview($display_id, $args = array()) {
           unset($exposed_input[$key]);
         }
       }
-      $this->executable->setExposedInput($exposed_input);
+      $this->getExecutable()->setExposedInput($exposed_input);
 
-      if (!$this->executable->setDisplay($display_id)) {
+      if (!$this->getExecutable()->setDisplay($display_id)) {
         return [
           '#markup' => t('Invalid display id @display', array('@display' => $display_id)),
         ];
       }
 
-      $this->executable->setArguments($args);
+      $this->getExecutable()->setArguments($args);
 
       // Store the current view URL for later use:
-      if ($this->executable->display_handler->getOption('path')) {
-        $path = $this->executable->getUrl();
+      if ($this->getExecutable()->display_handler->getOption('path')) {
+        $path = $this->getExecutable()->getUrl();
       }
 
       // Make view links come back to preview.
@@ -646,7 +646,7 @@ public function renderPreview($display_id, $args = array()) {
       }
 
       // Execute/get the view preview.
-      $preview = $this->executable->preview($display_id, $args);
+      $preview = $this->getExecutable()->preview($display_id, $args);
 
       if ($show_additional_queries) {
         $this->endQueryCapture();
@@ -660,13 +660,13 @@ public function renderPreview($display_id, $args = array()) {
       // below the view preview.
       if ($show_info || $show_query || $show_stats) {
         // Get information from the preview for display.
-        if (!empty($this->executable->build_info['query'])) {
+        if (!empty($this->getExecutable()->build_info['query'])) {
           if ($show_query) {
-            $query_string = $this->executable->build_info['query'];
+            $query_string = $this->getExecutable()->build_info['query'];
             // Only the sql default class has a method getArguments.
             $quoted = array();
 
-            if ($this->executable->query instanceof Sql) {
+            if ($this->getExecutable()->query instanceof Sql) {
               $quoted = $query_string->getArguments();
               $connection = Database::getConnection();
               foreach ($quoted as $key => $val) {
@@ -722,7 +722,7 @@ public function renderPreview($display_id, $args = array()) {
                   '#template' => "<strong>{% trans 'Title' %}</strong>",
                 ),
               ),
-              Xss::filterAdmin($this->executable->getTitle()),
+              Xss::filterAdmin($this->getExecutable()->getTitle()),
             );
             if (isset($path)) {
               // @todo Views should expect and store a leading /. See:
@@ -743,7 +743,7 @@ public function renderPreview($display_id, $args = array()) {
                   '#template' => "<strong>{% trans 'Query build time' %}</strong>",
                 ),
               ),
-              t('@time ms', array('@time' => intval($this->executable->build_time * 100000) / 100)),
+              t('@time ms', array('@time' => intval($this->getExecutable()->build_time * 100000) / 100)),
             );
 
             $rows['statistics'][] = array(
@@ -753,7 +753,7 @@ public function renderPreview($display_id, $args = array()) {
                   '#template' => "<strong>{% trans 'Query execute time' %}</strong>",
                 ),
               ),
-              t('@time ms', array('@time' => intval($this->executable->execute_time * 100000) / 100)),
+              t('@time ms', array('@time' => intval($this->getExecutable()->execute_time * 100000) / 100)),
             );
 
             $rows['statistics'][] = array(
@@ -763,7 +763,7 @@ public function renderPreview($display_id, $args = array()) {
                   '#template' => "<strong>{% trans 'View render time' %}</strong>",
                 ),
               ),
-              t('@time ms', array('@time' => intval($this->executable->render_time * 100000) / 100)),
+              t('@time ms', array('@time' => intval($this->getExecutable()->render_time * 100000) / 100)),
             );
           }
           \Drupal::moduleHandler()->alter('views_preview_info', $rows, $this->executable);
@@ -873,14 +873,14 @@ public function cacheSet() {
     if (isset($executable->current_display)) {
       // Add the knowledge of the changed display, too.
       $this->changed_display[$executable->current_display] = TRUE;
-      unset($executable->current_display);
+      $executable->current_display = NULL;
     }
 
-    // Unset handlers; we don't want to write these into the cache.
-    unset($executable->display_handler);
-    unset($executable->default_display);
+    // Unset handlers. We don't want to write these into the cache.
+    $executable->display_handler = NULL;
+    $executable->default_display = NULL;
     $executable->query = NULL;
-    unset($executable->displayHandlers);
+    $executable->displayHandlers = NULL;
     \Drupal::service('user.shared_tempstore')->get('views')->set($this->id(), $this);
   }
 
@@ -1132,7 +1132,11 @@ public static function postLoad(EntityStorageInterface $storage, array &$entitie
    * {@inheritdoc}
    */
   public function getExecutable() {
-    return $this->storage->getExecutable();
+    if (!isset($this->executable)) {
+      $this->executable = Views::executableFactory()->get($this);
+    }
+
+    return $this->executable;
   }
 
   /**
@@ -1242,13 +1246,6 @@ public function addDisplay($plugin_id = 'page', $title = NULL, $id = NULL) {
   /**
    * {@inheritdoc}
    */
-  public function getViewExecutable() {
-    return $this->storage->getViewExecutable();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function isInstallable() {
     return $this->storage->isInstallable();
   }
@@ -1287,4 +1284,14 @@ public function unsetThirdPartySetting($module, $key) {
   public function getThirdPartyProviders() {
     return $this->storage->getThirdPartyProviders();
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __sleep() {
+    $vars = get_object_vars($this);
+    unset($vars['executable']);
+    return array_keys($vars);
+  }
+
 }
diff --git a/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php b/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php
index 60a9d16..506bd32 100644
--- a/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php
+++ b/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Tests\UnitTestCase;
+use Drupal\views\Entity\View;
 use Drupal\views\ViewExecutable;
 use Drupal\views_ui\ViewUI;
 use Symfony\Component\DependencyInjection\Container;
@@ -113,4 +114,32 @@ public function testIsLocked() {
     $this->assertFalse($view_ui->isLocked());
   }
 
+  /**
+   * Tests serialization of the ViewUI object.
+   */
+  public function testSerialization() {
+    // Set a container so the DependencySerializationTrait has it.
+    $container = new ContainerBuilder();
+    \Drupal::setContainer($container);
+
+    $storage = new View([], 'view');
+    $executable = $this->getMockBuilder('Drupal\views\ViewExecutable')
+      ->disableOriginalConstructor()
+      ->setConstructorArgs([$storage])
+      ->getMock();
+
+    $view_ui = new ViewUI($storage, $executable);
+
+    // Make sure the executable is returned before serializing.
+    $this->assertInstanceOf('Drupal\views\ViewExecutable', $view_ui->getExecutable());
+
+    $serialized = serialize($view_ui);
+
+    // Make sure the ViewExecutable class is not found in the serialized string.
+    $this->assertSame(strpos($serialized, '"Drupal\views\ViewExecutable"'), FALSE);
+
+    $unserialized = unserialize($serialized);
+    $this->assertInstanceOf('Drupal\views_ui\ViewUI', $unserialized);
+  }
+
 }
