Skip to content

Commit

Permalink
Support bfcache.
Browse files Browse the repository at this point in the history
Also remove the legacy fallback for browsers without StorageManager.
Reason: It only applied to Safari<16 but those versions of safari had buggy storage implementations of localStorage anyway.
  • Loading branch information
dfahlander committed Jan 31, 2024
1 parent a032bf4 commit 46b2903
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 81 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { dexieStackFrameFilter } from './globals/constants';
// (implement interface DexieConstructor):
import './classes/dexie/dexie-static-props';
import './live-query/enable-broadcast';
import './support-bfcache';
import { liveQuery } from './live-query/live-query';
import { Entity } from './classes/entity/Entity';
import { cmp } from './functions/cmp';
Expand Down
36 changes: 24 additions & 12 deletions src/live-query/cache/signalSubscribers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,30 @@ export function signalSubscribersNow(
deleteAffectedCacheEntries = false
) {
const queriesToSignal = new Set<() => void>();
for (const key in updatedParts) {
const parts = /^idb\:\/\/(.*)\/(.*)\//.exec(key);
if (parts) {
const [, dbName, tableName] = parts;
const tblCache = cache[`idb://${dbName}/${tableName}`];
if (tblCache)
signalTableSubscribersNow(
tblCache,
updatedParts,
queriesToSignal,
deleteAffectedCacheEntries
);
if (updatedParts.all) {
// Signal all subscribers to requery.
for (const tblCache of Object.values(cache)) {
signalTableSubscribersNow(
tblCache,
updatedParts,
queriesToSignal,
deleteAffectedCacheEntries
);
}
} else {
for (const key in updatedParts) {
const parts = /^idb\:\/\/(.*)\/(.*)\//.exec(key);
if (parts) {
const [, dbName, tableName] = parts;
const tblCache = cache[`idb://${dbName}/${tableName}`];
if (tblCache)
signalTableSubscribersNow(
tblCache,
updatedParts,
queriesToSignal,
deleteAffectedCacheEntries
);
}
}
}
// Now when affected cache entries are removed, signal collected subscribers to requery.
Expand Down
77 changes: 9 additions & 68 deletions src/live-query/enable-broadcast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@ import {
} from '../globals/global-events';
import { propagateLocally, propagatingLocally } from './propagate-locally';

export let bc: BroadcastChannel;

export let createBC = ()=>{};

if (typeof BroadcastChannel !== 'undefined') {
const bc = new BroadcastChannel(STORAGE_MUTATED_DOM_EVENT_NAME);
createBC = () => {
bc = new BroadcastChannel(STORAGE_MUTATED_DOM_EVENT_NAME);
bc.onmessage = ev => ev.data && propagateLocally(ev.data);
}
createBC();

/**
* The Node.js BroadcastChannel will prevent the node process from exiting
Expand All @@ -28,71 +36,4 @@ if (typeof BroadcastChannel !== 'undefined') {
bc.postMessage(changedParts);
}
});

//
// Propagate remote changes locally via storage event:
//
bc.onmessage = (ev) => {
if (ev.data) propagateLocally(ev.data);
};
} else if (typeof self !== 'undefined' && typeof navigator !== 'undefined') {
// DOM verified - when typeof self !== "undefined", we are a window or worker. Not a Node process.

//
// Propagate local changes to remote tabs/windows via storage event and service worker
// via messages. We have this code here because of https://bugs.webkit.org/show_bug.cgi?id=161472.
//
globalEvents(DEXIE_STORAGE_MUTATED_EVENT_NAME, (changedParts) => {
try {
if (!propagatingLocally) {
if (typeof localStorage !== 'undefined') {
// We're a browsing window or tab. Propagate to other windows/tabs via storage event:
localStorage.setItem(
STORAGE_MUTATED_DOM_EVENT_NAME,
JSON.stringify({
trig: Math.random(),
changedParts,
})
);
}
if (typeof self['clients'] === 'object') {
// We're a service worker. Propagate to our browser clients.
[...self['clients'].matchAll({ includeUncontrolled: true })].forEach(
(client) =>
client.postMessage({
type: STORAGE_MUTATED_DOM_EVENT_NAME,
changedParts,
})
);
}
}
} catch {}
});

//
// Propagate remote changes locally via storage event:
//
if (typeof addEventListener !== 'undefined') {
addEventListener('storage', (ev: StorageEvent) => {
if (ev.key === STORAGE_MUTATED_DOM_EVENT_NAME) {
const data = JSON.parse(ev.newValue);
if (data) propagateLocally(data.changedParts);
}
});
}

//
// Propagate messages from service worker
//
const swContainer = self.document && navigator.serviceWorker; // self.document is to verify we're not the SW ourself
if (swContainer) {
// We're a browser window and want to propagate message from the SW:
swContainer.addEventListener('message', propagateMessageLocally);
}
}

function propagateMessageLocally({ data }: MessageEvent) {
if (data && data.type === STORAGE_MUTATED_DOM_EVENT_NAME) {
propagateLocally(data.changedParts);
}
}
2 changes: 1 addition & 1 deletion src/live-query/obs-sets-overlap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { rangesOverlap } from '../helpers/rangeset';
import { ObservabilitySet } from '../public/types/db-events';

export function obsSetsOverlap(os1: ObservabilitySet, os2: ObservabilitySet) {
return Object.keys(os1).some(
return os1.all || os2.all || Object.keys(os1).some(
(key) => os2[key] && rangesOverlap(os2[key], os1[key])
);
}
22 changes: 22 additions & 0 deletions src/support-bfcache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { connections } from "./globals/constants";
import { RangeSet } from "./helpers/rangeset";
import { bc, createBC } from "./live-query/enable-broadcast";
import { propagateLocally } from "./live-query/propagate-locally";


if (typeof addEventListener !== 'undefined') {
addEventListener('pagehide', (event) => {
if (event.persisted) {
bc?.close();
}
for (const db of connections) {
db.close({disableAutoOpen: false});
}
});
addEventListener('pageshow', (event) => {
if (event.persisted) {
createBC();
propagateLocally({all: new RangeSet(-Infinity, [[]])}); // Trigger all queries to requery
}
});
}

0 comments on commit 46b2903

Please sign in to comment.