diff --git a/app/code/Magento/Catalog/Helper/Product/Compare.php b/app/code/Magento/Catalog/Helper/Product/Compare.php
index 3a7ce70cbff528239712a353cb5f939f9a0878c4..69f4a613a5b9555e2c46038c2a6cc620b291ef60 100644
--- a/app/code/Magento/Catalog/Helper/Product/Compare.php
+++ b/app/code/Magento/Catalog/Helper/Product/Compare.php
@@ -231,6 +231,8 @@ class Compare extends \Magento\Framework\Url\Helper\Data
         $data = [
             \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => '',
             'product' => $product->getId(),
+            'confirmation' => true,
+            'confirmationMessage' => __('Are you sure you want to remove this item from your Compare Products list?')
         ];
         return $this->postHelper->getPostData($this->getRemoveUrl(), $data);
     }
@@ -254,6 +256,8 @@ class Compare extends \Magento\Framework\Url\Helper\Data
     {
         $params = [
             \Magento\Framework\App\ActionInterface::PARAM_NAME_URL_ENCODED => '',
+            'confirmation' => true,
+            'confirmationMessage' => __('Are you sure you want to remove all items from your Compare Products list?'),
         ];
         return $this->postHelper->getPostData($this->getClearListUrl(), $params);
     }
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php
index 39a67f9722e185894640178329d008de10cb574e..42456a396178c1a1001c45f49a0150612cdd566f 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Option/Value.php
@@ -33,6 +33,11 @@ class Value extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
      */
     protected $_config;
 
+    /**
+     * @var \Magento\Framework\Locale\FormatInterface
+     */
+    private $localeFormat;
+
     /**
      * Class constructor
      *
@@ -91,8 +96,9 @@ class Value extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
     protected function _saveValuePrices(\Magento\Framework\Model\AbstractModel $object)
     {
         $priceTable = $this->getTable('catalog_product_option_type_price');
+        $formattedPrice = $this->getLocaleFormatter()->getNumber($object->getPrice());
 
-        $price = (double)sprintf('%F', $object->getPrice());
+        $price = (double)sprintf('%F', $formattedPrice);
         $priceType = $object->getPriceType();
 
         if ($object->getPrice() && $priceType) {
@@ -410,4 +416,19 @@ class Value extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
 
         return $object;
     }
+
+    /**
+     * Get FormatInterface to convert price from string to number format
+     *
+     * @return \Magento\Framework\Locale\FormatInterface
+     * @deprecated
+     */
+    private function getLocaleFormatter()
+    {
+        if ($this->localeFormat === null) {
+            $this->localeFormat = \Magento\Framework\App\ObjectManager::getInstance()
+                ->get(\Magento\Framework\Locale\FormatInterface::class);
+        }
+        return $this->localeFormat;
+    }
 }
diff --git a/app/code/Magento/Catalog/Test/Unit/Helper/Product/CompareTest.php b/app/code/Magento/Catalog/Test/Unit/Helper/Product/CompareTest.php
index 9f4d41aefd6bb8d1fd02d8990bcdd12c33191035..51388c3725ba9dc430137514ba3c3fc103237d1f 100644
--- a/app/code/Magento/Catalog/Test/Unit/Helper/Product/CompareTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Helper/Product/CompareTest.php
@@ -115,7 +115,9 @@ class CompareTest extends \PHPUnit_Framework_TestCase
         $removeUrl = 'catalog/product_compare/remove';
         $postParams = [
             Action::PARAM_NAME_URL_ENCODED => '',
-            'product' => $productId
+            'product' => $productId,
+            'confirmation' => true,
+            'confirmationMessage' => __('Are you sure you want to remove this item from your Compare Products list?'),
         ];
 
         //Verification
@@ -156,7 +158,9 @@ class CompareTest extends \PHPUnit_Framework_TestCase
         //Data
         $clearUrl = 'catalog/product_compare/clear';
         $postParams = [
-            Action::PARAM_NAME_URL_ENCODED => ''
+            Action::PARAM_NAME_URL_ENCODED => '',
+            'confirmation' => true,
+            'confirmationMessage' => __('Are you sure you want to remove all items from your Compare Products list?'),
         ];
 
         //Verification
