DamonOehlman / detect-browser

Unpack a browser type and version from the useragent string

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

.fill is not defined in IE

wikiwong opened this issue · comments

commented

Hi just FYI, a54dc0f#diff-480465dfe1db7da61cf594d184bfe7b4R26

.fill is not defined in IE, throwing a JS error. It may need a polyfill

commented

It's generally bad practice to alter an array's length manually (as this lib does with version.length = 3).

Is there any case in which the following wouldn't work?

if (version.length < 3) {
  Array.prototype.push.apply(version, (version.length == 1) ? [0, 0] : [0]);
}
commented

Fixed with: #27


Until it's merged you can install with:

$ npm i --save DamonOehlman/detect-browser#pull/27/head
commented

Thanks @adamellsworth .

I think the original logic is a bit confusing.

if (version.length < 3) {
   version.length = 3;
   version.fill(0, 2);
}

The .fill function will fill in 0s from the 2nd index of the array, which works if the array is of length 2, but if it's of length 1, the 2nd element in the array will be undefined.

@adamellsworth I think your PR makes sense, but it assumes that versions is not an empty array (which may be a valid assumption, I'm not sure). If it is an empty array, versions will be [0], and not the intended 3 item array.

From your PR:

Array.prototype.push.apply(version, (version.length == 1) ? [0, 0] : [0]);

If we know versions will never be empty, or it doesn't really matter if it's a 3 item array, this is perfectly fine. If not, I think we need a bit more logic. Here's a crude example of filling an array recursively in a cross browser manner:

function fillTo(theArray, capacity, content) {
	if (theArray.length === capacity) {
		return theArray;
	}
	theArray.push(content);
	return fillTo(theArray, capacity, content);
}

var version = [1];
fillTo(version, 3, 0);
// outputs [1, 0, 0]

Bringing in @baribadamshin as his PR introduced the .fill logic. I'm sure there is a way we can achieve something similar without the fill (using .concat or plain old .push for example). I definitely think @baribadamshin's PR moved things in the right direction, we should be able to iron this one out pretty quickly.

I'll try to keep monitoring this issue so we can get it resolved quickly. On holidays at the moment so might be a bit more async than normal.

What about in that particular case we should revert to the original logic of:

while (version && version.length < 3) {
  version.push(0);
}

NB: The only reason the (version && ...) check is required is if I ever to do decide to use flow (https://flowtype.org) for this package that will be required to ensure everything typechecks.

Thoughts?

I think cycle or recursion it's overhead.

How about this?
version.concat([0, 0]).slice(0, 3)

if we have 1 element in version, we just fill empty numbers, in other case we cut excess.
[1] -> [1, 0, 0]
[1, 0] -> [1, 0, 0]

commented

https://jsperf.com/fill-alternate-tests-2

Not sure if I'm setting these up correctly, but if so the push.apply is the quickest alternative.

for those who can't run jsperf in their browsers


That being said, @DamonOehlman is right in that it may be undefined/null.

if (version && version.length < 3) { //...

// Also, it's pretty safe to utilize 'isArray' (ecma5) if preferred
if (version && Array.isArray(version) && version.length < 3) { //...

Edit: PR Updated

Cool, folks thanks for the update. Apologies for being offline for a bit. I'm going to merge this and publish the update as 1.6.1 (removing the package.json update) and manually update using the npm version command which I tend to find is the best approach for this kind of thing, just prior to a publish :)

@adamellsworth Actually I'm not sure I can do that (or it feels to impolite), I'll just merge it in as is - thanks.

Merged and published as 1.6.2.