From 01c7df3c32b4fd02dc174829e8ae62beff3145f0 Mon Sep 17 00:00:00 2001 From: Cody Bennett <23324155+CodyJasonBennett@users.noreply.github.com> Date: Tue, 7 Mar 2023 07:47:37 -0600 Subject: [PATCH] fix: loosen mangle --- package.json | 2 +- src/index.ts | 316 +++++++++++++++++++++++++++++++++---------------- src/types.ts | 109 ----------------- vite.config.js | 2 +- yarn.lock | 8 +- 5 files changed, 220 insertions(+), 217 deletions(-) delete mode 100644 src/types.ts diff --git a/package.json b/package.json index e525aa7..a060a4e 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@preact/preset-vite": "^2.5.0", "@react-three/cannon": "^6.5.2", "@react-three/drei": "^9.57.0", - "@react-three/fiber": "^8.11.8", + "@react-three/fiber": "^8.11.9", "jsdom": "^21.1.0", "preact": "^10.13.0", "three": "^0.150.1", diff --git a/src/index.ts b/src/index.ts index 1250af5..acab9ba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,159 +1,271 @@ -import { type Options, options as _options, render } from 'preact' -import type { Fiber, HostConfig, Reconciler } from './types' +import { + type VNode, + type Component, + type ComponentChildren, + type ComponentChild, + options as _options, + render, +} from 'preact' + +interface FiberNode extends HTMLElement { + ownerSVGElement?: null + fiber?: Fiber + containerInfo: T + hostConfig: HostConfig +} + +export interface Fiber

extends VNode

