Skip to content

API mock interceptor: pending mock responses not cancellable on disable #123

Description

@tyevco

Summary

In plugins/api-mock-interceptor/src/core/mocker.ts, the createMockXHRResponse method uses setTimeout(applyMock, 0) (line 128) without storing the timeout ID. This means pending mock responses cannot be cancelled when the interceptor is disabled.

Current Behavior

// mocker.ts:128
setTimeout(applyMock, 0);  // timeout ID not stored

If disableXHRInterception() is called while applyMock is queued in the event loop, the callback will still fire and attempt to modify XHR state on an object that may no longer be intercepted.

Suggested Fix

Store timeout IDs in a Set and clear them when the interceptor is disabled:

private pendingTimeouts = new Set<ReturnType<typeof setTimeout>>();

// In createMockXHRResponse:
const timeoutId = setTimeout(applyMock, 0);
this.pendingTimeouts.add(timeoutId);

// In disable/cleanup:
this.pendingTimeouts.forEach(id => clearTimeout(id));
this.pendingTimeouts.clear();

Impact

Low in practice — the setTimeout(fn, 0) delay is minimal, so the window for this race condition is very small. However, it could cause unexpected behavior if interceptor state is toggled rapidly.

Related

The same pattern exists in error-boundary-visualizer/src/core/store.ts line 319 where setTimeout(triggerError, simulation.delay) doesn't store the timeout ID for the delayed simulation trigger.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions