Deprecate proxyLazy and proxyInner top level destructure
This commit is contained in:
parent
e9081d2a52
commit
c785053b86
|
@ -40,7 +40,7 @@ import { Alerts, Button, Card, Forms, lodash, Parser, React, Select, Text, TextI
|
||||||
import Plugins, { ExcludedPlugins } from "~plugins";
|
import Plugins, { ExcludedPlugins } from "~plugins";
|
||||||
|
|
||||||
// Avoid circular dependency
|
// Avoid circular dependency
|
||||||
const { startDependenciesRecursive, startPlugin, stopPlugin } = proxyLazy(() => require("../../plugins")) as typeof import("../../plugins");
|
const PluginManager = proxyLazy(() => require("../../plugins")) as typeof import("../../plugins");
|
||||||
|
|
||||||
const cl = classNameFactory("vc-plugins-");
|
const cl = classNameFactory("vc-plugins-");
|
||||||
const logger = new Logger("PluginSettings", "#a6d189");
|
const logger = new Logger("PluginSettings", "#a6d189");
|
||||||
|
@ -109,7 +109,7 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on
|
||||||
|
|
||||||
// If we're enabling a plugin, make sure all deps are enabled recursively.
|
// If we're enabling a plugin, make sure all deps are enabled recursively.
|
||||||
if (!wasEnabled) {
|
if (!wasEnabled) {
|
||||||
const { restartNeeded, failures } = startDependenciesRecursive(plugin);
|
const { restartNeeded, failures } = PluginManager.startDependenciesRecursive(plugin);
|
||||||
if (failures.length) {
|
if (failures.length) {
|
||||||
logger.error(`Failed to start dependencies for ${plugin.name}: ${failures.join(", ")}`);
|
logger.error(`Failed to start dependencies for ${plugin.name}: ${failures.join(", ")}`);
|
||||||
showNotice("Failed to start dependencies: " + failures.join(", "), "Close", () => null);
|
showNotice("Failed to start dependencies: " + failures.join(", "), "Close", () => null);
|
||||||
|
@ -135,7 +135,7 @@ export function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, on
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = wasEnabled ? stopPlugin(plugin) : startPlugin(plugin);
|
const result = wasEnabled ? PluginManager.stopPlugin(plugin) : PluginManager.startPlugin(plugin);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
settings.enabled = false;
|
settings.enabled = false;
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { findByProps, webpackDependantLazy } from "@webpack";
|
||||||
import { Flux, FluxDispatcher } from "@webpack/common";
|
import { Flux, FluxDispatcher } from "@webpack/common";
|
||||||
|
|
||||||
// Avoid circular dependency
|
// Avoid circular dependency
|
||||||
const { settings } = proxyLazy(() => require(".")) as typeof import(".");
|
const SpotifyControls = proxyLazy(() => require(".")) as typeof import(".");
|
||||||
|
|
||||||
export interface Track {
|
export interface Track {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -91,7 +91,7 @@ export const SpotifyStore = webpackDependantLazy(() => {
|
||||||
public isSettingPosition = false;
|
public isSettingPosition = false;
|
||||||
|
|
||||||
public openExternal(path: string) {
|
public openExternal(path: string) {
|
||||||
const url = settings.store.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp")
|
const url = SpotifyControls.settings.store.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp")
|
||||||
? "spotify:" + path.replaceAll("/", (_, idx) => idx === 0 ? "" : ":")
|
? "spotify:" + path.replaceAll("/", (_, idx) => idx === 0 ? "" : ":")
|
||||||
: "https://open.spotify.com" + path;
|
: "https://open.spotify.com" + path;
|
||||||
|
|
||||||
|
|
|
@ -73,16 +73,16 @@ const handler: ProxyHandler<any> = {
|
||||||
* Wraps the result of factory in a Proxy you can consume as if it wasn't lazy.
|
* Wraps the result of factory in a Proxy you can consume as if it wasn't lazy.
|
||||||
* On first property access, the factory is evaluated.
|
* On first property access, the factory is evaluated.
|
||||||
*
|
*
|
||||||
|
* IMPORTANT:
|
||||||
|
* Destructuring at top level is not supported for proxyLazy.
|
||||||
|
*
|
||||||
* @param factory Factory returning the result
|
* @param factory Factory returning the result
|
||||||
* @param attempts How many times to try to evaluate the factory before giving up
|
* @param attempts How many times to try to evaluate the factory before giving up
|
||||||
* @returns Result of factory function
|
* @returns Result of factory function
|
||||||
*/
|
*/
|
||||||
export function proxyLazy<T = AnyObject>(factory: () => T, attempts = 5, isChild = false): ProxyLazy<T> {
|
export function proxyLazy<T = AnyObject>(factory: () => T, attempts = 5): ProxyLazy<T> {
|
||||||
const get = makeLazy(factory, attempts, { isIndirect: true });
|
const get = makeLazy(factory, attempts, { isIndirect: true });
|
||||||
|
|
||||||
let isSameTick = true;
|
|
||||||
if (!isChild) setTimeout(() => isSameTick = false, 0);
|
|
||||||
|
|
||||||
const proxyDummy = Object.assign(function () { }, {
|
const proxyDummy = Object.assign(function () { }, {
|
||||||
[SYM_LAZY_GET]() {
|
[SYM_LAZY_GET]() {
|
||||||
if (!proxyDummy[SYM_LAZY_CACHED]) {
|
if (!proxyDummy[SYM_LAZY_CACHED]) {
|
||||||
|
@ -111,27 +111,12 @@ export function proxyLazy<T = AnyObject>(factory: () => T, attempts = 5, isChild
|
||||||
return Reflect.get(target, p, receiver);
|
return Reflect.get(target, p, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're still in the same tick, it means the lazy was immediately used.
|
|
||||||
// thus, we lazy proxy the get access to make things like destructuring work as expected
|
|
||||||
// meow here will also be a lazy
|
|
||||||
// `const { meow } = proxyLazy(() => ({ meow: [] }));`
|
|
||||||
if (!isChild && isSameTick) {
|
|
||||||
return proxyLazy(
|
|
||||||
() => {
|
|
||||||
const lazyTarget = target[SYM_LAZY_GET]();
|
|
||||||
return Reflect.get(lazyTarget, p, lazyTarget);
|
|
||||||
},
|
|
||||||
attempts,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const lazyTarget = target[SYM_LAZY_GET]();
|
const lazyTarget = target[SYM_LAZY_GET]();
|
||||||
if (typeof lazyTarget === "object" || typeof lazyTarget === "function") {
|
if (typeof lazyTarget === "object" || typeof lazyTarget === "function") {
|
||||||
return Reflect.get(lazyTarget, p, lazyTarget);
|
return Reflect.get(lazyTarget, p, lazyTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("proxyLazy called on a primitive value. This can happen if you try to destructure a primitive at the same tick as the proxy was created.");
|
throw new Error("proxyLazy called on a primitive value.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -48,18 +48,17 @@ const handler: ProxyHandler<any> = {
|
||||||
* A proxy which has an inner value that can be set later.
|
* A proxy which has an inner value that can be set later.
|
||||||
* When a property is accessed, the proxy looks for the property value in its inner value, and errors if it's not set.
|
* When a property is accessed, the proxy looks for the property value in its inner value, and errors if it's not set.
|
||||||
*
|
*
|
||||||
|
* IMPORTANT:
|
||||||
|
* Destructuring at top level is not supported for proxyInner.
|
||||||
|
*
|
||||||
* @param err The error message to throw when the inner value is not set
|
* @param err The error message to throw when the inner value is not set
|
||||||
* @param primitiveErr The error message to throw when the inner value is a primitive
|
* @param primitiveErr The error message to throw when the inner value is a primitive
|
||||||
* @returns A proxy which will act like the inner value when accessed
|
* @returns A proxy which will act like the inner value when accessed
|
||||||
*/
|
*/
|
||||||
export function proxyInner<T = AnyObject>(
|
export function proxyInner<T = AnyObject>(
|
||||||
errMsg = "Proxy inner value is undefined, setInnerValue was never called.",
|
errMsg = "Proxy inner value is undefined, setInnerValue was never called.",
|
||||||
primitiveErrMsg = "proxyInner called on a primitive value. This can happen if you try to destructure a primitive at the same tick as the proxy was created.",
|
primitiveErrMsg = "proxyInner called on a primitive value."
|
||||||
isChild = false
|
|
||||||
): [proxy: ProxyInner<T>, setInnerValue: (innerValue: T) => void] {
|
): [proxy: ProxyInner<T>, setInnerValue: (innerValue: T) => void] {
|
||||||
let isSameTick = true;
|
|
||||||
if (!isChild) setTimeout(() => isSameTick = false, 0);
|
|
||||||
|
|
||||||
const proxyDummy = Object.assign(function () { }, {
|
const proxyDummy = Object.assign(function () { }, {
|
||||||
[SYM_PROXY_INNER_GET]: function () {
|
[SYM_PROXY_INNER_GET]: function () {
|
||||||
if (proxyDummy[SYM_PROXY_INNER_VALUE] == null) {
|
if (proxyDummy[SYM_PROXY_INNER_VALUE] == null) {
|
||||||
|
@ -78,24 +77,6 @@ export function proxyInner<T = AnyObject>(
|
||||||
return Reflect.get(target, p, receiver);
|
return Reflect.get(target, p, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're still in the same tick, it means the proxy was immediately used.
|
|
||||||
// And, if the inner value is still nullish, it means the proxy was used before setInnerValue was called.
|
|
||||||
// So, proxy the get access to make things like destructuring work as expected.
|
|
||||||
// We dont need to proxy if the inner value is available, and recursiveSetInnerValue won't ever be called anyways,
|
|
||||||
// because the top setInnerValue was called before we proxied the get access
|
|
||||||
// example here will also be a proxy:
|
|
||||||
// `const { example } = findByProps("example");`
|
|
||||||
if (isSameTick && !isChild && proxyDummy[SYM_PROXY_INNER_VALUE] == null) {
|
|
||||||
const [recursiveProxy, recursiveSetInnerValue] = proxyInner(errMsg, primitiveErrMsg, true);
|
|
||||||
|
|
||||||
recursiveSetInnerValues.push((innerValue: T) => {
|
|
||||||
// Set the inner value of the destructured value as the prop value p of the parent
|
|
||||||
recursiveSetInnerValue(Reflect.get(innerValue as object, p, innerValue));
|
|
||||||
});
|
|
||||||
|
|
||||||
return recursiveProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
const innerTarget = target[SYM_PROXY_INNER_GET]();
|
const innerTarget = target[SYM_PROXY_INNER_GET]();
|
||||||
if (typeof innerTarget === "object" || typeof innerTarget === "function") {
|
if (typeof innerTarget === "object" || typeof innerTarget === "function") {
|
||||||
return Reflect.get(innerTarget, p, innerTarget);
|
return Reflect.get(innerTarget, p, innerTarget);
|
||||||
|
@ -105,14 +86,8 @@ export function proxyInner<T = AnyObject>(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Values destructured in the same tick the proxy was created will push their setInnerValue here
|
|
||||||
const recursiveSetInnerValues = [] as Array<(innerValue: T) => void>;
|
|
||||||
|
|
||||||
// Once we set the parent inner value, we will call the setInnerValue functions of the destructured values,
|
|
||||||
// for them to get the proper value from the parent and use as their inner instead
|
|
||||||
function setInnerValue(innerValue: T) {
|
function setInnerValue(innerValue: T) {
|
||||||
proxyDummy[SYM_PROXY_INNER_VALUE] = innerValue;
|
proxyDummy[SYM_PROXY_INNER_VALUE] = innerValue;
|
||||||
recursiveSetInnerValues.forEach(setInnerValue => setInnerValue(innerValue));
|
|
||||||
|
|
||||||
// Avoid binding toString if the inner value is null.
|
// Avoid binding toString if the inner value is null.
|
||||||
// This can happen if we are setting the inner value as another instance of proxyInner, which will cause that proxy to instantly evaluate and throw an error
|
// This can happen if we are setting the inner value as another instance of proxyInner, which will cause that proxy to instantly evaluate and throw an error
|
||||||
|
|
|
@ -200,7 +200,7 @@ export function find<T = AnyObject>(filter: FilterFn, parse: (mod: any) => any =
|
||||||
if (typeof parse !== "function")
|
if (typeof parse !== "function")
|
||||||
throw new Error("Invalid find parse. Expected a function got " + typeof parse);
|
throw new Error("Invalid find parse. Expected a function got " + typeof parse);
|
||||||
|
|
||||||
const [proxy, setInnerValue] = proxyInner<T>(`Webpack find matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value. This can happen if you try to destructure a primitive in the top level definition of the find.");
|
const [proxy, setInnerValue] = proxyInner<T>(`Webpack find matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value.");
|
||||||
waitFor(filter, m => setInnerValue(parse(m)), { isIndirect: true });
|
waitFor(filter, m => setInnerValue(parse(m)), { isIndirect: true });
|
||||||
|
|
||||||
if (IS_REPORTER && !isIndirect) {
|
if (IS_REPORTER && !isIndirect) {
|
||||||
|
@ -448,7 +448,7 @@ export function mapMangledModule<S extends PropertyKey>(code: string | string[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [proxy] = proxyInner(`Webpack mapMangledModule mapper filter matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value. This can happen if you try to destructure a primitive in the top level definition of the find.");
|
const [proxy] = proxyInner(`Webpack mapMangledModule mapper filter matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value.");
|
||||||
// Use the proxy to throw errors because no export matched the filter
|
// Use the proxy to throw errors because no export matched the filter
|
||||||
mapping[newName] = proxy;
|
mapping[newName] = proxy;
|
||||||
}
|
}
|
||||||
|
@ -469,7 +469,7 @@ export function mapMangledModule<S extends PropertyKey>(code: string | string[],
|
||||||
export function findModuleFactory(...code: string[]) {
|
export function findModuleFactory(...code: string[]) {
|
||||||
const filter = filters.byFactoryCode(...code);
|
const filter = filters.byFactoryCode(...code);
|
||||||
|
|
||||||
const [proxy, setInnerValue] = proxyInner<ModuleFactory>(`Webpack module factory find matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value. This can happen if you try to destructure a primitive in the top level definition of the find.");
|
const [proxy, setInnerValue] = proxyInner<ModuleFactory>(`Webpack module factory find matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value.");
|
||||||
waitFor(filter, (_, { factory }) => setInnerValue(factory));
|
waitFor(filter, (_, { factory }) => setInnerValue(factory));
|
||||||
|
|
||||||
if (proxy[SYM_PROXY_INNER_VALUE] != null) return proxy[SYM_PROXY_INNER_VALUE] as ProxyInner<ModuleFactory>;
|
if (proxy[SYM_PROXY_INNER_VALUE] != null) return proxy[SYM_PROXY_INNER_VALUE] as ProxyInner<ModuleFactory>;
|
||||||
|
|
Loading…
Reference in a new issue