From 9c895a19b571f97b338a44b9017105274ae3a9ff Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Tue, 21 May 2024 02:18:52 +0200 Subject: [PATCH] Fix timeout count for nested plugins (#254) * Fix timeout count for nested plugins Signed-off-by: Matteo Collina * fixup Signed-off-by: Matteo Collina --------- Signed-off-by: Matteo Collina --- boot.js | 17 ++++++++-------- test/plugin-timeout-await.test.js | 33 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 test/plugin-timeout-await.test.js diff --git a/boot.js b/boot.js index db5edab..2addb6d 100644 --- a/boot.js +++ b/boot.js @@ -173,17 +173,16 @@ Boot.prototype._addPlugin = function (pluginFn, opts, isAfter) { // we always add plugins to load at the current element const current = this._current[0] - // In case of promises, adjust the timeout - if (isAfter && this._lastUsed) { - // We need to decrease it by 2ms to make sure the internal timeout - // is triggered earlier - const delta = Date.now() - current.startTime + 2 - if (this._lastUsed.timeout > 0 && delta > 0) { - this._lastUsed.timeout = this._lastUsed.timeout - delta - } + let timeout = this._opts.timeout + + if (!current.loaded && current.timeout > 0) { + const delta = Date.now() - current.startTime + // We need to decrease it by 3ms to make sure the internal timeout + // is triggered earlier than the parent + timeout = current.timeout - (delta + 3) } - const plugin = new Plugin(fastq(this, this._loadPluginNextTick, 1), pluginFn, opts, isAfter, this._opts.timeout) + const plugin = new Plugin(fastq(this, this._loadPluginNextTick, 1), pluginFn, opts, isAfter, timeout) this._trackPluginLoading(plugin) if (current.loaded) { diff --git a/test/plugin-timeout-await.test.js b/test/plugin-timeout-await.test.js new file mode 100644 index 0000000..13ecdd8 --- /dev/null +++ b/test/plugin-timeout-await.test.js @@ -0,0 +1,33 @@ +'use strict' + +/* eslint no-prototype-builtins: off */ + +const { test } = require('tap') +const boot = require('..') + +test('do not load', async (t) => { + const app = boot({}, { timeout: 10 }) + + app.use(first) + + async function first (s, opts) { + await s.use(second) + } + + async function second (s, opts) { + await s.use(third) + } + + function third (s, opts) { + return new Promise((resolve, reject) => { + // no resolve + }) + } + + try { + await app.start() + t.fail('should throw') + } catch (err) { + t.equal(err.message, 'Plugin did not start in time: \'third\'. You may have forgotten to call \'done\' function or to resolve a Promise') + } +})