skoppe / spasm

Write single page applications in D that compile to webassembly
MIT License
219 stars 17 forks source link

"No matching handler for type Int8Array" #3

Closed WolfieWerewolf closed 5 years ago

WolfieWerewolf commented 5 years ago

Hi there!.. This looks like exactly what I have been looking for. I am having an issue getting spasm to compile, however. I've read your note that 1.13.0-beta2 is the necessary version and I've updated to that using the install.sh (I am on linux mint).. when I run dub from the project root I get the following, however:

spasm 0.1.6: building configuration "library"...
source/spasm/sumtype.d(764,13): Error: static assert:  "No matching handler for type Int8Array"
source/spasm/sumtype.d(629,14):        instantiated from here: matchImpl!(const(SumType!(Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, Uint32Array, Uint8ClampedArray, Float32Array, Float64Array, DataView)))
source/spasm/sumtype.d(314,15):        instantiated from here: match!(const(SumType!(Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, Uint32Array, Uint8ClampedArray, Float32Array, Float64Array, DataView)))
source/spasm/bindings/common.d(4,25):        instantiated from here: SumType!(Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, Uint32Array, Uint8ClampedArray, Float32Array, Float64Array, DataView)
/home/wolfie/dlang/ldc-1.13.0-beta2/bin/ldc2 failed with exit code 1.

any advice would be appreciated... thanks

WolfieWerewolf commented 5 years ago

Please accept my apologies.. I just switched to: ldc-1.14.0-beta1 and was able to compile without any issues. I'm closing the ticket... but I'm sure I'll be back.. this project is great.

skoppe commented 5 years ago

Cool. Can I have a look at the code that didn't work with ldc 1.13.0?

The bindings are generated and I haven't tested everything against the browser, so there will be some places that need to be fixed.

