diff --git a/core/lib/Drupal/Core/Form/FormState.php b/core/lib/Drupal/Core/Form/FormState.php
index 33ca1fa..c40e166 100644
--- a/core/lib/Drupal/Core/Form/FormState.php
+++ b/core/lib/Drupal/Core/Form/FormState.php
@@ -769,6 +769,29 @@ public function isSubmitted() {
   /**
    * {@inheritdoc}
    */
+  public function isDirty(array $form)
+  {
+    foreach ($this->getUserInput() as $field => $value) {
+      if (!array_key_exists($field, $form)) {
+        return TRUE;
+      }
+
+      $default = '';
+      if (array_key_exists('#default_value', $form[$field])) {
+        $default = $form[$field]['#default_value'];
+      }
+
+      if ($default != $value) {
+        return TRUE;
+      }
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function setTemporary(array $temporary) {
     $this->temporary = $temporary;
     return $this;
diff --git a/core/lib/Drupal/Core/Form/FormStateInterface.php b/core/lib/Drupal/Core/Form/FormStateInterface.php
index b1e3f3b..2c0eda9 100644
--- a/core/lib/Drupal/Core/Form/FormStateInterface.php
+++ b/core/lib/Drupal/Core/Form/FormStateInterface.php
@@ -951,6 +951,17 @@ public function setSubmitted();
    */
   public function isSubmitted();
 
+    /**
+     * Determines if the form's values differ from default.
+     *
+     * @param array $form
+     *   The original form render array.
+     *
+     * @return bool
+     *   TRUE if the form state has values different than the defaults.
+     */
+  public function isDirty(array $form);
+
   /**
    * Sets temporary data.
    *
