rustwasm / wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript
https://rustwasm.github.io/docs/wasm-bindgen/
Apache License 2.0
7.72k stars 1.06k forks source link

fetch() example does not load localhost:8080 #2081

Closed guest271314 closed 4 years ago

guest271314 commented 4 years ago

Describe the Bug

fetch() example does not load at localhost:8080.

Steps to Reproduce

git this repository, install Rust, dependencies

$ git clone https://github.com/rustwasm/wasm-bindgen.git
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ npm install webpack
$ npm install webpack-dev-server
$ npm install webpack-cli
$ npm install html-webpack-plugin
$ npm install text-encoding
$ npm install @wasm-tool/wasm-pack-plugin
$ npm run serve
$ npm run serve

> @ serve /path/to/wasm-bindgen/examples/fetch
> webpack-dev-server

🧐  Checking for wasm-pack...

ℹ️  Installing wasm-pack 

✖ 「wdm」: Error: spawn cargo ENOENT
    at _errnoException (util.js:1022:11)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:190:19)
    at onErrorNT (internal/child_process.js:372:16)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
    at Function.Module.runMain (module.js:695:11)
    at startup (bootstrap_node.js:188:16)
    at bootstrap_node.js:609:3
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /home/ubuntu-studio/Music/wasm-bindgen/examples/fetch
ℹ 「wdm」: wait until bundle finished: /

If applicable, add a link to a test case (as a zip file or link to a repository we can clone).

Expected Behavior

The example to run at localhost:8080

You can build the example locally with: $ npm run serve and then visiting http://localhost:8080 in a browser should run the example!

Actual Behavior

localhost:8080 does not load

Additional Context

TL;DR Attempting to test fetch() in AudioWorkletGlobalScope https://github.com/web-platform-tests/wpt/issues/22871.