Specifically, some web host objects like Sequence, Int8Array, ReadableStream, Iterator and some others (basically everything from https://github.com/skoppe/spasm/blob/master/source/spasm/types.d#L319 down to ArrayPair) are currently opaque objects that don't have any methods on them. Sadly I cannot find any webidl files for them so I implement them whenever I need them.

WolfieWerewolf commented 5 years ago

It was failing to compile spasm itself. So I cloned your repo and tried to execute dub in the project root and that failed with the above. Anything that depended on spasm failed the same way (I tried fetch)... but before that I built the wasm.wasm example on the DLang Wiki without any trouble.. obviously it's a lot simpler.... Today is my first day ever looking at DLang but I spent the past three days trying to do fetch in Rust and failed miserably... I'm thinking Moz has really gone off the rails on that one... My intention is to select a wasm friendly language for a new product I'm developing and so far Dlang + spasm (great name BTW) are in the lead. I've pretty much tried everything that compiles to wasm..

WolfieWerewolf commented 5 years ago

Have you looked at this? https://github.com/Microsoft/TSJS-lib-generator/ That's what M$ uses to generate the TS bindings. specifically in here.. https://github.com/Microsoft/TSJS-lib-generator/tree/master/inputfiles/idl

skoppe commented 5 years ago

Today is my first day ever looking at DLang but I spent the past three days trying to do fetch in Rust and failed miserably...

Even so, there are a lot more people working on Rust+wasm than on this project. So while I am happy that you want to build things with spasm, I do have to manage your expectations a little.

I'm thinking Moz has really gone off the rails on that one... My intention is to select a wasm friendly language for a new product I'm developing and so far Dlang + spasm (great name BTW) are in the lead. I've pretty much tried everything that compiles to wasm..

Spasm can certainly do that, but it does require extra effort on your part beyond the 'it-should-just-work-out-of-the-box'.

skoppe commented 5 years ago

Have you looked at this? https://github.com/Microsoft/TSJS-lib-generator/

It seems they have some extra idl's that I don't have it. Will include them.

WolfieWerewolf commented 5 years ago

@skoppe

Even so, there are a lot more people working on Rust+wasm than on this project. So while I am happy that you want to build things with spasm, I do have to manage your expectations a little.

I appreciate you saying that but I do not expect things to JustWork(tm) where WebAssembly is concerned and I'm also not entirely convinced that "more people" working on software necessarily makes it better though I am hopeful that my efforts will be of value to you and this project eventually.

Spasm can certainly do that, but it does require extra effort on your part beyond the 'it-should-just-work-out-of-the-box'.

Yeah I don't expect anything to work-out-of-the-box especially bleeding edge stuff like this.

I'm sure you can tell by now that I'm willing to put in some effort. The piece I wanted to solve in Rust that was so daunting was a slightly modified version of your fetch example which I have reproduced in my fork of this project in examples/animated. It is a spasm / D implementation of the Rust code that I couldn't get to work. (below)

import spasm.bindings;
import spasm.dom;
import spasm.types;

void get_shaders(void delegate(string) callback){
    auto promise = window.fetch(RequestInfo("https://reqres.in/api/users/2"));
    promise.then(r => r.json).then((data){
        callback(data.as!(Json).data.avatar.as!string);
    });
}

/** Export to JS Side */
extern (C) export void _start(){
    get_shaders((data) => console.log(data));
}

The above works as expected although I did have to add a function to the jsExports object and I don't know exactly what it is supposed to do or why it was being called:

let jsExports = {
    _d_allocmemory: () => { console.log("_d_allocmemory")}, /** TODO @ Wolfie -> What's this for? */

The animation project (which will be different than it is now) dumps it's compiled wasm into: bootstrap-vanilla/webRoot

While I think webpack has a lot of very good use cases I find that during development it makes it difficult for me to understand what's happening... So I implemented this little web server that I wrote a while back in TS for testing and used ES6 import to load your modules rather than webpack to bundle it up into traditional modules...

That aside here's the rust code that I could not get to work:

fn get_shaders(_callback: &'static Fn(JsValue)) {
    let fetch = & | _val: JsValue | {
        _callback(_val);
    };

    JsValue::get_global("wolf")
        .call_method_with_args("fetch", &[&"shaders/cube.glsl", &wrap(fetch)]);
}

fn init_webgl() {
    shaders(&|_val: JsValue| {
        let console_ = JsValue::get_global("console");
        console_.call_method_with_arg("log", _val);
    });
}

It blew up with some lifetime business that was difficult to understand. Even when I went to the gitter chat rust forum one of the guys say "yeah that's a tricky one" and I was thinking... I just want this to call back when the fetch is done... I don't know rust or D but was able to make it work in D without any issues.

Finally please take a look at the commits to my fork, which is up-to-date with your latest changes here: https://github.com/WolfieWerewolf/spasm

Let me know if that stuff is acceptable to you and I'll submit a PR. Or if there are things you would like me to change I can do that first, whatever you think?

skoppe commented 5 years ago

Yeah I don't expect anything to work-out-of-the-box especially bleeding edge stuff like this.

Great. And I do appreciate you trying this out.

It blew up with some lifetime business that was difficult to understand. Even when I went to the gitter chat rust forum one of the guys say "yeah that's a tricky one" and I was thinking... I just want this to call back when the fetch is done... I don't know rust or D but was able to make it work in D without any issues.

Ai, that Rust code looks awful. Specifically the part where it is calling functions by string. Go has that as well I believe.

Finally please take a look at the commits to my fork, which is up-to-date with your latest changes here: https://github.com/WolfieWerewolf/spasm

Let me know if that stuff is acceptable to you and I'll submit a PR. Or if there are things you would like me to change I can do that first, whatever you think?

I don't mind having different bootstrappers, in fact it's one of the reasons I called the first one bootstrap-webpack. But to understand whether your changes would be accepted, consider this: the bootstrap sub-package is meant for end-users so that they can easily setup/build the required js glue code. End-users should be able to run a simple dub run spasm:bootstrap-xxx which should copy required js glue code, copy an index[.template].html and whatever required config for that flavor of bootstrapping. Furthermore, after bootstrapping, there should be convenient commands to create a production build for js/index (bundled, minified) and to run a dev-server. Those are the only criteria.

A quick glance over your commits showed your bootstrap-vanilla only does a dev-server, but I might be mistaken.

skoppe commented 5 years ago

The above works as expected although I did have to add a function to the jsExports object and I don't know exactly what it is supposed to do or why it was being called:

let jsExports = {
    _d_allocmemory: () => { console.log("_d_allocmemory")}, /** TODO @ Wolfie -> What's this for? */

I don't know. It seems similar to the array_cast thing you got with underrun. You still at ldc 1.14? What command do you use to compile?

WolfieWerewolf commented 5 years ago

From a fresh bash I do this: source ~/dlang/ldc-1.14.0-beta1/activate dub build --compiler=ldc2 --build=release --force subsequently I just execute the dub line...

WolfieWerewolf commented 5 years ago

@skoppe

A quick glance over your commits showed your bootstrap-vanilla only does a dev-server, but I might be mistaken.

You are mostly correct.. It provides a web server but it also loads your existing boilerplate using ES6 imports rather than generating / consuming a UMD module (which is what I believe webpack is producing). And yes, the intention is to build it out so that it works for end users but I wanted to get your blessing to go ahead and do that before putting a lot of work into it. I've arrived at Open Source projects in the past where they seemed welcoming at first and after I did a bunch of work and submitted a PR they said "no thank you"... so I wanted to understand your requirements before going all the way with this. So if we are in agreement does it make sense to move the JS boilerplate stuff out of the bootstrap-webpack to a common location that can be shared by any bootstrapper?

skoppe commented 5 years ago

If you think it provides additional value, I'll welcome it. As long as it fulfils the above mentioned criteria.

skoppe commented 5 years ago

From a fresh bash I do this: source ~/dlang/ldc-1.14.0-beta1/activate dub build --compiler=ldc2 --build=release --force subsequently I just execute the dub line...

Ok. I'll try with 1.14 as well. Probably update the CI to run both 1.13 and 1.14

BTW, you can loose the --force flag. You don't need it except in exceptional cases, and it slows down compilation a lot.

WolfieWerewolf commented 5 years ago

Thanks mate..