"***********************************************************************************************"

Using the modified version of M below, m can handle mixtures of synchronous and asynchronous arguments. idP(a) has no effect if a is a promise. Otherwise, idP transforms a into a promise. To see this in action, click "Restart" (below).

    var dF3x = () => {}; 

    function M (x) {
        return function go (func){
            if (func === dF3x) return x;
            else x = idP(x).then(v => func(v));
            return go;
        };
    };
    
    const m = M(3); 

In the demonstration below, "m" is given mixtures of simple functions and promises.



          m(() => 4)(addP(3)) (squareP) (v => v-7)(dF3x).then(v => (A = v)); = A    // x is changed to 4, then  (4+3)**2 - 7 = 42

         m(v => v/42)(v => v + 5)(v=>v*7)(pause(600))(dF3x).then(v => (B = v)); = B     //  (42/42)*6*7 = 42

         m(addP(7))(Math.sqrt)(v => v*6)(hello)(dF3x).then(a => (C = a)); = C     //  Math.sqrt(42 + 7) * 6 = 42

          m(divP(14))(v => v * 3)(addP(5))(v=> v * 3)(dF3x).then(v => (D = v)) = D     //  ((42 / 14) * 3 + 5) * 3 = 42

The asynchronous functions used above are in this list:

    function wait(ms) {
      return new Promise(r => setTimeout(r, ms));
    }
    
    async function squareP (x) {
      await wait(300)
      return x*x;
    }
    
    let pause = t => async x => {
      await wait(t)
      return x;
    }
    
    async function hello (x) {
      await wait(1000)
      A = "Hello "
      await wait(700)
      B = "World"
      await wait(700)
      A = 42
      await wait(700)
      B = 42
      return x;
    }
    
    let divPinverse = a => async b => {
      await wait (300)
      return a/b;
    }
    
    let addP =  x => async y => {
      await wait(300)
      return parseInt(x,10) + parseInt(y,10);
    }
    
    let doubleP = async y => {
      await wait(600)
      return 2 * parseInt(y,10) 
    }
    
    let multP = x => async y => {
      await wait(600)
      return x * y;
    }
    
    let divP = a => async b => {
      await wait (300)
      return b/a;
    }
    
    async function cubeP (x) {
      await wait(600)
      return x*x*x;
    } 

Here's the restart code:

    function restart () {
      A = "A"
      B = "B"
      C = "C"
      D = "D"
    m(() => 4)(addP(3)) (squareP) (v => v-7)(dF3x).then(v => (A = v));
      
    m(v => v/42)(v => v + 5)(v=>v*7)(pause(600))(dF3x).then(v => (B = v));

    m(addP(7))(Math.sqrt)(v => v*6)(hello)(dF3x).then(a => (C = a));

    m(divP(14))(v => v * 3)(addP(5))(v=> v * 3)(dF3x).then(v => (D = v)); 

    }

m = M(3)

m(v=>v**3)