Reputation: 1399
I am initializing a new array from a mappable function:
let data = Array.from(Array(20).keys(), new_datum);
It gets webpack'd (v 3.5.5) to:
var data = Array.from(Array(20).keys(), new_datum);
For completeness, here's that function, though I doubt it's relevant:
function new_datum() {
return {
name: Math.floor((Date.now() - START_TIME) / 1000),
Temperature: Math.random() * 100
}
}
This works fine in my Chrome browser on desktop. However, when using Cordova (v 7.1.0) and Android (26) to compile this to an SDK and run on my phone (kitkat 4.4.4, Chrome 56.0.2924.87), I get the following:
Uncaught TypeError: Object [object Array] has no method 'keys'
My intuition is, "something something ECMA6", because the Array.keys() method is pretty new, but since I am still pretty green with JS, I am stumped.
Edit: Additionally, looking at the App's userAgent:
5.0 (Linux; Android 4.4.4; XT1080 Build/SU6-7.7) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Mobile Safari/537.36
I see that Cordova is using Chrome 33 for some bizarre reason. That's likely the problem.
Addendum:
Since I confirmed the Cordova app is indeed using Chrome 33, this is likely the reason why Array methods do not work properly.
It looks like there are some limitations with respect to WebView and hence Cordova chrome version. There are workarounds, but I suspect the easiest approach is just tooling the app for Chrome 33.
Upvotes: 1
Views: 433
Reputation: 11721
Cordova is not using any specific version of chrome and may not even be using chrome at all.
Let me explain : what cordova does is that it uses the Webview component to bundle your html into a native application.
For Android, depending on the device you're using, the engine of the webview component is different. It may be based on the old android browser, the device manufacturer's browser or for device using android newer than 4.4 chrome. And for most devices, the webview can't be updated.
So the app behaviour is different for each device : html5 support, css support, strict mode, js version, wether or not you need to configure Content-Security-Policy...
You may have surprises with cordova each time a user uses your app on a new device.
You have to use javascript / css /html supported by the oldest platform version you target (for that you can refer to canIuse) and at the same time conform with the newest requirements (like Content Security Policy that is mandatory starting android 4.4).
Starting with Android 5.0 the webview (based on chrome) is in an apk and is updatable, so cordova apps runing on android 5 devices will be able to use up to date html5 features.
If you want to be sure that your app will behave the same way on all devices (except for screen size), I think the best choice for the moment is to use Crosswalk.
Crosswalk is a webview based on latest versions of Chromium.
If you add the Crosswalk Cordova plugin to your app, cordova will use the crosswalk engine instead of the system webview so your app will use the same engine on all devices and you have no more surprise with a javascript line working on a device but not on an other.
The only drawback of using Crosswalk is that you embed the Chromium engine in your apk, wich makes it much bigger (+17Mb for the apk and +50Mb on the device once the app installed).
Edit: sad to hear about the EOL of official Crosswalk project. Version 2.3 works perfectly in the Cordova plugin, hope someone will update it in the future.
Upvotes: 1
Reputation: 1074495
You're correct that the error is telling you that the platform you're running that code on uses a JavaScript engine which doesn't supply Array.prototype.keys
, which is new as of ES2015 (so, not really all that new). Chrome's had it since well before v56, so the environment you're running that code in is not Chrome 56. I think you're probably right that your code is being run by Chrome 33 instead.
Your only choices are to upgrade the platform or not use Array.prototype.keys
in your code. If you go the latter route, I'd be leery of many of the other new things from ES2015.
As Andy points out, there's no reason to use Array#keys
there anyway. Just
let data = Array.from(Array(20), new_datum);
or
let data = Array.from({length:20}, new_datum);
is sufficient (provided the platform supports let
and Array.from
).
Upvotes: 1