I've been playing around with JavaScript to WASM. There's a few different libraries; Javy, jco, js2wasm, to the extent applicable AssemblyScript.
In trying to include the qjs-wasi.wasm build in a benchmark I have that includes various languages compiled to WASM I went ahead and just hardcoded some JavaScript into qjs.c before compilation to WASM with WASI-SDK.
I'm wondering what is the most practical way to accept STDIN and/or point to a file for the embedding part before compilation?
The relevant part of qjs.c, after commenting a lot of unused code that won't be used because I dropped parsing options and interactive mode https://github.com/quickjs-ng/quickjs/blob/master/qjs.c#L638-L645
const char *str =
"import * as bjson from 'qjs:bjson';\n"
"import * as std from 'qjs:std';\n"
"import * as os from 'qjs:os';\n"
"globalThis.bjson = bjson;\n"
"globalThis.std = std;\n"
"globalThis.os = os;\n"
"print('hello world');\n"
"const output = new Uint8Array([97]);\n"
"std.out.write(output.buffer, 0, output.length);\n"
"std.out.flush();";
eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
That was the test. What I did after that was minify the JavaScript input with bun build --minify then threw it in there.
I'm thinking I can do something similar with Bellard's MicroQuickJS, which after strip is around a little over 200 KiB.
You'd probably have the best luck asking on quickjs-ng about their project and ways to use it.
FWIW you're missing a major JS-on-Wasm runtime, StarlingMonkey (a BA project); fwiw, StarlingMonkey does natively support snapshotting with JS source read from a file or stdin. (See the docs for more.)
There's no STDIN reading and STDOUT writing in StarlingMonkey. I tried. Back when it was redfire? I might even have an outstanding issue over there.
This is how I came to this https://github.com/quickjs-ng/quickjs/issues/1527.
I understand there's no I/O in ECMA-262 - which is a serious omission / handicap. I have to jump through RegExp hoops to read STDIN in SpiderMonkey proper .
// Call readline() N times to catch `\r\n\r\n"` from 2d port.postMessage()
let stdin;
while (true) {
stdin = readline();
if (stdin !== null) {
break;
}
}
let data = `${stdin}`.replace(/[\r\n]+|\\x([0-9A-Fa-f]{2,4})/gu, "")
.replace(/[^A-Za-z0-9\s\[,\]\{\}:_"]+/igu, "")
.replace(/^"rnrn/gu, "")
.replace(/^[#\r\n\}_]+(?=\[)/gu, "")
.replace(/^"(?=["\{]+)|^"(?!"$)/gu, "")
.replace(/^\[(?=\[(?!.*\]{2}$))/gu, "")
.replace(/^\{(?!\}|.+\}$)/gu, "")
.replace(/^[0-9A-Z]+(?=[\[\{"])/igu, "")
.replace(/^[\]\}](?=\[)/i, "")
.trimStart().trim();
return encodeMessage(data);
}
V8's d8 is worse. Basically impossible. So I use head and dd.
fwiw, StarlingMonkey does natively support snapshotting with JS source read from a file or stdin. (See the docs for more.)
Yeah, I'd like to see a direct reference for that capability. I havn't seen it.
Back when it was redfire?
I have no idea what redfire is, sorry, but AFAIK StarlingMonkey has never been "redfire".
Yeah, I'd like to see a direct reference
https://github.com/bytecodealliance/StarlingMonkey/blob/main/README.md
"./componentize.sh index.js -o index.wasm"
it appears I was mistaken about a mode to read source from stdin (maybe that was the old Fastly SDK this evolved from). In any case that has nothing to do with stdin/stdout access from the guest itself, it's just the plumbing to get JS into the snapshot
Didn't that start out as SpiderFire?
I mean actual read and write in the runtime. Like we can do in QuickJS. I'll have to dig through my issues.
With all due respect, the component thing is just a bunch more code for no reason, in my opinion. But I'll try out what you're suggesting, later, and post back here the results.
It appears that SpiderFire is a completely separate runtime. StarlingMonkey is a Bytecode Alliance-hosted project built on SpiderMonkey that was evolved from earlier serverless/FaaS-focused SDK work we had been doing. No lineage to other runtimes.
With all due respect, the component thing is just a bunch more code for no reason, in my opinion.
FWIW, you're of course welcome to your opinion, but pointing this out in this way comes off as antagonistic. I'm trying to help you find runtimes that can snapshot JS, that's all. Good day and best of luck!
I am not sure I fully follow the conversation, but regarding compiling JS to Wasm AOT that's something achievable, for example, with Javy: https://github.com/bytecodealliance/javy/blob/main/docs/docs-using-dynamic-linking.md
Yes, StarlingMonkey as well -- there are two BA projects that achieve this
There's no STDIN reading and STDOUT writing in StarlingMonkey
StarlingMonkey does support stdin reading and stdout writing through wasi. For example you can use ComponentizeJS or jco (both uses StarlingMonkey) that will turn your wit world import into js modules that you can import and that is true for wasi:cli/stdin / wasi:cli/stdout.
I had a similar issue in the past. I ended up providing a tool that would compile my code which then calls include_str() at a location and sticks it in a static.
They are probably so much better ways though
Chris Fallin said:
It appears that SpiderFire is a completely separate runtime. StarlingMonkey is a Bytecode Alliance-hosted project built on SpiderMonkey that was evolved from earlier serverless/FaaS-focused SDK work we had been doing. No lineage to other runtimes.
With all due respect, the component thing is just a bunch more code for no reason, in my opinion.
FWIW, you're of course welcome to your opinion, but pointing this out in this way comes off as antagonistic. I'm trying to help you find runtimes that can snapshot JS, that's all. Good day and best of luck!
That's just my opinion. I look at WIT and am like that's a whole different language to learn. Thanks.
andreaTP said:
I am not sure I fully follow the conversation, but regarding compiling JS to Wasm AOT that's something achievable, for example, with Javy: https://github.com/bytecodealliance/javy/blob/main/docs/docs-using-dynamic-linking.md
Yeah, I've done this using Javy, js2wasm, Facebook's Static Hermes.
Hit a roadblock when it came to defining WIT. Though I was able to do tge wasm-tools to component thing on AssemblyScript and Javy. Didnt add anything observable to me.
A generic WIT definition for stdin and stdout would be useful. Seems like theres a lot of flux and everybody doez it diffefently, like WASI implementations in general.
bw, ive tried with jco, starlingmonkey, componentizejs, componentize qjs. ill try again later today
A generic WIT definition for stdin and stdout would be useful.
That's wasi:cli/stdin and wasi:cli/stdout, as pointed out to you above. You shouldn't need to write any new WIT for this.
Chris Fallin said:
A generic WIT definition for stdin and stdout would be useful.
That's
wasi:cli/stdinandwasi:cli/stdout, as pointed out to you above. You shouldn't need to write any new WIT for this.
To be clear, I'm not trying to _find_ JavaScript to WASM compilers, I'm testing, vetting, and comparing them.
I've got about 30 different versions of the same algorithm - several already using JavaScript to WASM compilation targets, from Rust to C, Zig to QuickJS, and around 7 or 8 compiled to WASM; see https://github.com/guest271314/native-messaging-webassembly/blob/main/install_hosts.js#L39-L114 and https://guest271314.github.io/native-messaging-webassembly/.
What I'm doing now is attempting to do a JavaScript to WASM only comparison. I'm not looking for a single solution. I'm seeing which ones do what, which ones don't do what.
Back outta the field. I'll see what happens with
StarlingMonkey and STDIN.
Ahh, this is what the roadblock in StarlingMonkey world was last time I looked
This mode currently only supports the creation of HTTP server components, which means that the
index.jsfile must register afetchevent handler. For example, yourindex.jscould contain the following code:
There's not networking involved in my code.
Tomasz Andrzejak said:
There's no STDIN reading and STDOUT writing in StarlingMonkey
StarlingMonkey does support
stdinreading andstdoutwriting through wasi. For example you can useComponentizeJSorjco(both uses StarlingMonkey) that will turn yourwitworld import into js modules that you can import and that is true forwasi:cli/stdin/wasi:cli/stdout.
I don't have a WIT world. I just have working JavaScript code. Same algorithm implemented for node, deno, bun, tjs, qjs, llrt, js (SpiderMonkey), d8 (V8), shermes. In WASM only world, using javy, js2wasm (https://github.com/guest271314/js2); see https://github.com/guest271314/NativeMessagingHosts.
So, if I'm reading you folks correctly the only WIT I need to do the Component Model thing with ComponentizeJS or jco is this basic WIT, that js2wasm output, right?
package js2wasm:nm-js2wasm;
world module {
/// Core import: wasi_snapshot_preview1.fd_write
import fd-write: func(fd: s32, iovs: s32, iovs-len: s32, nwritten: s32) -> s32;
/// Core import: wasi_snapshot_preview1.fd_read
import fd-read: func(fd: s32, iovs: s32, iovs-len: s32, nread: s32) -> s32;
}
@Chris Fallin @Tomasz Andrzejak
Here's a JavaScript runtime agnostic Native Messaging host https://github.com/guest271314/NativeMessagingHosts/blob/main/nm_host.js. The same code works using node, deno, bun, and tjs (txiki.js).
In theory all I need is this WIT
world module {
/// Core import: wasi_snapshot_preview1.fd_write
import fd-write: func(fd: s32, iovs: s32, iovs-len: s32, nwritten: s32) -> s32;
/// Core import: wasi_snapshot_preview1.fd_read
import fd-read: func(fd: s32, iovs: s32, iovs-len: s32, nread: s32) -> s32;
}
and the code should be compilable to WASM with jco or @bytecodealliance/componentize-js or componentize.sh, right?
(deleted)
I went ahead and filed this issue in ComponentizeJS. https://github.com/bytecodealliance/ComponentizeJS/issues/342.
I was really just asking how you folks would go about emdedding JavaScript source into QuickJS's qjs.c before compilation to qjs-wasi.wasm with WASI-SDK.
But since ther are suggestions to use Bytecode Alliance gear, sure, I can add Bytecode Alliance gear to my test. I look forward to clarification about reading STDIN, writing to STDOUT, and the minimal WIT for the Component Model thingy. Thanks.
andreaTP said:
I am not sure I fully follow the conversation, but regarding compiling JS to Wasm AOT that's something achievable, for example, with Javy: https://github.com/bytecodealliance/javy/blob/main/docs/docs-using-dynamic-linking.md
AFAICT there's no AOT compilation going on at all in Bytecode Alliance's Javy, nor the qjs-wasi.wasm example I originally asked about.
The QuickJS engine is embedded and the JavaScript is dynamically evaluated. If that were not the case there'd be no need to embed rquicks into Javy, and the resulting WASM plug.wasm file wouldn't almost idenitically match the size of qjs.
js2wasm https://github.com/loopdive/js2 _does_ do the AOT thing in WASM GC, that works with wasmtime 45+, where WASM GC is still being worked on, the last I checked a couple days ago.
Nonetheless, yes, I'm familiar with Javy. I created a version of the Node.js example that runs in the browser https://github.com/guest271314/javy-browser-host.
Just for the record, here's the Facebook (Meta) Static Hermes style of JavaScript compilation to WASM with WASI-SDK, in pertinanet part https://gist.github.com/guest271314/b10eac16be88350ffcd19387e22ad4d5#emit-c-from-javascript-source-with-shermes-compile-to-wasm-with-wasi-sdk-clang-and-clang.
And one way to read STDIN in using shermes https://gist.github.com/guest271314/fec412134903e50521c12370edc88ef3. It wasn't/ain't a simple matter over there, either...
WASM GC, that works with
wasmtime45+, where WASM GC is still being worked on, the last I checked a couple days ago.
That's an inaccurate characterization. Wasm GC is in fact a tier 1 feature now and on by default, and has been essentially stable and usable for quite some time now. doc link
I was really just asking how you folks would go about emdedding JavaScript source into QuickJS's
qjs.cbefore compilation toqjs-wasi.wasmwith WASI-SDK.
And as mentioned above, QuickJS is not a Bytecode Alliance project, so this is the wrong place to ask. I'd encourage you to ask the maintainers of that code how to use it. Best of luck!
Chris Fallin said:
WASM GC, that works with
wasmtime45+, where WASM GC is still being worked on, the last I checked a couple days ago.That's an inaccurate characterization. Wasm GC is in fact a tier 1 feature now and on by default, and has been essentially stable and usable for quite some time now. doc link
I was really just asking how you folks would go about emdedding JavaScript source into QuickJS's
qjs.cbefore compilation toqjs-wasi.wasmwith WASI-SDK.And as mentioned above, QuickJS is not a Bytecode Alliance project, so this is the wrong place to ask. I'd encourage you to ask the maintainers of that code how to use it. Best of luck!
See https://github.com/bytecodealliance/wasmtime/issues/13386#issuecomment-4635521910 re everything working just great in WASM GC
Ah yeah #13382 definitely didn't fix this issue, this issue was spawned from discussion on that PR.
and https://github.com/bytecodealliance/wasmtime/issues/13216#issuecomment-4637655407
Regarding this repo, in first benchmarks I stumbled over the
array.copyperformance gap tracked in #13279 and that a fix is expected to ship in the next release.
Guess who was testing js2waasm using wasmtime 44 and encountered what is described and relayed that to the maintainer - who relayed that feedback upstream?
Anyway, I was thinking it's all about spreading the knowledge, domain and range of WebAssembly here - not just BCA. Guess I am terribly mistaken.
In any event I have filed issues in ComponentizeJS and StalingMonkey - both Bytecode Alliance projects, respectfully asking exacly how the I/O works and how to cobble together the new WIT thing the CM expects. No QuickJS involved. Just comparisons to working code - including Javy, another BCA offspring. If StarlingMoney and ComponentizeJS can do, kindly illuminate the path to achieving implementing the Native Messaging protocol using those BCA projects.
Again, thank for your time and effort. Have a great day.
A little update. @Tomasz Andrzejak Has been very helpful over here https://github.com/andreiltd/componentize-qjs/issues/2. Got a Native Messaging host working using componentize-qjs, using WASI P2. Along the way found out wasmtime is apparently buffering writes to STDOUT when P3 is used. Ironically, when the P2 version got to working they disclosed they are using library-specific read and write methods!If the point of WIT is a comprehensive template for all of the things, across different languages, as soon as that gets going people create custom methods outside of the template. Thus these issues.
I think when streams.methodOutputStreamBlockingWriteAndFlush(output, data.subarray(off, off + WRITE_CHUNK)) and const r = streams.methodInputStreamBlockingRead(input, n - off)are replaced with the P2 versions found in wasi:io/streams@0.2.6 I should be able to use the same code with at least componentize-js and jco - as long as those respective libraries have not also created custom interfaces.
Finally got this working using jco. Very different code and import expectations cf. componentize-qjs.
bun x jco componentize nm_jco_p2.js \
--wit native-messaging-p2 \
--world-name native-messaging-p2 \
-d http -d fetch-event \
--out nm_jco_p2.wasm
OK Successfully written nm_jco_p2.wasm.
HTTP included by default is a bit pushy downstream from StarlingMonkey...
AssemblyScript compiled to WASI P1 and then "adapted" into Component Model by wasm-tools is 31.3 KiB.
nm_jco_p2.wasm is 12.1 MiB. Insane... I'll reproduce the build a couple more times from scratch then close out the issues I filed with steps to reproduce. Definitely a learning experience...
Here you go, componentize-qjs and ComponentizeJS/jco Component Model based WASI P2 Native Messaging hosts, respectively
I still havn't been able to do the componentize.sh thing in StarlingMonkey proper.
/media/user/x/StarlingMonkey/cmake-build-release/componentize.sh nm_componentize_js.js -o sm.wasm
Componentizing nm_componentize_js.js into sm.wasm
Error: failed to run main module `/media/user/x/StarlingMonkey/cmake-build-release/starling-raw.wasm`
Caused by:
no func export named `wizer-initialize` found
error: failed to read from `sm.wasm`
Caused by:
0: No such file or directory (os error 2)
I'm pretty sure downstream ComponentizeJS/jco output has stuff in there that ain't being used, even after --disable http --disable fetch-event.
The WASM using WASI P2 (couldn't get wasmtime 45 to run the WASI P3 stuff without inserting newlines, which compromises integrity of roundtrip/echo) output by ComponentizeJS/jco is a whopping 13.4 MiB for a Native Messaging host. The WAT output by wasm-tools print is 170 MiB. Insane...
@guest271314 same as in the other two places where I just sent you messages: please be mindful of your tone. You've made your feelings on all kinds of things we're working on well known by now, and we're not in need of more information about them. We, the Bytecode Alliance's TSC, will start removing your messages or prevent you from sending additional ones if you don't tone it down
@guest271314 same as in the other two places where I just sent you messages: please be mindful of your tone. You've made your feelings on all kinds of things we're working on well known by now, and we're not in need of more information about them. We, the Bytecode Alliance's TSC, will start removing your messages or prevent you from sending additional ones if you don't tone it down
Do what you do.
I don't take well to threats of reprisals for posting my opinion on technical matters.
guest271314 said:
I don't take well to threats of reprisals for posting my opinion on technical matters.
dude. you are barging into someone's house uninvited and telling them you don't like the interior decor. you might even have good points, but that doesn't mean that the way you're making them is acceptable.
fitzgen (he/him) said:
guest271314 said:
I don't take well to threats of reprisals for posting my opinion on technical matters.
dude. you are barging into someone's house uninvited and telling them you don't like the interior decor. you might even have good points, but that doesn't mean that the way you're making them is acceptable.
I don't entertain likes and dislikes. I deal with technical facts. Maybe other folks might not like the terseness and pedantic inpependent observations that they can reproduce?
Some raw data to chew on. The Component Model WASM output by componentize-js/jco is around 8 times slower to execute by wasmtime than the next slowest to execute by wasmtime, Go source code compiled with go, not to be confused with the same source code compiled with tinygo. All I can say is, wow...
0 'nm_zig' 0.09759999999900659
1 'nm_go' 0.10093333333482345
2 'nm_lua' 0.10776666666318972
3 'nm_zig_wasi' 0.10803333333134651
4 'nm_shermes' 0.12583333333333332
5 'nm_assemblyscript' 0.13146666667113702
6 'nm_qjs' 0.14363333333283665
7 'nm_rust' 0.1475
8 'nm_c_wasi' 0.152
9 'nm_cpp' 0.15306666666517654
10 'nm_c' 0.15910000000149013
11 'nm_warpo' 0.1645
12 'nm_componentize_qjs' 0.1686000000014901
13 'nm_tjs' 0.16963333333283662
14 'nm_javy' 0.1742666666681568
15 'nm_qjs_wasi' 0.1772000000004967
16 'nm_rust_wasi' 0.1772000000004967
17 'nm_tinygo_wasi' 0.1963666666696469
18 'nm_deno' 0.22149999999751646
19 'nm_nodejs' 0.2383333333333333
20 'nm_bun' 0.2388999999985099
21 'nm_cpp_wasi' 0.24506666666766008
22 'nm_typescript' 0.2626333333328366
23 'nm_ruby' 0.26753333333383006
24 'nm_bash' 0.2878666666671634
25 'nm_python' 0.3299000000009934
26 'nm_spidermonkey' 0.3761000000014901
27 'nm_d8' 0.4375000000024835
28 'nm_javy_node_wasi' 0.4617000000029803
29 'nm_llrt' 0.8525666666676601
30 'nm_go_wasi' 1.3399666666686534
31 'nm_componentize_js' 8.171066666670145
One more run, just to make sure the previous was not an anomoly. Same algorithm. 10 runs, averages. Yep, the componentize-js/jco result even gets smoked by Bash!
0 'nm_rust' 0.11625999999940395
1 'nm_zig' 0.11707999999895691
2 'nm_shermes' 0.11987999999970197
3 'nm_lua' 0.12004999999999999
4 'nm_go' 0.12407999999895691
5 'nm_zig_wasi' 0.13098000000044702
6 'nm_c' 0.13629999999925493
7 'nm_cpp' 0.13901999999880793
8 'nm_qjs' 0.14403999999985098
9 'nm_tjs' 0.144689999999851
10 'nm_warpo' 0.1599100000008941
11 'nm_c_wasi' 0.16444000000059605
12 'nm_assemblyscript' 0.16951999999955297
13 'nm_qjs_wasi' 0.171380000000447
14 'nm_componentize_qjs' 0.17316999999955296
15 'nm_javy' 0.17483000000193716
16 'nm_rust_wasi' 0.17595
17 'nm_deno' 0.19719999999850987
18 'nm_bun' 0.214310000000149
19 'nm_nodejs' 0.222270000000298
20 'nm_tinygo_wasi' 0.2259699999988079
21 'nm_js2wasm' 0.2277000000014901
22 'nm_typescript' 0.23329999999999998
23 'nm_cpp_wasi' 0.267280000000447
24 'nm_ruby' 0.27748999999985097
25 'nm_go_wasi' 0.29124999999850987
26 'nm_python' 0.292139999999851
27 'nm_spidermonkey' 0.293410000000894
28 'nm_bash' 0.295620000000298
29 'nm_javy_node_wasi' 0.38675000000000004
30 'nm_d8' 0.3936500000014901
31 'nm_componentize_js' 0.666629999999702
32 'nm_llrt' 0.7768699999980628
I don't entertain likes and dislikes. I deal with technical facts. Maybe other folks might not like the terseness and pedantic inpependent observations that they can reproduce?
This is the last message I'll send on this topic, but to reemphasize: you don't get to make the rules in our spaces. I know that you disagree with the rules we made, but nevertheless: you can choose to abide by them and be welcome, or you can choose not to, and not be welcome.
And regarding the numbers you shared: neither these numbers nor anything else I've seen you share here give us any new information. If at any point you'd come in with an open mind and asked questions about what you're seeing instead of calling things "insane", I might be up for explaining to you why what you're seeing isn't ideal, but also not unexpected. But since you've given me, and others here, absolutely no reason to engage with you, I'll use my time in better ways instead.
And regarding the numbers you shared: neither these numbers nor anything else I've seen you share here give us any new information. If at any point you'd come in with an open mind and asked questions about what you're seeing instead of calling things "insane", I might be up for explaining to you why what you're seeing isn't ideal,
Oh. That's what struck a nerve. Don't take that as a personal or organizational affront. It's a term of art, a human expression; the same as "WTH", "I was shocked to find out", "Wow". But you expect a question:
Given the art in the sector that co-existed, VM Ware Labs WASM Workers Server, WasmEdge, Workerd - why didn't the team instead statically analyze the JavaScript source code, and pull ONLY what was NEEDED by the source code from SpiderMonkey source code to complete the instruction?
The first two systems you name use QuickJS-based JS runtimes within Wasm, and workerd (I am assuming Cloudflare's project by that name) is native V8, which can run JS in the usual host-JIT'd fashion.
None of these "statically analyze the JavaScript source code and pull only what was needed". Static analysis of JavaScript is an enormously deep and difficult subject, and not something that one "just does" as if it's obvious. SpiderMonkey is large because it's a browser-targeted JavaScript engine.
To echo Till, I am extremely tired of your mode of engagement here. Ranging from the snide and dismissive "[insane] is a term of art, a human expression" (as if we need this to be explained) to the misinformed (why doesn't one just simply statically analyze JS?) to the enormously entitled (your shit sucks, why haven't you solved it yet).
If you're interested in helping, then help. Asking questions is not helping. We are all hardworking folks trying to solve real problems with real constraints, and there is no grand conspiracy to screw that up in just such a way to annoy you. These are just hard problems and we're pushing the state of the art in new niches. If you think you can do better, then go and do better, rather than talking to others as if we owe you this.
In summary: you're coming off extremely poorly and creating a toxic environment here. (It is probably no coincidence, if I take the matching username as a true match, that you are also banned on Reddit and on StackOverflow.) As far as I am concerned, the TSC needs to take further action. Good day and good luck.
None of these "statically analyze the JavaScript source code and pull only what was needed". Static analysis of JavaScript is an enormously deep and difficult subject, and not something that one "just does" as if it's obvious.
If you're interested in helping, then help.
See https://github.com/loopdive/js2
(It is probably no coincidence, if I take the matching username as a true match, that you are also banned on Reddit and on StackOverflow.) As far as I am concerned, the TSC needs to take further action. Good day and good luck.
Yep, that's me. And around 3 dozen more https://guest271314.com.
This is just constructive feedback. Some nudges. Y'all are the experts. No ill will. I'm on the front-end testing your gear, and comparing your gear to other art in the sector right now.
I'm not the only programmer in the field that has noticed starting a 13 MiB WASM file is expensive. That's what science is about. Not getting mad because somebody says, that ain't the buisness, based on the evidence. Other than that, great work!
von Braun wasn't recruited under Operation Paperclip because he wasn't gonna test, and testing without regard for the how the evidence would turn on this or that fragility or excess was needed to get the U.S. to the moon.
von Braun believed in testing. I cannot emphasize that term enough – test, test, test. Test to the point it breaks.
@guest271314 as I said before, whether your behavior is welcome here or not is not a matter of discussion. You've been given a substantial amount of constructive feedback by a number of people, and chose to react with arguments instead of acknowledging the simple fact that if you want to be welcome here, you need to accept that you need to adjust your behavior to align with our expectations.
Since you've made it entirely clear that you have no intention of doing so, I'm deactivating your account here and banning you from engaging in our GitHub repos going forward.
Last updated: Jul 29 2026 at 05:03 UTC