diff --git a/app/code/Magento/Catalog/view/frontend/requirejs-config.js b/app/code/Magento/Catalog/view/frontend/requirejs-config.js
index c0d05a322b7cd9e0a0603cdbef8505963ead80fa..6c7a8d3a969fff3090e0c24bbb431eebf83b9e6b 100644
--- a/app/code/Magento/Catalog/view/frontend/requirejs-config.js
+++ b/app/code/Magento/Catalog/view/frontend/requirejs-config.js
@@ -6,7 +6,6 @@
 var config = {
     map: {
         '*': {
-            compareItems:           'Magento_Catalog/js/compare',
             compareList:            'Magento_Catalog/js/list',
             relatedProducts:        'Magento_Catalog/js/related-products',
             upsellProducts:         'Magento_Catalog/js/upsell-products',
diff --git a/app/code/Magento/Catalog/view/frontend/web/js/compare.js b/app/code/Magento/Catalog/view/frontend/web/js/compare.js
deleted file mode 100644
index 66f8767bf2b8830c4229588d7c0a7ac5a8b6a422..0000000000000000000000000000000000000000
--- a/app/code/Magento/Catalog/view/frontend/web/js/compare.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright © 2016 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-/*jshint browser:true jquery:true*/
-/*global confirm:true*/
-define([
-    "jquery",
-    "jquery/ui",
-    "mage/decorate"
-], function($){
-    "use strict";
-
-    $.widget('mage.compareItems', {
-        _create: function() {
-            this.element.decorate('list', true);
-            this._confirm(this.options.removeSelector, this.options.removeConfirmMessage);
-            this._confirm(this.options.clearAllSelector, this.options.clearAllConfirmMessage);
-        },
-
-        /**
-         * Set up a click event on the given selector to display a confirmation request message
-         * and ask for that confirmation.
-         * @param selector Selector for the confirmation on click event
-         * @param message Message to display asking for confirmation to perform action
-         * @private
-         */
-        _confirm: function(selector, message) {
-            $(selector).on('click', function() {
-                return confirm(message);
-            });
-        }
-    });
-
-    return $.mage.compareItems;
-});
\ No newline at end of file
diff --git a/app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js b/app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js
index 5dba397d9bc43d7e149887fe5519c54469d09b0e..9662b3fc7268b7366b9a448e90ca75690506b13a 100644
--- a/app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js
+++ b/app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js
@@ -2,37 +2,32 @@
  * Copyright © 2016 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
+
 define([
     'uiComponent',
     'Magento_Customer/js/customer-data',
-    'mage/translate'
-], function (Component, customerData) {
+    'jquery',
+    'mage/mage',
+    'mage/decorate'
+], function (Component, customerData, $) {
     'use strict';
 
     var sidebarInitialized = false;
 
+    /**
+     * Initialize sidebar
+     */
     function initSidebar() {
         if (sidebarInitialized) {
             return;
         }
-        sidebarInitialized = true;
-        require([
-            'jquery',
-            'mage/mage'
-        ], function ($) {
-            /*eslint-disable max-len*/
-            $('[data-role=compare-products-sidebar]').mage('compareItems', {
-                'removeConfirmMessage': $.mage.__('Are you sure you want to remove this item from your Compare Products list?'),
-                'removeSelector': '#compare-items a.action.delete',
-                'clearAllConfirmMessage': $.mage.__('Are you sure you want to remove all items from your Compare Products list?'),
-                'clearAllSelector': '#compare-clear-all'
-            });
 
-            /*eslint-enable max-len*/
-        });
+        sidebarInitialized = true;
+        $('[data-role=compare-products-sidebar]').decorate('list', true);
     }
 
     return Component.extend({
+        /** @inheritdoc */
         initialize: function () {
             this._super();
             this.compareProducts = customerData.get('compare-products');
diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
index c4d9657a322dab4b48a1668f908021de223f050b..d176b5be6a4551d9d7162ebf5d9436f99aadcd37 100644
--- a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
+++ b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
@@ -151,25 +151,28 @@ class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implemen
         $request->setPackageQty($oldQty);
 
         if (!empty($rate) && $rate['price'] >= 0) {
-            /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
-            $method = $this->_resultMethodFactory->create();
-
-            $method->setCarrier('tablerate');
-            $method->setCarrierTitle($this->getConfigData('title'));
-
-            $method->setMethod('bestway');
-            $method->setMethodTitle($this->getConfigData('name'));
-
             if ($request->getFreeShipping() === true || $request->getPackageQty() == $freeQty) {
                 $shippingPrice = 0;
             } else {
                 $shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']);
             }
-
-            $method->setPrice($shippingPrice);
-            $method->setCost($rate['cost']);
-
+            $method = $this->createShippingMethod($shippingPrice, $rate['cost']);
             $result->append($method);
+        } elseif (empty($rate) && $request->getFreeShipping() === true || $request->getPackageQty() == $freeQty) {
+
+            /**
+             * Promotion rule was applied for the whole cart.
+             *  In this case all other shipping methods could be omitted
+             * Table rate shipping method with 0$ price must be shown if grand total is more than minimal value.
+             * Free package weight has been already taken into account.
+             */
+            $request->setPackageValue($freePackageValue);
+            $request->setPackageQty($freeQty);
+            $rate = $this->getRate($request);
+            if (!empty($rate) && $rate['price'] >= 0) {
+                $method = $this->createShippingMethod(0, 0);
+                $result->append($method);
+            }
         } else {
             /** @var \Magento\Quote\Model\Quote\Address\RateResult\Error $error */
             $error = $this->_rateErrorFactory->create(
@@ -241,4 +244,27 @@ class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implemen
     {
         return ['bestway' => $this->getConfigData('name')];
     }
+
+    /**
+     * Get the method object based on the shipping price and cost
+     *
+     * @param float $shippingPrice
+     * @param float $cost
+     * @return \Magento\Quote\Model\Quote\Address\RateResult\Method
+     */
+    private function createShippingMethod($shippingPrice, $cost)
+    {
+        /** @var  \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
+        $method = $this->_resultMethodFactory->create();
+
+        $method->setCarrier('tablerate');
+        $method->setCarrierTitle($this->getConfigData('title'));
+
+        $method->setMethod('bestway');
+        $method->setMethodTitle($this->getConfigData('name'));
+
+        $method->setPrice($shippingPrice);
+        $method->setCost($cost);
+        return $method;
+    }
 }
diff --git a/app/code/Magento/Review/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ReviewTest.php b/app/code/Magento/Review/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ReviewTest.php
index 7685fc0fed94df32b0e0638e65d6d15f6de1d5ce..b93cb70fdda3d9cc9b6d8d9f7bb565d576392de4 100644
--- a/app/code/Magento/Review/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ReviewTest.php
+++ b/app/code/Magento/Review/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ReviewTest.php
@@ -8,6 +8,8 @@ namespace Magento\Review\Test\Unit\Ui\DataProvider\Product\Form\Modifier;
 use Magento\Catalog\Test\Unit\Ui\DataProvider\Product\Form\Modifier\AbstractModifierTest;
 use Magento\Framework\UrlInterface;
 use Magento\Review\Ui\DataProvider\Product\Form\Modifier\Review;
+use Magento\Framework\Module\Manager as ModuleManager;
+use Magento\Ui\DataProvider\Modifier\ModifierInterface;
 
 /**
  * Class ReviewTest
@@ -19,36 +21,73 @@ class ReviewTest extends AbstractModifierTest
      */
     protected $urlBuilderMock;
 
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    private $moduleManagerMock;
+
     protected function setUp()
     {
         parent::setUp();
         $this->urlBuilderMock = $this->getMockBuilder(UrlInterface::class)
             ->getMockForAbstractClass();
+        $this->moduleManagerMock = $this->getMock(ModuleManager::class, [], [], '', false);
     }
 
+    /**
+     * @return ModifierInterface
+     */
     protected function createModel()
     {
-        return $this->objectManager->getObject(Review::class, [
+        $model = $this->objectManager->getObject(Review::class, [
             'locator' => $this->locatorMock,
             'urlBuilder' => $this->urlBuilderMock,
         ]);
+
+        $reviewClass = new \ReflectionClass(Review::class);
+        $moduleManagerProperty = $reviewClass->getProperty('moduleManager');
+        $moduleManagerProperty->setAccessible(true);
+        $moduleManagerProperty->setValue(
+            $model,
+            $this->moduleManagerMock
+        );
+
+        return $model;
     }
 
-    public function testModifyMetaToBeEmpty()
+    public function testModifyMetaDoesNotAddReviewSectionForNewProduct()
+    {
+        $this->productMock->expects($this->once())
+            ->method('getId');
+
+        $this->assertSame([], $this->getModel()->modifyMeta([]));
+    }
+
+    public function testModifyMetaDoesNotAddReviewSectionIfReviewModuleOutputIsDisabled()
     {
         $this->productMock->expects($this->once())
             ->method('getId')
-            ->willReturn(0);
+            ->willReturn(1);
+
+        $this->moduleManagerMock->expects($this->any())
+            ->method('isOutputEnabled')
+            ->with('Magento_Review')
+            ->willReturn(false);
 
         $this->assertSame([], $this->getModel()->modifyMeta([]));
     }
 
-    public function testModifyMeta()
+    public function testModifyMetaAddsReviewSectionForExistingProductIfReviewModuleOutputIsEnabled()
     {
         $this->productMock->expects($this->once())
             ->method('getId')
             ->willReturn(1);
 
+        $this->moduleManagerMock->expects($this->any())
+            ->method('isOutputEnabled')
+            ->with('Magento_Review')
+            ->willReturn(true);
+
         $this->assertArrayHasKey(Review::GROUP_REVIEW, $this->getModel()->modifyMeta([]));
     }
 
diff --git a/app/code/Magento/Review/Ui/DataProvider/Product/Form/Modifier/Review.php b/app/code/Magento/Review/Ui/DataProvider/Product/Form/Modifier/Review.php
index 82141b5ab2f12a03e44463555e7b0a302630b0d2..0ef1057eb4be7ffd23fe794bef67663dc247b5c6 100644
--- a/app/code/Magento/Review/Ui/DataProvider/Product/Form/Modifier/Review.php
+++ b/app/code/Magento/Review/Ui/DataProvider/Product/Form/Modifier/Review.php
@@ -12,6 +12,8 @@ use Magento\Catalog\Model\Locator\LocatorInterface;
 use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier;
 use Magento\Ui\Component\Form;
 use Magento\Framework\UrlInterface;
+use Magento\Framework\Module\Manager as ModuleManager;
+use Magento\Framework\App\ObjectManager;
 
 /**
  * Class Review
@@ -34,6 +36,11 @@ class Review extends AbstractModifier
      */
     protected $urlBuilder;
 
+    /**
+     * @var ModuleManager
+     */
+    private $moduleManager;
+
     /**
      * @param LocatorInterface $locator
      * @param UrlInterface $urlBuilder
@@ -51,7 +58,7 @@ class Review extends AbstractModifier
      */
     public function modifyMeta(array $meta)
     {
-        if (!$this->locator->getProduct()->getId()) {
+        if (!$this->locator->getProduct()->getId() || !$this->getModuleManager()->isOutputEnabled('Magento_Review')) {
             return $meta;
         }
 
@@ -114,4 +121,19 @@ class Review extends AbstractModifier
 
         return $data;
     }
+
+    /**
+     * Retrieve module manager instance using dependency lookup to keep this class backward compatible.
+     *
+     * @return ModuleManager
+     *
+     * @deprecated
+     */
+    private function getModuleManager()
+    {
+        if ($this->moduleManager === null) {
+            $this->moduleManager = ObjectManager::getInstance()->get(ModuleManager::class);
+        }
+        return $this->moduleManager;
+    }
 }
diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form.phtml
index 4b53e0ccb1e9fefd91ea23c555dc64c7f617ca72..fe212490a2fd00c9e18fc6fea8ab28b01e34e45d 100644
--- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/form.phtml
+++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/form.phtml
@@ -8,7 +8,7 @@
 
 /** @var \Magento\Sales\Block\Adminhtml\Order\Create\Form $block */
 ?>
-<form id="edit_form" data-order-config='<?php /* @escapeNotVerified */ echo $block->getOrderDataJson() ?>' data-load-base-url="<?php /* @escapeNotVerified */ echo $block->getLoadBlockUrl() ?>" action="<?php /* @escapeNotVerified */ echo $block->getSaveUrl() ?>" method="post" enctype="multipart/form-data">
+<form id="edit_form" data-order-config='<?php echo $block->escapeHtml($block->getOrderDataJson()) ?>' data-load-base-url="<?php /* @escapeNotVerified */ echo $block->getLoadBlockUrl() ?>" action="<?php /* @escapeNotVerified */ echo $block->getSaveUrl() ?>" method="post" enctype="multipart/form-data">
     <?php echo $block->getBlockHtml('formkey')?>
     <div id="order-message">
         <?php echo $block->getChildHtml('message') ?>
diff --git a/app/code/Magento/SalesRule/etc/di.xml b/app/code/Magento/SalesRule/etc/di.xml
index 2c731823b778fabe6faab37024f4e9ea60247538..83364f924397d857030a9f039ed1ab59dc0fd5f0 100644
--- a/app/code/Magento/SalesRule/etc/di.xml
+++ b/app/code/Magento/SalesRule/etc/di.xml
@@ -78,7 +78,7 @@
     <type name="Magento\Framework\Model\Entity\RepositoryFactory">
         <arguments>
             <argument name="entities" xsi:type="array">
-                <item name="Magento\SalesRule\Api\Data\RuleInterface" xsi:type="string">Magento\SalesRule\Api\RuleRepositoryInterface</item>
+                <item name="Magento\SalesRule\Api\Data\RuleInterface" xsi:type="string">Magento\SalesRule\Model\ResourceModel\Rule</item>
             </argument>
         </arguments>
     </type>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php
index 546b055b0045b29d6cfe216b1b0efdc7407ebc0a..4de51f3e2ca9b8d5089cb6818d380f0ac9465e46 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/ListCompare.php
@@ -86,6 +86,13 @@ class ListCompare extends Block
      */
     protected $messageBlock = '#messages';
 
+    /**
+     * Selector for confirm.
+     *
+     * @var string
+     */
+    protected $confirmModal = '.confirm._show[data-role=modal]';
+
     /**
      * Get product info.
      *
@@ -189,6 +196,13 @@ class ListCompare extends Block
     public function removeProduct($index = 1)
     {
         $this->_rootElement->find(sprintf($this->removeButton, $index), Locator::SELECTOR_XPATH)->click();
+        $modalElement = $this->browser->find($this->confirmModal);
+        /** @var \Magento\Ui\Test\Block\Adminhtml\Modal $modal */
+        $modal = $this->blockFactory->create(
+            \Magento\Ui\Test\Block\Adminhtml\Modal::class,
+            ['element' => $modalElement]
+        );
+        $modal->acceptAlert();
     }
 
     /**
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php
index 596dbd38664b3b097302e6f6f0e62d13fbe96017..ab65865af6534c2b2478490b7f08fd7f108496fe 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Product/Compare/Sidebar.php
@@ -32,6 +32,13 @@ class Sidebar extends ListCompare
      */
     protected $clearAll = '#compare-clear-all';
 
+    /**
+     * Selector for confirm.
+     *
+     * @var string
+     */
+    protected $confirmModal = '.confirm._show[data-role=modal]';
+
     /**
      * Get compare products block content.
      *
@@ -79,5 +86,12 @@ class Sidebar extends ListCompare
             }
         );
         $this->_rootElement->find($this->clearAll)->click();
+        $modalElement = $this->browser->find($this->confirmModal);
+        /** @var \Magento\Ui\Test\Block\Adminhtml\Modal $modal */
+        $modal = $this->blockFactory->create(
+            \Magento\Ui\Test\Block\Adminhtml\Modal::class,
+            ['element' => $modalElement]
+        );
+        $modal->acceptAlert();
     }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php
index f610ee5e15473c89cc2f4fe4f6f3cc9e92a48eac..3c27a65c4a74385f546c108c077c128ebb4edcfb 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ProductTest.php
@@ -476,13 +476,24 @@ class ProductTest extends \PHPUnit_Framework_TestCase
     }
 
     /**
-     * @magentoDataFixture Magento/Catalog/_files/product_simple.php
+     * @magentoDataFixture Magento/Catalog/_files/product_simple_with_custom_options.php
      * @magentoAppIsolation enabled
      */
     public function testGetOptions()
     {
-        $this->_model = $this->productRepository->get('simple');
-
-        $this->assertEquals(4, count($this->_model->getOptions()));
+        $this->_model = $this->productRepository->get('simple_with_custom_options');
+        $options = $this->_model->getOptions();
+        $this->assertNotEmpty($options);
+        $expectedValue = [
+            '3-1-select' => 3000.00,
+            '3-2-select' => 5000.00,
+            '4-1-radio' => 600.234,
+            '4-2-radio' => 40000.00
+        ];
+        foreach ($options as $option) {
+            foreach ($option->getValues() as $value) {
+                $this->assertEquals($expectedValue[$value->getSku()], floatval($value->getPrice()));
+            }
+        }
     }
 }
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php
new file mode 100644
index 0000000000000000000000000000000000000000..0366e90cd9772036315678f6e3b10d1f59b615fb
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize();
+
+/** @var \Magento\TestFramework\ObjectManager $objectManager */
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+
+/** @var \Magento\Catalog\Api\CategoryLinkManagementInterface $categoryLinkManagement */
+$categoryLinkManagement = $objectManager->create(\Magento\Catalog\Api\CategoryLinkManagementInterface::class);
+
+/** @var $product \Magento\Catalog\Model\Product */
+$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
+$product->isObjectNew(true);
+$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)
+    ->setAttributeSetId(4)
+    ->setWebsiteIds([1])
+    ->setName('Simple Product')
+    ->setSku('simple_with_custom_options')
+    ->setPrice(10)
+    ->setWeight(1)
+    ->setShortDescription("Short description")
+    ->setTaxClassId(0)
+    ->setDescription('Description with <b>html tag</b>')
+    ->setMetaTitle('meta title')
+    ->setMetaKeyword('meta keyword')
+    ->setMetaDescription('meta description')
+    ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
+    ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
+    ->setStockData(
+        [
+            'use_config_manage_stock' => 1,
+            'qty' => 100,
+            'is_qty_decimal' => 0,
+            'is_in_stock' => 1,
+        ]
+    )->setCanSaveCustomOptions(true)
+    ->setHasOptions(true);
+
+$oldOptions = [
+    [
+        'previous_group' => 'select',
+        'title' => 'Test Select',
+        'type' => 'drop_down',
+        'is_require' => 1,
+        'sort_order' => 0,
+        'values' => [
+            [
+                'option_type_id' => -1,
+                'title' => 'Option 1',
+                'price' => '3,000.00',
+                'price_type' => 'fixed',
+                'sku' => '3-1-select',
+            ],
+            [
+                'option_type_id' => -1,
+                'title' => 'Option 2',
+                'price' => '5,000.00',
+                'price_type' => 'fixed',
+                'sku' => '3-2-select',
+            ],
+        ]
+    ],
+    [
+        'previous_group' => 'select',
+        'title' => 'Test Radio',
+        'type' => 'radio',
+        'is_require' => 1,
+        'sort_order' => 0,
+        'values' => [
+            [
+                'option_type_id' => -1,
+                'title' => 'Option 1',
+                'price' => '600.234',
+                'price_type' => 'fixed',
+                'sku' => '4-1-radio',
+            ],
+            [
+                'option_type_id' => -1,
+                'title' => 'Option 2',
+                'price' => '40,000.00',
+                'price_type' => 'fixed',
+                'sku' => '4-2-radio',
+            ],
+        ]
+    ]
+];
+
+$options = [];
+
+/** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory $customOptionFactory */
+$customOptionFactory = $objectManager->create(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class);
+
+foreach ($oldOptions as $option) {
+    /** @var \Magento\Catalog\Api\Data\ProductCustomOptionInterface $option */
+    $option = $customOptionFactory->create(['data' => $option]);
+    $option->setProductSku($product->getSku());
+
+    $options[] = $option;
+}
+
+$product->setOptions($options);
+
+/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepositoryFactory */
+$productRepositoryFactory = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+$productRepositoryFactory->save($product);
+
+$categoryLinkManagement->assignProductToCategories(
+    $product->getSku(),
+    [2]
+);
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..88e0fb198576060eb8295e633a985d9d6e3ff96a
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_with_custom_options_rollback.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+use Magento\Framework\Exception\NoSuchEntityException;
+
+\Magento\TestFramework\Helper\Bootstrap::getInstance()->getInstance()->reinitialize();
+
+/** @var \Magento\Framework\Registry $registry */
+$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class);
+
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', true);
+
+/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
+$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+    ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);
+try {
+    $product = $productRepository->get('simple_with_custom_options', false, null, true);
+    $productRepository->delete($product);
+} catch (NoSuchEntityException $e) {
+
+}
+$registry->unregister('isSecureArea');
+$registry->register('isSecureArea', false);
diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates.php
new file mode 100644
index 0000000000000000000000000000000000000000..5cac40809565e1ed28df9529446550975b39f9f3
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+$resource = $objectManager->get(\Magento\Framework\App\ResourceConnection::class);
+$connection = $resource->getConnection();
+$resourceModel = $objectManager->create(\Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate::class);
+$entityTable = $resourceModel->getTable('shipping_tablerate');
+$data =
+    [
+        'website_id' => 1,
+        'dest_country_id' => 'US',
+        'dest_region_id' => 0,
+        'dest_zip' => '*',
+        'condition_name' => 'package_qty',
+        'condition_value' => 1,
+        'price' => 10,
+        'cost' => 10
+    ];
+$connection->query(
+    "INSERT INTO {$entityTable} (`website_id`,  `dest_country_id`, `dest_region_id`, `dest_zip`, `condition_name`,"
+    . "`condition_value`, `price`, `cost`) VALUES (:website_id,  :dest_country_id, :dest_region_id, :dest_zip,"
+    . " :condition_name, :condition_value, :price, :cost);",
+    $data
+);
diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_rollback.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_rollback.php
new file mode 100644
index 0000000000000000000000000000000000000000..10f5563eee8aae9c826a8967e93658b59d9c2eca
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_rollback.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+$resource = $objectManager->get(\Magento\Framework\App\ResourceConnection::class);
+$connection = $resource->getConnection();
+$resourceModel = $objectManager->create(\Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate::class);
+$entityTable = $resourceModel->getTable('shipping_tablerate');
+$connection->query("DELETE FROM {$entityTable};");
diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ed966d0c9b998a23145bde4f2432019628a3c6f
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Quote/Model/ShippingMethodManagementTest.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Quote\Model;
+
+/**
+ * Class ShippingMethodManagementTest
+ */
+class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase
+{
+
+    /**
+     * @magentoAppIsolation enabled
+     * @magentoDbIsolation enabled
+     * @magentoConfigFixture current_store carriers/tablerate/active 1
+     * @magentoConfigFixture current_store carriers/tablerate/condition_name package_qty
+     * @magentoDataFixture Magento/SalesRule/_files/cart_rule_free_shipping.php
+     * @magentoDataFixture Magento/Sales/_files/quote.php
+     * @magentoDataFixture Magento/OfflineShipping/_files/tablerates.php
+     */
+    public function testEstimateByAddressWithCartPriceRule()
+    {
+        $this->executeTestFlow(0, 0);
+    }
+
+    /**
+     * @magentoAppIsolation enabled
+     * @magentoDbIsolation enabled
+     * @magentoConfigFixture current_store carriers/tablerate/active 1
+     * @magentoConfigFixture current_store carriers/tablerate/condition_name package_qty
+     * @magentoDataFixture Magento/Sales/_files/quote.php
+     * @magentoDataFixture Magento/OfflineShipping/_files/tablerates.php
+     */
+    public function testEstimateByAddress()
+    {
+        $this->executeTestFlow(5, 10);
+    }
+
+    /**
+     * Provide testing of shipping method estimation based on address
+     *
+     * @param int $flatRateAmount
+     * @param int $tableRateAmount
+     */
+    private function executeTestFlow($flatRateAmount, $tableRateAmount)
+    {
+        $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+        /** @var \Magento\Quote\Model\Quote $quote */
+        $quote = $objectManager->get(\Magento\Quote\Model\Quote::class);
+        $quote->load('test01', 'reserved_order_id');
+        $cartId = $quote->getId();
+        if (!$cartId) {
+            $this->fail('quote fixture failed');
+        }
+        /** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */
+        $quoteIdMask = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
+            ->create(\Magento\Quote\Model\QuoteIdMaskFactory::class)
+            ->create();
+        $quoteIdMask->load($cartId, 'quote_id');
+        //Use masked cart Id
+        $cartId = $quoteIdMask->getMaskedId();
+        $data = [
+            'data' => [
+                'country_id' => "US",
+                'postcode' => null,
+                'region' => null,
+                'region_id' => null
+            ]
+        ];
+        /** @var \Magento\Quote\Api\Data\EstimateAddressInterface $address */
+        $address = $objectManager->create(\Magento\Quote\Api\Data\EstimateAddressInterface::class, $data);
+        /** @var  \Magento\Quote\Api\GuestShippingMethodManagementInterface $shippingEstimation */
+        $shippingEstimation = $objectManager->get(\Magento\Quote\Api\GuestShippingMethodManagementInterface::class);
+        $result = $shippingEstimation->estimateByAddress($cartId, $address);
+        $this->assertNotEmpty($result);
+        $expectedResult = [
+            'tablerate' =>
+                [
+                    'method_code' => 'bestway',
+                    'amount' => $tableRateAmount
+                ],
+            'flatrate' => [
+                'method_code' => 'flatrate',
+                'amount' => $flatRateAmount
+            ]
+        ];
+        foreach ($result as $rate) {
+            $this->assertEquals($expectedResult[$rate->getCarrierCode()]['amount'], $rate->getAmount());
+            $this->assertEquals($expectedResult[$rate->getCarrierCode()]['method_code'], $rate->getMethodCode());
+        }
+    }
+}
diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt
index d58f71f3fbc9e1635f1c8f8ee529a9a5e73214a0..29b5280ec6693f70c8d65a1f40e25c644897ace1 100644
--- a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt
+++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt
@@ -41,13 +41,11 @@ app/code/Magento/Catalog/view/base/web/js/price-utils.js
 app/code/Magento/Catalog/view/base/web/js/tier-price.js
 app/code/Magento/Catalog/view/frontend/requirejs-config.js
 app/code/Magento/Catalog/view/frontend/web/js/catalog-add-to-cart.js
-app/code/Magento/Catalog/view/frontend/web/js/compare.js
 app/code/Magento/Catalog/view/frontend/web/js/gallery.js
 app/code/Magento/Catalog/view/frontend/web/js/list.js
 app/code/Magento/Catalog/view/frontend/web/js/product/list/toolbar.js
 app/code/Magento/Catalog/view/frontend/web/js/related-products.js
 app/code/Magento/Catalog/view/frontend/web/js/upsell-products.js
-app/code/Magento/Catalog/view/frontend/web/js/view/compare-products.js
 app/code/Magento/Catalog/view/frontend/web/js/view/image.js
 app/code/Magento/Catalog/view/frontend/web/js/zoom.js
 app/code/Magento/Catalog/view/frontend/web/product/view/validation.js
@@ -511,7 +509,6 @@ lib/web/mage/captcha.js
 lib/web/mage/collapsible.js
 lib/web/mage/common.js
 lib/web/mage/cookies.js
-lib/web/mage/dataPost.js
 lib/web/mage/decorate.js
 lib/web/mage/deletable-item.js
 lib/web/mage/dialog.js
@@ -603,13 +600,11 @@ vendor/magento/module-catalog/view/base/web/js/price-utils.js
 vendor/magento/module-catalog/view/base/web/js/tier-price.js
 vendor/magento/module-catalog/view/frontend/requirejs-config.js
 vendor/magento/module-catalog/view/frontend/web/js/catalog-add-to-cart.js
-vendor/magento/module-catalog/view/frontend/web/js/compare.js
 vendor/magento/module-catalog/view/frontend/web/js/gallery.js
 vendor/magento/module-catalog/view/frontend/web/js/list.js
 vendor/magento/module-catalog/view/frontend/web/js/product/list/toolbar.js
 vendor/magento/module-catalog/view/frontend/web/js/related-products.js
 vendor/magento/module-catalog/view/frontend/web/js/upsell-products.js
-vendor/magento/module-catalog/view/frontend/web/js/view/compare-products.js
 vendor/magento/module-catalog/view/frontend/web/js/view/image.js
 vendor/magento/module-catalog/view/frontend/web/js/zoom.js
 vendor/magento/module-catalog/view/frontend/web/product/view/validation.js
diff --git a/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php b/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php
index befff770156178dd2324e42365b62ac52414c9e8..ecfb67320cb0d58decdf67de64d2058814f1eaf8 100644
--- a/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php
+++ b/lib/internal/Magento/Framework/Interception/PluginList/PluginList.php
@@ -75,6 +75,11 @@ class PluginList extends Scoped implements InterceptionPluginList
      */
     protected $_pluginInstances = [];
 
+    /**
+     * @var \Psr\Log\LoggerInterface
+     */
+    private $logger;
+
     /**
      * @param ReaderInterface $reader
      * @param ScopeInterface $configScope
@@ -149,6 +154,7 @@ class PluginList extends Scoped implements InterceptionPluginList
             }
             $this->_inherited[$type] = null;
             if (is_array($plugins) && count($plugins)) {
+                $this->filterPlugins($plugins);
                 uasort($plugins, [$this, '_sort']);
                 $this->trimInstanceStartingBackslash($plugins);
                 $this->_inherited[$type] = $plugins;
@@ -348,4 +354,34 @@ class PluginList extends Scoped implements InterceptionPluginList
             }
         }
     }
+
+    /**
+     * Remove from list not existing plugins
+     *
+     * @param array $plugins
+     * @return void
+     */
+    private function filterPlugins(array &$plugins)
+    {
+        foreach ($plugins as $name => $plugin) {
+            if (empty($plugin['instance'])) {
+                unset($plugins[$name]);
+                $this->getLogger()->info("Reference to undeclared plugin with name '{$name}'.");
+            }
+        }
+    }
+
+    /**
+     * Returns logger instance
+     *
+     * @deprecated
+     * @return \Psr\Log\LoggerInterface
+     */
+    private function getLogger()
+    {
+        if ($this->logger === null) {
+            $this->logger = $this->_objectManager->get(\Psr\Log\LoggerInterface::class);
+        }
+        return $this->logger;
+    }
 }
diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php
index 1291ae44bce6522bf61f1bdbc42c3089a09abd48..b3fe011a0a490727c0682f1863aa731622753264 100644
--- a/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php
+++ b/lib/internal/Magento/Framework/Interception/Test/Unit/PluginList/PluginListTest.php
@@ -60,7 +60,6 @@ class PluginListTest extends \PHPUnit_Framework_TestCase
         $omConfigMock->expects($this->any())->method('getOriginalInstanceType')->will($this->returnArgument(0));
 
         $this->_objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class);
-        $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0));
 
         $definitions = new \Magento\Framework\ObjectManager\Definition\Runtime();
 
@@ -80,6 +79,7 @@ class PluginListTest extends \PHPUnit_Framework_TestCase
 
     public function testGetPlugin()
     {
+        $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0));
         $this->_configScopeMock->expects($this->any())->method('getCurrentScope')->will($this->returnValue('backend'));
         $this->_model->getNext(\Magento\Framework\Interception\Test\Unit\Custom\Module\Model\Item::class, 'getName');
         $this->_model->getNext(
@@ -131,6 +131,7 @@ class PluginListTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetPlugins($expectedResult, $type, $method, $scopeCode, $code = '__self')
     {
+        $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0));
         $this->_configScopeMock->expects(
             $this->any()
         )->method(
@@ -206,6 +207,7 @@ class PluginListTest extends \PHPUnit_Framework_TestCase
      */
     public function testInheritPluginsWithNonExistingClass()
     {
+        $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0));
         $this->_configScopeMock->expects($this->any())
             ->method('getCurrentScope')
             ->will($this->returnValue('frontend'));
@@ -213,12 +215,34 @@ class PluginListTest extends \PHPUnit_Framework_TestCase
         $this->_model->getNext('SomeType', 'someMethod');
     }
 
