Skip to content

feat: add fiber type guards and assertion utilities#34

Open
MarcelOlsen wants to merge 10 commits into
fiber/typesfrom
fiber/type-guards
Open

feat: add fiber type guards and assertion utilities#34
MarcelOlsen wants to merge 10 commits into
fiber/typesfrom
fiber/type-guards

Conversation

@MarcelOlsen

@MarcelOlsen MarcelOlsen commented Feb 13, 2026

Copy link
Copy Markdown
Owner

Add type predicates for fiber tags (isHostComponent, isFunctionComponent,
etc.) and assertion helpers for the fiber tree.

Summary by CodeRabbit

Release Notes

  • Refactor
    • Added comprehensive runtime type validation and assertion utilities for the core fiber system. Includes type guards for component types, state management utilities, safe property accessors, and enhanced validation for DOM and internal relationships to strengthen overall framework type safety and reliability.

@coderabbitai

coderabbitai Bot commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MarcelOlsen MarcelOlsen force-pushed the fiber/type-guards branch 2 times, most recently from 40c8468 to 922519f Compare February 14, 2026 16:17
@MarcelOlsen MarcelOlsen force-pushed the fiber/types branch 2 times, most recently from 93ee6bd to c1702e0 Compare February 15, 2026 13:10
@MarcelOlsen MarcelOlsen force-pushed the fiber/type-guards branch 3 times, most recently from 712f744 to 20e7d76 Compare February 15, 2026 15:31
Add type predicates for fiber tags (isHostComponent, isFunctionComponent,
etc.) and assertion helpers for the fiber tree.
@MarcelOlsen MarcelOlsen marked this pull request as ready for review February 15, 2026 15:41

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/fiber/typeGuards.ts`:
- Around line 70-100: Change these boolean-returning helpers to real TypeScript
type guard predicates so the compiler can narrow the Fiber type: update each
function signature (isFunctionComponentFiber, isMemoComponentFiber,
isFragmentFiber, isContextProviderFiber, isContextConsumerFiber) to return a
predicate (for example "fiber is FunctionComponentFiber" or "fiber is Fiber & {
tag: WorkTag.FunctionComponent }" if specific subtype types aren’t defined) and
keep the existing tag comparison bodies unchanged; ensure you import or declare
the narrower subtype names (or use the inline intersection form) so TS can
narrow after calls.
- Around line 302-307: isTextProps currently only checks that props is a
non-null object and that "nodeValue" exists, which allows invalid shapes like {
nodeValue: {} }; update isTextProps to also validate that props.nodeValue is of
the expected TextProps type (string or number) before returning true—keep the
initial null/object guard, then check typeof (props as any).nodeValue ===
"string" || typeof (props as any).nodeValue === "number"; reference the
isTextProps function and TextProps type to locate where to add this stricter
runtime check.
- Around line 31-65: The type guards isHostComponentFiber, isHostTextFiber,
isHostRootFiber and isHostPortalFiber incorrectly assert stateNode is non-null
by only checking fiber.tag; update each guard to also check fiber.stateNode !==
null (e.g., return fiber.tag === WorkTag.HostComponent && fiber.stateNode !==
null) so the narrowing excludes the null case and matches the declared stateNode
union type, preserving safety during mount/unmount phases.
- Around line 451-462: The exported type guards isHTMLElement and
isHTMLInputElement can throw ReferenceError in non-DOM environments; update both
functions to first check typeof HTMLElement !== "undefined" (and typeof
HTMLInputElement !== "undefined" for isHTMLInputElement) before using
instanceof, and return false if those globals are undefined so the guards safely
work in Node/SSR contexts.
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and e0d8218.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (11)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (1)
src/fiber/typeGuards.ts (1)

374-427: Bitwise lane/flag helpers look tight.
Nice, simple, consistent helpers — no drama here.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread src/fiber/typeGuards.ts Outdated
Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/fiber/typeGuards.ts`:
- Around line 359-379: assertUpdateQueue currently only checks hook.queue !==
null and can return an object that isn't an UpdateQueue; update it to reuse the
existing isUpdateQueue type guard so it validates the shape. In
assertUpdateQueue(Hook) call isUpdateQueue(hook.queue) and throw a descriptive
Error (e.g., "Hook queue is not a valid UpdateQueue") when the guard fails;
otherwise return hook.queue typed as UpdateQueue<S>. This ensures the function
enforces the UpdateQueue shape rather than just non-null.
- Around line 602-629: The current isMemoComponent only checks $$typeof and
falsely narrows to the full MemoComponent shape; update isMemoComponent to
validate all three properties declared on MemoComponent: confirm "$$typeof"
exists and is a symbol, that "type" exists (e.g., "type" in obj and obj["type"]
!== undefined) and that "compare" exists and is either null or a function
(typeof obj["compare"] === "function" || obj["compare"] === null); keep the same
return type (value is MemoComponent) so downstream code is safe. Ensure you
reference the MemoComponent type and the isMemoComponent function when editing.
- Around line 445-498: isElement and isTextNode access Node.ELEMENT_NODE /
Node.TEXT_NODE directly which can throw in SSR/Node; update both type guards to
first check typeof Node !== "undefined" (same pattern as
isHTMLElement/isHTMLInputElement) so they return false when Node is undefined,
e.g. change isElement to return typeof Node !== "undefined" && node.nodeType ===
Node.ELEMENT_NODE and isTextNode to return typeof Node !== "undefined" &&
node.nodeType === Node.TEXT_NODE; ensure assertElement and assertTextNode still
call these guards (no other changes needed).
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and 0ac7f6c.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (11)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (8)
src/fiber/typeGuards.ts (8)

