I am currently going over the WebRTC tutorial on their docs when I noticed that they use forEach after their usage of map(). In order to use forEach and expect a value instead of undefined array, map() would have needed to return an array, which I don't see how it can, because it doesn't return anything.
function updateCameraList(cameras) {
const listElement = document.querySelector('select#availableCameras');
listElement.innerHTML = '';
cameras.map(camera => {
const cameraOption = document.createElement('option');
cameraOption.label = camera.label;
cameraOption.value = camera.deviceId;
}).forEach(cameraOption => listElement.add(cameraOption));
}
The code will not work since the map returns nothing.
Here is an alternative method
function updateCameraList(cameras) {
document.getElementById('availableCameras').innerHTML = cameras
.map(({label, deviceId}) => `<option value="${deviceId}">${label}</option>`)
.join("");
}
I learned today that we now can use label instead of text
https://jsfiddle.net/mplungjan/osyLzqk2/
Here is a safer version since there is a tiny possibility for XSS
function updateCameraList(cameras) {
const sel = document.getElementById('availableCameras')
cameras.forEach(({label, deviceId}) => {
const option = new Option(label,deviceId);
sel.add(option)
})
}
And here is a non working attempt of XSS - at least it does nothing in Chrome
const cameras = [{ deviceId : `xss"></option></select><img src="x" onerror="alert(1)" />` , label:"bla" }]
function updateCameraList(cameras) {
const xssString = cameras
.map(({label, deviceId}) => `<option value="${deviceId}">${label}</option>`)
.join("")
console.log(xssString)
document.getElementById('availableCameras').innerHTML = xssString;
}
updateCameraList(cameras)
<select id="availableCameras"></select>