(How to use/test compiled WASM fetch() at example https://rustwasm.github.io/wasm-bindgen/exbuild/fetch/ ?) Screenshot_2020-04-11_18-09-07 Screenshot_2020-04-11_17-59-19

alexcrichton commented 4 years ago

Sorry there's a lot going on here and it's not really clear to me what's going on. I'm going to close this for now since this looks like it's either Rust-toolchain-related (e.g. with Cargo/rustc) or it's related to web APIs, but from the logs so far it doesn't look like an issue for wasm-bindgen to address.

guest271314 commented 4 years ago

@alexcrichton New to Rust. If download the entire demonstration page https://rustwasm.github.io/wasm-bindgen/exbuild/fetch/ how to run the WASM build of fetch()?

alexcrichton commented 4 years ago

@guest271314 sorry I don't understand what you're asking. I don't know what you mean by how to run the wasm build or what you mean by downloading the demonstration page.

Pauan commented 4 years ago

@guest271314 The error you are getting is this: spawn cargo ENOENT

That means that Cargo / Rust were not installed correctly. So make sure that cargo and rustc are accessible on your $PATH.

guest271314 commented 4 years ago

@alexcrichton If gather the gist of the WASM fetch(), the code provides a means to use fetch() in any scope, including AudioWorkletGlobalScope, where fetch() is not defined, but WebAssembly is, and is a minimal, complete, verifiable example.

At webpack:///./index.js? there is code

const rust = Promise.all(/*! import() */[__webpack_require__.e(0), __webpack_require__.e(1)]).then(__webpack_require__.bind(null, /*! ./pkg */ "./pkg/index.js"));

rust
  .then(m => {
      return m.run("rustwasm/wasm-bindgen").then((data) => {
          console.log(data);

          console.log("The latest commit to the wasm-bindgen %s branch is:", data.name);
          console.log("%s, authored by %s <%s>", data.commit.sha, data.commit.commit.author.name, data.commit.commit.author.email);
      })
  })
  .catch(console.error);

which am gathering is a fetch() call? Therefore, if download all the code at that link should be able to run the code at a different page. What exactly does the code do? Could not locate any references to fetch() nor how to disambiguate globalThis.fetch() from the WASM fetch() version built.

Am able to do

index.html

const worker = new SharedWorker('worker.js', {
  name: 'audio-worklet-worker',
  type: 'module'
});
const workerPort = worker.port;
const aw = new AudioWorkletNode(ac, 'audio-worklet-worker');
aw.onprocessorerror = e => {throw e;};
aw.port.postMessage(null, [workerPort]);

worker.js

let audioWorkletPort;
self.onconnect = e => {
  ([audioWorkletPort] = e.ports);
  audioWorkletPort.onmessage = async e => {
    try {
      const request = await fetch(e.data.url);
      const rs = await request.body;
      const reader = rs.getReader();
      reader
        .read()
        .then(async function processStream({ value, done }) {
          if (done) {
            audioWorkletPort.postMessage({ value, done });
            return await reader.closed;
          } else {
            audioWorkletPort.postMessage({ value, done }, [
              value ? value.buffer : [],
            ]);
          }
          return reader
            .read()
            .then(processStream)
            .catch(e => {
              throw e;
            });
        })
        .catch(e => {
          throw e;
        });
    } catch (e) {
      console.error(e);
      audioWorkletPort.postMessage(e.message);
      throw e;
    };
  };
};

audioWorklet.js

import {url} from './urls.mjs';
let workerPort;
let buffers;
let offset = 0;
class WorkletWorker extends AudioWorkletProcessor {
  constructor(options) {
    super(options);
    this.port.onmessage = async e => {
      if (!workerPort) {
        [workerPort] = e.ports;
        const rs = await this.sharedWorkerFetch(url);
        const reader = rs.getReader();
        reader
          .read()
          .then(async function processStream({ value, done }) {
            if (done) {
              return await reader.closed;
            }
            buffers = new Float32Array(value.buffer);
            return reader.read().then(processStream);
          })
          .then(_ => console.log('input stream done'))
          .catch(console.error);
      }
    };
  }
  async sharedWorkerFetch(url = '', options = {}) {
    if (workerPort) {
      return new ReadableStream({
        start(controller) {
          workerPort.onmessageerror = e => {
            controller.error(e);
          };
          workerPort.onmessage = async ({ data: { value, done } }) => {
            if (done) {
              workerPort.onmessage = null;
              workerPort.onmessageerror = null;
              controller.close();
            } else {
              controller.enqueue(value);
            }
          };
          workerPort.postMessage({ url });
        }
      });
    }
  }
  process(inputs, outputs) {
    if (buffers !== undefined && offset < buffers.length) {
      outputs[0][0].set(buffers.subarray(offset, (offset += 128)));
    }
    return true;
  }
}
registerProcessor('audio-worklet-worker', WorkletWorker);

right now. However, that does not prove nor disprove that defining and using fetch() in AudioWorkletGlobalScope proper will, or will not, in fact impact performance of AudioWorkletProcessor, which is why am interested in carrying out the necessary tests to begin with.

guest271314 commented 4 years ago

@guest271314 The error you are getting is this: spawn cargo ENOENT

That means that Cargo / Rust were not installed correctly. So make sure that cargo and rustc are accessible on your $PATH.

Ok. Will try again. It would be helpful if all of the dependencies requires for Node and Rust were listed in a single document. Have performed other experiments since filed this issue which crashed the OS at least twice. Will try the entire process, again.

Pauan commented 4 years ago

@guest271314 The only dependency needed is Rustup (and Node if you're using npm), but it seems like something went wrong with your Rustup installation.

I've never once seen an OS crash because of the Rust tools, so it sounds like there's something very wrong with your setup.

guest271314 commented 4 years ago

@Pauan Did not state that the OS crashed because of Rust tools. See the exact language used

Have performed other experiments since filed this issue which crashed the OS at least twice.

Am constantly running various experiments and tests. Do not have the same OS that did a few days ago. The tests that crashed the OS were unrelated to Rust AFAICT. Node was still running do to the serve call long after had closed the document which was intended to load the module. Cannot directly reproduce exactly what occurred because that OS configuration is gone forever.

Again, it would be helpful to list all of the dependencies needed for the module to run, so will not get any errors finding out at command-line that a webpack dependency is required.

Pauan commented 4 years ago

Again, it would be helpful to list all of the dependencies needed for the module to run, so will not get any errors finding out at command-line that a webpack dependency is required.

As I said, the only dependencies you need are Rustup and Node. Then you just run npm install and npm run serve. It's as simple as that, you don't need to do anything else.

It's common knowledge that you have to use npm install before running an npm package. Though for completeness we should mention it in the docs. We would gladly accept a PR which does that, it's a simple fix.

guest271314 commented 4 years ago

It's common knowledge that you have to use npm install before running an npm package.

Am not your common huckleberry.

https://github.com/rustwasm/wasm-bindgen/pull/2082