Description
Given the following generated HTML, an alert will occur. If you click OK, it will perform an action on a backing bean. However, if you cancel, it should not.
<input type="submit" value="Test" onclick="return faces.util.chain(this, event,function(event){return confirm('Please Confirm');});">
On Faces 3.0, if cancel is pressed, then the backing bean is not invoked. On Faces 4.0, however, pressing cancel does invoke the bean.
Faces 3.0:
jsf.util.chain snippet:
if (FUNC == typeof arguments[cnt]) { ret = arguments[cnt].call(source, event); } else { //either a function or a string can be passed in case of a string we have to wrap it into another function ret = new Function("event", arguments[cnt]).call(source, event); } //now if one function returns false in between we stop the execution of the cycle //here, note we do a strong comparison here to avoid constructs like 'false' or null triggering if (ret === false /*undefined check implicitly done here by using a strong compare*/) { return false; } }
Faces 4.0:
function chain(source, event, ...funcs) { // we can use our lazy stream each functionality to run our chain here. // by passing a boolean as return value into the onElem call // we can stop early at the first false, just like the spec requests let ret; funcs.every(func => { let returnVal = resolveAndExecute(source, event, func); if (returnVal !== false) { ret = returnVal; } return returnVal !== false; }); return ret; }
It looks like conditions changed here? "ret === false" became "returnVal !== false" ? If cancel is pressed, false is returned, which means the chain function returns false in 3.0. In faces 4.0, ret is never set (due to the new condition), so undefined (ret) is returned now instead.