chore: revert 8347e24
This commit is contained in:
parent
5e06aa831d
commit
811bd30756
7 changed files with 165 additions and 1 deletions
|
|
@ -1,11 +1,14 @@
|
|||
import * as PluginApiReact_ from '@revenge-mod/react'
|
||||
import * as PluginApiReactJsxRuntime from '@revenge-mod/react/jsx-runtime'
|
||||
import * as PluginApiReactNative from '@revenge-mod/react/native'
|
||||
|
||||
export type PluginApiReact = typeof PluginApiReact_ & {
|
||||
jsxRuntime: typeof PluginApiReactJsxRuntime
|
||||
native: typeof PluginApiReactNative
|
||||
}
|
||||
|
||||
export const react: PluginApiReact = {
|
||||
...PluginApiReact_,
|
||||
jsxRuntime: PluginApiReactJsxRuntime,
|
||||
native: PluginApiReactNative,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,18 @@
|
|||
".": {
|
||||
"default": "./src/index.ts"
|
||||
},
|
||||
"./jsx-runtime": {
|
||||
"default": "./src/jsx-runtime/index.ts"
|
||||
},
|
||||
"./native": {
|
||||
"default": "./src/native/index.ts"
|
||||
},
|
||||
"./preinit": {
|
||||
"default": "./src/preinit.ts"
|
||||
},
|
||||
"./init": {
|
||||
"default": "./src/init.ts"
|
||||
},
|
||||
"./types": {
|
||||
"types": "./src/types.ts"
|
||||
}
|
||||
|
|
|
|||
1
lib/react/src/init.ts
Normal file
1
lib/react/src/init.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
import './jsx-runtime/patches'
|
||||
11
lib/react/src/jsx-runtime/_internal.ts
Normal file
11
lib/react/src/jsx-runtime/_internal.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import type { ElementType } from 'react'
|
||||
import type { AfterJSXCallback, BeforeJSXCallback, InsteadJSXCallback } from '.'
|
||||
|
||||
export const jPatches = new Map<
|
||||
ElementType | string,
|
||||
[
|
||||
before?: Set<BeforeJSXCallback>,
|
||||
after?: Set<AfterJSXCallback>,
|
||||
instead?: Set<InsteadJSXCallback>,
|
||||
]
|
||||
>()
|
||||
108
lib/react/src/jsx-runtime/index.ts
Normal file
108
lib/react/src/jsx-runtime/index.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import { jPatches } from './_internal'
|
||||
import type { ComponentProps, ElementType, Key, ReactElement } from 'react'
|
||||
import type { ReactJSXRuntime } from '..'
|
||||
|
||||
export type AnyJSXFactoryFunction = (typeof ReactJSXRuntime)['jsx' | 'jsxs']
|
||||
|
||||
export type BeforeJSXCallback<
|
||||
E extends ElementType = ElementType,
|
||||
P = ComponentProps<E>,
|
||||
> = (
|
||||
args: [element: E, props: P, key?: Key | undefined],
|
||||
) => Parameters<AnyJSXFactoryFunction>
|
||||
|
||||
export type InsteadJSXCallback<
|
||||
E extends ElementType = ElementType,
|
||||
P = ComponentProps<E>,
|
||||
> = (
|
||||
args: [element: E, props: P, key?: Key | undefined],
|
||||
jsx: AnyJSXFactoryFunction,
|
||||
) => ReturnType<AnyJSXFactoryFunction> | null
|
||||
|
||||
export type AfterJSXCallback = (
|
||||
fiber: ReactElement,
|
||||
) => ReturnType<AnyJSXFactoryFunction> | null
|
||||
|
||||
/**
|
||||
* Registers a hook to be called after a JSX element with the specified type is created.
|
||||
*
|
||||
* @param type The type of the element.
|
||||
* @param patch The hook.
|
||||
* @returns A function to unpatch.
|
||||
*/
|
||||
export function afterJSX(type: ElementType, patch: AfterJSXCallback) {
|
||||
let patches = jPatches.get(type)
|
||||
if (!patches) {
|
||||
patches = [undefined, new Set(), undefined]
|
||||
jPatches.set(type, patches)
|
||||
}
|
||||
|
||||
const set = patches[1]!
|
||||
|
||||
set.add(patch as AfterJSXCallback)
|
||||
return () => {
|
||||
const res = set.delete(patch as AfterJSXCallback)
|
||||
if (res) attemptCleanup(type)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a hook to be called before a JSX element with the specified type is created.
|
||||
*
|
||||
* @param type The type of the element.
|
||||
* @param patch The hook.
|
||||
* @returns A function to unpatch.
|
||||
*/
|
||||
export function beforeJSX<
|
||||
E extends ElementType = ElementType,
|
||||
P = ComponentProps<E>,
|
||||
>(type: E, patch: BeforeJSXCallback<E, P>) {
|
||||
let patches = jPatches.get(type)
|
||||
if (!patches) {
|
||||
patches = [new Set(), undefined, undefined]
|
||||
jPatches.set(type, patches)
|
||||
}
|
||||
|
||||
const set = patches[0]!
|
||||
|
||||
set.add(patch as BeforeJSXCallback)
|
||||
return () => {
|
||||
const res = set.delete(patch as BeforeJSXCallback)
|
||||
if (res) attemptCleanup(type)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback to run instead when a JSX element with the specified type is created.
|
||||
*
|
||||
* @param type The type of the element.
|
||||
* @param patch The hook.
|
||||
* @returns A function to unpatch.
|
||||
*/
|
||||
export function insteadJSX<
|
||||
E extends ElementType = ElementType,
|
||||
P = ComponentProps<E>,
|
||||
>(type: E, patch: InsteadJSXCallback<E, P>) {
|
||||
let patches = jPatches.get(type)
|
||||
if (!patches) {
|
||||
patches = [undefined, undefined, new Set()]
|
||||
jPatches.set(type, patches)
|
||||
}
|
||||
|
||||
const set = patches[2]!
|
||||
|
||||
set.add(patch as InsteadJSXCallback)
|
||||
return () => {
|
||||
const res = set.delete(patch as InsteadJSXCallback)
|
||||
if (res) attemptCleanup(type)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
function attemptCleanup(type: ElementType) {
|
||||
const patches = jPatches.get(type)!
|
||||
if (patches[0]?.size || patches[1]?.size || patches[2]?.size) return
|
||||
jPatches.delete(type)
|
||||
}
|
||||
34
lib/react/src/jsx-runtime/patches.ts
Normal file
34
lib/react/src/jsx-runtime/patches.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { instead } from '@revenge-mod/patcher'
|
||||
import { ReactJSXRuntime } from '..'
|
||||
import { jPatches } from './_internal'
|
||||
import type { ReactElement } from 'react'
|
||||
import type { AnyJSXFactoryFunction } from '.'
|
||||
|
||||
const jsx = ReactJSXRuntime.jsx
|
||||
|
||||
const patch = (
|
||||
args: Parameters<AnyJSXFactoryFunction>,
|
||||
orig: AnyJSXFactoryFunction,
|
||||
) => {
|
||||
const [type] = args
|
||||
const patches = jPatches.get(type)
|
||||
if (!patches) return Reflect.apply(orig, ReactJSXRuntime, args)
|
||||
|
||||
const [before, after, instead] = patches
|
||||
|
||||
if (before) for (const cb of before) args = cb(args)
|
||||
|
||||
let fiber: ReactElement | null | undefined
|
||||
|
||||
// If there are instead patches, fiber will always be set by the instead patches
|
||||
if (instead) for (const cb of instead) fiber = cb(args, jsx)
|
||||
// If there aren't any instead patches, we compute the fiber normally, and it will be set
|
||||
else fiber = Reflect.apply(orig, ReactJSXRuntime, args)
|
||||
|
||||
if (after) for (const cb of after) fiber = cb(fiber!)
|
||||
|
||||
return fiber!
|
||||
}
|
||||
|
||||
instead(ReactJSXRuntime, 'jsx', patch)
|
||||
instead(ReactJSXRuntime, 'jsxs', patch)
|
||||
|
|
@ -39,10 +39,11 @@ onModuleFirstRequired(IndexModuleId, function onIndexRequired() {
|
|||
|
||||
// Initialize init libraries
|
||||
require('@revenge-mod/utils/init')
|
||||
require('@revenge-mod/react/init')
|
||||
require('@revenge-mod/storage/init')
|
||||
require('@revenge-mod/externals/init')
|
||||
require('@revenge-mod/discord/init')
|
||||
require('@revenge-mod/components/init')
|
||||
require('@revenge-mod/externals/init')
|
||||
|
||||
// Run all init plugins
|
||||
require('~/plugins/init')
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue