All entries

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.
7 files changed +58 -34

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;
};