Skip to content

docs(types): add jsdocs types#229

Merged
alexander-akait merged 8 commits into
mainfrom
claude/add-jsdoc-types-xR8WE
Apr 28, 2026
Merged

docs(types): add jsdocs types#229
alexander-akait merged 8 commits into
mainfrom
claude/add-jsdoc-types-xR8WE

Conversation

@alexander-akait
Copy link
Copy Markdown
Member

Summary

Add jsdocs types to generate types

What kind of change does this PR introduce?

refactor

Did you add tests for your changes?

Existing

Does this PR introduce a breaking change?

No

If relevant, what needs to be documented once your changes are merged or what have you already documented?

Nothing

Use of AI

Yes, claude

…peScript

Annotate every file in lib/ with JSDoc types that mirror the public types
in tapable.d.ts. Add a tsconfig.json and a `build:types` script so .d.ts
files can be generated from the JSDoc sources into ./types (gitignored).
The public tapable.d.ts is unchanged so consumer types are unaffected.

Use the EXPECTED_ANY / EXPECTED_FUNCTION typedefs (mirroring the
eslint-config-webpack convention) to satisfy strict JSDoc rules. Adding
typescript as a direct devDependency activates the project's strict
JSDoc rules on README and benchmark files; restore prior lint behavior
for those paths via narrow rule overrides.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 27, 2026

⚠️ No Changeset found

Latest commit: 49bf9b4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented Apr 27, 2026

CLA Not Signed

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 27, 2026

Merging this PR will not alter performance

✅ 92 untouched benchmarks


Comparing claude/add-jsdoc-types-xR8WE (49bf9b4) with main (bb120cf)

Open in CodSpeed

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

❌ Patch coverage is 98.38710% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.25%. Comparing base (bb120cf) to head (49bf9b4).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
lib/Hook.js 83.33% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #229      +/-   ##
==========================================
- Coverage   99.35%   99.25%   -0.11%     
==========================================
  Files          15       15              
  Lines         775      805      +30     
  Branches      128      140      +12     
==========================================
+ Hits          770      799      +29     
- Misses          5        6       +1     
Flag Coverage Δ
integration 99.25% <98.38%> (-0.11%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

alexander-akait and others added 7 commits April 28, 2026 03:01
- Pass generic args to CompileOptions in all hook subclasses (needs 2-3
  type args after upstream made it generic).
- Default args parameter to a properly typed cast (via unknown -> ArgumentNames)
  instead of bare [] in Hook constructor and every subclass factory function.
- Cast subclass factory return values to the declared Hook<T, R, AdditionalOptions>
  return type (via unknown), since `new Hook(...)` produces the default-parameter
  variance that does not assign to the generic return.
- Fix typo in Hook.CompileOptions where `args` was incorrectly typed as
  `ArgumentNames<AsArray<T>>[]` (an array of arg-arrays); it should be
  `ArgumentNames<AsArray<T>>` to match the constructor signature.
- Cast _createCall results inside CALL_DELEGATE / CALL_ASYNC_DELEGATE /
  PROMISE_DELEGATE so the `EXPECTED_FUNCTION` return is assignable to the
  delegate fields.
- Widen mergeOptions parameter to `string | (TapOptions & IfSet<...>)` so
  the wrapped withOptions can recurse through it.
- Cast `taps[i]` to `FullTap & IfSet<AdditionalOptions>` when calling
  `interceptor.register` in Hook#intercept.
- Add MultiHook tap/tapAsync/tapPromise @template T,R declarations so the
  JSDoc types resolve, and cast withOptions / tapPromise call sites where
  the underlying hook contract is wider than the local generics.
- Initialize `fn` as `EXPECTED_FUNCTION | undefined` and cast on return
  in HookCodeFactory#create; type the `every` callback param explicitly;
  cast options.args when assigning to the local `_args: string[]`.
Lock down the optimization that lives in `Hook.js`: the
`Object.setPrototypeOf(Hook.prototype, null)` call and the trailing
`this.compile = this.compile` (and friends) self-assignments in the
constructor. Together they force `compile`/`tap`/`tapAsync`/`tapPromise`
to be own properties in a fixed insertion order so that subclass
overrides (`SyncHook`, `AsyncSeriesHook`, ...) overwrite existing slots
instead of triggering a hidden-class transition - keeping shared call
sites monomorphic.

The new tests assert:
  - Hook.prototype has a null prototype.
  - compile / tap / tapAsync / tapPromise and the call/_call,
    callAsync/_callAsync, promise/_promise pairs are own properties.
  - The base Hook layout is the documented 15-key sequence.
  - Every subclass instance shares the same 16-key layout (base + the
    trailing `constructor` slot the factories add) - across all 10
    subclass families.
  - Exercising a hook (intercept/tap/call) does not introduce new own
    properties or change ordering.
  - Async* hooks keep `call`/`_call` as own properties holding
    `undefined` rather than deleting them, so the layout still matches.

A future "cleanup" that removes the self-assignments or rearranges the
constructor will now fail the suite instead of silently regressing
hot-path performance.
The base `content` placeholder shadowed the subclass overrides on the
prototype chain - every `this.content(options)` lookup in
`contentWithInterceptors` had to walk past `HookCodeFactory.prototype`
before hitting the concrete `SyncHookCodeFactory`/`AsyncSeriesHookCodeFactory`
implementation. On the hot compile path that's a real cost in webpack
where `compile()` runs for every hook on every plugin registration.

Remove the stub so `content` exists only on subclass prototypes - V8
sees a single, monomorphic shape for the lookup. Use the
`@ts-expect-error abstract method ... for performance reasons` pattern
already established on `Hook.js` (CALL_DELEGATE etc.) to keep
`lint:types` green at the two call sites.

The trade-off: instantiating `HookCodeFactory` directly and calling
`content` now throws `TypeError: this.content is not a function`
instead of the prior friendlier `Error: Abstract: should be overridden`.
The class is internal and never exposed; this is acceptable.
Each subclass factory (SyncHook, AsyncParallelHook, ...) was returning the
generic `Hook<T, R, AdditionalOptions>` type, so consumers calling
`new SyncHook()` got `Hook<...>` from JSDoc-generated types instead of the
specific `SyncHook<...>` declared in the public `tapable.d.ts`.

Mirror the public class declarations: each subclass file gets a typedef
that re-exports the corresponding class from `tapable.d.ts` (with a
`Type` suffix to avoid colliding with the factory function name in scope),
then wires it as the factory's `@returns` and inner cast target.

This keeps the V8 hidden-class optimization intact (still factory
functions, no real `class extends Hook`) while aligning the JSDoc types
with what tapable.d.ts already promises to consumers.
@alexander-akait alexander-akait merged commit 052563d into main Apr 28, 2026
31 of 34 checks passed
@alexander-akait alexander-akait deleted the claude/add-jsdoc-types-xR8WE branch April 28, 2026 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants