function scrollArray( elem, left, top ) {
	directionCheck( left, top );

	if ( options.accelerationMax !== 1 ) {
		const now = window.performance.now();
		const elapsed = now - lastScroll;
		if ( elapsed < options.accelerationDelta ) {
			let factor = ( 1 + ( 30 / elapsed ) ) / 2;
			if ( factor > 1 ) {
				factor = Math.min( factor, options.accelerationMax );
				left *= factor;
				top  *= factor;
			}
		}
		lastScroll = window.performance.now();
	}

	// push a scroll command
	queue.push({
		x    : left,
		y    : top,
		lastX: left < 0 ? 0.99 : -0.99,
		lastY: top  < 0 ? 0.99 : -0.99,
		start: window.performance.now()
	});

	// don't act if there's a pending queue
	if ( pending ) {
		return;
	}

	const scrollWindow = elem === document.body;

	function step( now ) {
		let scrollX = 0;
		let scrollY = 0;

		for ( let i = 0; i < queue.length; i++ ) {
			const item = queue[ i ];
			const elapsed = now - item.start;
			const finished = elapsed >= options.animationTime;

			// scroll position: [0, 1]
			let position = finished
				? 1
				: elapsed / options.animationTime;

			// easing [optional]
			if ( options.pulseAlgorithm ) {
				position = pulse( position );
			}

			// only need the difference
			const x = ( item.x * position - item.lastX ) >> 0;
			const y = ( item.y * position - item.lastY ) >> 0;

			// add this to the total scrolling
			scrollX += x;
			scrollY += y;

			// update last values
			item.lastX += x;
			item.lastY += y;

			// delete and step back if it's over
			if ( finished ) {
				queue.splice( i, 1 );
				i--;
			}
		}

		// scroll left and top
		if ( scrollWindow ) {
			window.scrollBy( scrollX, scrollY );

		} else if ( elem ) {
			if ( scrollX ) { elem.scrollLeft += scrollX; }
			if ( scrollY ) { elem.scrollTop  += scrollY; }
		}

		// clean up if there's nothing left to do
		if ( !left && !top ) {
			queue = [];
		}

		if ( queue.length ) {
			requestAnimationFrame( step );
		} else {
			pending = false;
		}
	}

	// start a new queue of actions
	requestAnimationFrame( step );
	pending = true;
}
Pushes scroll actions to the scrolling queue.