dreaded-fixes #7
@ -1,4 +1,6 @@
 | 
			
		||||
import { type StateCapture } from "./hmr-react.tsx";
 | 
			
		||||
type Processor = (filename:string)=>void;
 | 
			
		||||
const Processors:Set<Processor> = new Set();
 | 
			
		||||
export const Process =(p:Processor)=>Processors.add(p)
 | 
			
		||||
 | 
			
		||||
const FileListeners = new Map() as Map<string, Array<(module:unknown)=>void>>;
 | 
			
		||||
export const FileListen =(inPath:string, inHandler:()=>void)=>
 | 
			
		||||
@ -15,56 +17,7 @@ Socket.addEventListener('message', async(event:{data:string})=>
 | 
			
		||||
    // send the updated members to any listeners for that file
 | 
			
		||||
    const reImport = await import(document.location.origin+event.data+"?reload="+Math.random());
 | 
			
		||||
    FileListeners.get(event.data)?.forEach(reExport=>reExport(reImport));
 | 
			
		||||
    HMR.update();
 | 
			
		||||
    Processors.forEach(p=>p(event.data))
 | 
			
		||||
});
 | 
			
		||||
Socket.addEventListener("error", ()=>{clearInterval(SocketTimer); console.log("HMR socket lost")})
 | 
			
		||||
const SocketTimer = setInterval(()=>{Socket.send("ping")}, 5000);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
Each custom component is secretly modified to have an extra state and id.
 | 
			
		||||
When there is an HMR update, this state is changed, forcing it to re-render.
 | 
			
		||||
 | 
			
		||||
Each *user-created* React.useState is secretly modified and accompanied by an ID.
 | 
			
		||||
Every time its state is set, the HMR.statesNew map for this ID is set to contain the new state and updater.
 | 
			
		||||
When a component is removed, any of it's states in HMR.statesNew are also removed. 
 | 
			
		||||
(HMR.statesNew is the "running total" of all states currently at play).
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
When a state is interacted with:
 | 
			
		||||
- statesNew for this id is set
 | 
			
		||||
- the internal state is also set in the traditional way
 | 
			
		||||
 | 
			
		||||
When there is an HMR update:
 | 
			
		||||
- All custom components are re-rendered...
 | 
			
		||||
  for each useState(value) call that then happens in the re-render:
 | 
			
		||||
  - if there is a "statesOld" value for this state, use that and ignore the passed value, otherwise use the passed value
 | 
			
		||||
  - if this state has not been interacted with since the last reload (statesNew is empty at this id), set statesNew<id> with whatever is in statesOld<id>
 | 
			
		||||
- statesNew is moved into *statesOld*
 | 
			
		||||
- statesNew is cleared.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
const HMR =
 | 
			
		||||
{
 | 
			
		||||
    reloads:1,
 | 
			
		||||
    RegisteredComponents: new Map() as Map<string, ()=>void>,
 | 
			
		||||
    statesNew: new Map() as Map<string, StateCapture>,
 | 
			
		||||
    statesOld: new Map() as Map<string, StateCapture>,
 | 
			
		||||
    wireframe: false,
 | 
			
		||||
    RegisterComponent(reactID:string, value:()=>void):void
 | 
			
		||||
    {
 | 
			
		||||
        this.RegisteredComponents.set(reactID, value);
 | 
			
		||||
    },
 | 
			
		||||
    update()
 | 
			
		||||
    {
 | 
			
		||||
        this.reloads++;
 | 
			
		||||
        this.RegisteredComponents.forEach(handler=>handler());
 | 
			
		||||
        this.RegisteredComponents.clear();
 | 
			
		||||
        this.statesOld = this.statesNew;
 | 
			
		||||
        this.statesNew = new Map();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {HMR};
 | 
			
		||||
const SocketTimer = setInterval(()=>{Socket.send("ping")}, 5000);
 | 
			
		||||
@ -1,5 +1,56 @@
 | 
			
		||||
import * as ReactParts from "react-original";
 | 
			
		||||
import { HMR } from "./hmr-listen.tsx";
 | 
			
		||||
import { Process } from "./hmr-listen.tsx";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
Each custom component is secretly modified to have an extra state and id.
 | 
			
		||||
When there is an HMR update, this state is changed, forcing it to re-render.
 | 
			
		||||
 | 
			
		||||
Each *user-created* React.useState is secretly modified and accompanied by an ID.
 | 
			
		||||
Every time its state is set, the HMR.statesNew map for this ID is set to contain the new state and updater.
 | 
			
		||||
When a component is removed, any of it's states in HMR.statesNew are also removed. 
 | 
			
		||||
(HMR.statesNew is the "running total" of all states currently at play).
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
When a state is interacted with:
 | 
			
		||||
- statesNew for this id is set
 | 
			
		||||
- the internal state is also set in the traditional way
 | 
			
		||||
 | 
			
		||||
When there is an HMR update:
 | 
			
		||||
- All custom components are re-rendered...
 | 
			
		||||
  for each useState(value) call that then happens in the re-render:
 | 
			
		||||
  - if there is a "statesOld" value for this state, use that and ignore the passed value, otherwise use the passed value
 | 
			
		||||
  - if this state has not been interacted with since the last reload (statesNew is empty at this id), set statesNew<id> with whatever is in statesOld<id>
 | 
			
		||||
- statesNew is moved into *statesOld*
 | 
			
		||||
- statesNew is cleared.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
const HMR =
 | 
			
		||||
{
 | 
			
		||||
    reloads:1,
 | 
			
		||||
    RegisteredComponents: new Map() as Map<string, ()=>void>,
 | 
			
		||||
    statesNew: new Map() as Map<string, StateCapture>,
 | 
			
		||||
    statesOld: new Map() as Map<string, StateCapture>,
 | 
			
		||||
    wireframe: false,
 | 
			
		||||
    RegisterComponent(reactID:string, value:()=>void):void
 | 
			
		||||
    {
 | 
			
		||||
        this.RegisteredComponents.set(reactID, value);
 | 
			
		||||
    },
 | 
			
		||||
    update()
 | 
			
		||||
    {
 | 
			
		||||
        this.reloads++;
 | 
			
		||||
        this.RegisteredComponents.forEach(handler=>handler());
 | 
			
		||||
        this.RegisteredComponents.clear();
 | 
			
		||||
        this.statesOld = this.statesNew;
 | 
			
		||||
        this.statesNew = new Map();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Process(()=>HMR.update())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export type StateType = boolean|number|string|Record<string, string>
 | 
			
		||||
export type StateCapture = {state:StateType, set:ReactParts.StateUpdater<StateType>, reload:number};
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user