Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[module-detection] zustand - React state management #79

Open
Tracked by #41
0xdevalias opened this issue Dec 20, 2023 · 0 comments
Open
Tracked by #41

[module-detection] zustand - React state management #79

0xdevalias opened this issue Dec 20, 2023 · 0 comments
Labels
enhancement New feature or request scope: unminify

Comments

@0xdevalias
Copy link

0xdevalias commented Dec 20, 2023

This relates to the 'module-detection' feature described in the following issue:

Overview

zustand is a state management library used in React apps:

  • https://github.com/pmndrs/zustand
    • Bear necessities for state management in React

    • A small, fast and scalable bearbones state-management solution using simplified flux principles. Has a comfy API based on hooks, isn't boilerplatey or opinionated.

Code

Unminifying this source (Ref):

Original (prettified)
// unpacked/_next/static/chunks/pages/_app.js, lines 58342-58372
    81292: function (U, B, G) {
      "use strict";
      G.d(B, {
        ZP: function () {
          return tt;
        },
        oR: function () {
          return X;
        },
      });
      var Y = G(97703),
        V = G(70079),
        Z = G(92280);
      let { useSyncExternalStoreWithSelector: J } = Z;
      function X(U, B = U.getState, G) {
        let Y = J(
          U.subscribe,
          U.getState,
          U.getServerState || U.getState,
          B,
          G
        );
        return (0, V.useDebugValue)(Y), Y;
      }
      let Q = (U) => {
          let B = "function" == typeof U ? (0, Y.Z)(U) : U,
            G = (U, G) => X(B, U, G);
          return Object.assign(G, B), G;
        },
        tt = (U) => (U ? Q(U) : Q);
    },
Source (unpacked)
// module-81292.js
"use strict";
var Y = require(97703);
var V = require(70079);
var Z = require(92280);
let { useSyncExternalStoreWithSelector: J } = Z;
function X(U, B = U.getState, G) {
  let Y = J(U.subscribe, U.getState, U.getServerState || U.getState, B, G);
  return (0, V.useDebugValue)(Y), Y;
}

let Q = (U) => {
  let B = "function" == typeof U ? (0, Y.Z)(U) : U;
  let G = (U, G) => X(B, U, G);
  return Object.assign(G, B), G;
};

let tt = (U) => (U ? Q(U) : Q);

module.exports = {
  ZP: tt,
  oR: X,
};

Transformed (unminified)

// module-81292.js
import Y, { Z as Z$0 } from "module-97703.js";
import Z from "module-92280.js";

const { useDebugValue } = require(70079);

let { useSyncExternalStoreWithSelector } = Z;
function X(U, B = U.getState, G) {
  let Y = useSyncExternalStoreWithSelector(
    U.subscribe,
    U.getState,
    U.getServerState || U.getState,
    B,
    G
  );
  useDebugValue(Y);
  return Y;
}

let Q = (U) => {
  let B = typeof U == "function" ? Z$0(U) : U;
  let G = (U, G) => X(B, U, G);
  Object.assign(G, B);
  return G;
};

let tt = (U) => (U ? Q(U) : Q);

export default {
  ZP: tt,
  oR: X,
};

Searching for some of those symbols on GitHub code search:

Of those results, this looks the most promising:

