centralized fake sockets

This commit is contained in:
Seth Trowbridge 2024-10-12 12:28:41 -04:00
parent 5cdb1cbf89
commit 3f9b3ba645
13 changed files with 205 additions and 78 deletions

View File

@ -1,6 +1,11 @@
<script>
globalThis.Listen = [];
</script>
<script type="module" src="test_receiver.mjs"></script> <script type="module" src="test_receiver.mjs"></script>
<!-- <!-- if test_rand.mjs exports a random number as default, there will be 4 different values if there is a cachebust on the import
<script type="module"> <script type="module">
import r1 from "./test_rand.mjs?1"; import r1 from "./test_rand.mjs?1";
import r2 from "./test_rand.mjs?2"; import r2 from "./test_rand.mjs?2";

View File

@ -1,43 +0,0 @@
import { useState as preactUseState, useEffect as preactUseEffect } from 'preact/hooks';
import { useState as reactUseState, useEffect as reactUseEffect } from 'react';
import { options as preactOptions } from 'preact';
const isPreact = typeof preactUseState === 'function';
const useState = isPreact ? preactUseState : reactUseState;
const useEffect = isPreact ? preactUseEffect : reactUseEffect;
function useLogger(componentName) {
useEffect(() => {
console.log(`${isPreact ? 'Preact' : 'React'}: Component ${componentName} mounted`);
return () => {
console.log(`${isPreact ? 'Preact' : 'React'}: Component ${componentName} unmounted`);
};
}, [componentName]);
useEffect(() => {
console.log(`${isPreact ? 'Preact' : 'React'}: Component ${componentName} rendered`);
});
}
if (isPreact) {
preactOptions.__r = (vnode) => {
console.log('Preact: Rendering component:', vnode);
};
preactOptions.diffed = (vnode) => {
console.log('Preact: Component diffed:', vnode);
};
preactOptions.unmount = (vnode) => {
console.log('Preact: Unmounting component:', vnode);
};
}
// Example component using the custom hook
function MyComponent() {
useLogger('MyComponent');
return <div>My Component</div>;
}
export default MyComponent;

View File

@ -2,6 +2,6 @@
<head></head> <head></head>
<body> <body>
<div id="app"></div> <div id="app"></div>
<script type="module" src="./preact.js"></script> <script type="module" src="preact.js"></script>
</body> </body>
</html> </html>

View File

@ -3,28 +3,62 @@ import * as Preact from "https://esm.sh/preact@10.23.1";
import * as React from "https://esm.sh/preact@10.23.1/compat"; import * as React from "https://esm.sh/preact@10.23.1/compat";
const H = Preact.h; const H = Preact.h;
console.log(React);
/** @typedef {(vnode:Preact.VNode)=>unknown} DeepHook*/
/** @type {DeepHook|undefined} */ const SPOOF =(...args)=>
const renderOld =Preact.options.__r;
/** @type {DeepHook} */
const renderNew =(vnode)=>
{ {
console.log("render!") console.log("spoof state", ...args);
console.log(vnode);
// how to examine state context here? const [hookGet, hookSet] = React.useState(...args);
};
const spoofSetter = (...args)=>{
console.log("spoofed setter", ...args);
hookSet(...args);
}
return [
hookGet,
spoofSetter
]
}
function OptionsHook(key, hookNew)
{
const hookOld =Preact.options[key];
Preact.options[key] = hookOld ? (...args)=>{hookOld(...args); hookNew(...args);} : hookNew;
}
OptionsHook("__r", (/** @type {Preact.VNode}*/vnode)=>
{
console.log("render!");
console.log();
});
OptionsHook("__h", (component_instance, hook_index, hook_state)=>
{
console.log("Hook!")
console.log(hook_index, hook_state);
})
OptionsHook("__", (...args)=>
{
console.log("unknown!")
console.log(...args);
})
Preact.options.__r = renderOld ? /**@type{DeepHook}*/((vnode)=>{renderOld(vnode); renderNew(vnode);}) : renderNew;
const Component =()=> const Component =()=>
{ {
const [countGet, countSet] = React.useState(3); const [countGet, countSet] = SPOOF(12345);
return H("h1", {onClick(){countSet(countGet+1)}}, `count: ${countGet}`); const [textGet, textSet] = SPOOF("Count is:");
return H("h1", {onClick(){countSet(countGet+1)}}, `${textGet} ${countGet}`);
} }
const root = document.querySelector("#app")||document.body; const root = document.querySelector("#app")||document.body;
Preact.render(H(Component, {HEY:"HEY"}), root); Preact.render(
H(Preact.Fragment, null,
H(Component),
H(Component),
), root);

View File

@ -1,4 +1,5 @@
import {changing} from "./test_changer.mjs"; import {changing, Component} from "./test_changer.mjs";
import {Component as ComponentOther} from "./test_changer_other.mjs";
const area = document.createElement("pre"); const area = document.createElement("pre");
document.body.append(area); document.body.append(area);
@ -8,4 +9,8 @@ export function Render()
{ {
console.log("pulling changing", changing) console.log("pulling changing", changing)
area.innerHTML = changing; area.innerHTML = changing;
console.log("compoenent render:")
Component();
ComponentOther();
} }

