From 76092fc43dcc3e951820db59ac52d4c528a30ded Mon Sep 17 00:00:00 2001 From: Peter Harpending Date: Wed, 18 Oct 2023 22:26:22 -0600 Subject: [PATCH 1/2] b_lib <-> good/bad popup ipc now solved this was the big problem that was a huge hiccup. it is now solved. The next thing is just getting the buttons to work the way they're expected to other than that it's all fine. --- jrx/pages/gb.html | 2 + jrx/pages/gb.js | 17 ++++++ jrx/scratch/clown-town.ts | 50 +++++++++++++++ jrx/src/b_lib.ts | 124 +++++++++++++++++++++----------------- 4 files changed, 137 insertions(+), 56 deletions(-) create mode 100644 jrx/pages/gb.js create mode 100644 jrx/scratch/clown-town.ts diff --git a/jrx/pages/gb.html b/jrx/pages/gb.html index 939e9e2..c6bfc13 100644 --- a/jrx/pages/gb.html +++ b/jrx/pages/gb.html @@ -15,5 +15,7 @@
+ + diff --git a/jrx/pages/gb.js b/jrx/pages/gb.js new file mode 100644 index 0000000..372c14c --- /dev/null +++ b/jrx/pages/gb.js @@ -0,0 +1,17 @@ +// see b_lib.ts, function gb for the thing that talks to this +main(); + +async function main() { + // connect to the runtime + let port = browser.runtime.connect(); + // wait for a message + port.onMessage.addListener( + function({title, miscinfo, timeout_ms}) { + console.log('title', title); + console.log('miscinfo', miscinfo); + console.log('timeout_ms', timeout_ms); + document.getElementById('title-h1').innerHTML = title; + document.getElementById('miscinfo').innerHTML = miscinfo; + } + ); +} diff --git a/jrx/scratch/clown-town.ts b/jrx/scratch/clown-town.ts new file mode 100644 index 0000000..7231835 --- /dev/null +++ b/jrx/scratch/clown-town.ts @@ -0,0 +1,50 @@ + + function + the_function_that_runs_in_the_context_of_gb_dot_html + (gb_title : string, + gb_miscinfo : string, + gb_timeout_ms : number) + : string + { + // FIXME: not alerting user about bobs + alert('bobs!'); + //// the last evaluated statement of this function is the "return value" + //// as far as scripting.executeScript is concerned + //console.log('gb_title', gb_title); + //console.log('gb_miscinfo', gb_miscinfo); + //console.log('gb_timeout_ms', gb_timeout_ms); + + //document.getElementById('title-h1')!.innerHTML = gb_title; + + return 'good'; + } + + console.log('badness'); + // @ts-ignore i'm just assuming typescript is going to be stupid here i don't even know + let dialog_result: Array<{result: gb} | {error: any}> = + await browser.scripting.executeScript( + // @ts-ignore i'm just assuming typescript is going to be stupid here i don't even know + {func : the_function_that_runs_in_the_context_of_gb_dot_html, + args : [title, miscinfo, timeout_ms], + target : {tabId : tabid}, + // script just hangs forever without this line + // in no case does it alert user about bobs + // alright + // need a break + // when we get back, let's try a file + // otherwise we're going to have to try a totally different idiom + // maybe go back to some retarded message passing nonsense + injectImmediately: true + } + ); + + console.log('dialog_result', dialog_result[0]); + // @ts-ignore + if (dialog_result[0].error) { + // @ts-ignore + throw dialog_result.error; + } + else { + // @ts-ignore + return dialog_result[0].result; + } diff --git a/jrx/src/b_lib.ts b/jrx/src/b_lib.ts index 7b1bef3..6250ab6 100644 --- a/jrx/src/b_lib.ts +++ b/jrx/src/b_lib.ts @@ -495,6 +495,40 @@ let GB_MIN = 60*GB_SEC; * Timeout should be a multiple of 5. Use `GB_SEC` or `GB_MIN` because you're * stupid and can't do math. * + * # Why this is stupid + * + * Ok super important thing: there's a very stupid idiom in here for talking to + * the good/bad popup window. This is not because I am stupid. This is because + * web browsers are stupid. + * + * We cannot just spawn a window and then start talking to it. The problem is + * that this isn't Erlang where the process has a mailbox and we can count on + * the messages being delivered there and then being there when the process + * initiates a `raseev`. + * + * Instead the good/bad popup-window process has to spawn *and then listen for + * messages*, and if we send a message before it's listening, tough, it just + * doesn't get there. + * + * First instinct was of course to just wait for however many milliseconds for + * the popup window to spawn before sending it messages. But 200ms was not + * enough time for this approach to work on my beast of a machine. Given that + * our users are going to be running JR on normal machines, this approach is + * simply infeasible. + * + * Instead after much denial and error, I found the approach where the good/bad page script + * initiates a connection works consistently and is idiomatically sane, at + * least in relative terms. In this case, we are using the Port abstraction + * rather than the "one-off" connection thing that Mozilla says is low class. + * It is better in this case so that we don't have to deal with process-level + * global state in this function. + * + * If we wanted to interleave that nonsense into the global raseev loop at the + * top of this file, we would have to basically have some registry of pages + * we're trying to talk to, and then have some message queue that pairs each + * message from a script with whomever is trying to listen to it. That's + * doable but I would prefer not to create global state if it's unnecessary. + * * @internal */ async function @@ -504,72 +538,50 @@ gb timeout_ms : number) : Promise { - console.log('507'); + // we're going to make an unresolved result first + // write our code to handle messages from the popup window + // which updates this variable + // once this variable is updated with resolved: true + // then the entire function returns + let the_result : {resolved : false} + | {resolved : true, + result : gb} + = {resolved : false}; + // this is a closure that talks to the popup window from this context + // it updates the_result when it gets something back from the user + let port_talker_toer_lambda = + function(port : browser.runtime.Port) { + // @ts-ignore bad type info in the typedefs + port.postMessage({title : title, + miscinfo : miscinfo, + timeout_ms : timeout_ms}); + + // oh my god + // nested lambdas + // i think we've reached peak js + let result_handler = + function(result_from_gb_popup_window : gb) { + // the message will either be good or bad + the_result = {resolved : true, + result : result_from_gb_popup_window}; + }; + // @ts-ignore types from github are wrong + port.onMessage.addListener(result_handler); + } + browser.runtime.onConnect.addListener(port_talker_toer_lambda); + // does the user want to sign the message let confirm_window = await browser.windows.create({url : '../pages/gb.html', type : 'popup'}); - console.log('509'); // @ts-ignore shut the fuck up - let tabid : number = confirm_window.tabs[0].id; - console.log('515'); - - function - the_function_that_runs_in_the_context_of_gb_dot_html - (gb_title : string, - gb_miscinfo : string, - gb_timeout_ms : number) - : string - { - // FIXME: not alerting user about bobs - alert('bobs!'); - //// the last evaluated statement of this function is the "return value" - //// as far as scripting.executeScript is concerned - //console.log('gb_title', gb_title); - //console.log('gb_miscinfo', gb_miscinfo); - //console.log('gb_timeout_ms', gb_timeout_ms); - - //document.getElementById('title-h1')!.innerHTML = gb_title; - - return 'good'; - } - - console.log('badness'); - // @ts-ignore i'm just assuming typescript is going to be stupid here i don't even know - let dialog_result: Array<{result: gb} | {error: any}> = - await browser.scripting.executeScript( - // @ts-ignore i'm just assuming typescript is going to be stupid here i don't even know - {func : the_function_that_runs_in_the_context_of_gb_dot_html, - args : [title, miscinfo, timeout_ms], - target : {tabId : tabid}, - // script just hangs forever without this line - // in no case does it alert user about bobs - // alright - // need a break - // when we get back, let's try a file - // otherwise we're going to have to try a totally different idiom - // maybe go back to some retarded message passing nonsense - injectImmediately: true - } - ); - - console.log('dialog_result', dialog_result[0]); - // @ts-ignore - if (dialog_result[0].error) { - // @ts-ignore - throw dialog_result.error; - } - else { - // @ts-ignore - return dialog_result[0].result; - } - + // let tabid : number = confirm_window.tabs[0].id; + return 'bad'; } - /** * Make the dumb address_subscribe thing * From 0f337f1519265024375ded4a611b736ed3e9d4be Mon Sep 17 00:00:00 2001 From: Peter Harpending Date: Wed, 18 Oct 2023 22:30:57 -0600 Subject: [PATCH 2/2] jex: add -w/-f options to dwim(-|+|++)/install, make extinstall its own command --- utils/jex/src/jex.erl | 44 +++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/utils/jex/src/jex.erl b/utils/jex/src/jex.erl index 3efe365..88c8adf 100644 --- a/utils/jex/src/jex.erl +++ b/utils/jex/src/jex.erl @@ -9,7 +9,7 @@ %%% @end -module(jex). --vsn("0.1.0"). +-vsn("0.2.0"). -export([start/1]). -compile([export_all, nowarn_export_all]). @@ -64,10 +64,18 @@ help_screen() -> "\n" "PORCELAIN COMMANDS:\n" " dwim- build project but don't make a release (init, clean, pull, build)\n" + " -w, --weak (on `jex build` step) continue building even if tsc fails\n" + " -f, --force (on `jex build` step) use cp -rf instead of cp -r\n" " dwim+ build and make a minimal release (init, clean, pull, build, mindist, push)\n" + " -w, --weak (on `jex build` step) continue building even if tsc fails\n" + " -f, --force (on `jex build` step) use cp -rf instead of cp -r\n" " dwim++ build and make a full release (init, clean, pull, build, mindist, push, mkdocs, pushdocs)\n" + " -w, --weak (on `jex build` step) continue building even if tsc fails\n" + " -f, --force (on `jex build` step) use cp -rf instead of cp -r\n" " install synonym for dwim++\n" - " install [TARBALL_PATH] install the given package\n" + " -w, --weak (on `jex build` step) continue building even if tsc fails\n" + " -f, --force (on `jex build` step) use cp -rf instead of cp -r\n" + " extinstall TARGZ_PATH install a prebuilt jex package\n" " ls list installed packages\n" " viewdocs [PKG [PORT]] view package docs for PKG in browser\n" " get_mindist [PKG] get the mindist tarball for an installed package\n" @@ -110,11 +118,11 @@ help_screen() -> %% Porcelain -dispatch(["dwim-"]) -> dwim(minus); -dispatch(["dwim+"]) -> dwim(plus); -dispatch(["dwim++"]) -> dwim(plus_plus); -dispatch(["install"]) -> install(); -dispatch(["install", Path]) -> install(Path); +dispatch(["dwim-" | BuildOpts]) -> dwim(minus, BuildOpts); +dispatch(["dwim+" | BuildOpts]) -> dwim(plus, BuildOpts); +dispatch(["dwim++" | BuildOpts]) -> dwim(plus_plus, BuildOpts); +dispatch(["install" | BuildOpts]) -> install(BuildOpts); +dispatch(["extinstall", Path]) -> extinstall(Path); dispatch(["ls"]) -> ls(); dispatch(["viewdocs"]) -> viewdocs(); dispatch(["viewdocs", Pkg]) -> viewdocs(Pkg); @@ -166,23 +174,25 @@ man() -> %%----------------------------------------------------------------------------- -%% jex dwim +%% jex dwim(-|+|++) / jex install %%----------------------------------------------------------------------------- -dwim(minus) -> +dwim(minus, BuildOpts) -> init(), clean(), pull(), - build([]); -dwim(plus) -> - dwim(minus), + build(BuildOpts); +dwim(plus, BuildOpts) -> + dwim(minus, BuildOpts), mindist([]), push(); -dwim(plus_plus) -> - dwim(plus), +dwim(plus_plus, BuildOpts) -> + dwim(plus, BuildOpts), mkdocs(), pushdocs(). +install(BuildOpts) -> + dwim(plus_plus, BuildOpts). %%----------------------------------------------------------------------------- %% jex cfgbarf @@ -676,13 +686,11 @@ srsly_readme_path() -> %%----------------------------------------------------------------------------- -%% jex install TARBALL_PATH +%% jex extinstall TARBALL_PATH %%----------------------------------------------------------------------------- -install() -> - dwim(plus_plus). -install(TarballPath) -> +extinstall(TarballPath) -> case file_exists(TarballPath) of false -> error({file_dne, TarballPath}); true -> install2(TarballPath)