+    /**
+     * @covers \Magento\Framework\Interception\PluginList\PluginList::getNext
+     * @covers \Magento\Framework\Interception\PluginList\PluginList::_inheritPlugins
+     */
+    public function testInheritPluginsWithNotExistingPlugin()
+    {
+        $loggerMock = $this->getMock(\Psr\Log\LoggerInterface::class);
+        $this->_objectManagerMock->expects($this->once())
+            ->method('get')
+            ->with(\Psr\Log\LoggerInterface::class)
+            ->willReturn($loggerMock);
+        $loggerMock->expects($this->once())
+            ->method('info')
+            ->with("Reference to undeclared plugin with name 'simple_plugin'.");
+        $this->_configScopeMock->expects($this->any())
+            ->method('getCurrentScope')
+            ->will($this->returnValue('frontend'));
+
+        $this->assertNull($this->_model->getNext('typeWithoutInstance', 'someMethod'));
+    }
+
     /**
      * @covers \Magento\Framework\Interception\PluginList\PluginList::getNext
      * @covers \Magento\Framework\Interception\PluginList\PluginList::_loadScopedData
      */
     public function testLoadScopedDataCached()
     {
+        $this->_objectManagerMock->expects($this->any())->method('get')->will($this->returnArgument(0));
         $this->_configScopeMock->expects($this->once())
             ->method('getCurrentScope')
             ->will($this->returnValue('scope'));
diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/_files/reader_mock_map.php b/lib/internal/Magento/Framework/Interception/Test/Unit/_files/reader_mock_map.php
index 832a5a67599da7f9dbfe46e2732324b536f267c8..87bbe0d35dd2561799cd5d2024347c8fb48c2b73 100644
--- a/lib/internal/Magento/Framework/Interception/Test/Unit/_files/reader_mock_map.php
+++ b/lib/internal/Magento/Framework/Interception/Test/Unit/_files/reader_mock_map.php
@@ -70,6 +70,11 @@ return [
                         'instance' => 'NonExistingPluginClass',
                     ],
                 ],