27-110: Tag guard block is clean and consistent, chat.
Real predicates, no weirdness. This is exactly the kind of boring, predictable narrowing we want.


116-242: Host fiber assertions are crisp and maintainable.
Error paths are explicit, narrowing is solid, and it’s readable. Nice.


248-298: MemoizedState guards are minimal and tidy.
No surprise casts or spooky action at a distance. Good stuff.


304-353: Props guards look solid.
The runtime checks are aligned with the shape, and the flow is clean.


385-439: Bitmask helpers are fine.
These are simple and do exactly what they say. No notes.


504-524: FiberRoot guard/assert is straightforward.
Simple shape check + assert = good.


530-573: Fiber structural guards are clean.
Clear intent, zero ambiguity.


579-596: Dynamic property helpers are fine for escape hatches.
It’s explicit, and it keeps the scary casts in one place.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/fiber/typeGuards.ts`:
- Around line 362-379: isUpdateQueue currently only checks for keys and can
accept junk; update it to validate the actual required UpdateQueue shape and
types (e.g., ensure "dispatch" is a function, "lanes" is a number, "pending" is
an object or null and any other required fields from the UpdateQueue type such
as the queue's list/head/tail or "last"/"baseState" if present in your type).
Use the UpdateQueue type definition to enumerate and check each mandatory
property and their types inside isUpdateQueue (still returning value is
UpdateQueue<S>); keep assertUpdateQueue<S>(hook: Hook) as-is but rely on the
stronger isUpdateQueue guard to avoid false positives.
- Around line 251-268: The type guards isHookState and isEffectState use partial
checks and must be expanded to validate the full runtime shape: update
isHookState to also check for "baseState" and "baseQueue" properties (in
addition to "memoizedState", "next", "queue") and update isEffectState to also
check for "destroy" and "next" (in addition to "tag", "create", "deps"); ensure
each guard still rejects null/non-objects and uses the same obj alias (value as
Record<string, unknown>) so TypeScript can safely narrow to Hook and Effect
respectively.
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and 732d6af.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (11)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (10)
src/fiber/typeGuards.ts (10)

27-110: Tag guards are clean and actually narrow now.
Yo, predicates + null checks = TS can finally trust these.


116-242: StateNode asserts/readers are tight.
Consistent checks, clear errors, no weird surprises.


274-298: Memoized-state accessors are clean and minimal.
No drama here.


304-353: Props guards/readers look solid.
Nice to see the real TextProps check instead of “trust me bro.”


385-439: Lanes/flags helpers are crisp and consistent.
Bitwise ops are clean and readable.


445-498: DOM guards are SSR‑safe and consistent.
Good defensive checks — no ReferenceError landmines.


533-573: Fiber relationship guards are straightforward and clear.
No notes.


579-596: Dynamic property helpers are fine.
Simple and focused.


602-635: Component guards are sane.
The memo shape check is finally legit.


504-524: 🧹 Nitpick | 🔵 Trivial

DRY this: FiberRoot guards already exist in src/fiber/types.ts.
Duplicate implementations drift over time. Consider re‑exporting or delegating to the canonical versions.

♻️ Delegate to the existing implementations
-import { NoFlags, NoLanes, WorkTag } from "./types";
+import {
+	NoFlags,
+	NoLanes,
+	WorkTag,
+	isFiberRoot as isFiberRootImpl,
+	assertFiberRoot as assertFiberRootImpl,
+} from "./types";
@@
-export function isFiberRoot(value: unknown): value is FiberRoot {
-	if (value === null || typeof value !== "object") {
-		return false;
-	}
-	const obj = value as Record<string, unknown>;
-	return "containerInfo" in obj && "current" in obj && "pendingLanes" in obj;
-}
+export const isFiberRoot = isFiberRootImpl;
@@
-export function assertFiberRoot(value: unknown): asserts value is FiberRoot {
-	if (!isFiberRoot(value)) {
-		throw new Error("Expected FiberRoot");
-	}
-}
+export const assertFiberRoot = assertFiberRootImpl;

Likely an incorrect or invalid review comment.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts
- isUpdatedQueue now vlaidates all five UpdateQueue<S> fields
- isHookState now checks all five Hook properties

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/fiber/typeGuards.ts`:
- Around line 602-619: The current helpers setDynamicProperty and
getDynamicProperty allow assigning user-controlled keys like "__proto__",
"constructor", or "prototype", which can cause prototype pollution; update both
functions to explicitly reject unsafe keys (at minimum "__proto__",
"constructor", "prototype") by throwing or returning early when such keys are
passed, or change their names to indicate they are unsafe (e.g.,
setDynamicPropertyUnsafe/getDynamicPropertyUnsafe) if you don't want to add
guards; reference the functions setDynamicProperty and getDynamicProperty when
making this change so callers can be updated or audited accordingly.
- Around line 527-536: The current isFiberRoot type guard only checks for key
existence; tighten it by verifying the types of those keys: ensure
obj.containerInfo is non-null and object-ish, obj.current is non-null and
object-ish, and obj.pendingLanes is a number (use typeof checks and null checks)
before returning true. Update the isFiberRoot function to replace the simple
"'containerInfo' in obj && 'current' in obj && 'pendingLanes' in obj" with
explicit checks for obj.containerInfo !== null && typeof obj.containerInfo ===
"object" && obj.current !== null && typeof obj.current === "object" && typeof
obj.pendingLanes === "number".
- Around line 359-363: The error thrown in assertTextProps incorrectly always
says "Expected TextProps in fiber.pendingProps" even though you check const
props = fiber.pendingProps ?? fiber.memoizedProps; update the check so the
thrown Error names the actual source (pendingProps or memoizedProps) used —
e.g., determine which prop source was selected (by checking if
fiber.pendingProps is undefined) and include that identifier in the Error
message when isTextProps(props) is false; reference assertTextProps,
fiber.pendingProps, fiber.memoizedProps, isTextProps, and TextProps when making
the change.
- Around line 251-279: The current isHookState and isEffectState only check for
property presence and accept invalid shapes; update both guards to validate
basic types for key fields: in isHookState ensure "next" is either null or an
object, and that "queue" and "baseQueue" are either null or objects (and that
"memoizedState"/"baseState" are present but may be any), and in isEffectState
ensure "tag" is a number, "create" is a function, "destroy" is either null or a
function, "deps" is either null or an array, and "next" is either null or an
object; keep the existing property checks but add these minimal
typeof/Array.isArray/null checks for the symbols
"memoizedState","baseState","baseQueue","queue","next","tag","create","destroy","deps"
inside isHookState and isEffectState respectively.
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and f7cc92d.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (11)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (7)
src/fiber/typeGuards.ts (7)

