diff --git a/config/install/webform.settings.yml b/config/install/webform.settings.yml
index 5706f727..798ae75d 100644
--- a/config/install/webform.settings.yml
+++ b/config/install/webform.settings.yml
@@ -41,6 +41,7 @@ settings:
   default_submission_exception_message: 'Unable to process this submission. Please contact the site administrator.'
   default_submission_locked_message: 'This submission has been locked.'
   default_submission_log: false
+  default_autofill_message: 'This submission has been autofilled with your previous submission.'
   preview_classes: |
     messages messages--error
     messages messages--warning
diff --git a/config/schema/webform.entity.webform.schema.yml b/config/schema/webform.entity.webform.schema.yml
index 80f5abc9..f233dbf1 100644
--- a/config/schema/webform.entity.webform.schema.yml
+++ b/config/schema/webform.entity.webform.schema.yml
@@ -152,6 +152,18 @@ webform.webform.*:
         submission_login_message:
           type: text
           label: 'Login message when access denied to submission'
+        autofill:
+          type: boolean
+          label: 'Autofill with previous submission'
+        autofill_message:
+          type: text
+          label: 'Autofill with previous submission message'
+        autofill_excluded_elements:
+          type: sequence
+          label: 'Autofill excluded elements'
+          sequence:
+            type: string
+            label: 'Element key'
         wizard_progress_bar:
           type: boolean
           label: 'Show wizard progress bar'
diff --git a/config/schema/webform.settings.schema.yml b/config/schema/webform.settings.schema.yml
index ba9f6ebc..51d48cbb 100644
--- a/config/schema/webform.settings.schema.yml
+++ b/config/schema/webform.settings.schema.yml
@@ -117,6 +117,9 @@ webform.settings:
         default_submission_locked_message:
           type: text
           label: 'Default submission locked message'
+        default_autofill_message:
+          type: text
+          label: 'Default submission autofill message'
         form_classes:
           type: string
           label: 'Form CSS classes '
diff --git a/includes/webform.install.update.inc b/includes/webform.install.update.inc
index c34a4960..718cab51 100644
--- a/includes/webform.install.update.inc
+++ b/includes/webform.install.update.inc
@@ -1939,3 +1939,12 @@ function webform_update_8103() {
   $config->setData($data);
   $config->save();
 }
+
+
+/**
+ * Issue #2940490: Autofill webform with previous submission data.
+ */
+function webform_update_8104() {
+  _webform_update_admin_settings();
+  _webform_update_webform_settings();
+}
diff --git a/src/Entity/Webform.php b/src/Entity/Webform.php
index a1261129..bcc53281 100644
--- a/src/Entity/Webform.php
+++ b/src/Entity/Webform.php
@@ -851,6 +851,9 @@ class Webform extends ConfigEntityBundleBase implements WebformInterface {
       'submission_login_message' => '',
       'submission_exception_message' => '',
       'submission_locked_message' => '',
+      'autofill' => FALSE,
+      'autofill_message' => '',
+      'autofill_excluded_elements' => [],
       'wizard_progress_bar' => TRUE,
       'wizard_progress_pages' => FALSE,
       'wizard_progress_percentage' => FALSE,
diff --git a/src/EntitySettings/WebformEntitySettingsSubmissionsForm.php b/src/EntitySettings/WebformEntitySettingsSubmissionsForm.php
index 61e62c68..4bc35226 100644
--- a/src/EntitySettings/WebformEntitySettingsSubmissionsForm.php
+++ b/src/EntitySettings/WebformEntitySettingsSubmissionsForm.php
@@ -438,6 +438,43 @@ class WebformEntitySettingsSubmissionsForm extends WebformEntitySettingsBaseForm
     ];
     $form['draft_settings']['draft_container']['token_tree_link'] = $this->tokenManager->buildTreeLink();
 