+            ],
+            'typeWithoutInstance' => [
+                'plugins' => [
+                    'simple_plugin' => [],
+                ],
             ]
         ]
     ]
diff --git a/lib/web/mage/dataPost.js b/lib/web/mage/dataPost.js
index e1c297ffcef4b9a6a3d64806d5f93eb57e938644..2d47929f57213c338c5b121310c544b3876331ec 100644
--- a/lib/web/mage/dataPost.js
+++ b/lib/web/mage/dataPost.js
@@ -2,50 +2,88 @@
  * Copyright © 2016 Magento. All rights reserved.
  * See COPYING.txt for license details.
  */
-/*jshint browser:true jquery:true*/
-/*global confirm:true*/
+
 define([
-    "jquery",
-    "mage/template",
-    "jquery/ui"
-], function($,mageTemplate){
-    
+    'jquery',
+    'mage/template',
+    'Magento_Ui/js/modal/confirm',
+    'jquery/ui'
+], function ($, mageTemplate, uiConfirm) {
+    'use strict';
+
     $.widget('mage.dataPost', {
         options: {
-            formTemplate: '<form action="<%- data.action %>" method="post">'
-                + '<% _.each(data.data, function(value, index) { %>'
-                    + '<input name="<%- index %>" value="<%- value %>">'
-                + '<% }) %></form>',
+            formTemplate: '<form action="<%- data.action %>" method="post">' +
+            '<% _.each(data.data, function(value, index) { %>' +
+            '<input name="<%- index %>" value="<%- value %>">' +
+            '<% }) %></form>',
             postTrigger: ['a[data-post]', 'button[data-post]', 'span[data-post]'],
             formKeyInputSelector: 'input[name="form_key"]'
         },
-        _create: function() {
+
+        /** @inheritdoc */
+        _create: function () {
             this._bind();
         },
-        _bind: function() {
+
+        /** @inheritdoc */
+        _bind: function () {
             var events = {};
-            $.each(this.options.postTrigger, function(index, value) {
+
+            $.each(this.options.postTrigger, function (index, value) {
                 events['click ' + value] = '_postDataAction';
             });
+
             this._on(events);
         },
-        _postDataAction: function(e) {
-            e.preventDefault();
+
+        /**
+         * Handler for click.
+         *
+         * @param {Object} e
+         * @private
+         */
+        _postDataAction: function (e) {
             var params = $(e.currentTarget).data('post');
+
+            e.preventDefault();
             this.postData(params);
         },
-        postData: function(params) {
-            var formKey = $(this.options.formKeyInputSelector).val();
+
+        /**
+         * Data post action.
+         *
+         * @param {Object} params
+         */
+        postData: function (params) {
+            var formKey = $(this.options.formKeyInputSelector).val(),
+                $form;
+
             if (formKey) {
-                params.data.form_key = formKey;
+                params.data['form_key'] = formKey;
             }
-            $(mageTemplate(this.options.formTemplate, {
+
+            $form = $(mageTemplate(this.options.formTemplate, {
                 data: params
-            })).appendTo('body').hide().submit();
+            }));
+
+            if (params.data.confirmation) {
+                uiConfirm({
+                    content: params.data.confirmationMessage,
+                    actions: {
+                        /** @inheritdoc */
+                        confirm: function () {
+                            $form.appendTo('body').hide().submit();
+                        }
+                    }
+                });
+            } else {
+                $form.appendTo('body').hide().submit();
+            }
         }
     });
-    
+
     $(document).dataPost();
 
     return $.mage.dataPost;
-});
\ No newline at end of file
+});