31-110: Clean tag guards with real predicates—nice.
Yo, these are actual TS predicates now and the tag checks are straight to the point. This is the kind of boring correctness I like.


116-242: Host fiber asserts are tight and readable.
Tag check + null check + clear error = good guard rails. This is solid.


371-402: UpdateQueue guard is finally legit.
Nice: you validate the core fields + function/null checks, and assertUpdateQueue reuses it.


408-462: Branded lane/flag helpers are clean.
These wrappers keep bitwise ops from leaking number everywhere. 👍


468-521: DOM guards are SSR-safe—good call.
The typeof checks prevent ReferenceError in non-DOM envs, and the asserts reuse the guards. Solid.


553-596: Fiber relationship guards are simple and correct.
Null checks are all you need here, and the assertions are consistent.


625-658: Memo component guard is full-shape now—nice.
You’re checking $$typeof, type, and compare, and isFunctionType stays clean and obvious.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts
- setDynamicProperty / getDynamicProperty, both now reject __proto__, constructor, and prototype keys by throwing an error, preventing prototype pollution
- isFiberRoot now validates types: containerInfo must be a non-null object
- assertTextProps error message now correctly names the actual source (pendingProps or memoizedProps) based on which one was used
- isHookState now validates that baseQueue, queue, and next are each either null or an object
- isEffectState now validates that tag is a number, create is a function, destroy is undefined or a function, deps is null or an array, and next is null or an object.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/fiber/typeGuards.ts`:
- Around line 31-65: Replace the explicit inline return types in the type guards
with the existing Host*Fiber aliases to centralize the contract; update
isHostComponentFiber, isHostTextFiber, isHostRootFiber, and isHostPortalFiber to
return the corresponding HostComponentFiber, HostTextFiber, HostRootFiber, and
HostPortalFiber types (e.g., "fiber is HostComponentFiber") while keeping the
same tag checks (WorkTag.HostComponent, WorkTag.HostText, WorkTag.HostRoot,
WorkTag.HostPortal) and stateNode null checks so the narrowed tag and stateNode
types come from the shared aliases.
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and 9d9c9e1.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (11)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (11)
src/fiber/typeGuards.ts (11)

70-110: Tag guards are clean and properly typed.
Nice, tight predicates for the non-host tags.


116-242: Assertions + Host*Fiber types are solid.
Clear error messages and explicit narrowing — good stuff.


248-318: Memoized-state guards look tight.
Minimal-but-real shape checks; nice balance.


324-375: Props guards are straightforward and readable.
nodeValue check is the right call for runtime narrowing.


381-412: UpdateQueue guard + assertion is clean.
Good to see the assertion route through the guard.


418-472: Bitwise helpers are concise and well-named.
“Unsafe” labeling is a nice cue to callers.


478-531: DOM guards are SSR-safe — nice.
The typeof checks are the right defensive move.


537-563: FiberRoot guard is properly tightened.
Good shape validation without overfitting.


569-612: Fiber structure guards are clean and predictable.
Exactly what you want here.


618-645: Prototype-pollution defenses are on point.
UNSAFE_KEYS is a solid, centralized guard.


651-684: Component type guards look good.
isMemoComponent shape checks are tight and practical.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/fiber/typeGuards.ts`:
- Around line 245-281: The isHookState guard currently accepts any non-null
object for "queue" and "baseQueue"; tighten it by validating those with
isUpdateQueue when non-null. Update isHookState to: import/ensure isUpdateQueue
is in scope and replace the checks (obj["baseQueue"] === null || typeof
obj["baseQueue"] === "object") and (obj["queue"] === null || typeof obj["queue"]
=== "object") with (obj["baseQueue"] === null ||
isUpdateQueue(obj["baseQueue"])) and (obj["queue"] === null ||
isUpdateQueue(obj["queue"])); keep the other property checks and return shape
unchanged.
- Around line 337-369: The error message in assertTextProps can report the wrong
source when fiber.pendingProps is null because the code uses nullish coalescing
(??) but checks only for undefined; update the source detection in
assertTextProps to use a nullish check (e.g., check pendingProps !== null &&
pendingProps !== undefined or pendingProps == null) so the computed source
("pendingProps" vs "memoizedProps") correctly reflects which prop was used when
throwing the Error in assertTextProps.
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and 5665e2f.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (11)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (16)
src/fiber/typeGuards.ts (16)

