August 19, 2026
b7e0f69c5ad861d7a39de8c6a7be15aa70726ec0264412c5916c197ba83427e3 Previous:
166e1f5d Bundle: 93.8 KB Sidekick module gains a registerNavigationReadinessProvider method; library version bumped to 0.38.9.
Highlights
- The sidekick module adds a new registerNavigationReadinessProvider method that lets apps register a readiness provider and returns an unregister function that cleans up when called.
- Internal library version string was bumped from 0.38.8+8a261cd7 to 0.38.9+efa5798b.
- The fetch, print, share, and window.open/history interception helpers were renamed internally with no observable behavior change.
Infrastructure Changes
REPORT.md +5 -5
@@ -1,6 +1,6 @@
# Shopify App Bridge — Unminification Report
Generated: 2026-08-07T08:21:59.333Z
Generated: 2026-08-19T08:08:19.816Z
## Files
@@ -8,7 +8,7 @@ Generated: 2026-08-07T08:21:59.333Z
|------|------|-------|------|
| _bootstrap.js | 30.1KB | 1052 | Infrastructure |
| _remote-ui.js | 6.1KB | 257 | Infrastructure |
| _utilities.js | 76.1KB | 2849 | Infrastructure |
| _utilities.js | 76.2KB | 2858 | Infrastructure |
| _web-vitals.js | 11.6KB | 527 | Infrastructure |
| analytics.js | 211B | 11 | Module |
| app.js | 346B | 15 | Module |
@@ -24,7 +24,7 @@ Generated: 2026-08-07T08:21:59.333Z
| picker.js | 451B | 18 | Module |
| polaris.js | 240B | 12 | Module |
| pos.js | 5.7KB | 248 | Module |
| print.js | 562B | 25 | Module |
| print.js | 558B | 25 | Module |
| resource-picker.js | 2.8KB | 117 | Module |
| reviews.js | 365B | 16 | Module |
| s-app-nav.js | 175B | 10 | Module |
@@ -35,7 +35,7 @@ Generated: 2026-08-07T08:21:59.333Z
| share.js | 1.3KB | 58 | Module |
| shopifyQL.js | 262B | 12 | Module |
| shortcut.js | 461B | 24 | Module |
| sidekick.js | 4.7KB | 154 | Module |
| sidekick.js | 5.3KB | 179 | Module |
| support.js | 508B | 21 | Module |
| telemetry.js | 935B | 35 | Module |
| title-bar.js | 7.6KB | 290 | Module |
@@ -46,7 +46,7 @@ Generated: 2026-08-07T08:21:59.333Z
| user.js | 940B | 37 | Module |
| visibility.js | 973B | 34 | Module |
| web-vitals.js | 1.9KB | 66 | Module |
| **Total** | **176.8KB** | **6718** | |
| **Total** | **177.5KB** | **6752** | |
## Pipeline Stages
modules/_bootstrap.js +2 -2
@@ -234,7 +234,7 @@
type: t.type,
lastModified: t.lastModified,
},
content: Tt(t),
content: interceptProperty(t),
};
} else {
if (Array.isArray(t)) {
@@ -498,7 +498,7 @@
window.shopify = n.shopify;
window.polaris = n.polaris;
const t = window.open;
safeAsyncCall(self, 'open', function (n, e, o) {
deepClone(self, 'open', function (n, e, o) {
return n != null && generateId(n).protocol !== 'https:'
? window.opener.open(n, e, o)
: t.call(this, n, e, o);
modules/_utilities.js Truncated +23 -24
@@ -583,7 +583,7 @@ function checkPrivateField(t) {
return n.buffer;
}
const restoreProperty = globalThis.XMLHttpRequest;
function Tt(t) {
function interceptProperty(t) {
let n = null;
try {
n = URL.createObjectURL(t);
@@ -602,7 +602,7 @@ function Tt(t) {
}
}
}
function interceptProperty(t, n) {
function Tt(t, n) {
if (!{}.hasOwnProperty.call(t, n))
throw new TypeError('attempted to use private field on non-instance');
return t;
@@ -627,24 +627,24 @@ function It(t = false) {
writable: true,
value: new Set(),
});
interceptProperty(this, o)[o] = t;
Tt(this, o)[o] = t;
if (!((n = e) == null)) {
n.add(this);
}
}
get value() {
return interceptProperty(this, o)[o];
return Tt(this, o)[o];
}
set value(t) {
if (t !== interceptProperty(this, o)[o]) {
if (t !== Tt(this, o)[o]) {
interceptProperty(this, o)[o] = t;
Tt(this, o)[o] = t;
interceptProperty(this, i)[i].forEach((n) => n(t));
Tt(this, i)[i].forEach((n) => n(t));
}
}
subscribe(t) {
interceptProperty(this, i)[i].add(t);
Tt(this, i)[i].add(t);
return () => {
interceptProperty(this, i)[i].delete(t);
Tt(this, i)[i].delete(t);
};
}
}
@@ -727,11 +727,11 @@ function It(t = false) {
};
}
It(true);
const Mt = '0.38.8+8a261cd7';
const Mt = '0.38.9+efa5798b';
const deepClone = Symbol();
const safeAsyncCall = Symbol();
function safeAsyncCall(t, n, e) {
function deepClone(t, n, e) {
const o = t[n];
e[deepClone] = o;
e[safeAsyncCall] = o;
Object.defineProperty(t, n, {
enumerable: true,
configurable: true,
@@ -741,7 +741,7 @@ function safeAsyncCall(t, n, e) {
return o;
}
function xt(t, n) {
const e = t[n][deepClone];
const e = t[n][safeAsyncCall];
if (e) {
Object.defineProperty(t, n, {
enumerable: true,
@@ -770,7 +770,7 @@ const SHOPIFY_PROTOCOLS = ({ api, protocol, internalApiPromise }) => {
verified: false,
};
}
safeAsyncCall(globalThis, 'fetch', async function (a, s) {
deepClone(globalThis, 'fetch', async function (a, s) {
const request = new Request(a instanceof Request ? a.clone() : a, s);
const { appOrigins: u = [] } = api.config;
const url = new URL(request.url);
@@ -1076,7 +1076,7 @@ const tn = ({ internalApiPromise, saveBarManager, rpcEventTarget }) => {
true,
);
const a = self.open;
safeAsyncCall(self, 'open', function (t, e, o) {
deepClone(self, 'open', function (t, e, o) {
const i = t ? generateId(t).protocol : undefined;
if (t == null || !i || !qt.includes(i)) return a.call(this, t, e, o);
const r = e == null || e === '' ? '_blank' : Xt(e);
@@ -1155,16 +1155,16 @@ const tn = ({ internalApiPromise, saveBarManager, rpcEventTarget }) => {
});
}
}
safeAsyncCall(history, 'pushState', function (t, n, e) {
deepClone(history, 'pushState', function (t, n, e) {
c.call(history, t, n, e);
s.pushState(e);
});
safeAsyncCall(history, 'replaceState', function (t, n, e) {
deepClone(history, 'replaceState', function (t, n, e) {
c.call(history, t, n, e);
s.replaceState(e);
});
const f = HTMLFormElement.prototype.submit;
safeAsyncCall(HTMLFormElement.prototype, 'submit', function () {
deepClone(HTMLFormElement.prototype, 'submit', function () {
if (Yt(this)) {
saveBarManager.allowNextUnload();
}
@@ -1206,7 +1206,7 @@ const nn = ({ protocol, internalApiPromise }) => {
}
if (o && 'navigate' in o) {
o.navigate;
const n = safeAsyncCall(o, 'navigate', function (e, o) {
const n = deepClone(o, 'navigate', function (e, o) {
const i = s(e);
return i
? (protocol.send('Navigation.redirect.admin.path', {
@@ -1236,7 +1236,7 @@ const nn = ({ protocol, internalApiPromise }) => {
);
else {
const t = history.pushState;
safeAsyncCall(history, 'pushState', function (n, e, o) {
deepClone(history, 'pushState', function (n, e, o) {
const r = location.href;
t.call(this, n, e, o);
if (o && new URL(o, r).href !== r) {
@@ -1247,7 +1247,7 @@ const nn = ({ protocol, internalApiPromise }) => {
xt(history, 'pushState');
});
const n = history.replaceState;
safeAsyncCall(history, 'replaceState', function (t, e, o) {
deepClone(history, 'replaceState', function (t, e, o) {
const r = location.href;
n.call(this, t, e, o);
if (o && new URL(o, r).href !== r) {
@@ -1268,7 +1268,7 @@ const nn = ({ protocol, internalApiPromise }) => {
);
}
const r = self.open;
safeAsyncCall(self, 'open', function (e, o, i) {
deepClone(self, 'open', function (e, o, i) {
if (e == null) return r.call(this, e, o, i);
const a = (function (t) {
const url = new URL(t, location.href);
@@ -1305,7 +1305,7 @@ const nn = ({ protocol, internalApiPromise }) => {
throw Error('_modal is not yet implemented');
case '':
case '_blank':
if (!/noopener/i.test(i) && !T() && !C()) break;
... (truncated)
Diff truncated at 200 lines
Module Changes
modules/fetch.js +1 -1
@@ -23,7 +23,7 @@ const SHOPIFY_PROTOCOLS = ({ api, protocol, internalApiPromise }) => {
verified: false,
};
}
safeAsyncCall(globalThis, 'fetch', async function (a, s) {
deepClone(globalThis, 'fetch', async function (a, s) {
const request = new Request(a instanceof Request ? a.clone() : a, s);
const { appOrigins: u = [] } = api.config;
const url = new URL(request.url);
modules/print.js +1 -1
@@ -4,8 +4,8 @@
*/
const printModule = ({ protocol, internalApiPromise }) => {
safeAsyncCall(self, 'print', function () {
deepClone(self, 'print', function () {
const e = document.scrollingElement?.scrollHeight || document.body.offsetHeight;
parseUrl(async () => {
const { print: o } = (await internalApiPromise) || {};
modules/share.js +1 -1
@@ -4,9 +4,9 @@
*/
const shareModule = ({ protocol, internalApiPromise }) => {
const e = navigator.share;
safeAsyncCall(navigator, 'share', async function (o) {
deepClone(navigator, 'share', async function (o) {
if (!o) return e.call(navigator, o);
const { share: i } = (await internalApiPromise) || {};
const { title: r, text: a, url: s } = o;
modules/sidekick.js +25 -0
@@ -148,6 +148,31 @@ const sidekickModule = ({ api, internalApiPromise, rpcEventTarget }) => {
});
return i;
},
registerNavigationReadinessProvider: (t) => {
let e;
let o = false;
function i() {
e?.();
u(e);
e = undefined;
}
parseUrl(async () => {
const { sidekick: r } = (await internalApiPromise) || {};
if (!o) {
if (!r || typeof r.registerNavigationReadinessProvider != 'function')
throw Error('Sidekick API is not available');
e = await r.registerNavigationReadinessProvider(t);
s(e);
if (o) {
i();
}
}
});
return function () {
o = true;
i();
};
},
};
api.sidekick = a;
};