Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 33 additions & 10 deletions src/localspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const DefaultDriverOrder = [
DefaultDrivers.INDEXEDDB._driver,
DefaultDrivers.LOCALSTORAGE._driver,
];
const PendingDefaultDriverDefinitions: Record<string, Promise<void>> = {};

const OptionalDriverMethods = [
'dropInstance',
Expand Down Expand Up @@ -137,6 +138,30 @@ function callWhenReady(
} as ReadyWrappedMethod;
}

function defineDefaultDriverOnce(
definer: { defineDriver: (driver: Driver) => Promise<void> },
driver: Driver
): Promise<void> {
const driverName = driver._driver;

if (DefinedDrivers[driverName]) {
return Promise.resolve();
}

const pendingDefinition = PendingDefaultDriverDefinitions[driverName];
if (pendingDefinition) {
return pendingDefinition;
}

const definitionPromise = definer.defineDriver(driver).finally(() => {
if (PendingDefaultDriverDefinitions[driverName] === definitionPromise) {
delete PendingDefaultDriverDefinitions[driverName];
}
});
PendingDefaultDriverDefinitions[driverName] = definitionPromise;
return definitionPromise;
}

export class LocalSpace implements LocalSpaceInstance {
readonly INDEXEDDB = 'asyncStorage';
readonly LOCALSTORAGE = 'localStorageWrapper';
Expand Down Expand Up @@ -169,16 +194,14 @@ export class LocalSpace implements LocalSpaceInstance {
const driverName = driver._driver;
(this as unknown as Record<string, string>)[driverTypeKey] = driverName;

if (!DefinedDrivers[driverName]) {
driverInitializationPromises.push(
this.defineDriver(driver).catch((error) => {
console.warn(
`Failed to define LocalSpace driver "${driverName}"`,
error
);
})
);
}
driverInitializationPromises.push(
defineDefaultDriverOnce(this, driver).catch((error) => {
console.warn(
`Failed to define LocalSpace driver "${driverName}"`,
error
);
})
);
}
}

Expand Down
34 changes: 34 additions & 0 deletions test/driver-initialization.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,38 @@ describe('driver initialization ordering', () => {
vi.resetModules();
}
});

it('does not redefine default drivers when creating instances before singleton ready', async () => {
vi.resetModules();

const userAgentSpy = vi
.spyOn(window.navigator, 'userAgent', 'get')
.mockReturnValue('Safari/605.1.15');
const consoleInfoSpy = vi
.spyOn(console, 'info')
.mockImplementation(() => {});

try {
const { default: localspace } = await import('../src/index');

const instances = Array.from({ length: 4 }, (_, index) =>
localspace.createInstance({
name: `singleton-race-${index}`,
storeName: `singleton_race_${index}`,
})
);

await Promise.all(instances.map((instance) => instance.ready()));

const redefineCalls = consoleInfoSpy.mock.calls.filter(([message]) =>
typeof message === 'string' &&
message.includes('Redefining LocalSpace driver')
);
expect(redefineCalls).toHaveLength(0);
} finally {
consoleInfoSpy.mockRestore();
userAgentSpy.mockRestore();
vi.resetModules();
}
});
});