31-59: Host fiber guards look tight.
Tag + non-null stateNode checks are clean and consistent.


61-104: Tag-only fiber guards are clean.
Straightforward and readable.


110-140: Host*Fiber aliases are solid.
Centralized contracts = easier maintenance.


147-204: Assertions are crisp with useful failure messages.
No notes here.


210-236: Host stateNode helpers are straightforward.
Looks good.


288-312: Memoized state helpers are clean.
All good.


318-332: TextProps guard is properly strict.
Nice and simple.


378-406: UpdateQueue guard + assert are solid.
No issues.


415-466: Lane/flag helpers are clean and consistent.
Ship it.


475-503: DOM guards are SSR-safe and tidy.
Good defensive checks.


510-525: DOM asserts are straight to the point.
No notes.


534-557: FiberRoot guard shape checks look good.
Solid runtime narrowing.


566-606: Fiber relationship guards are clean.
Nice and minimal.


612-639: Dynamic property helpers are hardened — good call.
Prototype pollution defense is on point.


648-669: MemoComponent guard looks complete.
Checks line up with the type.


674-678: Function-type guard is fine.
No issues.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/fiber/typeGuards.ts`:
- Around line 531-557: Remove the duplicate isFiberRoot and assertFiberRoot
implementations here and instead import and re-export the canonical definitions
from the other module (the existing isFiberRoot and assertFiberRoot in
src/fiber/types.ts), or move the single authoritative implementation into this
module and update types.ts to re-export it; ensure the current symbols
isFiberRoot and assertFiberRoot remain available from this file by using a
re-export so callers keep working and you avoid duplicate/ drifting
implementations.
- Around line 245-258: The isHookState type guard wrongly validates
Hook.baseQueue as UpdateQueue via isUpdateQueue, but Hook.baseQueue is Update |
null; update the check in isHookState to accept null or an Update (either by
replacing isUpdateQueue with an isUpdate guard if available, or by loosening the
check to only assert null or an object shaped like an Update) so legitimate
hooks don't fail assertHookState; refer to the isHookState function, the Hook
type, the baseQueue property, and replace the (obj["baseQueue"] === null ||
isUpdateQueue(obj["baseQueue"])) check accordingly.
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and 946f3f0.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (11)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (3)
src/fiber/typeGuards.ts (3)

31-237: Solid guard + assert layering.
This is clean: tag guards feed into assert helpers, and the Host*Fiber aliases keep the contracts consistent. Good, tight surface.


318-466: Props + UpdateQueue + lane/flag helpers look tight.
Nice runtime checks and the branded bitwise helpers are straightforward and consistent.


472-525: DOM + dynamic-property + memo guards are in good shape.
SSR-safe DOM checks are solid, and the unsafe key block is exactly the kind of hardening I want to see.

Also applies to: 612-678

Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/fiber/typeGuards.ts`:
- Around line 300-313: The two helpers getMemoizedState<T> and
assertMemoizedState<T> perform unchecked casts and can mislead downstream users
into thinking they validate the shape; update their JSDoc comments to explicitly
warn that these functions do not perform runtime validation of T and recommend
using specific guards (for example mention isHookState) when validation is
required, and ensure the assertMemoizedState doc notes it throws if
memoizedState is null; keep the implementation unchanged but add those
clarifying sentences to the JSDoc for both functions.
- Around line 114-141: Move the Host* type aliases so they appear before the
type guard functions that reference them: place HostComponentFiber,
HostTextFiber, HostRootFiber, and HostPortalFiber above the type guard
implementations (e.g., the functions that use the "fiber is HostComponentFiber"
style predicates) so the file reads top-to-bottom; simply cut the four type
alias blocks and paste them above the corresponding isHost... type guard
functions to improve readability and maintainability.
- Around line 437-456: The three functions mergeLanesUnsafe,
intersectLanesUnsafe, and removeLanesUnsafe should be renamed to remove the
misleading "Unsafe" suffix (e.g., mergeLanes, intersectLanes, removeLanes) and
their JSDoc updated to reflect they perform bitwise ops while handling branded
Lane/Lanes types; update all references/exports/usages across the codebase to
the new names so imports and calls continue to work, and keep the current
implementations and signatures intact (only change the identifier names and
docs).
- Around line 403-420: The isUpdateQueue type guard currently only checks that
obj["pending"] is null or an object; update it to validate pending using the
existing isUpdate type guard (i.e., require obj["pending"] === null ||
isUpdate(obj["pending"])) so pending is fully validated as an Update<S> when
present; modify the isUpdateQueue function accordingly and keep the other field
checks (lanes, dispatch, lastRenderedReducer, lastRenderedState) unchanged.
📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and eaebf87.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (12)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • Update (181-187)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (11)
src/fiber/typeGuards.ts (11)