// zustand/src/react.ts, lines 7-10
import ReactExports from 'react'
import useSyncExternalStoreExports from 'use-sync-external-store/shim/with-selector'
import { createStore } from './vanilla.ts'
// zustand/src/react.ts, lines 18-19
const { useDebugValue } = ReactExports
const { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports
  • For this code: const { useDebugValue } = require(70079);
    • module-70079.js is literally just module.exports = require(99504);
    • module-99504.js is react.production.min.js
// zustand/src/react.ts, lines 50-74
export function useStore(api, selector = api.getState, equalityFn) {
  // ..snip..
  const slice = useSyncExternalStoreWithSelector(
    api.subscribe,
    api.getState,
    api.getServerState || api.getState,
    selector,
    equalityFn,
  )
  useDebugValue(slice)
  return slice
}
// zustand/src/react.ts, lines 101-122
const createImpl = (createState) => {
  // ..snip..
  const api = typeof createState === 'function' ? createStore(createState) : createState

  const useBoundStore = (selector, equalityFn) => useStore(api, selector, equalityFn)

  Object.assign(useBoundStore, api)

  return useBoundStore
}

export const create = ((createState) => createState ? createImpl(createState) : createImpl)

From that, it seems the Z$0 function is createStore, which in this bundled code, is imported from 97703:

Original (prettified)
// unpacked/_next/static/chunks/pages/_app.js, lines 58373-L58400
    97703: function (U, B, G) {
      "use strict";
      G.d(B, {
        Z: function () {
          return V;
        },
      });
      let Y = (U) => {
          let B;
          let G = new Set(),
            Y = (U, Y) => {
              let V = "function" == typeof U ? U(B) : U;
              if (!Object.is(V, B)) {
                let U = B;
                (B = (null != Y ? Y : "object" != typeof V)
                  ? V
                  : Object.assign({}, B, V)),
                  G.forEach((G) => G(B, U));
              }
            },
            V = () => B,
            Z = (U) => (G.add(U), () => G.delete(U)),
            J = () => G.clear(),
            X = { setState: Y, getState: V, subscribe: Z, destroy: J };
          return (B = U(Y, V, X)), X;
        },
        V = (U) => (U ? Y(U) : Y);
    },
Source (unpacked)
// module-97703.js
"use strict";
let Y = (U) => {
  let B;
  let G = new Set();

  let Y = (U, Y) => {
    let V = "function" == typeof U ? U(B) : U;
    if (!Object.is(V, B)) {
      let U = B;
      (B = (null != Y ? Y : "object" != typeof V)
        ? V
        : Object.assign({}, B, V)),
        G.forEach((G) => G(B, U));
    }
  };

  let V = () => B;
  let Z = (U) => (G.add(U), () => G.delete(U));
  let J = () => G.clear();
  let X = { setState: Y, getState: V, subscribe: Z, destroy: J };
  return (B = U(Y, V, X)), X;
};

let V = (U) => (U ? Y(U) : Y);

module.exports = {
  Z: V,
};

Transformed (unminified)

// module-97703.js
let Y = (U) => {
  let B;
  let G = new Set();

  let Y = (U, Y) => {
    let V = typeof U == "function" ? U(B) : U;
    if (!Object.is(V, B)) {
      let U = B;

      B = (Y != null ? Y : typeof V != "object") ? V : Object.assign({}, B, V);

      G.forEach((G) => G(B, U));
    }
  };

  let V = () => B;
  let Z = (U) => {
    G.add(U);

    return () => G.delete(U);
  };
  let J = () => G.clear();
  let X = { setState: Y, getState: V, subscribe: Z, destroy: J };
  B = U(Y, V, X);
  return X;
};

let V = (U) => (U ? Y(U) : Y);

export default {
  Z: V,
};

Which based on the above, seems to correspond to:

// zustand/src/vanilla.ts, lines 60-106
const createStoreImpl = createState => {
  let state
  const listeners = new Set()

  const setState = (partial, replace) => {
    const nextState = typeof partial === "function" ? partial(state) : partial
    if (!Object.is(nextState, state)) {
      const previousState = state
      state =
        replace ?? (typeof nextState !== "object" || nextState === null)
          ? nextState
          : Object.assign({}, state, nextState)
      listeners.forEach(listener => listener(state, previousState))
    }
  }

  const getState = () => state

  const subscribe = listener => {
    listeners.add(listener)
    return () => listeners.delete(listener)
  }

  const destroy = () => {
    listeners.clear()
  }

  const api = { setState, getState, subscribe, destroy }
  state = createState(setState, getState, api)
  return api
}

export const createStore = createState =>
  createState ? createStoreImpl(createState) : createStoreImpl
@pionxzh pionxzh added enhancement New feature or request scope: unminify labels Dec 20, 2023
@pionxzh pionxzh mentioned this issue Dec 24, 2023
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request scope: unminify
Projects
None yet
Development

No branches or pull requests

2 participants