rhaiscript / rhai

Rhai - An embedded scripting language for Rust.
https://crates.io/crates/rhai
Apache License 2.0
3.73k stars 175 forks source link

Rhai playground (using WebAssembly) #169

Closed alvinhochun closed 3 years ago

alvinhochun commented 4 years ago

The idea is to make a playground for Rhai scripts that runs in a web browser which can showcase the features of the Rhai scripting language. It might also be possible for others to repurpose it as a Rhai script editor.

I've started an attempt on https://github.com/alvinhochun/rhai-playground, but I am not making any promises. The master branch gets automatically built and deployed to: https://alvinhochun.github.io/rhai-playground-unstable/ I might irregularly upload specific builds to: https://alvinhochun.github.io/rhai-demo/

Wish list (not a roadmap or to-do list):

schungx commented 4 years ago

How about something like a "click here to load the Playground" button?

I'll start figuring out how to embed JS scripts and custom HTML into mdbook...

There is a chapter in the Rhai book on the playground: https://schungx.github.io/rhai/start/playground.html

Right now it only contains a link. I think this can be beefed up with an embedded Playground!

I don't think it will ever be possible to demo something like registering a custom type

No I don't think it'll be possible also, short of compiling the Rust code.

alvinhochun commented 4 years ago

How about something like a "click here to load the Playground" button?

I'll start figuring out how to embed JS scripts and custom HTML into mdbook...

There is a chapter in the Rhai book on the playground: https://schungx.github.io/rhai/start/playground.html

Right now it only contains a link. I think this can be beefed up with an embedded Playground!

Well, I was thinking of allowing Rhai code snippets in the Book to be loaded into and run on the playground, kind of like how they do with the Rust snippets There'd be a "play" button next to the code snippet that will load the playground inline with the code snippet.

For the playground page, I think a link should be enough...

schungx commented 4 years ago

Well, I was thinking of allowing Rhai code snippets in the Book to be loaded into and run on the playground, kind of like how they do with the Rust snippets There'd be a "play" button next to the code snippet that will load the playground inline with the code snippet.

That would actually be cool!

But then I'd probably need to revise the code snippets to be higher quality. For example, right now I'm just doing:

let x = 42;
x == 42;        // x is 42

To be a self-running snippet, it probably needs to be:

let x = 42;
print(x);          // prints 42

In a screenful of examples, it may actually be less readable. I'll have to think about this.

And also, a lot of Rhai scripts in the book depend on registered functions to work, so unless we build separate WASM modules with different functions, we'll have a problem running them...

alvinhochun commented 4 years ago

Well, I was thinking of allowing Rhai code snippets in the Book to be loaded into and run on the playground, kind of like how they do with the Rust snippets There'd be a "play" button next to the code snippet that will load the playground inline with the code snippet.

That would actually be cool!

But then I'd probably need to revise the code snippets to be higher quality. For example, right now I'm just doing:

let x = 42;
x == 42;        // x is 42

To be a self-running snippet, it probably needs to be:

let x = 42;
print(x);          // prints 42

In a screenful of examples, it may actually be less readable. I'll have to think about this.

Perhaps print(x == 42) is fine too, or perhaps with a function which prints a raw debug representation (like dbg!() in Rust)?

Or perhaps an REPL-style execution would work better for some snippets?

And also, a lot of Rhai scripts in the book depend on registered functions to work, so unless we build separate WASM modules with different functions, we'll have a problem running them...

For those examples I think you can just not enable the playground.

We can make it work if you are ok with building a playground with those functions included. But synchronizing the code between the build and the book will be a bit of trouble. I think it'll need a tool to automatically generate the code from the snippets in the book. Let's perhaps ignore that for now.

schungx commented 4 years ago

Perhaps print(x == 42) is fine too, or perhaps with a function which prints a raw debug representation (like dbg!() in Rust)?

There is debug(...)...

Let's perhaps ignore that for now.

Yup.

schungx commented 4 years ago

Hi @alvinhochun, if I add a lifetime and a reference to TokenizeState, will it screw up your playground?

alvinhochun commented 4 years ago

Hi @alvinhochun, if I add a lifetime and a reference to TokenizeState, will it screw up your playground?

Yes, probably. The highlighting process requires TokenizeState to be passed to JavaScript, which cannot handle references at all. Preferably it should also be trivially serde-able, because when I hand out Rust objects to JavaScript and they got GC'ed without explicitly freed it actually leaks memory on the WASM heap, and the only way to prevent this is to convert it to a JS object.

schungx commented 4 years ago

OK then, I'll find a way of not having to do this.

alvinhochun commented 4 years ago

I'm thinking perhaps I should make a Reddit post about the playground, how do you feel about this?

schungx commented 4 years ago

I'm thinking perhaps I should make a Reddit post about the playground, how do you feel about this?

This is a great idea. However, you really need a semi-permanent URL for this, because you don't want it to change later on.

Have you decided on the final URL for the playground?

Right now it is a couple of links to different versions.

Maybe have a landing URL that is the current stable version, then a link to "vnext" or "experimental" on the landing page?

schungx commented 4 years ago

Also, right now, there is a noticeable pause when the user presses Run the first time. That is to wait for the WASM package to load. This is bad for user experience, especially the very first button click.

I'd suggest either pre-loading that WASM package or put up a spinning loading gif...

alvinhochun commented 4 years ago

I'm thinking perhaps I should make a Reddit post about the playground, how do you feel about this?

This is a great idea. However, you really need a semi-permanent URL for this, because you don't want it to change later on.

Have you decided on the final URL for the playground?

Right now it is a couple of links to different versions.

Maybe have a landing URL that is the current stable version, then a link to "vnext" or "experimental" on the landing page?

I suppose I will be keeping https://alvinhochun.github.io/rhai-playground-unstable/. If you think it is necessary to have one to be called "stable" I would just copy the current build to https://alvinhochun.github.io/rhai-playground/.

alvinhochun commented 4 years ago

Also, right now, there is a noticeable pause when the user presses Run the first time. That is to wait for the WASM package to load. This is bad for user experience, especially the very first button click.

I'd suggest either pre-loading that WASM package or put up a spinning loading gif...

How about I just print "Initializing Web Worker..." to the output box for now?

schungx commented 4 years ago

Suggestion:

Right now it says "Running" on the Stop button's tooltip - if it is actually running, it'd start counting.

Therefore, you can change that text to "Initializing, please wait...", plus also put a message to the output box.

That should do it.

alvinhochun commented 4 years ago

Ok, I've dealt with some of the issues. Most notably, there is now only one .wasm file which saves about 150KiB of download (gzipped) loading the worker. Frequent output printing no longer take as much resources (you can run primes.rhai with print without making the browser slow down to a crawl). I also add a loading tooltip like you suggested.

alvinhochun commented 4 years ago

I made https://alvinhochun.github.io/rhai-demo/ a redirect. You can change all references to the new URL https://alvinhochun.github.io/rhai-playground-unstable/.

I'll probably make a Reddit post later today...

schungx commented 4 years ago

Ah, I see it.

https://www.reddit.com/r/rust/comments/hmtve2/rhai_playground_or_a_toy_project_of_using_rhai/

alvinhochun commented 4 years ago

I implemented a modules proof-of-concept on the modules-test branch (not deployed). (Honestly, I find my code quite amusing...)

So, I want to allow scripts to be added as modules with user-specified names, which can be used when running the main script. Of course, the Playground has to provide a way to manage the modules, perhaps even the ability for them to be exported and re-imported. Makes sense?

Or would you suggest me work on something else before that?

schungx commented 4 years ago

So, I want to allow scripts to be added as modules with user-specified names, which can be used when running the main script. Of course, the Playground has to provide a way to manage the modules, perhaps even the ability for them to be exported and re-imported. Makes sense?

That would make it more than a simple Playground, though. You're going to be keeping a local store of scripts on behalf of users.

You may actually have a "standard" list of modules and hook up a module resolver so users can load different pre-built modules. But to allow users to register their own modules and use it in their scripts, that's going to add a whole new dimension of functionalities.

You might as well also have script storage.

schungx commented 4 years ago

But still, having modules working in WASM is way cool!

alvinhochun commented 4 years ago

That would make it more than a simple Playground, though. You're going to be keeping a local store of scripts on behalf of users.

You may actually have a "standard" list of modules and hook up a module resolver so users can load different pre-built modules. But to allow users to register their own modules and use it in their scripts, that's going to add a whole new dimension of functionalities.

You might as well also have script storage.

I had given script storage a bit of thought before. The "simple" way is to use localStorage to store scripts, but localStorage size is rather limited. I have no experience with IndexedDB and it seems a bit complicated on first glance. Therefore I want to leave this for later.

For now, I wanted to just make a per-session (i.e. until page refresh) script storage to start with. I can perhaps implement something like drag-drop to add files as scripts to make it easier to load user modules. If you want to suggest any "standard modules", I can include them too.

There is also the case of embedding - if a page embeds the playground, I would like the page to be able to provide predefined modules, and also not have it affect the local storage.

schungx commented 4 years ago

For now, I wanted to just make a per-session (i.e. until page refresh) script storage to start with. I can perhaps implement something like drag-drop to add files as scripts to make it easier to load user modules. If you want to suggest any "standard modules", I can include them too.

Well, if you do that, people are gonna hate you... nobody wants to redo a whole bunch of modules the next time round.

I think indexDB is probably the best.

Actually localStorage shouldn't be too bad. The typical scripts are very short. They should fit comfortably inside localStorage.

schungx commented 4 years ago

Pinging @alvinhochun ... The latest drop adds closures support. Would be really interested to see if running in the playground! :-D

alvinhochun commented 4 years ago

Done, I've bumped it to Rhai 0.18.1 and it's deployed.

(As you can see, there had not been any changes recently because I shifted my focus to another project, but I will get back to it soon.)

schungx commented 3 years ago

Since the Playground is now part of the org, closing this now.