Skip to content

Object has circular references

objectHasCircularReferences is a built‑in scan rule that detects objects that contain circular (self‑referential) references.

It performs a depth‑first traversal using a WeakSet to track visited nodes. When the rule encounters an object that has already been seen, it emits a warn‑level object.has.circular-references scan event. If the value is not a non‑array object or no cycles are found, no events are emitted.

Signature

export const objectHasCircularReferences: ScanRule (raw: unknown, path: FieldPath) => JaneEvent[]

Events

Event code Description
object.has.circular-references Object graph contains circular references.

Design rationale

  • Detects cyclic object graphs that can break serializers, diffing logic, or recursive analysis.
  • Uses a WeakSet to track visited objects and detect revisits efficiently.
  • Performs a stack‑based traversal to avoid unbounded recursion.
  • Emits a warning when a cycle is detected.
  • Surfaces structural hazards early so containment and policy layers can respond safely.
  • Performs no mutation or restructuring of the input.

Invoke

objectHasCircularReferences runs automatically whenever the scan stage is enabled.

Activation methods:

  • Enable scan explicitly: jane.value(input).scan().
  • Use a mode that enables scan:
  • strict() enables scan by default.
  • moderate() and lax() do not enable scan unless .scan() is called.
  • Enable scan with policy: jane.value(input).withPolicy({ mode: 'strict' }).

If scan is not enabled or if the value is not a plain object, objectHasCircularReferences does not run and no cycle detection occurs.

Examples

Circular reference detected

const obj: any = {};
obj.self = obj;

const result = objectHasCircularReferences(obj, "$");
// → [ JaneEvent{ kind: "warn", code: "object.has.circular-references", ... } ]

Nested but acyclic object

const result = objectHasCircularReferences({ a: { b: 1 } }, "$");
// → []

Non‑object or array value

const result = objectHasCircularReferences([1, 2, 3], "$");
// → []