[ https://issues.apache.org/jira/browse/MYFACES-4658?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17833828#comment-17833828 ]
Werner Punz edited comment on MYFACES-4658 at 4/4/24 6:14 AM: -------------------------------------------------------------- Ok the discrepancy is indeed in the undefined handling, the spec states either Here is the spec on this issue: A varargs function that invokes an arbitrary number of scripts. If any script in the chain returns false, the chain is short-circuited and subsequent scripts are not invoked. Any number of scripts may specified after the {{event}} argument. boolean {{false}} if any scripts in the chain return {{{}false{}}}, otherwise returns {{true}} So the old code is correct the new code is wrong here! I will make a fix for it including a test! This test exposes the issue: {code:java} // code placeholder it("chain must handle the true false return values correctly", function () { let func1 = () => { return true; } let func2 = () => { return false; } let func3 = () => { return undefined; } let func4 = () => { return null; } let ret = faces.util.chain(this, {}, func1); expect(ret).to.be.true; ret = faces.util.chain(this, {}, func2); expect(ret).to.be.false; ret = faces.util.chain(this, {}, func3); expect(ret).to.be.true; ret = faces.util.chain(this, {}, func4); expect(ret).to.be.true; }) {code} was (Author: werpu): Ok the discrepancy is indeed in the undefined handling, the spec states either Here is the spec on this issue: A varargs function that invokes an arbitrary number of scripts. If any script in the chain returns false, the chain is short-circuited and subsequent scripts are not invoked. Any number of scripts may specified after the {{event}} argument. boolean {{false}} if any scripts in the chain return {{{}false{}}}, otherwise returns {{true}} {{}} So the old code is correct the new code is wrong here! I will make a fix for it including a test! This test exposes the issue: {code:java} // code placeholder it("chain must handle the true false return values correctly", function () { let func1 = () => { return true; } let func2 = () => { return false; } let func3 = () => { return undefined; } let func4 = () => { return null; } let ret = faces.util.chain(this, {}, func1); expect(ret).to.be.true; ret = faces.util.chain(this, {}, func2); expect(ret).to.be.false; ret = faces.util.chain(this, {}, func3); expect(ret).to.be.true; ret = faces.util.chain(this, {}, func4); expect(ret).to.be.true; }) {code} > faces.util.chain behavior changed > --------------------------------- > > Key: MYFACES-4658 > URL: https://issues.apache.org/jira/browse/MYFACES-4658 > Project: MyFaces Core > Issue Type: Bug > Affects Versions: 4.0.2 > Reporter: Volodymyr Siedlecki > Assignee: Werner Punz > Priority: Major > > 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. > {code:java} > <input type="submit" value="Test" onclick="return faces.util.chain(this, > event,function(event){return confirm('Please Confirm');});">{code} > 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: > {noformat} > 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; > } > }{noformat} > Faces 4.0: > {noformat} > 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; > }{noformat} > 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. -- This message was sent by Atlassian Jira (v8.20.10#820010)