Compare commits

..

No commits in common. "2b83a2abe6e511c8f6086e14fd340634bda47b0d" and "c44c1df257a6f52dc99f9da3fe3b1fec4330a9ac" have entirely different histories.

3 changed files with 61 additions and 77 deletions

View File

@ -196,30 +196,18 @@ export async function Check()
const confTasks = (config.json.tasks || {}) as Record<string, string>; const confTasks = (config.json.tasks || {}) as Record<string, string>;
config.json.tasks = {...confTasks, ...tasks}; config.json.tasks = {...confTasks, ...tasks};
const optionsRequired = const options =
{ {
"lib": ["deno.window", "dom", "dom.iterable", "dom.asynciterable"], "lib": ["deno.window", "dom", "dom.asynciterable"],
"jsx": "react-jsx", "jsx": "react-jsx",
"jsxImportSource": "react" "jsxImportSource": "react"
} }
const optionsCurrent = config.json.compilerOptions as Record<string, string|string[]> || {}; const compOpts = config.json.compilerOptions as Record<string, string|string[]> || {};
//const compLib:string[] = compOpts.lib as string[] || []; const compLib:string[] = compOpts.lib as string[] || [];
compOpts.jsx = options.jsx;
if(!optionsCurrent.lib) compOpts.jsxImportSource = options.jsxImportSource;
{ compOpts.lib = [...compLib, ...options.lib];
optionsCurrent.lib = []; config.json.compilerOptions = compOpts;
}
optionsRequired.lib.forEach(s=>
{
if(!optionsCurrent.lib.includes(s))
{
(optionsCurrent.lib as string[]).push(s);
}
});
optionsCurrent.jsx = optionsRequired.jsx;
optionsCurrent.jsxImportSource = optionsRequired.jsxImportSource;
config.json.compilerOptions = optionsCurrent;
await bake(imports); await bake(imports);
await bake(config); await bake(config);

View File

@ -1,6 +1,4 @@
type Processor = (filename:string)=>void; import { type StateCapture } from "./hmr-react.tsx";
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>>; const FileListeners = new Map() as Map<string, Array<(module:unknown)=>void>>;
export const FileListen =(inPath:string, inHandler:()=>void)=> export const FileListen =(inPath:string, inHandler:()=>void)=>
@ -17,7 +15,56 @@ Socket.addEventListener('message', async(event:{data:string})=>
// send the updated members to any listeners for that file // send the updated members to any listeners for that file
const reImport = await import(document.location.origin+event.data+"?reload="+Math.random()); const reImport = await import(document.location.origin+event.data+"?reload="+Math.random());
FileListeners.get(event.data)?.forEach(reExport=>reExport(reImport)); FileListeners.get(event.data)?.forEach(reExport=>reExport(reImport));
Processors.forEach(p=>p(event.data)) HMR.update();
}); });
Socket.addEventListener("error", ()=>{clearInterval(SocketTimer); console.log("HMR socket lost")}) Socket.addEventListener("error", ()=>{clearInterval(SocketTimer); console.log("HMR socket lost")})
const SocketTimer = setInterval(()=>{Socket.send("ping")}, 5000); 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};

View File

@ -1,56 +1,5 @@
import * as ReactParts from "react-original"; import * as ReactParts from "react-original";
import { Process } from "./hmr-listen.tsx"; import { HMR } 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 StateType = boolean|number|string|Record<string, string>
export type StateCapture = {state:StateType, set:ReactParts.StateUpdater<StateType>, reload:number}; export type StateCapture = {state:StateType, set:ReactParts.StateUpdater<StateType>, reload:number};