konsoletyper / teavm

Compiles Java bytecode to JavaScript, WebAssembly and C
https://teavm.org
Apache License 2.0
2.55k stars 260 forks source link

[WASM] Cant instanciate the XMLHttpRequest Class #912

Closed TrOllOchamO closed 2 months ago

TrOllOchamO commented 2 months ago

Hello ! This issue might seem stupid, and I'm sorry about it, but I don't understand why I'm unable to instantiate the XMLHttpRequest class :(

Following what I have seen in the repo inside the Client.java file and in the XMLHttpRequest class, I tried both solutions in my simple example below, but each of the two failed to compile.

  public static void main(String[] args) {
    // ERROR because XMLHttpRequest is an abstract class
    var xhr = new XMLHttpRequest(); 
    // ERROR because @Import is missing on the native create function (also marked as deprecated) 
    var xhr = XMLHttpRequest.create(); 
    xhr.onComplete(() -> receiveResponse(xhr.getResponseText()));
    xhr.open("GET", "resource.json");
    xhr.send();
  }

  private static void receiveResponse(String _text) {
    System.out.println("Hello request");
  }

Am I being dumb or is it maybe not supported for WASM ? Thanks in advance, --Barnabé

konsoletyper commented 2 months ago

What TeaVM version are you using? XMLHttpRequest became non-abstract quite recently, I think it was a couple months ago. And JSO does not work with WebAssembly. See this example (and this JS file) to learn how to interact with JS from WebAssembly backend.

Personally, I recommend using JS backend, since in most cases WebAssembly gives nothing but pain.

TrOllOchamO commented 2 months ago

I'm using the version 0.9.2, Ok, nice to know ! Could have spent quite some time on it xD

I will take a closer look at your example, for now I was using the generated classes.wasm-runtime.js file to import my JS functions to WASM like so :

    const options = {
      installImports: (importObj, _controller) => {
        importObj.request = { 
          fetch : ExpressionInterpreter.fetch,
        };
      }
    };
    const teavm = await TeaVM.wasm.load(wasmPath, options);

Is it ok to do so ? Or it might perturbate the TeaVM runtime ?

And yup, I already read that in one of your previous post, It is probably a great advice, but I'm doing some R&D for my company (about compiling Java specifically to WASM), so I'll have to deal with pain for now :skull:

Thank you for your time, --Barnabé

konsoletyper commented 2 months ago

Is it ok to do so

It's ok, but make sure that fetch function you pass to WebAssembly only consumes and produces numbers. I think it will take quite some time to write all wrappers properly, from both JS and Java side, like allocating buffers in Java side, filling request parameters, then decoding these parameters on JS side, etc.

TrOllOchamO commented 2 months ago

So I came to something that should work well enough, I link a copy of it here in case someone in the future stumble upon this issue and want to look at how I solved my issue.

Thanks for your help again @konsoletyper :)

TrOllOchamO commented 2 months ago

/!\ For anyone reading it, warning, my current POC code don't handle errors /!\