Stream: ComponentizeJS

Topic: ✔ Forcing resource drop


view this post on Zulip Chad Kimes (Feb 20 2024 at 22:15):

Hi! I'm poking at ComponentizeJS and trying to figure out how to explicitly drop a resource. I have this code targeting WASI preview 2 HTTP working in Rust:

    if let Some(body) = body {
        let req_body = req.body().expect("getting body");
        let stream = req_body.write().expect("getting body");
        stream.blocking_write_and_flush(body).expect("writing content");
        drop(stream);
        OutgoingBody::finish(req_body, None).expect("finishing body");
    }

As per the WIT definitions, dropping the writer is necessary before calling OutgoingBody::finish:

  resource outgoing-body {

    /// Returns a stream for writing the body contents.
    ///
    /// The returned `output-stream` is a child resource: it must be dropped
    /// before the parent `outgoing-body` resource is dropped (or finished),
    /// otherwise the `outgoing-body` drop or `finish` will trap.
    ///
    /// Returns success on the first call: the `output-stream` resource for
    /// this `outgoing-body` may be retrieved at most once. Subsequent calls
    /// will return error.
    write: func() -> result<output-stream>;

However I can't figure out how to cause the drop to execute in JS:

    if (body) {
        let reqBody = req.body();
        let stream = reqBody.write();
        stream.blockingWriteAndFlush(body);
        stream.drop(); // TypeError: stream.drop is not a function
        OutgoingBody.finish(reqBody);
    }

I know that I'm mostly on the right path, since GET methods work but my POSTs with a body are failing. Eliding the drop altogether results in the documented trap when calling OutgoingBody.finish. How can I force this stream to be dropped?

view this post on Zulip Guy Bedford (Feb 20 2024 at 22:25):

You can use stream[Symbol.for('dispose')](); to do the dispose from JS

view this post on Zulip Chad Kimes (Feb 20 2024 at 22:25):

And of course 5 minutes after posting that I find: https://github.com/bytecodealliance/ComponentizeJS/blob/89ac2c5730866ebe47afaf3a8ae231c59761796e/test/cases/resource-borrow-import/source.js#L3

I had tried with Symbol.dispose previously and that didn't work, so apparently the magic was Symbol.for('dispose')

view this post on Zulip Guy Bedford (Feb 20 2024 at 22:25):

When Spidermonkey supports Symbol.dispose we will switch to that

view this post on Zulip Guy Bedford (Feb 20 2024 at 22:25):

so then it will be the new using syntax eventually

view this post on Zulip Guy Bedford (Feb 20 2024 at 22:26):

we should better document this though certainly

view this post on Zulip Chad Kimes (Feb 20 2024 at 22:26):

Right, and I suppose if I had adopted typescript's using then I wouldn't have seen this at all

view this post on Zulip Chad Kimes (Feb 20 2024 at 22:32):

While you're active - is there a recommended bundler for joining multiple JS files together? I just want to unclutter my main file by putting some helpers somewhere else, but naive concat quickly runs into import collisions

view this post on Zulip Chad Kimes (Feb 20 2024 at 22:32):

preferably something invokeable from the mjs file

view this post on Zulip Guy Bedford (Feb 20 2024 at 22:46):

Note it's still Symbol.for('dispose') instead of Symbol.dispose. We could directly define Symbol.dispose = Symbol.for('dispose') to make this easier I suppose, posted https://github.com/bytecodealliance/ComponentizeJS/pull/81. For bundling modules, esbuild / swc / rollup are all good.

This allows for consistently disposing all resources via resource[Symbol.dispose]().

view this post on Zulip Chad Kimes (Feb 20 2024 at 22:53):

oh nice! that looks great

view this post on Zulip Notification Bot (Feb 20 2024 at 23:06):

Chad Kimes has marked this topic as resolved.


Last updated: Dec 23 2024 at 12:05 UTC