From a0d6f892908d56565a67ed5dc75e96a44bf300c5 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Fri, 11 Oct 2024 13:04:47 -0400 Subject: [PATCH] idk --- .vscode/launch.json | 13 ++++ .vscode/settings.json | 3 + deno.json | 6 +- deno.lock | 13 ++++ index.html | 39 ++++++++++ junk/module_inspector.js | 131 ++++++++++++++++++++++++++++++++++ junk/module_inspector.test.ts | 4 +- junk/module_inspector.ts | 14 ++-- preactthing.tsx | 43 +++++++++++ state-preserve/index.html | 7 ++ state-preserve/preact.js | 30 ++++++++ test_changer.mjs | 14 ++-- transpiler/index.html | 27 +++++++ 13 files changed, 332 insertions(+), 12 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 deno.lock create mode 100644 junk/module_inspector.js create mode 100644 preactthing.tsx create mode 100644 state-preserve/index.html create mode 100644 state-preserve/preact.js create mode 100644 transpiler/index.html diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..61dbebd --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "request": "attach", + "name": "Attach", + "type": "node" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6de865a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "deno.enable": true, +} \ No newline at end of file diff --git a/deno.json b/deno.json index 9e26dfe..ccc0eff 100644 --- a/deno.json +++ b/deno.json @@ -1 +1,5 @@ -{} \ No newline at end of file +{ + "tasks": { + "dbg": "deno run -A --inspect-wait junk/module_inspector.test.ts" + } +} \ No newline at end of file diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..02fee21 --- /dev/null +++ b/deno.lock @@ -0,0 +1,13 @@ +{ + "version": "3", + "remote": { + "https://esm.sh/preact@10.23.1": "5c90e3946c882878ada8f82671a1e2cfc3d307eb1253e83cee74f04194cecf41", + "https://esm.sh/preact@10.23.1/compat": "e6e124f2c59692ee4dda7d1b9271a6169c57eaa43077495497a44313195fc859", + "https://esm.sh/preact@10.23.1/debug": "8d66a656164fe5d5f40078740a444af0cbf38f4eefe415e7bbf76ceefdde4c32", + "https://esm.sh/stable/preact@10.23.1/denonext/compat.js": "49c7e42b0555fab75f189e8317d39a252bbb38b49224badf4a110c6a708954f7", + "https://esm.sh/stable/preact@10.23.1/denonext/debug.js": "baec17edc90c1c0ba53a2f64c66b3890779169e71289450634543a5a2aab839a", + "https://esm.sh/stable/preact@10.23.1/denonext/devtools.js": "bb198cea043a5878c0367867e1be710e9a11581f8ab10ca0a51091e3d2add74d", + "https://esm.sh/stable/preact@10.23.1/denonext/hooks.js": "6962ffaaded3eee1cff070f660b6304007754ef1993d63241d2f3807a10ee21e", + "https://esm.sh/stable/preact@10.23.1/denonext/preact.mjs": "c30c9bd2ab4b41104f97c0679413cdfe37ec2fa0131a7c5a1a2d3b6f6fae9670" + } +} diff --git a/index.html b/index.html index 5f1dc91..10399b5 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,6 @@ + + + + \ No newline at end of file diff --git a/junk/module_inspector.js b/junk/module_inspector.js new file mode 100644 index 0000000..dca71ac --- /dev/null +++ b/junk/module_inspector.js @@ -0,0 +1,131 @@ +/** + * @typedef {function(string): boolean} GlyphCheck + */ + +/** + * @type {GlyphCheck} + */ +const isAlphaLike = (inGlyph) => { + const inCode = inGlyph.charCodeAt(0); + + if (inCode >= 97 && inCode <= 122) { + return true; + } + + if (inCode >= 65 && inCode <= 90) { + return true; + } + + return `$_.`.includes(inGlyph); +}; + +/** + * @type {GlyphCheck} + */ +const isWhiteSpace = (inGlyph) => `\n\r\t `.includes(inGlyph); + +/** + * @type {GlyphCheck} + */ +const isQuote = (inGlyph) => `"'\``.includes(inGlyph); + +/** + * @param {GlyphCheck} inCheck + * @returns {GlyphCheck} + */ +const isNot = (inCheck) => (inGlyph) => !inCheck(inGlyph); + +/** + * @param {string} inText + * @param {number} inStart + * @param {GlyphCheck} inTest + * @returns {number} + */ +const contiguous = (inText, inStart, inTest) => { + let ok = true; + let index = inStart; + let count = 0; + while (ok && count < inText.length) { + count++; + ok = inTest(inText.charAt(index++)); + } + return index - 1; +}; + +/** + * @param {string} inFile + * @param {number} [inIndex=0] + * @param {Array<{internal: string, external: string}>} inLocal + * @param {Array} inForeign + * @returns {number|boolean} + */ +const findNextExport = (inFile, inIndex = 0, inLocal, inForeign) => { + const pos = inFile.indexOf("export", inIndex); + if (pos !== -1) { + if (!isAlphaLike(inFile.charAt(pos - 1)) || !isAlphaLike(inFile.charAt(pos + 6))) { + const nextCharInd = contiguous(inFile, pos + 6, isWhiteSpace); + const nextChar = inFile[nextCharInd]; + + if (nextChar === "*") { + const firstQuoteInd = contiguous(inFile, nextCharInd + 1, isNot(isQuote)); + const secondQuoteInd = contiguous(inFile, firstQuoteInd + 1, isNot(isQuote)); + inForeign.push(inFile.substring(nextCharInd, secondQuoteInd + 1)); + } else if (nextChar == "{") { + const endBracketInd = contiguous(inFile, nextCharInd, (inGlyph) => inGlyph !== "}"); + const nextLetterInd = contiguous(inFile, endBracketInd + 1, isWhiteSpace); + if (inFile.substring(nextLetterInd, nextLetterInd + 4) == "from") { + const firstQuoteInd = contiguous(inFile, nextLetterInd + 4, isNot(isQuote)); + const secondQuoteInd = contiguous(inFile, firstQuoteInd + 1, isNot(isQuote)); + inForeign.push(inFile.substring(nextCharInd, secondQuoteInd + 1)); + } else { + const members = inFile.substring(nextCharInd + 1, endBracketInd).replaceAll(" as ", "|||").replace(/\s/g, ''); + members.split(",").forEach(part => { + const renamed = part.split("|||"); + inLocal.push({ internal: renamed, external: renamed || renamed }); + }); + } + } else if (isAlphaLike(nextChar)) { + const keywordEndInd = contiguous(inFile, nextCharInd, isAlphaLike); + const keyword = inFile.substring(nextCharInd, keywordEndInd); + if (keyword === "default") { + inLocal.push({ internal: keyword, external: keyword }); + } else if (["const", "let", "var", "function", "class"].includes(keyword)) { + const varStartInd = contiguous(inFile, keywordEndInd + 1, isWhiteSpace); + const varEndInd = contiguous(inFile, varStartInd + 1, isAlphaLike); + const keyword = inFile.substring(varStartInd, varEndInd); + inLocal.push({ internal: keyword, external: keyword }); + } + } + } + + return pos + 7; + } else { + return false; + } +}; + +/** + * @param {string} inFile + * @returns {[local: string[], foreign: string[]]} + */ +export const Exports = (inFile) => { + let match = /** @type {number|boolean} */ (0); + let count = 0; + const local = /** @type {string[]} */ ([]); + const foreign = /** @type {string[]} */ ([]); + while (match !== false && count < 200) { + count++; + match = findNextExport(inFile, match, local, foreign); + } + return [local, foreign]; +}; + +/** + * @param {string|URL} inURL + * @returns {Promise<[local: string[], foreign: string[]]>} + */ +export const FileExports = async (inURL) => { + const resp = await fetch(inURL); + const text = await resp.text(); + return Exports(text); +}; diff --git a/junk/module_inspector.test.ts b/junk/module_inspector.test.ts index 285801c..b2a1db7 100644 --- a/junk/module_inspector.test.ts +++ b/junk/module_inspector.test.ts @@ -1,12 +1,14 @@ import * as Inspector from "./module_inspector.ts"; +console.log(); + Deno.test("check string parsing", ()=>{ const [local, global] = Inspector.Exports(` // export in comment /** * -* export const TESTtt +* export const * / const fakeexport =()=>{}; const exportfake =()=>{}; diff --git a/junk/module_inspector.ts b/junk/module_inspector.ts index 7c72d67..53e774a 100644 --- a/junk/module_inspector.ts +++ b/junk/module_inspector.ts @@ -32,7 +32,7 @@ const contiguous =(inText:string, inStart:number, inTest:GlyphCheck):number=> return index-1; } -const findNextExport =(inFile:string, inIndex=0, inLocal:Array, inForeign:Array)=> +const findNextExport =(inFile:string, inIndex=0, inLocal:Array<{internal:string, external:string }>, inForeign:Array)=> { const pos = inFile.indexOf("export", inIndex); if(pos !== -1) @@ -65,11 +65,12 @@ const findNextExport =(inFile:string, inIndex=0, inLocal:Array, inForeig } else { - const members = inFile.substring(nextCharInd+1, endBracketInd).replace(/\s/g, ''); + const members = inFile.substring(nextCharInd+1, endBracketInd).replaceAll(" as ", "|||").replace(/\s/g, ''); members.split(",").forEach(part=> { - const renamed = part.split(" as "); - inLocal.push(renamed[1] || renamed[0]); + const renamed = part.split("|||"); + //inLocal.push(renamed[1] || renamed[0]); + inLocal.push({internal:renamed[0], external:renamed[1]||renamed[0]}) }); } @@ -80,7 +81,7 @@ const findNextExport =(inFile:string, inIndex=0, inLocal:Array, inForeig const keyword = inFile.substring(nextCharInd, keywordEndInd); if(keyword === "default") { - inLocal.push(keyword); + inLocal.push({internal:keyword, external:keyword}); //console.log(`MEMBER: >>${keyword})}<<`); } else if(["const", "let", "var", "function", "class"].includes(keyword)) @@ -88,7 +89,8 @@ const findNextExport =(inFile:string, inIndex=0, inLocal:Array, inForeig const varStartInd = contiguous(inFile, keywordEndInd+1, isWhiteSpace); const varEndInd = contiguous(inFile, varStartInd+1, isAlphaLike); //console.log(`MEMBER: >>${inFile.substring(varStartInd, varEndInd)}<<`); - inLocal.push(inFile.substring(varStartInd, varEndInd)) + const keyword = inFile.substring(varStartInd, varEndInd); + inLocal.push({internal:keyword, external:keyword}); } } } diff --git a/preactthing.tsx b/preactthing.tsx new file mode 100644 index 0000000..12f074a --- /dev/null +++ b/preactthing.tsx @@ -0,0 +1,43 @@ +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
My Component
; +} + +export default MyComponent; diff --git a/state-preserve/index.html b/state-preserve/index.html new file mode 100644 index 0000000..45951ef --- /dev/null +++ b/state-preserve/index.html @@ -0,0 +1,7 @@ + + + +
+ + + \ No newline at end of file diff --git a/state-preserve/preact.js b/state-preserve/preact.js new file mode 100644 index 0000000..fe3c3b8 --- /dev/null +++ b/state-preserve/preact.js @@ -0,0 +1,30 @@ +import "https://esm.sh/preact@10.23.1/debug"; +import * as Preact from "https://esm.sh/preact@10.23.1"; +import * as React from "https://esm.sh/preact@10.23.1/compat"; +const H = Preact.h; + +console.log(React); + +/** @typedef {(vnode:Preact.VNode)=>unknown} DeepHook*/ + +/** @type {DeepHook|undefined} */ +const renderOld =Preact.options.__r; + +/** @type {DeepHook} */ +const renderNew =(vnode)=> +{ + console.log("render!") + console.log(vnode); + // how to examine state context here? +}; + +Preact.options.__r = renderOld ? /**@type{DeepHook}*/((vnode)=>{renderOld(vnode); renderNew(vnode);}) : renderNew; + +const Component =()=> +{ + const [countGet, countSet] = React.useState(3); + return H("h1", {onClick(){countSet(countGet+1)}}, `count: ${countGet}`); +} + +const root = document.querySelector("#app")||document.body; +Preact.render(H(Component, {HEY:"HEY"}), root); \ No newline at end of file diff --git a/test_changer.mjs b/test_changer.mjs index 1f30936..b03ae51 100644 --- a/test_changer.mjs +++ b/test_changer.mjs @@ -1,14 +1,20 @@ -export let changing = 2; +export let changing = 42; +//////////////////////////////////////////// +let ReImported = {}; const thisURL = new URL(import.meta.url) const thisFile = thisURL.pathname; if(!thisURL.search) { setInterval(()=>{ import(thisFile+"?"+Math.random()).then(module=>{ - - changing = module.changing; - console.log(changing); + ReImported = module; + for(let key in module) + { + const statement = `${key}=ReImported.${key}` + eval(statement); + console.log(statement); + } }) }, 3000); } \ No newline at end of file diff --git a/transpiler/index.html b/transpiler/index.html new file mode 100644 index 0000000..8171c0c --- /dev/null +++ b/transpiler/index.html @@ -0,0 +1,27 @@ + + + + + + + + + + + \ No newline at end of file