diff --git a/expose.json b/expose.json index e10398fba3..d87a2e77c6 100644 --- a/expose.json +++ b/expose.json @@ -1,94 +1,130 @@ { - "$comment": "Apply-time source patches that expose Spotify internals on the Spicetify global, applied to the xpui-modules.js extracted from the v8 snapshot. Fetched by the CLI through index.json; the CLI embeds a copy as its offline baseline. `replace` is a capture-group template (${0} whole match, ${N} group N; `$$` for a literal dollar). `once` stops after the first match. `onMiss` is `warn` (a miss means a Spotify update moved the code) or `quiet` (a miss is expected on some supported builds). `note` records the measured hit count per build.", "version": 1, "patches": [ { "name": "Expose PlatformAPI", - "note": "1.2.84: 1, 1.2.96: 1.", "pattern": "((?:setTitlebarHeight|registerFactory)[\\w(){}<>:.,&$!=;\"\"?!#%/\\- ]+)(\\{version:[a-zA-Z_\\$][\\w\\$]*,)", "replace": "${1}Spicetify._platform=${2}", "once": false, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 1, + "1.2.96": 1 + } }, { "name": "Redux store", - "note": "1.2.84: 0, 1.2.96: 1. The store is created inside an IIFE invoked with the session/features/seoExperiment object; this anchors on the only `return (0,createStore)((0,combineReducers)({` in that IIFE and routes the created store through the global. 1.2.84 builds the store another way and has no seoExperiment key at all, so ReduxStore is not exposed there yet.", "pattern": "return(\\(0,[\\w$]+\\.[\\w$]+\\)\\(\\(0,[\\w$]+\\.[\\w$]+\\)\\(\\{(?s:.{0,1500}?)\\)\\}\\(\\{session:[\\w$]+,features:[\\w$]+,seoExperiment:[\\w$]+\\},\\{platform:)", "replace": "return Spicetify.Platform.ReduxStore=${1}", "once": true, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 0, + "1.2.96": 1 + }, + "note": "The store is created inside an IIFE invoked with the session/features/seoExperiment object; this anchors on the only `return (0,createStore)((0,combineReducers)({` in that IIFE and routes the created store through the global. 1.2.84 builds the store another way and has no seoExperiment key at all, so ReduxStore is not exposed there yet." }, { "name": "React Component: Platform Provider", - "note": "1.2.84: 0, 1.2.96: 2.", "pattern": "(,[$\\w]+=)((function\\([\\w$]{1}\\)\\{var [\\w$]+=[\\w$]+\\.platform,[\\w$]+=[\\w$]+\\.children,)|(\\(\\{platform:[\\w$]+,children:[\\w$]+\\}\\)=>\\{))", "replace": "${1}Spicetify.ReactComponent.PlatformProvider=${2}", "once": false, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 0, + "1.2.96": 2 + } }, { "name": "Spotify Custom Snackbar Interface", - "note": "1.2.84: 1, 1.2.96: 1.", "pattern": "\\b\\w\\s*\\(\\)\\s*[^;,]*enqueueCustomSnackbar:\\s*(\\w)\\s*[^;]*;", "replace": "${0}Spicetify.Snackbar.enqueueCustomSnackbar=${1};", "once": false, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 1, + "1.2.96": 1 + } }, { "name": "Spotify Image Snackbar Interface", - "note": "1.2.84: 1, 1.2.96: 1. The enqueue arrow is returned through useCallback rather than assigned.", "pattern": "return(\\(0,[\\w$]+\\.useCallback\\)\\(\\(\\{message:[\\w$]+,\\s*imageSrc)", "replace": "return Spicetify.Snackbar.enqueueImageSnackbar=${1}", "once": false, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 1, + "1.2.96": 1 + }, + "note": "The enqueue arrow is returned through useCallback rather than assigned." }, { "name": "React Component: Navigation for navLinks", - "note": "1.2.84: 1, 1.2.96: 0. The wrapper finds Navigation through webpack at runtime (react-components.js), so a miss is covered.", "pattern": "(;const [\\w\\d]+=)((?:\\(0,[\\w\\d]+\\.memo\\))[\\(\\d,\\w\\.\\){:}=]+=[\\d\\w]+\\.[\\d\\w]+\\.getLocaleForURLPath\\(\\))", "replace": "${1}Spicetify.ReactComponent.Navigation=${2}", "once": true, - "onMiss": "quiet" + "onMiss": "quiet", + "hits": { + "1.2.84": 1, + "1.2.96": 0 + }, + "note": "The wrapper finds Navigation through webpack at runtime (react-components.js), so a miss is covered." }, { "name": "Context Menu V2", - "note": "1.2.84: 1, 1.2.96: 1.", "pattern": "(\"Menu\".+?children:)([\\w$][\\w$\\d]*)", "replace": "${1}[Spicetify.ContextMenuV2.renderItems(),${2}].flat()", "once": false, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 1, + "1.2.96": 1 + } }, { "name": "Map styled-components classes", - "note": "1.2.84: 1, 1.2.96: 1.", "pattern": "(\\w+ [\\w$_]+)=[\\w$_]+\\([\\w$_]+>>>0\\)", "replace": "${1}=Spicetify._getStyledClassName(arguments,this)", "once": false, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 1, + "1.2.96": 1 + } }, { "name": "Tippy.js", - "note": "1.2.84: 2, 1.2.96: 2.", "pattern": "([\\w\\$_]+)\\.setDefaultProps=", "replace": "Spicetify.Tippy=${1};${0}", "once": false, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 2, + "1.2.96": 2 + } }, { "name": "Flipper components", - "note": "1.2.84: 1, 1.2.96: 0. react-flip-toolkit left the client in 1.2.9x; nothing remains to expose there.", "pattern": "([\\w$]+)=((?:function|\\()([\\w$.,{}()= ]+(?:springConfig|overshootClamping)){2})", "replace": "${1}=Spicetify.ReactFlipToolkit.spring=${2}", "once": false, - "onMiss": "quiet" + "onMiss": "quiet", + "hits": { + "1.2.84": 1, + "1.2.96": 0 + }, + "note": "react-flip-toolkit left the client in 1.2.9x; nothing remains to expose there." }, { "name": "Snackbar", - "note": "1.2.84: 1, 1.2.96: 1.", "pattern": "\\w+\\s*=\\s*\\w\\.call\\(this,[^)]+\\)\\s*\\|\\|\\s*this\\)\\.enqueueSnackbar", "replace": "Spicetify.Snackbar=${0}", "once": false, - "onMiss": "warn" + "onMiss": "warn", + "hits": { + "1.2.84": 1, + "1.2.96": 1 + } } ] } diff --git a/scripts/classmap_capture.py b/scripts/classmap_capture.py index dd2fed812f..ad9c35bbd6 100644 --- a/scripts/classmap_capture.py +++ b/scripts/classmap_capture.py @@ -20,7 +20,7 @@ Examples -------- python3 scripts/classmap_capture.py migrate \\ - --base-classmap ../classmaps/1020040/classmap-190747c4b8f.json \\ + --base-classmap ../classmaps/1020040/classmap.json \\ --base-css-dir ../xpui-archive/1.2.40.599 \\ --target-spa "/Applications/Spotify.app/Contents/Resources/Apps/xpui.spa" \\ --css-map css-map.json \\ diff --git a/scripts/classmap_e2e.sh b/scripts/classmap_e2e.sh index 9926b7d2b5..d118620858 100755 --- a/scripts/classmap_e2e.sh +++ b/scripts/classmap_e2e.sh @@ -74,7 +74,7 @@ STOCK_SPA_CANDIDATES=( "/Applications/Spotify.app/Contents/Resources/Apps/xpui.spa" "/Applications/Spotify.app/Contents/Resources/Apps/xpui.spa.bak" ) -BASE_CLASSMAP="${BASE_CLASSMAP:-$ROOT/../classmaps/1020040/classmap-190747c4b8f.json}" +BASE_CLASSMAP="${BASE_CLASSMAP:-$ROOT/../classmaps/1020040/classmap.json}" BASE_CSS_DIR="${BASE_CSS_DIR:-$ROOT/../xpui-archive/1.2.40.599}" OUT_DIR="${OUT_DIR:-$ROOT/classmaps/1020092}" CSS_MAP="${CSS_MAP:-$ROOT/css-map.json}"