Skip to content

Allow JS root components to reinitialize on circuit restart#17

Open
hila-f-qodo wants to merge 2 commits intodevin_pr_code_review_bench_100_devin2_base_allow_js_root_components_to_reinitialize_on_circuit_restart_pr90from
devin_pr_code_review_bench_100_devin2_head_allow_js_root_components_to_reinitialize_on_circuit_restart_pr90
Open

Allow JS root components to reinitialize on circuit restart#17
hila-f-qodo wants to merge 2 commits intodevin_pr_code_review_bench_100_devin2_base_allow_js_root_components_to_reinitialize_on_circuit_restart_pr90from
devin_pr_code_review_bench_100_devin2_head_allow_js_root_components_to_reinitialize_on_circuit_restart_pr90

Conversation

@hila-f-qodo
Copy link
Copy Markdown

@hila-f-qodo hila-f-qodo commented Jan 26, 2026

Benchmark PR from qodo-benchmark#90


Open with Devin

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View issues and 3 additional flags in Devin Review.

Open in Devin Review

if (manager) {
// This will only happen in very nonstandard cases where someone has multiple hosts.
// It's up to the developer to ensure that only one of them enables dynamic root components.
if (manager && currentRendererId === rendererId) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Inverted condition prevents circuit restart but allows multi-host scenario

The condition logic in enableJSRootComponents is inverted from the intended behavior.

Click to expand

Actual vs Expected Behavior

Original code (correct):

if (manager && currentRendererId !== rendererId) {
  throw new Error('Dynamic root components have already been enabled.');
}

New code (incorrect):

if (manager && currentRendererId === rendererId) {
  throw new Error('Dynamic root components have already been enabled.');
}

The original code throws an error when a different renderer tries to enable JS root components (multi-host scenario not supported), but allows the same renderer to re-enable (circuit restart scenario).

The new code does the opposite: it throws an error when the same renderer tries to re-enable (breaking circuit restart), but allows different renderers to enable (which was supposed to be blocked).

Impact

  1. Circuit restart scenarios (the PR's stated goal) will fail with "Dynamic root components have already been enabled" error
  2. Multi-host scenarios (Server + WebAssembly) that should be blocked will now be allowed, potentially causing undefined behavior

The comment on lines 127-128 says "A different renderer type (e.g., Server vs WebAssembly) is trying to enable JS root components" but the condition currentRendererId === rendererId checks for the same renderer, contradicting the comment.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

// because the old circuit is gone. We don't dispose the old manager - doing so would cause
// JSDisconnectedException because the circuit that created it no longer exists.
currentRendererId = rendererId;
manager = managerInstance;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Missing assignment of jsComponentParametersByIdentifier causes undefined access

The assignment jsComponentParametersByIdentifier = jsComponentParameters; was removed from enableJSRootComponents, leaving the module-level variable uninitialized.

Click to expand

How the Bug Gets Triggered

The variable jsComponentParametersByIdentifier is declared at line 14 but never assigned a value in the new code. When RootComponentsFunctions.add() is called at line 30:

const component = new DynamicRootComponent(componentId, jsComponentParametersByIdentifier[componentIdentifier]);

This will access undefined[componentIdentifier], resulting in undefined being passed to the DynamicRootComponent constructor.

Impact

In the DynamicRootComponent constructor at lines 77-84:

constructor(componentId: number, parameters: JSComponentParameter[]) {
  this._componentId = componentId;
  for (const parameter of parameters) {  // <-- iterating over undefined
    if (parameter.type === 'eventcallback') {
      this._jsEventCallbackWrappers.set(parameter.name.toLowerCase(), new EventCallbackWrapper());
    }
  }
}

Iterating over undefined will throw a TypeError at runtime, breaking all dynamic root component creation.

Recommendation: Add jsComponentParametersByIdentifier = jsComponentParameters; after line 137 (after manager = managerInstance;)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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.

3 participants