boot-function #1
							
								
								
									
										6
									
								
								example/deno.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								example/deno.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "imports":
 | 
			
		||||
    {
 | 
			
		||||
        "react":"https://esm.sh/preact/compat"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								hmr/hmr.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								hmr/hmr.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,76 @@
 | 
			
		||||
 | 
			
		||||
let reloads = 0;
 | 
			
		||||
const listeners = new Map() as Map<string, Array<(module:unknown)=>void>>;
 | 
			
		||||
const socket:WebSocket = new WebSocket("ws://"+document.location.host);
 | 
			
		||||
socket.addEventListener('message', (event) =>
 | 
			
		||||
{
 | 
			
		||||
    let handlers = listeners.get(event.data)??[];
 | 
			
		||||
    reloads++;
 | 
			
		||||
    Promise.all(
 | 
			
		||||
        handlers.map(handler=>
 | 
			
		||||
        {
 | 
			
		||||
            return import(event.data+"?reload="+reloads)
 | 
			
		||||
            .then(updatedModule=>handler(updatedModule));
 | 
			
		||||
        })
 | 
			
		||||
    ).then(()=>HMR.update());
 | 
			
		||||
});
 | 
			
		||||
const socketTimer = setInterval(()=>{socket.send("ping")}, 1000);
 | 
			
		||||
 | 
			
		||||
export const FileListen =(inPath:string, inHandler:()=>void)=>
 | 
			
		||||
{
 | 
			
		||||
    const members = listeners.get(inPath)??[];
 | 
			
		||||
    members.push(inHandler);
 | 
			
		||||
    listeners.set(inPath, members);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const HMR = {
 | 
			
		||||
    reloads:0,
 | 
			
		||||
    registered: new Map() as Map<string, ()=>void>,
 | 
			
		||||
    states: new Map(),
 | 
			
		||||
    statesOld: new Map(),
 | 
			
		||||
    wireframe: false,
 | 
			
		||||
    onChange(key:string, value:()=>void):void
 | 
			
		||||
    {
 | 
			
		||||
        this.registered.set(key, value);
 | 
			
		||||
    },
 | 
			
		||||
    update()
 | 
			
		||||
    {
 | 
			
		||||
        this.reloads++;
 | 
			
		||||
        this.registered.forEach(handler=>handler());
 | 
			
		||||
        this.registered.clear();
 | 
			
		||||
        this.statesOld = this.states;
 | 
			
		||||
        this.states = new Map();
 | 
			
		||||
        this.echoState();
 | 
			
		||||
    },
 | 
			
		||||
    echoState()
 | 
			
		||||
    {
 | 
			
		||||
        let output = [];
 | 
			
		||||
        for(const[key, val] of HMR.statesOld)
 | 
			
		||||
        {
 | 
			
		||||
            output[key] = val.state+"--"+val.reload;
 | 
			
		||||
        }
 | 
			
		||||
        console.log(output);
 | 
			
		||||
        output = [];
 | 
			
		||||
        for(const[key, val] of HMR.states)
 | 
			
		||||
        {
 | 
			
		||||
            output[key] = val.state+"--"+val.reload;
 | 
			
		||||
        }
 | 
			
		||||
        console.log(output);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {HMR};
 | 
			
		||||
 | 
			
		||||
export const MapAt =(inMap, inIndex)=>
 | 
			
		||||
{
 | 
			
		||||
    let index = 0;
 | 
			
		||||
    for(const kvp of inMap)
 | 
			
		||||
    {
 | 
			
		||||
        if(index == inIndex)
 | 
			
		||||
        {
 | 
			
		||||
            return kvp;
 | 
			
		||||
        }
 | 
			
		||||
        index++;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										77
									
								
								hmr/react.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								hmr/react.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
import * as ReactParts from "react-original";
 | 
			
		||||
import { HMR, MapAt } from "./hmr.tsx";
 | 
			
		||||
 | 
			
		||||
const H = ReactParts.createElement;
 | 
			
		||||
 | 
			
		||||
const ProxyElement = (props)=>
 | 
			
		||||
{
 | 
			
		||||
    const id = ReactParts.useId();
 | 
			
		||||
    const [stateGet, stateSet] = ReactParts.useState(0);
 | 
			
		||||
    ReactParts.useEffect(()=>HMR.onChange(id, ()=>stateSet(stateGet+1)));
 | 
			
		||||
 | 
			
		||||
    const child = H(...props.__args);
 | 
			
		||||
 | 
			
		||||
    if(HMR.wireframe)
 | 
			
		||||
    {
 | 
			
		||||
        return H("div", {style:{padding:"10px", border:"2px solid red"}},
 | 
			
		||||
            H("p", null, stateGet),
 | 
			
		||||
            child
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        return child;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const ProxyCreate =(...args)=>
 | 
			
		||||
{
 | 
			
		||||
    return typeof args[0] != "string" ? H(ProxyElement, {__args:args, ...args[1]}) : H(...args);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const ProxyState =(arg)=>
 | 
			
		||||
{
 | 
			
		||||
    const id = ReactParts.useId();
 | 
			
		||||
    const trueArg = arg;
 | 
			
		||||
 | 
			
		||||
    // does statesOld have an entry for this state? use that instead of the passed arg
 | 
			
		||||
    const check =  MapAt(HMR.statesOld, HMR.states.size);
 | 
			
		||||
    if(check)
 | 
			
		||||
    {
 | 
			
		||||
        arg = check[1].state;
 | 
			
		||||
        console.info(`BOOTING with ${arg}`);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const lastKnowReloads = HMR.reloads;
 | 
			
		||||
    const [stateGet, stateSet] = ReactParts.useState(arg);
 | 
			
		||||
    ReactParts.useEffect(()=>{
 | 
			
		||||
        return ()=>{
 | 
			
		||||
            if(HMR.reloads == lastKnowReloads)
 | 
			
		||||
            {
 | 
			
		||||
                // this is a switch/ui change, not a HMR reload change
 | 
			
		||||
                const oldState = MapAt(HMR.statesOld, HMR.states.size-1);
 | 
			
		||||
                HMR.statesOld.set(oldState[0], {...oldState[1], state:trueArg});
 | 
			
		||||
            }
 | 
			
		||||
            HMR.states.delete(id);
 | 
			
		||||
        }
 | 
			
		||||
    }, []);
 | 
			
		||||
 | 
			
		||||
    if(!HMR.states.has(id))
 | 
			
		||||
    {
 | 
			
		||||
        HMR.states.set(id, {state:arg, set:stateSet, reload:HMR.reloads});
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    function proxySetter (arg)
 | 
			
		||||
    {
 | 
			
		||||
        //console.log("state spy update", id, arg);
 | 
			
		||||
        HMR.states.set(id, {state:arg, set:stateSet, reload:HMR.reloads});
 | 
			
		||||
        return stateSet(arg);
 | 
			
		||||
    }
 | 
			
		||||
    return [stateGet, proxySetter];
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export * from "react-original";
 | 
			
		||||
export { ProxyCreate as createElement, ProxyState as useState };
 | 
			
		||||
export const isProxy = true;
 | 
			
		||||
export default {...ReactParts.default, createElement:ProxyCreate, useState:ProxyState, isProxy:true};
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user