Repository: nuxt/nuxt.js
Pull request #8038 (2020-09-09 08:51:29)

fix(utils): support chaining functions with promise
<!--- Provide a general summary of your changes in the title above -->

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [x] Bug fix (a non-breaking change which fixes an issue)
- [ ] New feature (a non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)


## Description
<!--- Describe your changes in detail -->
<!--- Why is this change required? What problem does it solve? -->
<!--- If it resolves an open issue, please link to the issue here. For example "Resolves: #1337" -->
Fixing #8037 

## Checklist:
<!--- Put an `x` in all the boxes that apply. -->
<!--- If your change requires a documentation PR, please link it appropriately -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly. (PR: #)
- [ ] I have added tests to cover my changes (if not applicable, please state why)
- [ ] All new and existing tests are passing.



codecov-commenter: # [Codecov](https://codecov.io/gh/nuxt/nuxt.js/pull/8038?src=pr&el=h1) Report
> Merging [#8038](https://codecov.io/gh/nuxt/nuxt.js/pull/8038?src=pr&el=desc) into [dev](https://codecov.io/gh/nuxt/nuxt.js/commit/0bafd77306bac7436aa13de8577d9c201839326a?el=desc) will **increase** coverage by `0.08%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/nuxt/nuxt.js/pull/8038/graphs/tree.svg?width=650&height=150&src=pr&token=nGD1PtMB3M)](https://codecov.io/gh/nuxt/nuxt.js/pull/8038?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##              dev    #8038      +/-   ##
==========================================
+ Coverage   68.87%   68.96%   +0.08%     
==========================================
  Files          91       91              
  Lines        3849     3837      -12     
  Branches     1044     1042       -2     
==========================================
- Hits         2651     2646       -5     
+ Misses        971      967       -4     
+ Partials      227      224       -3     
```

| Flag | Coverage Δ | |
|---|---|---|
| #unittests | `68.96% <100.00%> (+0.08%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/nuxt/nuxt.js/pull/8038?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [packages/utils/src/task.js](https://codecov.io/gh/nuxt/nuxt.js/pull/8038/diff?src=pr&el=tree#diff-cGFja2FnZXMvdXRpbHMvc3JjL3Rhc2suanM=) | `100.00% <100.00%> (ø)` | |
| [packages/config/src/load.js](https://codecov.io/gh/nuxt/nuxt.js/pull/8038/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29uZmlnL3NyYy9sb2FkLmpz) | `75.28% <0.00%> (-2.63%)` | :arrow_down: |
| [packages/webpack/src/config/base.js](https://codecov.io/gh/nuxt/nuxt.js/pull/8038/diff?src=pr&el=tree#diff-cGFja2FnZXMvd2VicGFjay9zcmMvY29uZmlnL2Jhc2UuanM=) | `64.45% <0.00%> (-0.18%)` | :arrow_down: |
| [packages/webpack/src/config/client.js](https://codecov.io/gh/nuxt/nuxt.js/pull/8038/diff?src=pr&el=tree#diff-cGFja2FnZXMvd2VicGFjay9zcmMvY29uZmlnL2NsaWVudC5qcw==) | `69.44% <0.00%> (+6.94%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/nuxt/nuxt.js/pull/8038?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/nuxt/nuxt.js/pull/8038?src=pr&el=footer). Last update [0bafd77...9a4a97e](https://codecov.io/gh/nuxt/nuxt.js/pull/8038?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/packages/utils/src/task.js b/packages/utils/src/task.js
index a6a82995c..f9873f5c2 100644
--- a/packages/utils/src/task.js
+++ b/packages/utils/src/task.js
@@ -13,24 +13,28 @@ export const chainFn = function chainFn (base, fn) {
   if (typeof fn !== 'function') {
     return base
   }
-  return function (...args) {
-    if (typeof base !== 'function') {
-      return fn.apply(this, args)
-    }
-    let baseResult = base.apply(this, args)
-    // Allow function to mutate the first argument instead of returning the result
-    if (baseResult === undefined) {
-      [baseResult] = args
+
+  if (typeof base !== 'function') {
+    return fn
+  }
+
+  return function (arg0, ...args) {
+    const next = (previous = arg0) => {
+      const fnResult = fn.call(this, previous, ...args)
+
+      if (fnResult && typeof fnResult.then === 'function') {
+        return fnResult.then(res => res || previous)
+      }
+
+      return fnResult || previous
     }
-    const fnResult = fn.call(
-      this,
-      baseResult,
-      ...Array.prototype.slice.call(args, 1)
-    )
-    // Return mutated argument if no result was returned
-    if (fnResult === undefined) {
-      return baseResult
+
+    const baseResult = base.call(this, arg0, ...args)
+
+    if (baseResult && typeof baseResult.then === 'function') {
+      return baseResult.then(res => next(res))
     }
-    return fnResult
+
+    return next(baseResult)
   }
 }
diff --git a/renovate.json b/renovate.json
index 8362536b7..e6ac12e01 100644
--- a/renovate.json
+++ b/renovate.json
@@ -14,6 +14,7 @@
     "url-loader",
     "sass-loader",
     "css-loader",
+    "postcss-loader",
     "fs-extra",
     "chalk",
     "wrap-ansi",


Test patch:
diff --git a/packages/utils/test/task.test.js b/packages/utils/test/task.test.js
index 69cbbcdec..e2bc39070 100644
--- a/packages/utils/test/task.test.js
+++ b/packages/utils/test/task.test.js
@@ -103,4 +103,15 @@ describe('util: task', () => {
     const chainedFn = chainFn(firstFn, secondFn)
     expect(chainedFn({}, 10)).toEqual({ bar: 12 })
   })
+
+  test('chainFn (promise)', async () => {
+    const firstFn = () => Promise.resolve({ foo: 1 })
+    const secondFn = function (obj) {
+      obj.foo++
+      return Promise.resolve()
+    }
+
+    const chainedFn = chainFn(firstFn, secondFn)
+    expect(await chainedFn()).toEqual({ foo: 2 })
+  })
 })