EEZ Studio Embedded Dashboard Cycles: Understand What the Ancestor-Path Check Detects

An EEZ Studio Embedded Dashboard can reject a child with a cycle error before creating its loader. The inspected check follows the current chain of parent projects and compares the candidate Dashboard path with each ancestor's filePath.

The Embedded Dashboard reference describes loading an external Dashboard. The path resolution and cycle check appear together in the pinned widget implementation, EEZ Studio v0.29.0 commit 3000161d09d40a5c1dc2477ddc30b38037b3a612.

Understanding the checked relationship helps distinguish recursive embedding from ordinary reuse. Two widgets referring to the same child are not automatically the same situation as a child referring back to one of its ancestors.

Resolve the candidate, then walk the ancestors

The widget obtains a Dashboard string from its property. A valid URL is returned directly, and an absolute path is also returned directly. A relative path is resolved through the project store's absolute-path helper.

The loader logic then compares that resulting dashboardFilePath with the current parent project's filePath. If they match, it reports a cycle. Otherwise, when the parent context is run-embedded, it recursively checks the next parentProjectStore. Reaching a non-embedded parent without equality ends that search.

When a match is found, the component sets its cycle error instead of constructing a new LoadDashboard for that candidate. This is a check along the active ancestry chain, rather than a search through every Dashboard file in the project folder.

A embeds B, which attempts to embed A again; matching the candidate path to ancestor A triggers the cycle error before a new loader is created.
Original source-derived engineering concept diagram. Examples are hypothetical; no table, chart, embedded Dashboard or instrument operation was executed.

Draw the active chain before editing files

Consider a top-level A that embeds B. If B tries to embed A using the same resolved path string recorded for ancestor A, the comparison can find A while walking upward. A direct self-reference is the shorter version of the same relationship.

Now consider A containing two separate Embedded Dashboard widgets that both refer to B. B is repeated as a sibling destination, but it is not an ancestor of itself merely because another widget also refers to it. The shown cycle predicate alone does not reject that sibling reuse.

This does not guarantee that every sibling arrangement will load successfully. Missing files, invalid projects and runtime initialization can fail elsewhere. It simply separates the ancestry condition from unrelated loading outcomes.

For a reported cycle, record the candidate's resolved path and the filePath values of the active parent chain. A diagram of filenames without their resolved paths can conceal the actual equality that triggered the check.

The predicate compares strings, not every possible file identity

The inspected comparison uses path-string equality. This function does not itself canonicalize every possible filesystem alias, resolve symbolic-link identity or compare the contents of two projects. Other layers may normalize paths, but that must be established separately.

Do not infer that differently written paths are safe ways to construct recursive Dashboard graphs. Absence of a match in this predicate is not a design approval or a proof that all recursion is impossible. Use a deliberately acyclic embedding structure and treat path representation as part of diagnosis.

Similarly, a URL or an absolute path being returned unchanged by getDashboard does not establish the final identity rules of every loading layer. Limit conclusions to the values that actually reach this check.

Test a bounded topology

A proposed local fixture needs only two small Dashboard files and no network access or device operations. Compare direct self-reference, A-to-B-to-A with matching resolved paths, and two sibling references from A to B.

Observe the resolved candidate, ancestor chain and whether a child loader is created. Stop at the reported cycle rather than trying to circumvent it with aliases or construct an unbounded recursive graph. The fixture's purpose is to verify the guard, not to exhaust application resources.

When a legitimate design produces a cycle, split shared presentation or data responsibilities into a separate child that does not refer upward. An embedding relationship should express containment; using mutual containment to exchange state creates a structural problem that parameter renaming will not solve.

No Dashboard files were loaded for this analysis. The source-backed outcome is the guard's exact scope: equality against the active ancestors. That explains both why a back-reference can be rejected and why repeated use of the same child elsewhere requires a different diagnosis.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *