[ 
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)

Reply via email to