Visitar URL original
feat!: pass the Fastify instance to all application hooks by Puppo · Pull Request #7219 · fastify/fastify · GitHub
Skip to content

feat!: pass the Fastify instance to all application hooks - #7219

Open
Puppo wants to merge 4 commits into
fastify:mainfrom
Puppo:fix/application-hooks-instance
Open

Puppo wants to merge 4 commits into
fastify:mainfrom
Puppo:fix/application-hooks-instance

Conversation

@Puppo

@Puppo Puppo commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

Standardize how all application lifecycle hooks expose the associated Fastify instance so both function declarations and arrow functions have consistent access to the encapsulated scope (instance === this).

Motivation

Previously, application hooks exposed the Fastify instance inconsistently (#4967):

  • onRoute, onReady, onListen, and preClose bound this to the Fastify instance without passing it as an argument, preventing arrow functions from accessing the encapsulated instance.
  • onClose bound this and passed instance as the first argument.
  • onRegister bound this to the parent instance where .register() was called, while passing the newly created child scope as the first argument (instance !== this).

Hook Signatures & this Binding Overview (v5 vs. v6)

  • Application Hooks: Every application hook now binds this to the associated Fastify instance and passes that same instance (instance === this) as the first positional argument. Zero-arg and single-arg sync/async lifecycle handlers (() => {}, async () => {}, async (instance) => {}) continue to work seamlessly; callback-style handlers now take (instance, done).
  • Request/Reply Hooks (lifecycleHooks): All 10 Request/Reply hooks (including onTimeout and onRequestAbort) already bind this to the route's encapsulated FastifyInstance and expose the same instance to arrow functions via request.server (and reply.server where reply is available), so their signatures remain unchanged (No changes).
Hook Category this Binding (function) Arrow Function Instance Access v5 Signature v6 Signature Status
onRoute Application Scope where route is registered instance (1st arg) (routeOptions) (instance, routeOptions) Changed
onRegister Application Parent registering scope instance (parent), newInstance (child) (childInstance, opts) (instance, newInstance, opts) Changed
onReady Application Encapsulated scope owning the hook instance (1st arg) (done) / async () (instance, done) / async (instance) Changed
onListen Application Encapsulated scope owning the hook instance (1st arg) (done) / async () (instance, done) / async (instance) Changed
preClose Application Encapsulated scope owning the hook instance (1st arg) (done) / async () (instance, done) / async (instance) Changed
onClose Application Encapsulated scope owning the hook instance (1st arg) (instance, done) / async (instance) (instance, done) / async (instance) No changes
onRequest Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, done) / async (request, reply) (request, reply, done) / async (request, reply) No changes
preParsing Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, payload, done) / async (request, reply, payload) (request, reply, payload, done) / async (request, reply, payload) No changes
preValidation Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, done) / async (request, reply) (request, reply, done) / async (request, reply) No changes
preHandler Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, done) / async (request, reply) (request, reply, done) / async (request, reply) No changes
preSerialization Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, payload, done) / async (request, reply, payload) (request, reply, payload, done) / async (request, reply, payload) No changes
onSend Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, payload, done) / async (request, reply, payload) (request, reply, payload, done) / async (request, reply, payload) No changes
onResponse Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, done) / async (request, reply) (request, reply, done) / async (request, reply) No changes
onError Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, error, done) / async (request, reply, error) (request, reply, error, done) / async (request, reply, error) No changes
onTimeout Request/Reply Route encapsulated FastifyInstance request.server / reply.server (request, reply, done) / async (request, reply) (request, reply, done) / async (request, reply) No changes
onRequestAbort Request/Reply Route encapsulated FastifyInstance request.server (request, done) / async (request) (request, done) / async (request) No changes

Summary of Changes

  • Runtime (lib/hooks.js, lib/plugin-override.js, lib/route.js, fastify.js):
    • Pass instance as the first argument in hookRunnerApplication (onReady, preClose), onListenHookRunner (onListen), onRoute, and onRegister.
    • Update callback arity detection (fn.length >= 2) and FST_ERR_HOOK_INVALID_ASYNC_HANDLER validation for the new parameter counts.
  • TypeScript (types/hooks.d.ts, types/instance.d.ts, test/types/hooks.tst.ts):
    • Update callback and async hook handler types (onRouteHookHandler, onRegisterHookHandler, onReady*, onListen*, preClose*, onClose*) and preserve TypeProvider generic propagation on fastify.addHook(...).
  • Tests & Documentation:
    • Add test/hooks-application-instance.test.js covering root, arrow functions, nested child/grandchild encapsulation, fastify-plugin, and 0/1-arg sync/async handlers, and assert instance === this across existing hook test suites (including this and request.server encapsulation checks on onTimeout and onRequestAbort).
    • Update docs/Reference/Hooks.md (covering both Application Hooks and this / request.server on Request/Reply Hooks), docs/Reference/TypeScript.md, docs/Guides/Plugins-Guide.md, and examples/hooks.js.

Closes #4967

Checklist

@github-actions github-actions Bot added documentation Improvements or additions to documentation typescript TypeScript related labels Nov 12, 2026
@Puppo
Puppo requested a review from Eomm November 12, 2026 20:43
@Eomm Eomm added semver-major Issue or PR that should land as semver major notable-change A change that should be explicitly outlined in release notes and migration guides labels Nov 13, 2026
@Puppo
Puppo marked this pull request as ready for review November 13, 2026 09:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation notable-change A change that should be explicitly outlined in release notes and migration guides semver-major Issue or PR that should land as semver major typescript TypeScript related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ApplicationHooks have inconsistent reference to instance

2 participants