function withMacroTask (fn) {
  return fn._withTask || (fn._withTask = function () {
    useMacroTask = true;
    const res = fn.apply(null, arguments);
    useMacroTask = false;
    return res
  })
}
Wrap a function so that if any code inside triggers state change,
the changes are queued using a Task instead of a MicroTask.