Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
3f9b3ba645 |
@ -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";
|
||||||
|
@ -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;
|
|
@ -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>
|
@ -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);
|
@ -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();
|
||||||
}
|
}
|
@ -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
21
test_changer_other.mjs
Normal 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
18
test_framework.mjs
Normal 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);
|
||||||
|
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
export default Math.random();
|
|
@ -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
25
test_sockets.mjs
Normal 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();
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user