Find longest common string subsequence
Find the current max
There are some very simple improvements you can make to reduce the run time and the complexity.
Your code looks for sequences, puts them all in an array and then sorts and filters that array to find the longest. However if you check the length of each sequence as you find it and compare it against the longest you have found to that point you no longer need to keep an array of sequences, only the current longest.
This also helps reduce the amount of processing. When you know the length of the current longest sequence, you are able to know before calling findFirstSequence(s1,s2) if it will find a longer one. The function can not find a sequence longer than the shortest string you pass it so if either is shorter than the current max then skip the call.
Also in the function findFirstSequence(s1,s2) as you build the sequence you can workout how long it can possibly get well before you get the sequence. You can thus exit early from that function as well just by knowing the current longest sequence.
There are also two more places that you can exit early. When you first enter the function 'findLongestSubsequence` you can check if the string are the same. If they are ether one is thus the answer.
The same after the calls to removeDistinctChars(s1, s2) if s1NoDistinct === s2NoDistinct then you have the answer and can return the result then.
Some style points

Use semiColons, Javascript requires them, and if you dont add them it inserts them automatically. Unfortunately it does not always put them where you may think it will. If you can not list all the times ASI (Automatic Semicolon Insertion) can ignore the line end than you are best to put them in manually.

Watch your indentation. It's not bad, just one line is 2 space in too far. But good code does not have style errors.

Don't leave for loop segments empty. You have for (; s1Idx &lt; s1.length; ++s1Idx) { which is poor style. for (s1Idx = 0; s1Idx &lt; s1.length; ++s1Idx) { lets you know at a glance what the loop is starting at, rather than having to find where you set the value. In this case I would also say use i rather than s1Idx but that is more a personal preference.


A rewrite
So using your approach and just finding some early exits and avoiding repeated processing the following rewrite keeps track of the current longest sequence. Returning the first longest sequence found.
const findLongest = (s1, s2) =&gt; {
    const removeDistinct = (s1, s2) =&gt; s1.split(&quot;&quot;).filter(c =&gt; s2.includes(c)).join(&quot;&quot;);
    const findFirstSeq = (s1, s2) =&gt; {
        var seq = &quot;&quot;, i, j = 0;
        for (i = 0; i &lt; s1.length; i++) {
            const c = s1[i];
            while (j++ &lt; s2.length) {
                if (seq.length + (s2.length - j - 2) &lt; max) { return &quot;&quot; }
                if (c === s2[j - 1]) {
                    seq += c;
                    break;
                }
            }
        }
        return seq
    }
    const findSubseq = (s1, s2) =&gt; {
        if (s2.length &lt;= max || s1.length &lt;= max) { return maxSeq }
        while (s1.length &amp;&amp; s1.length &gt; max) {
            const seq = findFirstSeq(s1, s2);
            if (seq.length &gt; max) {
                max = seq.length;
                s1 = s1.slice(max);
                maxSeq = seq;
            } else { s1 = s1.slice(1) }
        }
        return maxSeq;
    }    
    var max = 0, maxSeq;
    if (s1 === s2) { return s1 }
    const s1D = removeDistinct(s1, s2);
    const s2D = removeDistinct(s2, s1);
    if (s1D === s2D) { return s1D }
    findSubseq(s1D, s2D);
    return findSubseq(s2D, s1D);
}