{ + __c?: Component & { + __P: FiberNode + } + __e: FiberNode + __: Fiber + __type?: string + stateNode?: I + type: string + container: FiberNode + props: P & { children: ComponentChildren } + memoizedProps?: P & { children: ComponentChildren } +} + +export interface HostConfig< + Type = string, + Props = Record, + Container = any, + Instance = any, + TextInstance = any, + PublicInstance = any, + HostContext = any, + UpdatePayload = any, +> { + createInstance( + type: Type, + props: Props, + rootContainer: Container, + hostContext: HostContext, + internalHandle: Fiber, + ): Instance + // createTextInstance( + // text: string, + // rootContainer: Container, + // hostContext: HostContext, + // internalHandle: Fiber, + // ): TextInstance + // appendInitialChild(parent: Instance, child: Instance | TextInstance): void + finalizeInitialChildren( + instance: Instance, + type: Type, + props: Props, + rootContainer: Container, + hostContext: HostContext, + ): boolean + prepareUpdate( + instance: Instance, + type: Type, + oldProps: Props, + newProps: Props, + rootContainer: Container, + hostContext: HostContext, + ): UpdatePayload | null + // shouldSetTextContent(type: Type, props: Props): boolean + // getRootHostContext(rootContainer: Container): HostContext | null + // getChildHostContext(parentHostContext: HostContext, type: Type, rootContainer: Container): HostContext + getPublicInstance(instance: Instance | TextInstance): PublicInstance + // prepareForCommit(containerInfo: Container): Record | null + // resetAfterCommit(containerInfo: Container): void + // preparePortalMount(containerInfo: Container): void + appendChild?(parent: Instance, child: Instance | TextInstance): void + appendChildToContainer?(container: Container, child: Instance | TextInstance): void + insertBefore?(parent: Instance, child: Instance | TextInstance, beforeChild: Instance | TextInstance): void + insertInContainerBefore?( + container: Container, + child: Instance | TextInstance, + beforeChild: Instance | TextInstance, + ): void + removeChild?(parent: Instance, child: Instance | TextInstance): void + removeChildFromContainer?(container: Container, child: Instance | TextInstance): void + // resetTextContent?(instance: Instance): void + // commitTextUpdate?(textInstance: TextInstance, oldText: string, newText: string): void + commitMount?(instance: Instance, type: Type, props: Props, internalHandle: Fiber): void + commitUpdate?( + instance: Instance, + updatePayload: UpdatePayload, + type: Type, + prevProps: Props, + nextProps: Props, + internalHandle: Fiber, + ): void + // hideInstance?(instance: Instance): void + // hideTextInstance?(textInstance: TextInstance): void + // unhideInstance?(instance: Instance, props: Props): void + // unhideTextInstance?(textInstance: TextInstance, text: string): void + // clearContainer?(container: Container): void + [name: string]: unknown +} // Creates an HTMLNode proxy for reconciliation -class PreactFiber extends (HTMLElement as { new (): Fiber['__e'] }) { +class FiberNode extends HTMLElement { setAttribute(name: string, value: any): void { - this.ownerSVGElement ??= null - this[name] = value + ;(this as Record)[name] = value - const vnode = this.__vnode - if (vnode) { - vnode.props[name] = value - if (vnode.stateNode) _options.diffed?.(vnode) + const fiber = this.fiber + if (fiber) { + fiber.props[name] = value + + if (!fiber.stateNode) { + // Cleanup overrides + this.ownerSVGElement = null + fiber.type = fiber.__type! + + // Create Fiber instance + const container = fiber.container + const HostConfig = (this.hostConfig ??= container.hostConfig) + const containerInfo = container.containerInfo + fiber.stateNode = HostConfig.createInstance(fiber.type, fiber.props, containerInfo, null, fiber) + + // Narrow ref as per reconciler's public instance + let ref = fiber.ref + Object.defineProperty(fiber, 'ref', { + get() { + return ref + }, + set(value) { + ref = (self) => { + const publicInstance = self === null ? null : HostConfig.getPublicInstance(fiber.stateNode) + if (value && 'current' in value) value.current = publicInstance + else value?.(publicInstance) + } + }, + }) + fiber.ref = ref + } + + options.diffed?.(fiber) } } appendChild(node: T): T { - const child = node as unknown as PreactFiber - if (this.__vnode) { - this.__hostConfig.appendChild(this.__vnode.stateNode, child.__vnode!.stateNode) + const child = node as unknown as FiberNode + if (this.fiber) { + this.hostConfig.appendChild!(this.fiber.stateNode, child.fiber!.stateNode) } else { - this.__hostConfig.appendChildToContainer(this.__containerInfo, child.__vnode!.stateNode) + this.hostConfig.appendChildToContainer!(this.containerInfo, child.fiber!.stateNode) } return super.appendChild(node) } insertBefore(node: T, beforeNode: Node | null): T { - const child = node as unknown as PreactFiber - const beforeChild = beforeNode as unknown as PreactFiber - if (this.__vnode) { - this.__hostConfig.insertBefore(this.__vnode.stateNode, child.__vnode!.stateNode, beforeChild.__vnode!.stateNode) + const child = node as unknown as FiberNode + const beforeChild = beforeNode as unknown as FiberNode + if (this.fiber) { + this.hostConfig.insertBefore!(this.fiber.stateNode, child.fiber!.stateNode, beforeChild.fiber!.stateNode) } else { - this.__hostConfig.insertInContainerBefore( - this.__containerInfo, - child.__vnode!.stateNode, - beforeChild.__vnode!.stateNode, - ) + this.hostConfig.insertInContainerBefore!(this.containerInfo, child.fiber!.stateNode, beforeChild.fiber!.stateNode) } return super.insertBefore(node, beforeNode) } removeChild(node: T): T { - const child = node as unknown as PreactFiber - if (this.__vnode) { - this.__hostConfig.removeChild(this.__vnode.stateNode, child.__vnode!.stateNode) + const child = node as unknown as FiberNode + if (this.fiber) { + this.hostConfig.removeChild!(this.fiber.stateNode, child.fiber!.stateNode) } else { - this.__hostConfig.removeChildFromContainer(this.__containerInfo, child.__vnode!.stateNode) + this.hostConfig.removeChildFromContainer!(this.containerInfo, child.fiber!.stateNode) } return super.removeChild(node) } } -interface InternalOptions extends Options { - __b: Options['diffed'] -} - let id!: string -export default function PreactReconciler(__hostConfig: HostConfig): Reconciler { +const options = _options as { + vnode?(fiber: Fiber): void + unmount?(fiber: Fiber): void + diffed?(fiber: Fiber): void + event?(event: Event): any + requestAnimationFrame?(callback: () => void): void + debounceRendering?(callback: () => void): void + useDebugValue?(value: string | number): void + __h(component: Component, index: number, type: number): void // HOOK + __b(fiber: Fiber): void // DIFF + __r(fiber: Fiber): void // RENDER + __e(error: any, fiber: Fiber, oldFiber: Fiber): void // CATCH_ERROR +} + +export default function PreactReconciler(hostConfig: HostConfig) { // Inject custom reconciler runtime if (!id) { - customElements.define((id = 'preact-fiber'), PreactFiber) + customElements.define((id = 'preact-fiber'), FiberNode) - const options = _options as InternalOptions - - const _diff = options.__b - options.__b = (vnode: Fiber) => { - // On first run, link managed nodes - if (typeof vnode.type === 'string') { - let container = vnode.__container - if (!container) { - let root = vnode.__ + // Link managed nodes on first run + const DIFF = options.__b + options.__b = (fiber) => { + if (typeof fiber.type === 'string') { + if (!fiber.container) { + let root = fiber.__ while (root.__) root = root.__ - container = vnode.__container = root.__c.__P - - const HostConfig = container.__hostConfig - if (HostConfig) { - vnode.__type = vnode.type - vnode.type = id - vnode.props.__vnode = vnode - vnode.props.__hostConfig = HostConfig + fiber.container = root.__c?.__P! + + if (fiber.container.hostConfig) { + fiber.__type = fiber.type + fiber.type = id + fiber.props.fiber = fiber } } } - _diff?.(vnode) + DIFF?.(fiber) } - const _diffed = options.diffed - options.diffed = (vnode: Fiber) => { - // Create and link managed instances - const container = vnode.__container - const HostConfig = container?.__hostConfig - const containerInfo = container?.__containerInfo + // Commit and reconcile props + const DIFFED = options.diffed + options.diffed = (fiber) => { + const container = fiber.container + const HostConfig = container?.hostConfig + const containerInfo = container?.containerInfo if (HostConfig) { - // Traverse up and build tree - let next = vnode - while (next) { - const node = next - if (node.__type && !node.stateNode) { - node.type = node.__type - delete node.__type - delete node.props.__vnode - delete node.props.__hostConfig - node.stateNode = HostConfig.createInstance(node.type, node.props, containerInfo, null, vnode) - let ref = node.ref - Object.defineProperty(node, 'ref', { - get() { - return ref - }, - set(value) { - ref = (self) => { - const publicInstance = self === null ? null : HostConfig.getPublicInstance(node.stateNode) - if (value && 'current' in value) value.current = publicInstance - else value?.(publicInstance) - } - }, - }) - node.ref = ref - } - next = next.__ - } - // On first run, finalize instance - if (!vnode.memoizedProps) { - const pending = HostConfig.finalizeInitialChildren(vnode.stateNode, vnode.type, vnode.props, containerInfo) - if (pending) HostConfig.commitMount(vnode.stateNode, vnode.type, vnode.props, vnode) + if (!fiber.memoizedProps) { + const pending = HostConfig.finalizeInitialChildren( + fiber.stateNode, + fiber.type, + fiber.props, + containerInfo, + null, + ) + if (pending) HostConfig.commitMount!(fiber.stateNode, fiber.type, fiber.props, fiber) } else { // On subsequent runs, reconcile props const update = HostConfig.prepareUpdate( - vnode.stateNode, - vnode.type, - vnode.memoizedProps, - vnode.props, + fiber.stateNode, + fiber.type, + fiber.memoizedProps, + fiber.props, containerInfo, null, ) // A payload was specified, update instance if (update) - HostConfig.commitUpdate(vnode.stateNode, update, vnode.type, vnode.memoizedProps, vnode.props, vnode) + HostConfig.commitUpdate!(fiber.stateNode, update, fiber.type, fiber.memoizedProps, fiber.props, fiber) } - vnode.memoizedProps = { ...vnode.props } + fiber.memoizedProps = { ...fiber.props } } - _diffed?.(vnode) + DIFFED?.(fiber) } } return { - createContainer(__containerInfo) { - return Object.assign(document.createElement(id), { __containerInfo, __hostConfig }) + createContainer(containerInfo: T): FiberNode { + return Object.assign(document.createElement(id), { containerInfo, hostConfig }) }, - updateContainer(element, root) { - render(element, root) + updateContainer(element: ComponentChild, container: FiberNode): void { + render(element, container) }, - createPortal() { + createPortal( + _children: ComponentChild, + _containerInfo: any, + _implementation: any, + _key?: string | null, + ): ComponentChild { return null // TODO }, - injectIntoDevTools() {}, + injectIntoDevTools(_devToolsConfig: any): any {}, } } - -export * from './types' diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 170c20a..0000000 --- a/src/types.ts +++ /dev/null @@ -1,109 +0,0 @@ -import type { VNode, ComponentChild } from 'preact' - -interface FiberContainer extends HTMLElement { - __containerInfo: any - __hostConfig: any -} - -export interface Fiber extends VNode { - __c: { - __P: FiberContainer - } - __: Fiber - __type?: string - __container: FiberContainer - stateNode?: any - props: any - memoizedProps: any - __e: HTMLElement & { - __vnode?: Fiber - __hostConfig: any - __containerInfo: any - [key: string]: unknown - } -} - -type Type = string -type Props = Record -type Container = unknown -type Instance = unknown -type TextInstance = unknown -type PublicInstance = unknown -type HostContext = unknown -type UpdatePayload = unknown - -type OpaqueHandle = Fiber -type OpaqueRoot = FiberContainer - -export interface HostConfig { - createInstance( - type: Type, - props: Props, - rootContainer: Container, - hostContext: HostContext, - internalHandle: OpaqueHandle, - ): Instance - // createTextInstance( - // text: string, - // rootContainer: Container, - // hostContext: HostContext, - // internalHandle: OpaqueHandle, - // ): TextInstance - // appendInitialChild(parent: Instance, child: Instance | TextInstance): void - finalizeInitialChildren( - instance: Instance, - type: Type, - props: Props, - rootContainer: Container, - hostContext: HostContext, - ): boolean - prepareUpdate( - instance: Instance, - type: Type, - oldProps: Props, - newProps: Props, - rootContainer: Container, - hostContext: HostContext, - ): UpdatePayload | null - // shouldSetTextContent(type: Type, props: Props): boolean - // getRootHostContext(rootContainer: Container): HostContext | null - // getChildHostContext(parentHostContext: HostContext, type: Type, rootContainer: Container): HostContext - getPublicInstance(instance: Instance | TextInstance): PublicInstance - // prepareForCommit(containerInfo: Container): Record | null - // resetAfterCommit(containerInfo: Container): void - // preparePortalMount(containerInfo: Container): void - appendChild?(parent: Instance, child: Instance | TextInstance): void - appendChildToContainer?(container: Container, child: Instance | TextInstance): void - insertBefore?(parent: Instance, child: Instance | TextInstance, beforeChild: Instance | TextInstance): void - insertInContainerBefore?( - container: Container, - child: Instance | TextInstance, - beforeChild: Instance | TextInstance, - ): void - removeChild?(parent: Instance, child: Instance | TextInstance): void - removeChildFromContainer?(container: Container, child: Instance | TextInstance): void - // resetTextContent?(instance: Instance): void - // commitTextUpdate?(textInstance: TextInstance, oldText: string, newText: string): void - commitMount?(instance: Instance, type: Type, props: Props, internalHandle: OpaqueHandle): void - commitUpdate?( - instance: Instance, - updatePayload: UpdatePayload, - type: Type, - prevProps: Props, - nextProps: Props, - internalHandle: OpaqueHandle, - ): void - // hideInstance?(instance: Instance): void - // hideTextInstance?(textInstance: TextInstance): void - // unhideInstance?(instance: Instance, props: Props): void - // unhideTextInstance?(textInstance: TextInstance, text: string): void - // clearContainer?(container: Container): void - [name: string]: unknown -} - -export interface Reconciler { - createContainer(containerInfo: any): OpaqueRoot - createPortal(children: ComponentChild, containerInfo: any, implementation: any, key?: string | null): ComponentChild - updateContainer(element: ComponentChild, container: OpaqueRoot): void - injectIntoDevTools(devToolsConfig: any): any -} diff --git a/vite.config.js b/vite.config.js index bfbf4e6..6f83bbc 100644 --- a/vite.config.js +++ b/vite.config.js @@ -40,7 +40,7 @@ export default vite.defineConfig({ async handler(code, { fileName }) { return vite.transformWithEsbuild(code, fileName, { minify: true, - mangleProps: /^__\w+/, + mangleProps: /^(__type|fiber|container|containerInfo|hostConfig)$/, mangleQuoted: true, }) }, diff --git a/yarn.lock b/yarn.lock index 6514d5f..02b9983 100644 --- a/yarn.lock +++ b/yarn.lock @@ -538,10 +538,10 @@ utility-types "^3.10.0" zustand "^3.5.13" -"@react-three/fiber@^8.11.8": - version "8.11.8" - resolved "https://registry.yarnpkg.com/@react-three/fiber/-/fiber-8.11.8.tgz#cdc0c3ca5f0bab1ad611b11eb9e1eb54097a4a14" - integrity sha512-u/rUmYBgPV9ZwKQ3cLcrl4P6XheaGmP9c1eCetrTG19FM2zwQoIfQFoazJJuH3fxC9tdjOwpKbjhr/vZKRgZ9g== +"@react-three/fiber@^8.11.9": + version "8.11.9" + resolved "https://registry.yarnpkg.com/@react-three/fiber/-/fiber-8.11.9.tgz#50ba430b1cd52c7853d1adeefe06ad397c35da93" + integrity sha512-5vZBlbdy+QbNIIjohERs1NL59LOo6XQwM4x4jjV1PKc5KkSy+73Y+/tQGdz6muEkbeOCt4TeM2KtcFjoAdjl1g== dependencies: "@babel/runtime" "^7.17.8" "@types/react-reconciler" "^0.26.7"