+    // Autofill settings.
+    $form['autofill_settings'] = [
+      '#type' => 'details',
+      '#title' => $this->t('Autofill settings'),
+      '#open' => TRUE,
+    ];
+    $form['autofill_settings']['autofill'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Autofill with previous submission data'),
+      '#return_value' => TRUE,
+      '#default_value' => $settings['autofill'],
+    ];
+    $form['autofill_settings']['autofill_container'] = [
+      '#type' => 'container',
+      '#states' => [
+        'visible' => [
+          ':input[name="autofill"]' => ['checked' => true],
+        ],
+      ],
+    ];
+    $form['autofill_settings']['autofill_container']['autofill_message'] = [
+      '#type' => 'webform_html_editor',
+      '#title' => $this->t('Autofill message'),
+      '#description' => $this->t('A message to be displayed when form is autofilled with previous submission data.'),
+      '#default_value' => $settings['autofill_message'],
+    ];
+    $form['autofill_settings']['autofill_container']['elements'] = [
+      '#type' => 'details',
+      '#title' => $this->t('Autofill elements'),
+      '#open' => $settings['autofill_excluded_elements'] ? TRUE : FALSE,
+    ];
+    $form['autofill_settings']['autofill_container']['elements']['autofill_excluded_elements'] = [
+      '#type' => 'webform_excluded_elements',
+      '#webform_id' => $this->getEntity()->id(),
+      '#default_value' => $settings['autofill_excluded_elements'],
+    ];
+
     return parent::form($form, $form_state);
   }
 
diff --git a/src/Form/AdminConfig/WebformAdminConfigSubmissionsForm.php b/src/Form/AdminConfig/WebformAdminConfigSubmissionsForm.php
index 6e5125d5..a503cabe 100644
--- a/src/Form/AdminConfig/WebformAdminConfigSubmissionsForm.php
+++ b/src/Form/AdminConfig/WebformAdminConfigSubmissionsForm.php
@@ -81,6 +81,12 @@ class WebformAdminConfigSubmissionsForm extends WebformAdminConfigBaseForm {
       '#required' => TRUE,
       '#default_value' => $settings['default_submission_locked_message'],
     ];
