Skip to content

Commit

Permalink
feat: Allow disabling cycle detection
Browse files Browse the repository at this point in the history
  • Loading branch information
jansav committed Apr 4, 2023
1 parent fd8b52f commit 661f346
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 35 deletions.
5 changes: 4 additions & 1 deletion packages/injectable/core/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,7 @@ export const deregistrationCallbackToken: RegistrationCallback;
export const isInjectable: (thing: any) => boolean;
export const isInjectionToken: (thing: any) => boolean;

export function createContainer(containerId: string): DiContainer;
export function createContainer(
containerId: string,
options?: { detectCycles?: boolean },
): DiContainer;
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import { checkForCyclesFor } from './checkForCyclesFor';
import { setDependeeFor } from './setDependeeFor';
import { checkForSideEffectsFor } from './checkForSideEffectsFor';
import { getRelatedInjectablesFor } from './getRelatedInjectablesFor';
import { noop } from 'lodash/fp';

export default containerId => {
export default (containerId, { detectCycles = true } = {}) => {
const injectableSet = new Set();
const overridingInjectables = new Map();
let sideEffectsArePrevented = false;
Expand Down Expand Up @@ -60,10 +61,12 @@ export default containerId => {
withMeta: true,
});

const checkForCycles = checkForCyclesFor({
dependeesByDependencyMap,
getNamespacedId,
});
const checkForCycles = detectCycles
? checkForCyclesFor({
dependeesByDependencyMap,
getNamespacedId,
})
: noop;

const withInjectionDecorators = withInjectionDecoratorsFor({
injectMany: nonDecoratedPrivateInjectMany,
Expand Down
71 changes: 42 additions & 29 deletions packages/injectable/core/src/scenarios/cycle-detection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,28 @@ import createContainer from '../dependency-injection-container/createContainer';
import getInjectable from '../getInjectable/getInjectable';

describe('cycle-detection', () => {
it('given di with cycle detection disabled, only bad work is done, throws error about maximum call stack size exceeded', () => {
const di = createContainer('some-container', { detectCycles: false });

di.register(
goodInjectable,
badInjectable,
workerInjectable,
someCyclicalInjectable1,
someCyclicalInjectable2,
);

expect(() => {
di.inject(badInjectable);
}).toThrow('Maximum call stack size exceeded');
});

describe('given no cycle and injected', () => {
let di;
let goodInjectable;
let badInjectable;
let someCyclicalInjectable1;

beforeEach(() => {
di = createContainer('some-container');

goodInjectable = getInjectable({
id: 'some-good-injectable',
instantiate: di => di.inject(workerInjectable)(true),
});

badInjectable = getInjectable({
id: 'some-bad-injectable',
instantiate: di => di.inject(workerInjectable)(false),
});

someCyclicalInjectable1 = getInjectable({
id: 'some-cyclical-injectable-1',
instantiate: di => di.inject(someCyclicalInjectable2),
});

const someCyclicalInjectable2 = getInjectable({
id: 'some-cyclical-injectable-2',
instantiate: di => di.inject(someCyclicalInjectable1),
});

const workerInjectable = getInjectable({
id: 'some-worker-injectable',
instantiate: di => good =>
good ? 'some-good-result' : di.inject(someCyclicalInjectable1),
});

di.register(
goodInjectable,
badInjectable,
Expand Down Expand Up @@ -85,3 +72,29 @@ describe('cycle-detection', () => {
});
});
});

const goodInjectable = getInjectable({
id: 'some-good-injectable',
instantiate: di => di.inject(workerInjectable)(true),
});

const badInjectable = getInjectable({
id: 'some-bad-injectable',
instantiate: di => di.inject(workerInjectable)(false),
});

const someCyclicalInjectable1 = getInjectable({
id: 'some-cyclical-injectable-1',
instantiate: di => di.inject(someCyclicalInjectable2),
});

const someCyclicalInjectable2 = getInjectable({
id: 'some-cyclical-injectable-2',
instantiate: di => di.inject(someCyclicalInjectable1),
});

const workerInjectable = getInjectable({
id: 'some-worker-injectable',
instantiate: di => good =>
good ? 'some-good-result' : di.inject(someCyclicalInjectable1),
});

0 comments on commit 661f346

Please sign in to comment.