32-60: DUDE, LOOK AT THESE TYPE GUARDS NOW! Actually narrowing types like a BOSS.

The previous feedback about these being fake type guards has been addressed. Now we've got proper fiber is HostComponentFiber predicates that TypeScript can actually use for narrowing. This is the way.

The stateNode !== null checks combined with tag checks means downstream code knows EXACTLY what it's dealing with. Clean.


148-237: These assertion functions are CHEF'S KISS.

Proper asserts fiber is X return types, descriptive error messages with the actual tag value, separate checks for tag and stateNode. This is how you do runtime validation that TypeScript can actually leverage.

assertHostFiber handling both HostComponent and HostText is a nice ergonomic touch for call sites that don't care which host type they have.


246-261: baseQueue validation is FIXED - using isUpdate now instead of isUpdateQueue.

Past review caught that Hook.baseQueue is Update | null, not UpdateQueue. This is now correctly validating with isUpdate(obj["baseQueue"]) at line 255. The type contract is no longer a lie. Good fix.


327-333: isTextProps actually validates the type now. No more "nodeValue: {}" sneaking through!

Previous feedback about this being a false type guard has been addressed. Now we check typeof nv === "string" || typeof nv === "number" which means the contract is actually enforced at runtime. TypeScript narrowing is no longer lying.


