Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning certain values asynchronously causes Deno to fail to resolve promise #828

Open
manterfield opened this issue Jul 16, 2024 · 3 comments
Assignees
Labels
bug Something isn't working

Comments

@manterfield
Copy link

Disclaimer: I could totally be doing something stupid here, but I can't see what.

Code that reproduces the issue for me:

// mod.ts

import { SlackAPI } from "https://deno.land/x/[email protected]/mod.ts";

const getClientAsync = async () => {
  // This return style always fails
  return SlackAPI("foo");
};

const getClientNestedAsync = async () => {
  // Nesting it in an object succeeds
  return { c: SlackAPI("foo") };
};

const getClient = () => {
  // Returning from a non-async function succeeds
  return SlackAPI("foo");
};

const run = async () => {
  console.log("Running");
  SlackAPI("foo");
  console.log("Got inline client");

  getClient();
  console.log("Got client from func");

  await getClientNestedAsync();
  console.log("Got client from nested async func");

  await getClientAsync();
  console.log("Got client from async func");
};

if (import.meta.main) {
  await run();
}

Run this with: deno run --allow-all mod.ts
Deno version: deno 1.44.4+86010be

If I run the above code, I get this output:

Running
Got inline client
Got client from func
Got client from nested async func
error: Top-level await promise never resolved
  await run();
  ^
    at <anonymous> (file:///Users/tm/Code/scratch/denobug/mod.ts:31:3)

I can swap the order of the getClient calls around - it always fails at the call to the async, non-nested return.

I first saw this behaviour in a worker, where it doesn't even show the error. It just seems to... stop. No error, nothing to show it has crashed - I have a lot going on in my worker though so can't rule out suppression.

I've also tested the returned client in all cases, and in all cases the client is functional/can make calls as expected. I've tried every odd variation I can think of, including assigning the client to a variable, using it first, then returning.

It seems that no matter what, if that specific value is returned from an async function, it crashes Deno and can not be caught.

@marvinhagemeister
Copy link
Contributor

Smaller reproduction case:

import { SlackAPI } from "https://deno.land/x/[email protected]/mod.ts";
await SlackAPI("foo");

Error:

error: Top-level await promise never resolved
await SlackAPI("foo");
^
    at <anonymous> (file:///Users/marvinh/dev/test/deno-slack/main.ts:3:1)

@marvinhagemeister marvinhagemeister added the bug Something isn't working label Jul 16, 2024
@manterfield
Copy link
Author

manterfield commented Jul 16, 2024

@marvinhagemeister Having dug into the Slack code more and taught myself a bit more about Proxies and nested promises, I'm not sure this is an issue with Deno.

The Slack code returns a Proxy with a getter. Deno checks if this is thenable, which is caught by the getter which in turn will eventually return a proxied function (so it appears as if it's a promise).

I suppose Deno could potentially help with making it clear what just happened, but I wonder if this is expected behaviour other than that.

@manterfield
Copy link
Author

Slack code that's relevant is here: https://github.com/slackapi/deno-slack-api/blob/26fcdd6645c96998a0d3870d325edf476ae83716/src/api-proxy.ts#L46-L57

Just so you can judge if this is Deno acting properly in the face of that.

@bartlomieju bartlomieju self-assigned this Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants