Skip to content

Commit

Permalink
fix(table): use stable sort algorithm to prevent SSR issues (#1399)
Browse files Browse the repository at this point in the history
* Create stable-sort.js

* add stable sort to utils

* [b-table] use stableSort
  • Loading branch information
tmorehouse authored and pi0 committed Nov 29, 2017
1 parent 4ccd6cc commit 21b33f2
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/components/table/table.vue
Expand Up @@ -62,7 +62,7 @@
</style>

<script>
import { warn, looseEqual, KeyCodes } from '../../utils'
import { warn, looseEqual, stableSort, KeyCodes } from '../../utils'
import { keys, assign } from '../../utils/object'
import { isArray, concat } from '../../utils/array'
import { listenOnRootMixin } from '../../mixins'
Expand Down Expand Up @@ -712,7 +712,7 @@
}
// Apply local Sort
if (sortBy && localSorting) {
items = items.sort(function sortItemsFn(a, b) {
items = stableSort(items, function sortItemsFn(a, b) {
let ret = null
if (typeof sortCompare === 'function') {
// Call user provided sortCompare routine
Expand Down
2 changes: 2 additions & 0 deletions src/utils/index.js
Expand Up @@ -13,6 +13,7 @@ import observeDom from './observe-dom'
import pluckProps from './pluckProps'
import prefixPropName from './prefixPropName'
import { registerComponent, registerComponents, registerDirective, registerDirectives, vueUse } from './plugins'
import stableSort from './stable-sort'
import suffixPropName from './suffixPropName'
import unPrefixPropName from './unPrefixPropName'
import upperFirst from './upperFirst'
Expand All @@ -37,6 +38,7 @@ export {
registerComponents,
registerDirective,
registerDirectives,
stableSort,
suffixPropName,
upperFirst,
unPrefixPropName,
Expand Down
28 changes: 28 additions & 0 deletions src/utils/stable-sort.js
@@ -0,0 +1,28 @@
/*
* Consitant and stable sort function across JavsaScript platforms
*
* Inconsistant sorts can cause SSR problems between client and server
* such as in <b-table> if sortBy is applied to the data on server side render.
* Chrome and V8 native sorts are inconsistant/unstable
*
* This function uses native sort with fallback to index compare when the a and b
* compare returns 0
*
* Algorithm bsaed on:
* https://stackoverflow.com/questions/1427608/fast-stable-sorting-algorithm-implementation-in-javascript/45422645#45422645
*
* @param {array} array to sort
* @param {function} sortcompare function
* @return {array}
*/

export default function stableSort (array, compareFn) {
// Using `.bind(compareFn)` on the wrapped anonymous function improves
// performance by avoiding the function call setup. We don't use an arrow
// function here as it binds `this` to the `stableSort` context rather than
// the `compareFn` context, which wouldn't give us the performance increase.
return array
.map((a, index) => [ index, a ])
.sort(function (a, b) { return this(a[1], b[1]) || a[0] - b[0] }.bind(compareFn))
.map(e => e[1])
}

0 comments on commit 21b33f2

Please sign in to comment.