362-370: Error source detection using != null - FIXED.

Past review caught the bug where !== undefined wouldn't catch null pendingProps. Now using != null (loose equality) correctly handles both null and undefined cases. The error message will accurately report which prop source was used.


426-431: assertUpdateQueue using isUpdateQueue now - FIXED!

Past review caught that this was only checking hook.queue === null and not validating shape. Now it properly uses isUpdateQueue<S>(hook.queue) to ensure the queue is actually valid before returning. The assertion means something now.


500-528: SSR-safe DOM guards - typeof checks before accessing globals. LETSGOOOO!

Previous feedback about ReferenceError in Node.js environments has been addressed:

  • Line 501: typeof Node !== "undefined" && node.nodeType === Node.ELEMENT_NODE
  • Line 508: typeof Node !== "undefined" && node.nodeType === Node.TEXT_NODE
  • Line 515: typeof HTMLElement !== "undefined" && node instanceof HTMLElement
  • Line 525: typeof HTMLInputElement !== "undefined" && element instanceof HTMLInputElement

Short-circuit evaluation means the globals are never accessed if they don't exist. This is ready for SSR (Phase 17 on the roadmap).


591-631: Simple but effective navigation guards. Love the ergonomics.

These are clean type predicates that narrow Fiber | null to Fiber. The pattern fiber is Fiber & { return: Fiber } is exactly right.

assertFiberParent returning the parent value is smart - lets you do const parent = assertFiberParent(fiber) instead of separate assert + access.


637-664: Prototype pollution protection is IN. Set-based O(1) lookup is clean.

Previous feedback about __proto__/constructor/prototype injection has been addressed. Both setter and getter now throw on unsafe keys - that's actually better than silently returning undefined because it surfaces misuse immediately.

The UNSAFE_KEYS Set at line 637 is efficient and easy to extend if needed.


682-694: isMemoComponent validates the FULL shape now. No more half-truths.

Previous feedback addressed - now checking:

  • typeof obj["$$typeof"] === "symbol"
  • "type" in obj && obj["type"] !== undefined
  • typeof obj["compare"] === "function" || obj["compare"] === null

If someone passes { $$typeof: Symbol() } without type or compare, it correctly returns false. The type guard matches the MemoComponent type contract.


559-571: Type validation is actually solid - no { pendingLanes: "nope" } slipping through here

The isFiberRoot guard is doing its job right:

  • containerInfo check: non-null AND object ✓
  • current check: non-null AND object ✓
  • pendingLanes check: number type ✓

And assertFiberRoot composition is clean - leans on isFiberRoot rather than duplicating logic. Good architectural instinct there.

Also checked src/fiber/types.ts - no duplicates exist. That past concern was a ghost. File maintains consistent pattern across all its guards, which is maintainable.