View File

@ -1,20 +1,21 @@
export let changing = "hello!"; /////////////////// injected /////////////////////////
////////////////////////////////////////////
let ReImported = {};
const thisURL = new URL(import.meta.url) const thisURL = new URL(import.meta.url)
const thisFile = thisURL.pathname; const thisFile = thisURL.pathname;
if(!thisURL.search) if(!thisURL.search)
{ {
setInterval(()=>{ await import("./test_sockets.mjs").then(m=>m.Register(thisFile, (module)=>{
import(thisFile+"?"+Math.random()).then(module=>{
ReImported = module;
for(let key in module) for(let key in module)
{ {
const statement = `${key}=ReImported.${key}` eval(`${key}=module.${key}`);
eval(statement);
console.log(statement);
} }
}) }));
}, 3000); }
////////////////////////////////////////////
import spoofHook from "./test_framework.mjs?changer"
export let changing = "123.";
export function Component()
{
spoofHook();
} }

21
test_changer_other.mjs Normal file
View File

@ -0,0 +1,21 @@
/////////////////// injected /////////////////////////
const thisURL = new URL(import.meta.url)
const thisFile = thisURL.pathname;
if(!thisURL.search)
{
await import("./test_sockets.mjs").then(m=>m.Register(thisFile, (module)=>{
for(let key in module)
{
eval(`${key}=module.${key}`);
}
}));
}
////////////////////////////////////////////
import spoofHook from "./test_framework.mjs?changer_other"
export let changing = "456";
export function Component()
{
spoofHook();
}

18
test_framework.mjs Normal file
View File

@ -0,0 +1,18 @@
const url =new URL(import.meta.url)
let context = url.search.substring(1)
if(context)
{
console.log("context found:", context);
}
else
{
console.log("no context:", url);
}
export default function(){
console.log("spoof hook context", context);
console.log("spoof hook this", this);
}

View File

@ -1 +0,0 @@
export default Math.random();

View File

@ -1,5 +1,7 @@
import * as App from "./test_application.mjs"; import * as App from "./test_application.mjs";
globalThis.Listen = [];
const button = document.createElement("button"); const button = document.createElement("button");
button.innerHTML = "Reload"; button.innerHTML = "Reload";
button.addEventListener("click", ()=> button.addEventListener("click", ()=>

25
test_sockets.mjs Normal file
View File

@ -0,0 +1,25 @@
/** @type {Map<string, ()=>Promise<void>} */
const Files = new Map();
globalThis.MODULE = {};
/** @type {(file:string, hnadler:()=>void)} */
export function Register(file, handler)
{
console.log("registering", file);
const WrapperHandler =()=> import(file+"?"+new Date().getTime()).then(handler);
Files.set(file, WrapperHandler);
}
const Loop =async()=>
{
console.log("looping!");
for (const [fileName, handler] of Files.entries())
{
await handler();
}
setTimeout(Loop, 3000);
}
Loop();

View File

@ -3,6 +3,65 @@
<body> <body>
<button id="open">open</button> <button id="open">open</button>
<script type="module"> <script type="module">
import { openDB } from "https://esm.sh/idb@8.0.0";
async function initDB() {
const db = await openDB('file-handles', 1, {
upgrade(db) {
if (!db.objectStoreNames.contains('handles')) {
db.createObjectStore('handles');
}
},
});
return db;
}
async function storeHandle(handle) {
const db = await initDB();
await db.put('handles', handle, 'directory');
}
async function getStoredHandle() {
const db = await initDB();
const handle = await db.get('handles', 'directory');
return handle;
}
async function verifyPermission(handle, readWrite) {
const options = {};
if (readWrite) {
options.mode = 'readwrite';
}
if ((await handle.queryPermission(options)) === 'granted') {
return true;
}
if ((await handle.requestPermission(options)) === 'granted') {
return true;
}
return false;
}
async function init() {
let handle = await getStoredHandle();
if (handle) {
const hasPermission = await verifyPermission(handle, true);
if (!hasPermission) {
handle = null;
}
}
if (!handle) {
handle = await globalThis.showDirectoryPicker();
await storeHandle(handle);
}
console.log('Directory handle:', handle);
return handle;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Function to walk through the directory and update file handles // Function to walk through the directory and update file handles
async function updateFileHandles(dirHandle, extension, path = "", map) { async function updateFileHandles(dirHandle, extension, path = "", map) {
@ -46,7 +105,8 @@ async function checkModifiedDates(map, date) {
// Main function to set up the intervals // Main function to set up the intervals
async function main() { async function main() {
const dirHandle = await window.showDirectoryPicker(); //const dirHandle = await window.showDirectoryPicker();
const dirHandle = await init();
const extension = '.html'; // Change this to the desired file extension const extension = '.html'; // Change this to the desired file extension
let fileHandlesMap = new Map(); let fileHandlesMap = new Map();