+    $form['submission_settings']['default_autofill_message'] = [
+      '#type' => 'webform_html_editor',
+      '#title' => $this->t('Default autofill message'),
+      '#description' => $this->t('Leave blank to not display a message when a form is autofilled.'),
+      '#default_value' => $settings['default_autofill_message'],
+    ];
     $form['submission_settings']['default_submission_label'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Default submission label'),
diff --git a/src/Plugin/WebformElement/WebformComputedBase.php b/src/Plugin/WebformElement/WebformComputedBase.php
index 726802c5..606e847b 100644
--- a/src/Plugin/WebformElement/WebformComputedBase.php
+++ b/src/Plugin/WebformElement/WebformComputedBase.php
@@ -73,9 +73,9 @@ abstract class WebformComputedBase extends WebformElementBase implements Webform
   /**
    * {@inheritdoc}
    */
-  protected function replaceTokens(array &$element, WebformSubmissionInterface $webform_submission) {
+  public function replaceTokens(array &$element, WebformSubmissionInterface $webform_submission = NULL) {
     foreach ($element as $key => $value) {
-      if (!Element::child($key) && !in_array($key, ['#markup'])) {
+      if (!Element::child($key) && !in_array($key, ['#value'])) {
         $element[$key] = $this->tokenManager->replace($value, $webform_submission);
       }
     }
diff --git a/src/Plugin/WebformElementBase.php b/src/Plugin/WebformElementBase.php
index a8bddb02..7cac7dc9 100644
--- a/src/Plugin/WebformElementBase.php
+++ b/src/Plugin/WebformElementBase.php
@@ -566,6 +566,9 @@ class WebformElementBase extends PluginBase implements WebformElementInterface {
     if (!empty($element['#title']) && empty($element['#admin_title'])) {
       $element['#admin_title'] = strip_tags($element['#title']);
     }
+
+    // Replace global tokens which could include the [site:name]
+    $this->replaceTokens($element);
   }
 
   /**
@@ -820,14 +823,9 @@ class WebformElementBase extends PluginBase implements WebformElementInterface {
   }
 
   /**
-   * Replace tokens for all element properties.
-   *
-   * @param array $element
-   *   An element.
-   * @param \Drupal\webform\WebformSubmissionInterface $webform_submission
-   *   A webform submission.
+   * {@inheritdoc}
    */
-  protected function replaceTokens(array &$element, WebformSubmissionInterface $webform_submission) {
+  public function replaceTokens(array &$element, WebformSubmissionInterface $webform_submission = NULL) {
     foreach ($element as $key => $value) {
       if (!Element::child($key)) {
         $element[$key] = $this->tokenManager->replace($value, $webform_submission);
diff --git a/src/Plugin/WebformElementInterface.php b/src/Plugin/WebformElementInterface.php
index c678ecbc..6a439cf7 100644
--- a/src/Plugin/WebformElementInterface.php
+++ b/src/Plugin/WebformElementInterface.php
@@ -316,6 +316,16 @@ interface WebformElementInterface extends PluginInspectionInterface, PluginFormI
    */
   public function checkAccessRules($operation, array $element, AccountInterface $account = NULL);
 
+  /**
+   * Replace tokens for all element properties.
+   *
+   * @param array $element
+   *   An element.
+   * @param \Drupal\webform\WebformSubmissionInterface $webform_submission
+   *   A webform submission.
+   */
+  public function replaceTokens(array &$element, WebformSubmissionInterface $webform_submission = NULL);
+
   /**
    * Display element disabled warning.
    *
diff --git a/src/Tests/WebformSubmissionFormAutofillTest.php b/src/Tests/WebformSubmissionFormAutofillTest.php
new file mode 100644
index 00000000..61d1ee58
--- /dev/null
+++ b/src/Tests/WebformSubmissionFormAutofillTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Drupal\webform\Tests;
+
+use Drupal\webform\Entity\Webform;
+
+/**
+ * Tests for webform submission form autofill.
+ *
+ * @group Webform
+ */
+class WebformSubmissionFormAutofillTest extends WebformTestBase {
+
+  /**
+   * Webforms to load.
+   *
+   * @var array
+   */
+  protected static $testWebforms = ['test_form_autofill'];
+
+  /**
+   * Test webform submission form autofill.
+   */
+  public function testAutofill() {
+    $this->drupalLogin($this->rootUser);
+
+    $webform = Webform::load('test_form_autofill');
+
+    // Check that elements are both blank.
+    $this->drupalGet('webform/test_form_autofill');
+    $this->assertFieldByName('textfield_autofill', '');
+    $this->assertFieldByName('textfield_excluded', '');
+
+    // Create a submission.
+    $edit = [
+      'textfield_autofill' => '{textfield_autofill}',
+      'textfield_excluded' => '{textfield_excluded}',
+    ];
+    $this->postSubmission($webform, $edit);
+
+    // Check that 'textfield_autofill' is autofilled and 'textfield_excluded'
+    // is empty.
+    $this->drupalGet('webform/test_form_autofill');
+    $this->assertFieldByName('textfield_autofill', '{textfield_autofill}');
+    $this->assertNoFieldByName('textfield_autofill', '{textfield_excluded}');
+    $this->assertFieldByName('textfield_excluded', '');
+
+    // Check that default configuration message is displayed.
+    $this->drupalGet('webform/test_form_autofill');
+    $this->assertFieldByName('textfield_autofill', '{textfield_autofill}');
+    $this->assertRaw('This submission has been autofilled with your previous submission.');
+
+    // Clear default autofill message.
+    \Drupal::configFactory()->getEditable('webform.settings')
+      ->set('settings.default_autofill_message', '')
+      ->save();
+
+    // Check no autofill message is displayed
+    $this->drupalGet('webform/test_form_autofill');
+    $this->assertFieldByName('textfield_autofill', '{textfield_autofill}');
+    $this->assertNoRaw('This submission has been autofilled with your previous submission.');
+
+    // Set custom automfill message.
+    $webform
+      ->setSetting('autofill_message', '{autofill_message}')
+      ->save();
+
+    // Check custom autofill message is displayed
+    $this->drupalGet('webform/test_form_autofill');
+    $this->assertFieldByName('textfield_autofill', '{textfield_autofill}');
+    $this->assertRaw('{autofill_message}');
+  }
+
+
+}
diff --git a/src/WebformMessageManagerInterface.php b/src/WebformMessageManagerInterface.php
index 1cf2a608..74fb2cfb 100644
--- a/src/WebformMessageManagerInterface.php
+++ b/src/WebformMessageManagerInterface.php
@@ -153,6 +153,11 @@ interface WebformMessageManagerInterface {
    */
   const PREPOPULATE_SOURCE_ENTITY_TYPE = 'prepopulate_source_entity_type';
 
+  /**
+   * Autofill.
+   */
+  const AUTOFILL = 'autofill_message';
+
   /**
    * Set the webform submission used for token replacement.
    *
diff --git a/src/WebformSubmissionForm.php b/src/WebformSubmissionForm.php
index 10f981d7..d7675ea8 100644
--- a/src/WebformSubmissionForm.php
+++ b/src/WebformSubmissionForm.php
@@ -188,7 +188,6 @@ class WebformSubmissionForm extends ContentEntityForm {
       $container->get('webform.token_manager'),
       $container->get('webform_submission.conditions_validator'),
       $container->get('webform.entity_reference_manager')
-
     );
   }
 
@@ -230,7 +229,7 @@ class WebformSubmissionForm extends ContentEntityForm {
     // Get the source entity and allow webform submission to be used as a source
     // entity.
     $this->sourceEntity = $this->requestHandler->getCurrentSourceEntity(['webform']);
-    if ($this->sourceEntity == $entity) {
+    if ($this->sourceEntity === $entity) {
       $this->sourceEntity = $this->requestHandler->getCurrentSourceEntity(['webform', 'webform_submission']);
     }
 
@@ -262,6 +261,18 @@ class WebformSubmissionForm extends ContentEntityForm {
       }
     }
 
+    // Autofill with previous submission.
+    if ($this->operation === 'add' && $entity->isNew() && $webform->getSetting('autofill')) {
+      $account = $entity->getOwner();
+      $options = ['in_draft' => FALSE];
+      $last_submission = $this->storage->getLastSubmission($webform, $source_entity, $account, $options);
+      if ($last_submission) {
+        $excluded_elements = $webform->getSetting('autofill_excluded_elements') ?: [];
+        $last_submission_data = array_diff_key($last_submission->getData(), $excluded_elements);
+        $entity->setData($last_submission_data + $entity->getData());
+      }
+    }
+
     // Alter webform settings before setting the entity.
     $entity->getWebform()->invokeHandlers('overrideSettings', $entity);
 
@@ -722,7 +733,7 @@ class WebformSubmissionForm extends ContentEntityForm {
   }
 
   /**
-   * Display draft and previous submission status messages for this webform submission.
+   * Display draft, previous submission, and autofill status messages for this webform submission.
    *
    * @param array $form
    *   An associative array containing the structure of the form.
@@ -808,6 +819,11 @@ class WebformSubmissionForm extends ContentEntityForm {
         $this->getMessageManager()->display(WebformMessageManagerInterface::SUBMISSION_PREVIOUS);
       }
     }
+
+    // Display autofill message.
+    if ($this->operation === 'add' && $webform_submission->isNew() && $webform->getSetting('autofill')) {
+      $this->getMessageManager()->display(WebformMessageManagerInterface::AUTOFILL);
+    }
   }
 
   /****************************************************************************/
diff --git a/src/WebformSubmissionViewBuilder.php b/src/WebformSubmissionViewBuilder.php
index d9b7109a..ad0ceb96 100644
--- a/src/WebformSubmissionViewBuilder.php
+++ b/src/WebformSubmissionViewBuilder.php
@@ -145,6 +145,9 @@ class WebformSubmissionViewBuilder extends EntityViewBuilder implements WebformS
         continue;
       }
 
+      // Replace tokens before building the element.
+      $webform_element->replaceTokens($element, $webform_submission);
+
       if ($build_element = $webform_element->$build_method($element, $webform_submission, $options)) {
         $build[$key] = $build_element;
       }
@@ -171,6 +174,9 @@ class WebformSubmissionViewBuilder extends EntityViewBuilder implements WebformS
         continue;
       }
 
+      // Replace tokens before building the element.
+      $webform_element->replaceTokens($element, $webform_submission);
+
       $title = $element['#admin_title'] ?: $element['#title'] ?: '(' . $key . ')';
       $html = $webform_element->formatHtml($element, $webform_submission, $options);
       $rows[] = [
diff --git a/src/WebformTokenManager.php b/src/WebformTokenManager.php
index 6ea40c10..7bfad992 100644
--- a/src/WebformTokenManager.php
+++ b/src/WebformTokenManager.php
@@ -68,11 +68,13 @@ class WebformTokenManager implements WebformTokenManagerInterface {
       return $text;
     }
 
-    // Replace @deprecated [webform-submission] with [webform_submission].
-    $text = str_replace('[webform-submission:', '[webform_submission:', $text);
+    if ($entity) {
+      // Replace @deprecated [webform-submission] with [webform_submission].
+      $text = str_replace('[webform-submission:', '[webform_submission:', $text);
 
-    // Set token data based on entity type.
-    $this->setTokenData($data, $entity);
+      // Set token data based on entity type.
+      $this->setTokenData($data, $entity);
+    }
 
     return $this->token->replace($text, $data, $options);
   }
diff --git a/tests/modules/webform_test/config/install/webform.webform.test_form_autofill.yml b/tests/modules/webform_test/config/install/webform.webform.test_form_autofill.yml
new file mode 100644
index 00000000..dceec6b5
--- /dev/null
+++ b/tests/modules/webform_test/config/install/webform.webform.test_form_autofill.yml
@@ -0,0 +1,141 @@
+langcode: en
+status: open
+dependencies:
+  enforced:
+    module:
+      - webform_test
+open: null
+close: null
+uid: null
+template: false
+id: test_form_autofill
+title: 'Test: Webform: Autofill'
+description: 'Test autofill with previous submission data.'
+category: 'Test: Webform'
+elements: |
+  textfield_autofill:
+    '#type': textfield
+    '#title': textfield_autofill
+  textfield_excluded:
+    '#type': textfield
+    '#title': textfield_excluded
+css: ''
+javascript: ''
+settings:
+  ajax: false
+  ajax_scroll_top: form
+  page: true
+  page_submit_path: ''
+  page_confirm_path: ''
+  form_submit_once: false
+  form_exception_message: ''
+  form_open_message: ''
+  form_close_message: ''
+  form_previous_submissions: true
+  form_confidential: false
+  form_confidential_message: ''
+  form_convert_anonymous: false
+  form_prepopulate: false
+  form_prepopulate_source_entity: false
+  form_prepopulate_source_entity_required: false
+  form_prepopulate_source_entity_type: ''
+  form_reset: false
+  form_disable_autocomplete: false
+  form_novalidate: false
+  form_required: false
+  form_unsaved: false
+  form_disable_back: false
+  form_submit_back: false
+  form_autofocus: false
+  form_details_toggle: false
+  form_login: false
+  form_login_message: ''
+  submission_label: ''
+  submission_log: false
+  submission_user_columns: {  }
+  submission_login: false
+  submission_login_message: ''
+  submission_exception_message: ''
+  submission_locked_message: ''
+  autofill: true
+  autofill_message: ''
+  autofill_excluded_elements:
+    textfield_excluded: textfield_excluded
+  wizard_progress_bar: true
+  wizard_progress_pages: false
+  wizard_progress_percentage: false
+  wizard_start_label: ''
+  wizard_confirmation: true
+  wizard_confirmation_label: ''
+  wizard_track: ''
+  preview: 0
+  preview_label: ''
+  preview_title: ''
+  preview_message: ''
+  preview_attributes: {  }
+  preview_excluded_elements: {  }
+  preview_exclude_empty: true
+  draft: all
+  draft_multiple: false
+  draft_auto_save: false
+  draft_saved_message: ''
+  draft_loaded_message: ''
+  confirmation_type: page
+  confirmation_title: ''
+  confirmation_message: ''
+  confirmation_url: ''
+  confirmation_attributes: {  }
+  confirmation_back: true
+  confirmation_back_label: ''
+  confirmation_back_attributes: {  }
+  limit_total: null
+  limit_total_interval: null
+  limit_total_message: ''
+  limit_user: null
+  limit_user_interval: null
+  limit_user_message: ''
+  entity_limit_total: null
+  entity_limit_total_interval: null
+  entity_limit_user: null
+  entity_limit_user_interval: null
+  purge: none
+  purge_days: null
+  results_disabled: false
+  results_disabled_ignore: false
+  token_update: false
+access:
+  create:
+    roles:
+      - anonymous
+      - authenticated
+    users: {  }
+    permissions: {  }
+  view_any:
+    roles: {  }
+    users: {  }
+    permissions: {  }
+  update_any:
+    roles: {  }
+    users: {  }
+    permissions: {  }
+  delete_any:
+    roles: {  }
+    users: {  }
+    permissions: {  }
+  purge_any:
+    roles: {  }
+    users: {  }
+    permissions: {  }
+  view_own:
+    roles: {  }
+    users: {  }
+    permissions: {  }
+  update_own:
+    roles: {  }
+    users: {  }
+    permissions: {  }
+  delete_own:
+    roles: {  }
+    users: {  }
+    permissions: {  }
+handlers: {  }