Comment thread src/fiber/typeGuards.ts Outdated
Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts
Comment thread src/fiber/typeGuards.ts
…eanup

  - Convert boolean-returning fiber tag helpers to real TS type predicates
  - Add stateNode !== null checks to host fiber type guards
  - Validate full shapes in isHookState, isEffectState, isUpdateQueue, and
    isMemoComponent instead of only checking key existence
  - Add isUpdate type guard for Update<S> shape validation
  - Tighten isTextProps to validate nodeValue is string or number
  - Tighten isFiberRoot to verify property types, not just presence
  - Guard isHTMLElement, isHTMLInputElement, isElement, isTextNode against
    missing DOM globals for SSR safety
  - Fix assertTextProps error message to report correct prop source
  - Reject prototype-polluting keys in setDynamicProperty/getDynamicProperty
  - Add JSDoc warnings to getMemoizedState/assertMemoizedState about unchecked casts
  - Rename mergeLanesUnsafe/intersectLanesUnsafe/removeLanesUnsafe to
    mergeLanes/intersectLanes/removeLanes
  - Move Host* type aliases above their corresponding type guard functions

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e73945 and adbf41b.

📒 Files selected for processing (1)
  • src/fiber/typeGuards.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: MarcelOlsen
Repo: MarcelOlsen/mini-react PR: 8
File: README.md:701-708
Timestamp: 2025-06-17T12:40:39.737Z
Learning: MarcelOlsen prefers to keep test documentation simple with just one example of running specific test files, rather than listing detailed commands for each test suite in the README.
🧬 Code graph analysis (1)
src/fiber/typeGuards.ts (1)
src/fiber/types.ts (12)
  • Fiber (225-334)
  • FiberRoot (390-443)
  • PortalStateNode (210-212)
  • Hook (170-176)
  • Effect (159-165)
  • Update (181-187)
  • UpdateQueue (192-200)
  • Lanes (54-54)
  • Lane (47-47)
  • NoLanes (75-75)
  • Flags (61-61)
  • NoFlags (93-93)
🔇 Additional comments (11)
src/fiber/typeGuards.ts (11)

31-58: Host fiber aliases are clean and readable.*
This is tidy and consistent.


98-141: Tag-only guards (Function/Memo/Fragment/Context) are fine.
No notes here.


152-241: Assertions are consistent and the errors read well.
This is clean and usable.


250-323: Hook/effect guards + memoized helpers look solid.
Nice balance of runtime checks vs. documented casts.


329-380: Props/TextProps handling is tight.
Nullish source selection + type check is on point.


436-502: UpdateQueue assert + lane/flag helpers are clean.
Straightforward, consistent, no weirdness.


507-560: DOM guards are SSR-safe; nice.
Good defensive checks.


569-642: FiberRoot + parent/child guards are straightforward.
Clear and simple.


647-674: Prototype-pollution key guard is good safety.
Nice hard stop.


680-713: MemoComponent guard + isFunctionType are tidy.
Looks good.


389-429: Hold up, the fields are all there, chief.
Just ran the verification and all those fields actually exist in the real Update and UpdateQueue types in src/fiber/types.ts—lane, action, hasEagerState, eagerState, next for Update, and pending, lanes, dispatch, lastRenderedReducer, lastRenderedState for UpdateQueue. So legit data won't get rejected by these guards due to missing fields.

That said, while you're checking field existence, you're not type-validating everything you should be—action and eagerState in Update, and lastRenderedState in UpdateQueue don't get type-checked, just existence-checked. That's sus for a type guard that's supposed to narrow the type. But that's a different issue than what you originally flagged.

Likely an incorrect or invalid review comment.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/fiber/typeGuards.ts`:
- Around line 68-96: The current type guards (isHostComponentFiber,
isHostTextFiber, isHostRootFiber, isHostPortalFiber) only check tag + non-null —
tighten them to validate the actual shape of stateNode by calling the existing
runtime validators instead of just checking !== null; e.g. in
isHostComponentFiber call the host element validator (e.g.,
isHostElementStateNode(stateNode)), in isHostTextFiber call the text-instance
validator (e.g., isTextStateNode(stateNode)), in isHostRootFiber call the
fiber-root validator (e.g., isFiberRoot(stateNode)), and in isHostPortalFiber
call the portal-state validator (e.g., isPortalStateNode(stateNode)) so each
function returns tag-check && stateNode !== null &&
correspondingValidator(stateNode).

Comment thread src/fiber/typeGuards.ts
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.

1 participant