Esanders has uploaded a new change for review.
https://gerrit.wikimedia.org/r/203054
Change subject: Test splice polyfill
......................................................................
Test splice polyfill
Requires us to check for browser test result on each call so
it can be overridden. Cache the browser test result to this
isn't an expensive overhead.
Change-Id: I15f9e2fa88fc53d8af40bd76228e77a53cdf7672
---
M src/ve.utils.js
M tests/ve.test.js
2 files changed, 104 insertions(+), 86 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor
refs/changes/54/203054/1
diff --git a/src/ve.utils.js b/src/ve.utils.js
index fe1380a..f655780 100644
--- a/src/ve.utils.js
+++ b/src/ve.utils.js
@@ -173,6 +173,30 @@
*/
ve.extendObject = $.extend;
+ve.spliceBroken = ( function () {
+ var a, n;
+
+ // This returns true in Safari 8
+ a = new Array( 100000 );
+ a.splice( 30, 0, 'x' );
+ a.splice( 20, 1 );
+ if ( a.indexOf( 'x' ) !== 29 ) {
+ return true;
+ }
+
+ // This returns true in Opera 12.15
+ a = [];
+ n = 256;
+ a[n] = 'a';
+ a.splice( n + 1, 0, 'b' );
+ if ( a[n] !== 'a' ) {
+ return true;
+ }
+
+ // Splice isn't broken
+ return false;
+} )();
+
/**
* Splice one array into another.
*
@@ -183,7 +207,7 @@
* performance tests should be conducted on each use of this method to verify
this is true for the
* particular use. Also, browsers change fast, never assume anything, always
test everything.
*
- * Includes a replacement for broken implementation of
Array.prototype.splice() found in Opera 12.
+ * Includes a replacement for broken implementations of
Array.prototype.splice().
*
* @param {Array|ve.dm.BranchNode} arr Target object (must have `splice`
method, object will be modified)
* @param {number} offset Offset in arr to splice at. This may NOT be
negative, unlike the
@@ -192,80 +216,61 @@
* @param {Array} data Array of items to insert at the offset. Must be
non-empty if remove=0
* @return {Array} Array of items removed
*/
-ve.batchSplice = ( function () {
- var arraySplice;
+ve.batchSplice = function ( arr, offset, remove, data ) {
+ // We need to splice insertion in in batches, because of parameter list
length limits which vary
+ // cross-browser - 1024 seems to be a safe batch size on all browsers
+ var splice, spliced,
+ index = 0,
+ batchSize = 1024,
+ toRemove = remove,
+ removed = [];
- // This returns true in Opera 12.15
- function spliceBrokenOpera() {
- var n = 256,
- a = [];
- a[n] = 'a';
- a.splice( n + 1, 0, 'b' );
- return a[n] !== 'a';
- }
-
- // This returns true in Safari 8
- function spliceBrokenSafari() {
- var a = new Array( 100000 );
- a.splice( 30, 0, 'x' );
- a.splice( 20, 1 );
- return a.indexOf( 'x' ) !== 29;
- }
-
- if ( !spliceBrokenOpera() && !spliceBrokenSafari() ) {
- arraySplice = Array.prototype.splice;
+ if ( !Array.isArray( arr ) ) {
+ splice = arr.splice;
} else {
- // Standard Array.prototype.splice() function implemented using
.slice() and .push().
- arraySplice = function ( offset, remove/*, data... */ ) {
- var data, begin, removed, end;
+ if ( !ve.spliceBroken ) {
+ splice = Array.prototype.splice;
+ } else {
+ // Standard Array.prototype.splice() function
implemented using .slice() and .push().
+ splice = function ( offset, remove/*, data... */ ) {
+ var data, begin, removed, end;
- data = Array.prototype.slice.call( arguments, 2 );
+ data = Array.prototype.slice.call( arguments, 2
);
- begin = this.slice( 0, offset );
- removed = this.slice( offset, remove );
- end = this.slice( offset + remove );
+ begin = this.slice( 0, offset );
+ removed = this.slice( offset, remove );
+ end = this.slice( offset + remove );
- this.length = 0;
- ve.batchPush( this, begin );
- ve.batchPush( this, data );
- ve.batchPush( this, end );
+ this.length = 0;
+ ve.batchPush( this, begin );
+ ve.batchPush( this, data );
+ ve.batchPush( this, end );
- return removed;
- };
+ return removed;
+ };
+ }
}
- return function ( arr, offset, remove, data ) {
- // We need to splice insertion in in batches, because of
parameter list length limits which vary
- // cross-browser - 1024 seems to be a safe batch size on all
browsers
- var splice, spliced,
- index = 0,
- batchSize = 1024,
- toRemove = remove,
- removed = [];
+ if ( data.length === 0 ) {
+ // Special case: data is empty, so we're just doing a removal
+ // The code below won't handle that properly, so we do it here
+ return splice.call( arr, offset, remove );
+ }
- splice = Array.isArray( arr ) ? arraySplice : arr.splice;
-
- if ( data.length === 0 ) {
- // Special case: data is empty, so we're just doing a
removal
- // The code below won't handle that properly, so we do
it here
- return splice.call( arr, offset, remove );
+ while ( index < data.length ) {
+ // Call arr.splice( offset, remove, i0, i1, i2, ..., i1023 );
+ // Only set remove on the first call, and set it to zero on
subsequent calls
+ spliced = splice.apply(
+ arr, [index + offset, toRemove].concat( data.slice(
index, index + batchSize ) )
+ );
+ if ( toRemove > 0 ) {
+ removed = spliced;
}
-
- while ( index < data.length ) {
- // Call arr.splice( offset, remove, i0, i1, i2, ...,
i1023 );
- // Only set remove on the first call, and set it to
zero on subsequent calls
- spliced = splice.apply(
- arr, [index + offset, toRemove].concat(
data.slice( index, index + batchSize ) )
- );
- if ( toRemove > 0 ) {
- removed = spliced;
- }
- index += batchSize;
- toRemove = 0;
- }
- return removed;
- };
-}() );
+ index += batchSize;
+ toRemove = 0;
+ }
+ return removed;
+};
/**
* Insert one array into another.
diff --git a/tests/ve.test.js b/tests/ve.test.js
index c125515..648fee5 100644
--- a/tests/ve.test.js
+++ b/tests/ve.test.js
@@ -266,35 +266,48 @@
);
} );
-QUnit.test( 'batchSplice', 8, function ( assert ) {
- var actualRet, expectedRet, i,
+QUnit.test( 'batchSplice', function ( assert ) {
+ var actualRet, expectedRet, i, n, msg,
+ spliceWasBroken = ve.spliceBroken,
actual = [ 'a', 'b', 'c', 'd', 'e' ],
expected = actual.slice( 0 ),
bigArr = [];
- actualRet = ve.batchSplice( actual, 1, 1, [] );
- expectedRet = expected.splice( 1, 1 );
- assert.deepEqual( expectedRet, actualRet, 'removing 1 element (return
value)' );
- assert.deepEqual( expected, actual, 'removing 1 element (array)' );
+ QUnit.expect( 8 * ( spliceWasBroken ? 1 : 2 ) );
- actualRet = ve.batchSplice( actual, 3, 2, [ 'w', 'x', 'y', 'z' ] );
- expectedRet = expected.splice( 3, 2, 'w', 'x', 'y', 'z' );
- assert.deepEqual( expectedRet, actualRet, 'replacing 2 elements with 4
elements (return value)' );
- assert.deepEqual( expected, actual, 'replacing 2 elements with 4
elements (array)' );
+ for ( n = 0; n < ( spliceWasBroken ? 1 : 2 ); n++ ) {
+ if ( !spliceWasBroken && n === 1 ) {
+ ve.spliceBroken = true;
+ }
- actualRet = ve.batchSplice( actual, 0, 0, [ 'f', 'o', 'o' ] );
- expectedRet = expected.splice( 0, 0, 'f', 'o', 'o' );
- assert.deepEqual( expectedRet, actualRet, 'inserting 3 elements (return
value)' );
- assert.deepEqual( expected, actual, 'inserting 3 elements (array)' );
+ msg = ve.spliceBroken ? 'slice/push' : 'native splice';
- for ( i = 0; i < 2100; i++ ) {
- bigArr[i] = i;
+ actualRet = ve.batchSplice( actual, 1, 1, [] );
+ expectedRet = expected.splice( 1, 1 );
+ assert.deepEqual( expectedRet, actualRet, msg + ': removing 1
element (return value)' );
+ assert.deepEqual( expected, actual, msg + ': removing 1 element
(array)' );
+
+ actualRet = ve.batchSplice( actual, 3, 2, [ 'w', 'x', 'y', 'z'
] );
+ expectedRet = expected.splice( 3, 2, 'w', 'x', 'y', 'z' );
+ assert.deepEqual( expectedRet, actualRet, msg + ': replacing 2
elements with 4 elements (return value)' );
+ assert.deepEqual( expected, actual, msg + ': replacing 2
elements with 4 elements (array)' );
+
+ actualRet = ve.batchSplice( actual, 0, 0, [ 'f', 'o', 'o' ] );
+ expectedRet = expected.splice( 0, 0, 'f', 'o', 'o' );
+ assert.deepEqual( expectedRet, actualRet, msg + ': inserting 3
elements (return value)' );
+ assert.deepEqual( expected, actual, msg + ': inserting 3
elements (array)' );
+
+ for ( i = 0; i < 2100; i++ ) {
+ bigArr[i] = i;
+ }
+ actualRet = ve.batchSplice( actual, 2, 3, bigArr );
+ expectedRet = expected.splice.apply( expected, [2, 3].concat(
bigArr.slice( 0, 1050 ) ) );
+ expected.splice.apply( expected, [1052, 0].concat(
bigArr.slice( 1050 ) ) );
+ assert.deepEqual( expectedRet, actualRet, msg + ': replacing 3
elements with 2100 elements (return value)' );
+ assert.deepEqual( expected, actual, msg + ': replacing 3
elements with 2100 elements (array)' );
}
- actualRet = ve.batchSplice( actual, 2, 3, bigArr );
- expectedRet = expected.splice.apply( expected, [2, 3].concat(
bigArr.slice( 0, 1050 ) ) );
- expected.splice.apply( expected, [1052, 0].concat( bigArr.slice( 1050 )
) );
- assert.deepEqual( expectedRet, actualRet, 'replacing 3 elements with
2100 elements (return value)' );
- assert.deepEqual( expected, actual, 'replacing 3 elements with 2100
elements (array)' );
+
+ ve.spliceBroken = spliceWasBroken;
} );
QUnit.test( 'insertIntoArray', 3, function ( assert ) {
--
To view, visit https://gerrit.wikimedia.org/r/203054
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I15f9e2fa88fc53d8af40bd76228e77a53cdf7672
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits