[HN Gopher] Extism: Make all software programmable with WebAssembly
       ___________________________________________________________________
        
       Extism: Make all software programmable with WebAssembly
        
       Author : nilslice
       Score  : 298 points
       Date   : 2022-12-01 13:53 UTC (9 hours ago)
        
 (HTM) web link (extism.org)
 (TXT) w3m dump (extism.org)
        
       | hybid wrote:
       | If I want to make all software programmable, I install Frida and
       | easily hook into pretty much anything at the same privilege
       | level.
       | 
       | Still, misleading headline aside, this sounds pretty cool as a
       | reasonably well sandboxed plug-in architecture for software that
       | chooses to use it.
       | 
       | Though if running in-process, it seems unlikely to be able to
       | defend against hostile plugins that use e.g. speculative
       | execution techniques to extract otherwise inaccessible data. But
       | perhaps that's not the threat model here.
        
         | warpech wrote:
         | For those who don't know what Frida is: https://frida.re/
         | 
         | I must say, this sentence from their docs describe it the best
         | to me: Greasemonkey for native apps
         | 
         | It has little to do with Extism, but still is interesting.
        
       | meowface wrote:
       | Three thoughts:
       | 
       | * That's an absolutely viscerally horrifying logo
       | 
       | * I absolutely love it and its design
       | 
       | * I am confused about why it's used for a project like this and
       | not some kind of internal NSA project, or maybe a nu-witch house
       | band logo, or something
        
         | nilslice wrote:
         | LOL
         | 
         | Thank you on all 3 points!!
         | 
         | I intended to invoke thoughts about how Extism enables one to
         | "extend from within", thus the octopus crawling out from the
         | skull. And also that the thing Extism should replace is rather
         | cursed... loading DLLs / dlopen tons of plug-ins into your
         | program to execute untrusted code is downright scary.
        
           | duxup wrote:
           | The logo is symbolic of the product or thing right (Extism),
           | not other things?
           | 
           | Not sure I would get the escaping from part by looking at a
           | logo.
        
       | beders wrote:
       | I've built a plugin-system back in 2003 or so based on the JVM
       | which can load/re-load bytecode relatively easily.
       | 
       | (the concept became popular in the JVM world and lead to
       | abominations like OSGi)
       | 
       | The problems that arose quickly were: - Executing order of
       | plugins attaching to the same extension point.
       | 
       | - Third party library dependencies having different versions
       | 
       | - Traceability and debugging
       | 
       | - Thread-safety
       | 
       | OTOH, it gave our custom dev team to develop integrations and
       | extensions that could be deployed and maintained independently of
       | the main product. So there's definitely a use-case in there, but
       | it requires some coordination regardless.
        
         | bhelx wrote:
         | Would love to hear more about your experience there.
         | 
         | > (the concept became popular in the JVM world and lead to
         | abominations like OSGi)
         | 
         | I remember this, though it was a couple years before my time.
         | Although some of the underlying technology has changed those
         | problems you outlined have remained the same. These things are
         | all relevant to our next steps. We've been thinking a lot about
         | what developer experience problems need to be solved.
        
       | haberman wrote:
       | I'm trying to figure out what Extism is actually providing here.
       | 
       | The underlying runtime appears to be Wasmtime, an existing
       | project that you can use separately.
       | 
       | For the system API, Extism supports WASI (a POSIX-like API for
       | WASM) which is already supported by Wasmtime. However it sounds
       | like it also has a different, non-WASI API that provides similar
       | functionality. I'm curious to hear a compare/contrast between
       | these two system APIs, or what motivated inventing a new non-WASI
       | system API. It does appear that WASI is in its early days; WASI
       | was announced in 2019
       | (https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webas...)
       | but it appears that all of the specific proposals are still early
       | stage and far from being standardized
       | (https://github.com/WebAssembly/WASI/blob/main/Proposals.md).
       | 
       | For the API, Extism provides a C API/ABI that can be called
       | through FFI, but AIUI Wasmtime already has such an API:
       | https://docs.wasmtime.dev/c-api/
       | 
       | Basically I'm trying to understand the conceptual difference
       | between this project and Wasmtime.
        
         | bhelx wrote:
         | It's a good question. It's hard to understand what all is
         | involved in building something like that until you have to get
         | into the details. You can think of Extism as a layer around
         | wasmtime. There is an ABI of sorts that helps you communicate
         | with the plugin: Send data to it, invoke functions, and get
         | data out. With our system, you don't need to enable WASI to use
         | a plugin. You can invoke functions directly. However, you can
         | use WASI for other purposes. And we are working on a way to do
         | POSIX-like stuff (e.g. programs with a main function that use
         | stdin and stdout).
         | 
         | Because we wrap wasmtime, we can also switch it out. That's how
         | we are able to run the same plugins in the browser. There we
         | use the browsers' implementation.
         | 
         | I think one day we will replace some internal pieces of Extism
         | with pieces of the Component Model spec. As of today it's not
         | in a state where we can do all of this in this many languages.
         | 
         | edit: rewording, grammar
        
           | haberman wrote:
           | That makes sense, thanks. It sounds like a key difference is
           | that Extism is trying to be portable to both web and
           | standalone WASM runtimes. And maybe part of the motivation
           | for a new WASI-like API is that WASI doesn't aspire to be
           | portable to the web, and Emscripten's standard library _only_
           | works on the web, whereas your system API is designed to be
           | portable to both.
        
             | bhelx wrote:
             | Yes I think that's a good way of putting it. Extism's
             | primary goal is universality. I think the idea of having a
             | plug-in system that is truly universal is exciting. Now we
             | can share and maybe even sell plugins into different
             | ecosystems. No more silo'd environments. I hope to see a
             | future where standards can be built on top of this and
             | plug-ins can outlive the applications themselves. Think
             | VSTs if you are into music software.
        
               | Existenceblinks wrote:
               | That's interesting, one of examples that is challenging
               | is a universal html template plugin. I'd love to try if
               | it's feasible. Basically it should be logic less like
               | Liquid. The unsure part is the custom tag, can it be
               | called by host or not.
        
           | singularity2001 wrote:
           | Linking wasmtime with host functions through the c abi is a
           | bit cumbersome so I believe (in theory) this product can
           | serve a real need by making plug-in integration more
           | streamlined. Wasm as new plugin target / intermediary is a
           | nobrainer (unless your game is written in c# or you like lua)
        
           | syrusakbary wrote:
           | Hey! Super exciting to see your progress on Extism.
           | 
           | I'm Syrus, from Wasmer. I did a quick review of your plugin
           | architecture and it looks great (tons of languages supported,
           | congrats!). I think Wasmer might be able able to help you so
           | you have the same implementation of the runtime inside and
           | outside of the browser (something similar as we did in
           | wasmer-js [1], where we reuse same WASI implementation, but
           | using the native Wasm engine from the browser).
           | 
           | I'd love to see how we can integrate your plugins into Wasmer
           | as well!
           | 
           | [1] https://github.com/wasmerio/wasmer-js
        
             | nilslice wrote:
             | Syrus, thanks for the kind words! Would love to work with
             | you on integration. I'll reach out & find some time to sync
             | up on it. Or, feel free to join our Discord and we can loop
             | in the team: https://discord.gg/cx3usBCWnc
        
             | bhelx wrote:
             | Thanks Syrus! wasmer-js looks really cool.
        
         | MuffinFlavored wrote:
         | > I'm trying to figure out what Extism is actually providing
         | here.
         | 
         | I'm trying to figure out if people really need compile to
         | WASM/WASI -> run it back in a WASM runtime.
        
       | Existenceblinks wrote:
       | The pdk is missing Zig which is, for many developers,
       | considerably the best for wasm target. It's as fast as Rust (from
       | benchmark I saw, Rust is fastest), though Zig's binary size is as
       | small as AssemblyScript's. Rust's binary size is considerably in
       | a range of middle to large, mostly middle.
       | 
       | It would be nice if there's an official wasm benchmark of source
       | languages, showing speed and binary size comparison.
        
         | bhelx wrote:
         | Yeah, that's a good idea. C is supported on the SDK and PDK
         | side. We are wondering if Zig can utilize the c libraries for
         | it.
        
       | jonnycomputer wrote:
       | "make all software programmable"
       | 
       | doesn't mean anything to me, and I doubt it means much to a lot
       | of others either.
       | 
       | I'm just talking a basic marketing fail here. bhelx below made it
       | make more sense that their whole intro page.
        
         | cormacrelf wrote:
         | Another marketing related comment: Extism is not a very nice
         | name. It sounds like exorcism, which apart from being a rather
         | unsympathetic concept, is more about ridding yourself of
         | foreign stuff that's controlling you rather than the other way
         | round. If anyone has any suggestions, drop them here.
        
           | hestefisk wrote:
           | Yeah it's a very strange and non catchy name. I guess naming
           | things is hard... interesting project nonetheless.
        
         | jonnycomputer wrote:
         | you mean like Emacs.
         | 
         | (:
        
           | bhelx wrote:
           | If you release a competing plug-in system using emacs i'll
           | definitely check it out :)
        
             | wtetzner wrote:
             | I think they meant that emacs is an example of programmable
             | software.
        
         | nilslice wrote:
         | Yea, marketing is hard. Glad bhelx is here to help :)
        
         | dqpb wrote:
         | I agree. They should get rid of that tagline.
        
       | cloudmike wrote:
       | As others have mentioned, "making software programmable" isn't
       | really landing for me.
       | 
       | In the tradition of borrowing terms from the games industry
       | (where we often see early popularization of good ideas), I wonder
       | if "modding" could be a helpful addition somewhere in your
       | marketing.
       | 
       | This seems to have worked for the term "multiplayer", though
       | "moddable" probably isn't as widely appreciated yet.
        
         | Kinrany wrote:
         | Even in gaming modding is still somewhat niche.
        
       | nilslice wrote:
       | For those who want to go straight to the code:
       | https://github.com/extism/extism
        
       | rvcdbn wrote:
       | Why not use protobuf for serializing data between plugin and host
       | language?
        
         | bhelx wrote:
         | You can bring your own serialization format. It's just bytes in
         | and bytes out.
        
       | pavlov wrote:
       | The manifest format could perhaps be less terse. It's really hard
       | to guess what this actually means without reading the docs:
       | "memory": {         "max": 5       }
       | 
       | Presumably the maximum amount of memory available to the plugin,
       | but which unit? 5 megabytes?
       | 
       | Turns out it's measured in pages of 64k each: "The units here are
       | pages where a page is 64Kib." [1]
       | 
       | So max==5 apparently means a hard upper limit of 320 kB. (For
       | when you want to run a 1984 copy of WordPerfect as a plugin, of
       | course.)
       | 
       | Maybe a "max_MB" property might be more useful to plugin authors,
       | and then just calculate the # of pages internally from that?
       | 
       | [1] https://extism.org/docs/concepts/manifest#schema
        
         | bhelx wrote:
         | We have an explanation of the manifest here:
         | https://extism.org/docs/concepts/manifest
         | 
         | it's still a work in progress. the point about units is a good
         | one. Might be a way to make that more clear.
        
         | bhelx wrote:
         | > Maybe a "max_MB" property might be more useful to plugin
         | authors, and then just calculate the # of pages internally from
         | that?
         | 
         | yeah, that's something to consider. You can only pass in
         | parameters that are a multiple of the page size so that may not
         | be an accurate representation. I do think we need to hint at
         | the unit in the name though.
        
       | Octokiddie wrote:
       | Interesting (I think), but the page lacks a problem statement
       | that the project seeks to solve.
       | 
       | As others have noted, "make all software programmable" seems a
       | bit vague. And it's vague because there's no problem in there.
       | When is software _not_ programmable?
       | 
       | I think the idea is to make application extensions easier to
       | integrate (like photoshop plugins), but I'm not sure.
       | 
       | Start with the problem statement, and everything else will fall
       | into place. Leave out the problem statement, and leave your
       | readers mystified.
        
         | bhelx wrote:
         | Point taken. We've been focused on talking to people who have
         | built, or tried to build, plug-in systems. But it's still a
         | confusing concept to the general public without enumerating
         | some examples.
        
       | ynx wrote:
       | Damn, this looks really cool. I've wanted to add wasm support to
       | my project at work for some time now, but unfortunately with no
       | good C# integrations (with Unity as the host), it just hasn't met
       | the mark yet. Really hoping that can be addressed in the near
       | future.
        
         | bhelx wrote:
         | If you need C# support we can work on it! I've done some
         | experimenting with it already. Please come join the discord or
         | file an issue.
        
       | intrepidhero wrote:
       | How big is the WASM runtime? If I embed Extism in my application
       | what is the impact on install size and memory usage?
        
         | bhelx wrote:
         | for install size, it depends on your architecture, we use
         | wasmtime under the hood so a lot of the size is related to
         | that: https://wasmtime.dev/
         | 
         | You can also take a look at our binary releases to get an idea:
         | https://github.com/extism/extism/releases/tag/v0.1.0
         | 
         | In terms of memory usage, as the host you can constrain the
         | memory that your plugin can use. There is a minimum of one Wasm
         | page (64KB in this case).
        
       | ilyt wrote:
       | Huh, just a week ago I thought it would be cool to add WASM
       | plugins to my Go app, as a way to not be dependent on Go for
       | plugins.
        
         | nilslice wrote:
         | I hope Extism can help you make that happen!
         | 
         | Here's an example of a Go app that calls Extism plugins in case
         | it helps:
         | 
         | https://github.com/extism/extism-fsnotify
        
       | bhelx wrote:
       | Hey folks, one of the authors here. Extism is a plug-in system.
       | If you aren't familiar with this terminology, plug-in systems
       | make your software programmable by end users such as your
       | customers or your open source community (e.g. VS-Code
       | Extensions). Currently plug-in systems are quite difficult to
       | build and limited to certain host and guest languages. Extism
       | makes this easier regardless of your language or domain
       | knowledge.
        
         | hestefisk wrote:
         | What would happen if you executed Extism on itself? Would the
         | world implode? :)
        
           | bhelx wrote:
           | I lay awake at night and think about how to do it. But maybe
           | it's a goal best left unfulfilled :)
        
           | nilslice wrote:
           | only one way to find out....
        
             | euroderf wrote:
             | Grey Goo: Wasm Edition
        
         | ar_lan wrote:
         | Thank you - I think the intro page could help make this
         | clearer. I'm not super familiar with the programmable nature of
         | things beyond something like an Arduino, so I was very confused
         | what "programmable software" meant in this context, and the
         | landing page still isn't super clear in that regard.
         | 
         | Your comment helps - would make sense to recalibrate on the
         | shared page.
        
       | sphinxster wrote:
       | This page needs a working example use-case.
        
         | nilslice wrote:
         | There are some examples, but the announcement is focused on the
         | project itself - we will follow up over the next week+ with
         | some end-to-end examples. Stay tuned!
        
         | nilslice wrote:
         | We also have some example projects in the GitHub org, pointing
         | out this one specifically, to create a UDF engine in sqlite3:
         | https://github.com/extism/extism-sqlite3
        
       | tomrod wrote:
       | I feel like I'm missing the bead.
       | 
       | What does it mean to "make all software programmable" -- meaning
       | make Wasm work with all languages? Is this really feasible?
       | 
       | Maybe I'm simply getting old and don't understand recent jargon
       | shifts.
        
         | pomatic wrote:
         | I think it would be better described as a 'universal framework
         | for incorporating plugins into your application'. If I am right
         | about these aspirations, they are quite grandiose. _Shiver_
         | Shades of COM or corba reborn?
        
           | dboreham wrote:
           | If I understand it, this is more about the plumbing of
           | calling the Rust wasm execution engine from various
           | languages. And probably the secondary problem of how do you
           | package wasm-hosted code such that it can interface with
           | multiple calling languages. Rust can build a shared object
           | with C linkage. All the languages have ways to call "native"
           | code (code with C linkage). This is the sauce to connect
           | those dots in a multi-language, batteries-included way.
           | Hopefully I got that right.
           | 
           | It's all in-process so not more like OLE than Corba ;)
        
         | ctvo wrote:
         | The idea is to offer extensibility points in software by
         | embedding their runtime into your current software. Say you
         | have a database and instead of a DLS for querying, allow
         | someone to upload a WebAssembly binary that has access to APIs
         | you'd expose (`filter`, `map`, ...). I'm guessing they ease
         | some of the complexity in moving data back and forth, their
         | runtime is supported on N languages, and they use wasm's
         | sandboxing properties.
         | 
         | The problem, for me, is even though the runtime supports many
         | languages, the languages the plugins can be written in is
         | limited. Rust and Go support wasm well, but AssemblyScript* is
         | not JavaScript / TypeScript. If the idea is to extend software
         | and make it more accessible, they need better support for
         | interpreted languages: JS, Python, Ruby, ...
         | 
         | * - Closures are still not supported:
         | https://github.com/AssemblyScript/assemblyscript/issues/798
        
           | meltedcapacitor wrote:
           | Yes! Shipping more copies of interpreter runtimes in trivial
           | plugins is exactly what the world needs.
        
             | ctvo wrote:
             | Or solve it a different way. I don't think your users care.
             | It doesn't change the fact that it's a limiting factor
             | right now.
        
             | bhelx wrote:
             | There will be ways to handle this problem in the future
             | with the Component Model spec. I've seen it working but
             | it's not easy to do yet. As of today though, yes bringing
             | your own runtime is costly.
        
         | jamil7 wrote:
         | No, it took me a bit to understand as well. It looks like a set
         | of host SDKs and a sandboxed runtime (guessing this is why
         | they're using wasm) you can drop into your own software and
         | expose some hooks that would allow your users to write their
         | own plugins for your app in a variety of languages.
        
         | bhelx wrote:
         | Extism is a plug-in system. Plug-in systems make your software
         | programmable by end users (such as your customers or your open
         | source community). Currently plug-in systems are quite
         | difficult to build and limited to certain host and guest
         | languages. Extism makes this easier regardless of your language
         | or domain knowledge.
        
           | robofanatic wrote:
           | > Plug-in systems make your software programmable by end
           | users (such as your customers or your open source community)
           | 
           | I am confused. Who is the "end user" or the "customer? It
           | seems like "developer" who is writing software for a customer
           | is your end user or may be not. Who will actually use this is
           | not clear from the website.
           | 
           | From couple of examples I think this comes close to something
           | like a SQL CLR integration, where for example you can call a
           | C# routine from SQL query.
           | 
           | https://learn.microsoft.com/en-
           | us/dotnet/framework/data/adon...
        
             | bhelx wrote:
             | Your end user would be a user of your application, e.g. a
             | customer. But it could also be a marketplace like situation
             | where people are developing plugins for your customers.
             | Examples of plugin systems are things like VS-Code
             | Extensions, Figma plugins, firefox extensions, etc.
             | 
             | Here is a good example of a wasm plugin system for an open
             | source project: https://istio.io/latest/docs/reference/conf
             | ig/proxy_extensio...
        
       | fulafel wrote:
       | How are you implementing JS platform support, is it a WebAssembly
       | JS interpreter?
        
         | nilslice wrote:
         | for JS on the Web, yes - we ported our runtime specific APIs to
         | TypeScript and expose them to the WebAssembly runtime in the
         | browser
         | 
         | for JS in Node, we use wasmtime embedded within our runtime --
         | looking into what the tradeoffs are to re-implement the whole
         | runtime in Node on its native WebAssembly runtime though.
         | Feedback welcome & appreciated!
        
       | kumarski wrote:
       | WebAssembly ecosystem booming it seems.
        
       | madmod wrote:
       | I wonder how this compares to https://suborbital.dev/
        
         | callahad wrote:
         | [I work for Suborbital]
         | 
         | We're both all in on extensible software powered by
         | WebAssembly, but the scope and domains differ.
         | 
         | Suborbital is more of a turnkey / batteries-included _service_
         | that handles the full lifecycle of extending SaaS applications
         | with user-defined plugins. So it includes a web-based editor
         | widget, a module builder service, storage and compute,
         | administrative dashboards, etc.
         | 
         | Extism, from my lay understanding, is more tightly scoped
         | toward being a great _library_ for running WebAssembly modules,
         | in the same way you might embed a Lua runtime into an
         | application for user scripting.
         | 
         | Another big difference is that you can use all of Extism right
         | now. Suborbital's hosted platform is still in closed beta :)
         | (Waitlist at https://form.typeform.com/to/DHxjRGKx)
        
           | bhelx wrote:
           | I haven't used suborbital yet but yeah, that sounds accurate.
           | We're aimed at being a library and Extism itself is focused
           | on building plug-in systems.
           | 
           | I just signed up for the waitlist! Looking forward to
           | learning more about it.
        
       | davidkunz wrote:
       | Is the interface defined through wit?
       | 
       | https://github.com/bytecodealliance/wit-bindgen
        
         | nilslice wrote:
         | Currently it is not, but we are closely tracking the Component
         | Model to see how we can best utilize it. There are a few places
         | we know we can leverage it, namely in the HTTP interfaces and
         | other imports we provide to plug-ins. But, we also want to
         | contribute to the language support on the codegen side. In
         | order to get the language support we have already, we couldn't
         | invest the time up front to build all the codegen in wit that
         | would have been necessary. Over time want to get there though!
        
           | davidkunz wrote:
           | Awesome, thanks for the answer!
        
             | nilslice wrote:
             | If you're interested in helping us get there, we'd love the
             | help. Hop in the Discord and we can talk about what it
             | would take.
        
         | bhelx wrote:
         | Currently no. It's up to you to define your own interface. We
         | plan to work on WIT bindings and eventually push support
         | though.
        
       | floober wrote:
       | This looks fantastic! I'm working on a desktop app and I've been
       | struggling with the extensibility story in the back of my mind
       | for a couple of weeks now.
       | 
       | Thanks for building this!
       | 
       | edit: For what it's worth, the use case and value of something
       | like this was immediately apparent to me.
        
         | nilslice wrote:
         | Awesome! We'd love to see what you end up building, and if you
         | use Extism please let us know what you find missing...
         | 
         | > For what it's worth, the use case and value of something like
         | this was immediately apparent to me.
         | 
         | Thank you for saying so. Negative feedback doesn't bother me (I
         | appreciate anyone taking time to speak up), but it's also
         | usually the only kind you get on the Internet :) so we
         | appreciate hearing that. Translating ideas into words is hard,
         | especially in software.
        
       | [deleted]
        
       | hestefisk wrote:
       | Is it single threaded?
        
         | bhelx wrote:
         | The plugins are, but not the host. You can create pools of
         | plugin instances if you need concurrency. Threading inside a
         | Wasm program is still a new concept but I think it will become
         | more common.
        
       | mike_hearn wrote:
       | Looks interesting. Based on prior experience, here are some
       | concerns people will bring up with this approach:
       | 
       | 1. Spectre. You may have to assume the plugin code can read
       | anything in the address space including any secrets like
       | passwords, keys, file contents etc. If the plugin can't
       | communicate with the outside world this may not be a problem.
       | 
       | 2. When you say WASM has a "sandboxing architecture", this is
       | only partially true. It's quite easy to define a simple language
       | that doesn't provide any useful IO APIs and then claim it's
       | sandboxed - that's practically the default state of a new
       | language that's being interpreted. The problems start when you
       | begin offering actual features exposed to the sandboxed code. The
       | app will have to offer APIs to the code being run by the WASM
       | engine and those APIs can/will contain holes through which
       | sandboxed code can escape. If you look at the history of
       | sandboxing, most sandbox escapes were due to bugs in the higher
       | privileged code exposed to sandboxed code so it could be useful,
       | but you can't help devs with that.
       | 
       | 3. WASM is mostly meant for low level languages (C, C++, Rust
       | etc). Not many devs want to write plugins in such low level
       | languages these days, they will often want to be using high level
       | languages. Even game engines are like that: "plugin" code is
       | often written in C#, Lua, Blueprint, etc. This is especially true
       | because WASM doesn't try to solve the API typing/object interop
       | problem (as far as I know?), which is why your example APIs are
       | all C ABI style APIs - the world moved on from those a long time
       | ago. You'll probably end up needing something like COM as
       | otherwise the APIs the host app can expose will be so limited and
       | require so much boilerplate that the plugin extension points will
       | just be kind of trivial.
        
         | outside1234 wrote:
         | For #1, I believe they are proposing that the plug-ins run in
         | their own memory space with the only shared anything are the
         | parameters coming in.
        
         | thingification wrote:
         | Thread on spectre and capability security (which I gather from
         | a glance here that wasmtime is using on some level https://gith
         | ub.com/bytecodealliance/wasmtime/blob/main/docs/...):
         | 
         | https://groups.google.com/g/cap-talk/c/NSDM-05fEuU/
        
         | singularity2001 wrote:
         | 3. WASM is mostly meant for low level languages
         | 
         | At least the common plugin language lua runs in wasm, and
         | micropython is less than a megabyte in wasm, so that point is a
         | bit weak. (having an extra level of abstraction may make the
         | plugins minimally slower, but running lua in wasm adds an extra
         | level of security)
        
         | fiedzia wrote:
         | >WASM doesn't try to solve the API typing/object interop
         | problem
         | 
         | There many initiative around wasm, one of them being
         | WebAssembly interface types, aimed at that problem. This makes
         | using wasm simple.
        
         | bhelx wrote:
         | Lots of good points here. I'll try my best to address them. But
         | you are right, There aren't really complete answers to each of
         | these problems.
         | 
         | Regarding #1, it's good to point out that spectre is still an
         | ongoing problem. wasmtime, the runtime we use, has mitigations
         | for spectre but things will likely come up. I think we need
         | more time and tools to work on things like detecting attacks
         | and mitigating future problems. Fortunately there are some big
         | companies working on it. Our team cannot solve that problem.
         | 
         | Regarding #2, sandboxing here refers to the memory access model
         | and fault isolation. For each capability you give the plugin
         | you may introduce risk. We don't claim to address this problem
         | but I think education and mitigation are good goals for us.
         | 
         | Regarding #3, I think there has been some good progress here. I
         | have an experimental C# plugin PDK and a JS one based on
         | quickjs. We also support Haskell. I think there will be
         | improvement here. And regarding the ABI comment, there are
         | going to be layers on top of this to make it more ergonomic.
        
         | titzer wrote:
         | > 3. WASM is mostly meant for low level languages
         | 
         | I've been saying it for years, but I think finally 2023 has the
         | chance of being the year in which Wasm GC ships and managed
         | languages start targeting Wasm more widely. We've made a lot of
         | progress with the design, and V8 has a basically complete
         | implementation. Google is targeting some internal apps to Wasm
         | GC and seeing perf improvements over compile-to-JS, so I think
         | this will likely be a success.
        
           | mike_hearn wrote:
           | That would be cool but I wonder how much difference it will
           | make. Most managed languages share at least two attributes:
           | 
           | 1. Large runtimes and std libs. Python's "batteries included"
           | is the epitome of this but even just java.base is large. This
           | doesn't play well at all with browser cache segmentation.
           | 
           | 2. You need a JIT for performance.
           | 
           | A good test of whether WASM is really heading towards
           | generality is whether you could implement V8 as
           | https://www.google.com/v8-js.wasm and just auto-include it
           | into HTML pages for backwards compatibility. I know you have
           | unusual experience and expertise in meta-circular VMs - is
           | WASM really heading in this direction? The two obvious
           | sticking points today are: V8 would get downloaded fresh on
           | each origin, and JITd fresh on each page load, and what does
           | such a runtime emit as compiled code?. Is your JITC being
           | JITCd by a JITC and if so is the JITCd output then being
           | JITCd a second time? If so, how on earth does this make
           | sense?
           | 
           | An alternative would be to explore whether the process level
           | sandboxes are now good enough to just allow native code to
           | run inside them and let people use their existing managed
           | language VMs. Google thought that was close to plausible many
           | years ago with NaCL, and kernel sandboxes got a lot stronger
           | since then. It seems we ended up with WASM more due to
           | Mozilla politics than what makes sense technically.
        
             | titzer wrote:
             | > 1. Large runtimes and std libs.
             | 
             | Indeed. With the web's model, it seems tempting to make the
             | browser cache do the work for you by putting the language
             | runtime at a standard URL. That works, modulo the security
             | features today that cache Wasm modules per-origin to avoid
             | an engine JIT bug creating a cross-origin vulnerability. GC
             | helps a bit with that in the sense that the GC algorithm
             | itself moves down into the engine.
             | 
             | > 2. You need a JIT for performance.
             | 
             | I worked a bit on a prototype JVM on Wasm that used the
             | Wasm bytecode format to encode Java constructs. That helps
             | because then you don't have another bytecode interpreter
             | running on level up, but ultimately you want somewhat more
             | control over the JIT and the code it generates. Wasm
             | engines supporting dynamic code generation at all (any
             | finer-grained than a module) would help a lot there.
             | 
             | Compiling V8 whole-hog seems like it would take a lot of
             | doing. In particular, it has JITs and an interpreter that
             | want to spit out machine code. That'd have to be replaced
             | with Wasm backends.
             | 
             | > It seems we ended up with WASM more due to Mozilla
             | politics than what makes sense technically.
             | 
             | The politics were...complicated. I'd tell my side but it's
             | probably best I don't.
        
               | piperswe wrote:
               | > Indeed. With the web's model, it seems tempting to make
               | the browser cache do the work for you by putting the
               | language runtime at a standard URL.
               | 
               | Sadly that wouldn't work with standard libraries that
               | heavily use monomorphized generics, like Rust and C++
        
               | grashalm wrote:
               | Re JVM on wasm with gc: it might be simpler at first to
               | build a Graal/native-image backend for wasm+gc. No
               | runtime JIT needed. Happy to join in on the fun.
        
               | mike_hearn wrote:
               | Hmm interesting. I thought the cache segmentation was to
               | block timing attacks by the web server (measure time
               | between first page send and js execution to figure out
               | what files are cached i.e. your browser history). I
               | didn't realize it was due to lack of confidence in the
               | JIT. Isn't a WASM JITC a fairly straightforward thing?
        
             | ilyt wrote:
             | > 1. Large runtimes and std libs. Python's "batteries
             | included" is the epitome of this but even just java.base is
             | large. This doesn't play well at all with browser cache
             | segmentation.
             | 
             | Right but that's only one, niche use case (why you'd want
             | _plugins_ in a web page ?).
             | 
             | Even if you are web app with plugins
             | 
             | * that is not a problem for first load, user adds plugins
             | later once they get familiar with the app
             | 
             | * you can still (I assume) just download it in the
             | background and shove it into local storage
             | 
             | The whole use case seems to be "there is an app that would
             | benefit from plugins and we don't want someone to learn the
             | language just to write that plugin" and the idea is pretty
             | sound - WASM embeds well and is fast enough.
        
           | galangalalgol wrote:
           | Aren't there already gc languages in wasm? I know julia is.
        
             | rob74 wrote:
             | There are, Go can also be compiled to WASM, but it has to
             | carry the whole Go runtime with it (including but not
             | limited to the GC), so the WASM files are a bit fat. You
             | can however use TinyGo, a "Go compiler for small places"
             | (https://tinygo.org/).
        
               | galangalalgol wrote:
               | Yeah, I get the runtime can be big, but letting gc cross
               | module boundaries seems really bad for sandboxing. I also
               | kind of wonder why we'd want to use those languages in
               | wasm other than their libraries and runtimes. If all you
               | want is gc and performance why not use JavaScript or
               | typescript? C# or go after a ~20% wasm penalty isn't
               | going to be that much faster than js right? Or use
               | something like nim that compiles to js and get libraries
               | as well. The case for wasm always seemed to be absolute
               | max performance in a safer package, which would send you
               | towards languages that support manual memory management
               | anyway.
        
               | titzer wrote:
               | One of the improvements that you get from the coming Wasm
               | GC proposal is an object model that is inherently more
               | space-efficient than JavaScript. While a lot of
               | speculative optimizations can make JITed JS (of the right
               | form) run fast with few checks, the object model
               | inherently requires boxing or tagging and is not as
               | memory-efficient as what Wasm GC structs give.
        
             | mattarm wrote:
             | My understanding is that they each bring their own GC and
             | run it as WASM code in the VM.
        
           | heather45879 wrote:
           | I think there's somewhat of a disconnect between the original
           | idea of WASM (in browser) versus headless. In the browser
           | folks get JavaScript for free which collects its own garbage.
           | WASM is there to supplement higher level language for
           | performance-intensive tasks and as such, "lower level"
           | languages make more sense for these code paths.
           | 
           | I'd like to point out also that providing users a million
           | languages to write plugins in for a product could create a
           | lot of bloat. Imagine an image editor with 5 plugins, each
           | written in its own language running in WASM sandboxes:
           | golang, C#, assemblyscript, ruby, python. That's 5 runtimes
           | each running it's own garbage collection logic.
           | 
           | I can see the value for compute hosts because the very nature
           | of the provided service is allowing users to write sandboxed
           | apps. But I think for stand-alone applications it's best to
           | support one or two simple targets, whether sandboxed or
           | otherwise.
           | 
           | There are languages (Lua for example) optimized for this
           | already.
           | 
           | I suppose the benefit is that each application which uses the
           | WASM backend can decide on their "official" language and
           | provide a decent built-in IDE experience.
        
             | wtetzner wrote:
             | > That's 5 runtimes each running it's own garbage
             | collection logic.
             | 
             | If the WASM runtime provides a GC, then all of those
             | languages can share a GC.
        
           | LAC-Tech wrote:
           | A one size fits all GC is never going to be a great solution
           | though, is it?
           | 
           | Different languages have different GCs that are designed to
           | work with their semantics. Some languages use a flag bit to
           | tell the runtime if a value is stack or heap (Go, Ocaml),
           | some languages allocate almost everything and assume a lot of
           | short lived objects (Java)...
           | 
           | How well will a generic WASM GC really work here?
        
             | wtetzner wrote:
             | But the competition is compile-to-javascript, which has
             | exactly the same problem. With WASM, you get to choose
             | between using a generic, potentially sub-optimal GC, or
             | having a larger payload and including a GC bundled with the
             | application.
        
             | ilyt wrote:
             | Probably better than no GC whatsoever. And not having to
             | bring whole GC code with you is benefit enough
        
           | zozbot234 wrote:
           | There's no such thing as one-size-fits-all GC. Wasm GC will
           | probably be just as successful as other attempts at generic
           | "managed" runtimes, which is to say, not very.
        
             | titzer wrote:
             | > There's no such thing as one-size-fits-all GC.
             | 
             | Two aspects to that.
             | 
             | One is the implementation, e.g. the GC algorithm. They vary
             | widely in their performance characteristics. For the most
             | part, they are semantically invisible. I fully expect many
             | different engines to have different algorithms, and
             | ultimately you can choose and tune the GC algorithm to your
             | application's needs.
             | 
             | Two is the semantics. We're aware of many failed attempts
             | to make generic runtimes, and a critical factor is how
             | universal the object model is. Of the many over the years,
             | most have originated for a single language or paradigm of
             | languages and have, in some sense, too high a level of
             | abstraction. Wasm GC is a lower level of abstraction
             | (think: typed structs), from which higher level constructs
             | are implemented (like vtables, objects, classes, etc).
             | Being lower level is a tradeoff towards universality that
             | we have consciously made. That said, there are downsides,
             | such as more casts, because it gets increasingly harder to
             | safely encode invariants of source languages to avoid such
             | casts at the lower level. We're OK with the overheads we've
             | measured so far but are always looking for mechanisms to
             | reduce or eliminate these.
        
               | zozbot234 wrote:
               | > We're OK with the overheads we've measured so far but
               | are always looking for mechanisms to reduce or eliminate
               | these.
               | 
               | You could encode arbitrary invariants by implementing
               | verifiable proof-carrying code within Wasm. Then a wasm-
               | to-native compiler could be designed to take advantage of
               | such invariants in order to dispense with these
               | overheads.
        
               | titzer wrote:
               | > proof-carrying code within Wasm
               | 
               | That's a legitimately neat idea. There are couple of
               | projects to improve safety of Wasm code using linear
               | memory (such as RichWasm by Amal Ahmed and MSWasm by a
               | number of folks at Stanford, UCSD, and CMU). Obviously
               | unrestricted aliasing of the giant byte array that is
               | memory makes this more difficult. I hope that Wasm GC can
               | offer an abstraction base to express even more
               | invariants. In some sense that will be a study in adding
               | more powerful types and more powerful proof constructs
               | that are either on the side or embedded in the code. So,
               | exciting future directions!
        
       | n4jm4 wrote:
       | Why not continue using long-standing C FFI?
       | 
       | This is not so clear.
        
       | nilslice wrote:
       | Authors are here to answer questions! To add a little bit of
       | detail:
       | 
       | Extism is an open-source universal plug-in system with the goal
       | of making all software programmable. Easily embed Extism into 13
       | popular programming languages (server or browser) and safely run
       | high-performance WebAssembly plug-ins inside your code.
       | 
       | What does it mean to "make software programmable"? Simply put,
       | you can give end-users the ability to extend your software with
       | their code.
       | 
       | Plug-in systems are usually implemented in 3 ways: 1. execute a
       | binary that is external to your process (like protoc) 2. re-
       | compile a program with an implementation of some interface 3.
       | dynamically link to native code / dlls
       | 
       | All 3 have major trade-offs on the performance-to-security ratio.
       | Extism provides a way to "have your cake and eat it too" in a
       | sense, that it doesn't compromise security for performance. True,
       | executing WebAssembly as we do here is not running at fully
       | native speed, but it's darn close. And its sandboxed architecture
       | offers the security you want if you're considering an alternative
       | to dll/dlopen.
       | 
       | We're only getting started here, and welcome feedback good and
       | bad. Please join our Discord[0] if you want to chat, or open
       | issues on GitHub[1].
       | 
       | [0]: https://discord.gg/cx3usBCWnc [1]:
       | https://github.com/extism/extism/issues
        
         | noveltyaccount wrote:
         | This is really interesting to me. I used to run a team that
         | owned a software library (that you've probably heard of) that
         | runs on Mac, Windows, iOS, Android, and embedded Linux. The
         | product is over a decade old, so it's in C++ because that was
         | the only real choice back then. We bolted on static analysis
         | yet still had senior engineers working full time to iron out
         | stability issues (deadlocks and other race conditions). I've
         | been thinking about alternatives for a while now; Rust
         | naturally, but also C# with Native AOT in .NET 7 (only supports
         | Windows and Linux so far, but maybe in the future). It got me
         | thinking though, why have to choose? There are a good number of
         | languages that can compile to WASM, so maybe just bridge the
         | platform-native presentation layer to WASM and put all the core
         | logic in WASM. It "should" provide near-native performance and
         | open up many other languages, and provide a nice migration path
         | to run the existing C++ and new code in another language side-
         | by-side. I know it's not explicitly the goal, but Extism seems
         | like it could provide that functionality. I'll be following
         | this project!
        
           | nilslice wrote:
           | Very interesting, would love to know more about the library
           | ;)
           | 
           | It does sound like you have found a _great_ use case for
           | WebAssembly, and yes, Extism could provide similar
           | functionality! We call it a "plug-in system" because that's a
           | fairly concrete thing to say, but there are many other ways
           | to use it.
        
         | traverseda wrote:
         | So what is the plan for higher level languages? Let's say I
         | wanted to be able to write extensions in python, is that one
         | the roadmap at all?
        
           | bhelx wrote:
           | If that is something you need come join the discord and let's
           | work on it! I've been experimenting with higher level
           | languages, specifically quickjs (js) and c#. Python should
           | work from what I know, but I can't speak intelligently to how
           | well it would work.
        
         | raible wrote:
         | I've had great success with a fourth way: my project language
         | compiles to C, which is loaded at runtime with libtcc
         | (specifically: git://repo.or.cz/tinycc). I've gone down the
         | .so/.dll route a few times in the past, but I can safely say:
         | never again. libtcc has the advantages of a jit (native C
         | speed), but with an elegant API and laudable portability.
        
         | kodablah wrote:
         | Awesome. Now I just need a way to define a cross-language
         | contract and this would be very helpful for my uses.
         | 
         | Ignoring performance for a second, one wonders if you could
         | take proto and use that as the data in/out _and_ the API/RPC
         | definition. Like many others, I've been wanting to add plugin
         | support to my software, but I want a well-defined contract
         | usable from others w/ complex types and known RPC calls. I
         | think code-gen from proto for all supported client/host
         | languages could get you there (at a perf cost compared to flat
         | buffers or capn proto).
        
         | exelib wrote:
         | You should put it into one-two sexy sentences. It was too
         | difficult to understand why do I need it.
        
         | RodgerTheGreat wrote:
         | There's at least one more approach to program extensibility
         | that you should probably address: interpreted languages,
         | especially Lua. Many games and utilities today use Lua or JS as
         | an extension language. They have battle-tested runtimes, come
         | with high-performance JITs, and provide the potential for rich
         | interactive debugging and incremental development options that
         | are not free with a WASM-based statically-compiled approach.
        
           | localhost wrote:
           | There are even entire applications written this way - Adobe
           | Lightroom was originally built from some core C++ imaging
           | code lifted from Photoshop but with all of the UI built in
           | Lua. The dev builds of Lightroom have an entire integrated
           | Lua dev environment in them.
        
           | nilslice wrote:
           | Thank you - that's a great point, and totally slipped my mind
           | when writing this.
        
           | bhelx wrote:
           | We think Lua is great and in many ways, Wasm has yet to catch
           | up! I do think it's still early days for Wasm, but it will.
        
       | jkcorrea wrote:
       | Congrats on the launch! Just yesterday I was pondering if I could
       | do something like this for a saas I'm working on: I'd like to
       | offer users the ability to extend their dashboard in certain ways
       | (a la WP/Shopify plugins), but those ways require extending the
       | ui AND the server code.
       | 
       | Extism seems like a great fit for this, I'll definitely be
       | checking it out :)
        
         | nilslice wrote:
         | Thanks! I want to highlight that Extism supports both server-
         | side AND browser environments, running the same plug-ins. So
         | SaaS is a great example of a place where end-users may want to
         | extend functionality that runs on the client, server, or both.
         | Feel free to reach out if you have any questions.
        
         | bhelx wrote:
         | Sounds very cool and like it could be a good fit for our
         | browser based runtime! There are still a few limits, but you
         | can currently run the same plugins in your backend and
         | frontend.
        
       | zacharyvoase wrote:
       | I'm genuinely curious: is the WebAssembly ecosystem just
       | reinventing the JVM piecemeal? "Write once run anywhere"?
        
         | bhelx wrote:
         | In many ways yes. We need to re-invent many things for this new
         | world. But I'd encourage you to read a bit more about how Wasm
         | is different. It's true it is a stack based virtual machine but
         | that's about where the comparisons end.
        
         | slaymaker1907 wrote:
         | I think you're probably right, but I don't think many people
         | would look at the JVM as a failure. Instead, I think WASM is
         | trying to bring the good parts of the JVM such as being a
         | simple compile target, small binaries, and a stable VM while
         | fixing the bad parts like having a huge attack surface area and
         | lacking certain features critical for performance (pointer
         | chasing, GC, etc.).
        
           | zacharyvoase wrote:
           | Well as vendors add access to system APIs to WASM, that
           | attack surface will indeed grow.
        
         | moffkalast wrote:
         | No, it's just "let's take random languages and transpile them
         | to Javascript but call it Webassembly and hope nobody notices".
         | In that sense it's much worse.
        
       | NuSkooler wrote:
       | Interesting. Just this week I've been building a little
       | experiment in order to utilize WASM based plugins in a project
       | I'm involved with. I'm using WasmEdge for the task and so far am
       | having pretty good luck.
       | 
       | Questions: 1. Can WASM plugins with Extism easily call back into
       | host provided APIs? 2. Complex types are supported?
        
         | nilslice wrote:
         | WasmEdge is really cool -- I'm super impressed with the work
         | they are doing and hope to eventually provide an alternative
         | runtime backend to Extism using WasmEdge (maybe they'd like to
         | help!)
         | 
         | To answer your questions: 1. Extism provides a specific set of
         | host provided APIs, and currently we don't have support for
         | user-supplied host functions beyond the ones we make available.
         | This will change though, and we're looking for feedback. We
         | held off because there wasn't a clear way to make it easy
         | across ALL the languages we support.
         | 
         | 2. Complex types are definitely supported, you need to encode
         | the data into raw bytes and can use whichever format you want
         | (only limited by which formats are available in host & plug-in
         | languages..)
         | 
         | Eventually we will move towards the Component Model which will
         | make the complex types story much simpler.
        
           | NuSkooler wrote:
           | Thanks for the info! I'll be keeping an eye on this for sure.
           | What I'm working on is a PoC and it's working well thus far.
           | As Extism advances and supports some of these upcoming
           | features, it may turn out to be "just right" for my needs.
        
       | nmstoker wrote:
       | As others have said, the term "software" is confusing.
       | Application or software product seem more apt.
       | 
       | The other small point I'd raise: there's mention that due to the
       | sandboxing of WASM it's "safe" to run untrusted code. Maybe I've
       | misunderstood. To me that seems true in so far as the untrusted
       | code cannot break out and can only do actions the hosting app
       | decides to allow, but this isn't much consolation if the app
       | allows actions that can be subverted.
       | 
       | For instance, if the app allows control over saving a file,
       | untrusted code only gets to handle that within the rails the app
       | sets but that still means dodgy code could fill up a hard drive
       | by saving over and over, or it could possibly save over important
       | files.
        
         | bhelx wrote:
         | > As others have said, the term "software" is confusing.
         | Application or software product seem more apt.
         | 
         | That's a great suggestion thanks!
         | 
         | > To me that seems true in so far as the untrusted code cannot
         | break out and can only do actions the hosting app decides to
         | allow, but this isn't much consolation if the app allows
         | actions that can be subverted.
         | 
         | Yes i think safe is a relative term here. Any user input is
         | "unsafe" to some degree. Your example is a good one! I think we
         | wrote this in the context of other relative ways to do this but
         | will be discussing better ways to talk about security and what
         | Extism protects and what it doesn't.
        
       | jayd16 wrote:
       | I'd love to see C# support for something like this as well. Would
       | be nice if Unity games could start supporting wasm plugins. Not
       | sure if something like that works for Ureal already.
       | 
       | Another question... Is something like this possible on iOS or
       | will these kinds of runtimes be banned by Apple?
        
         | bhelx wrote:
         | C# support on which side? The host or the plugin side? I've got
         | an experimental C# plugin almost working. I think I can do it.
         | A Host SDK library would be pretty easy since it's just FFI to
         | the runtime.
         | 
         | > Would be nice if Unity games could start supporting wasm
         | plugins
         | 
         | That would be pretty neat! I go back and forth over whether
         | this kind of thing will happen or not. Extism's goal is to be
         | very generic (universal). A game engine may have some competing
         | goals like performance or predictability. Still, I wouldn't be
         | surprised if some alternative engines didn't do this in the
         | next few years.
         | 
         | > Another question... Is something like this possible on iOS or
         | will these kinds of runtimes be banned by Apple?
         | 
         | Not today, but I think I know how to get there.
         | 
         | If you need this stuff for your project come join the discord
         | and we can try to prioritize it!
        
       | Jyaif wrote:
       | Does it require JIT? In other words, does it work in iOS?
        
         | bhelx wrote:
         | yes, Wasmtime does use a JIT. We haven't tried on mobile yet,
         | but I think I have some paths to make it work. If this is
         | something you need come join our discord and we can experiment
         | on it!
        
       | satvikpendem wrote:
       | Will WASM finally be the write once run everywhere system we've
       | been promised for the past few decades?
       | 
       | I can imagine every language compiling to the common format that
       | is WASM, so you can mix and match libraries from other languages
       | as you please, as well as chip manufacturers adding hardware
       | accelerated WASM processing units if it gets popular enough.
       | 
       | This really is the birth and death of Javascript.
        
         | bhelx wrote:
         | > Will WASM finally be the write once run everywhere system
         | we've been promised for the past few decades?
         | 
         | I think it has a good shot! If I'm hedging my bets though I'd
         | say there are some things it will just never be good at. That's
         | okay though it's not a zero sum game.
         | 
         | > This really is the birth and death of Javascript.
         | 
         | One thing I will not bet on is the death of javascript!
        
           | satvikpendem wrote:
           | > _I 'd say there are some things it will just never be good
           | at._
           | 
           | I'm curious, what would those be?
           | 
           | > _One thing I will not bet on is the death of javascript!_
           | 
           | Yep, I'm more so referring to the talk by Gary Bernhardt
           | foretelling of a WASM-like platform emerging [0].
           | 
           | [0] https://www.destroyallsoftware.com/talks/the-birth-and-
           | death...
        
         | marcosdumay wrote:
         | No. WASM will have the same problem that every "run everywhere"
         | system ever had: what makes software hard to port is not the
         | ability to execute it, it's the environment differences.
         | 
         | But it will be a powerful low trust portable VM, like none
         | mainstream today. Odds are it kills Lua.
         | 
         | (And yeah, it removes the Javascript monopoly on the browser.
         | At this point, it can't be killed, but it will shrink.)
        
           | satvikpendem wrote:
           | Perhaps we can compile a Docker image into WASM too, we've
           | seen Postgres recently. Or do you mean something else?
        
           | chubot wrote:
           | Lua is more like a C library and less like a VM. (Similarly,
           | LLVM isn't a VM, which is a common misunderstanding, given
           | the name)
           | 
           | As far as I know, people don't ship code to remote Lua VMs
           | and execute it. There is no compatibility guarantee across
           | versions, and there are nontrivial compile-time options (like
           | what the number type is).
           | 
           | That doesn't mean Lua isn't useful; it's just not designed
           | for the same things that WASM is.
        
       ___________________________________________________________________
       (page generated 2022-12-01 23:00 UTC)