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

Fix ENVIRONMENT_IS_WORKER detection on Deno #22778

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

kleisauke
Copy link
Collaborator

importScripts() is always undefined on Deno.

`importScripts()` is always `undefined` on Deno.
@kleisauke
Copy link
Collaborator Author

Test case:

Before:

$ cat > test.c << EOF
#include <assert.h>
#include <pthread.h>
#include <stdio.h>

#include <emscripten/em_asm.h>

void* worker_thread(void *arg) {
  int is_worker = EM_ASM_INT(return ENVIRONMENT_IS_WORKER);
  printf("ENVIRONMENT_IS_WORKER: %d\n", is_worker);
  return NULL;
}

int main() {
  int is_worker = EM_ASM_INT(return ENVIRONMENT_IS_WORKER);
  printf("ENVIRONMENT_IS_WORKER: %d\n", is_worker);

  pthread_t thread;
  pthread_create(&thread, NULL, worker_thread, NULL);
  pthread_join(thread, NULL);

  return 0;
}
EOF
$ emcc test.c -o test.js -sASSERTIONS=0 -pthread -sEXIT_RUNTIME
$ node test.js
ENVIRONMENT_IS_WORKER: 0
ENVIRONMENT_IS_WORKER: 1
$ emcc test.c -o test.mjs -sENVIRONMENT=web,worker -sASSERTIONS=0 -pthread
$ echo "import Module from './test.mjs';await Module();Deno.exit()" | deno run --allow-read -
ENVIRONMENT_IS_WORKER: 0 [repeated x times until OOM]

After:

$ emcc test.c -o test.mjs -sENVIRONMENT=web,worker -sASSERTIONS=0 -pthread
$ echo "import Module from './test.mjs';await Module();Deno.exit()" | deno run --allow-read -
ENVIRONMENT_IS_WORKER: 0
ENVIRONMENT_IS_WORKER: 1

@kripken
Copy link
Member

kripken commented Oct 23, 2024

Looks reasonable to me. The downside is maybe a few more bytes in size, but I don't see a way around that, and it mostly affects pthreads builds (which are larger anyhow).

other.test_no_pthread on CI will need to be updated a little, it looks like (it greps for Worker, which this PR adds; can first replace WorkerGlobalScope with another string, if there isn't anything nicer).

// Dummy importScripts. The presence of this global is used
// to detect that we are running on a Worker.
// TODO(sbc): Find another way?
importScripts: () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused because you say that deno never defines importScripts, but from the looks of this code it seems that node doesn't define it either. Isn't the point of this line to inject it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you're right. Node.js doesn't define importScripts either.

const { Worker, isMainThread } = require('node:worker_threads');

if (isMainThread) {
  // This re-loads the current file inside a Worker instance.
  new Worker(__filename);
} else {
  console.log(typeof importScripts);  // Prints 'undefined'.
}

Commit 4bab494 removes this altogether, since ENVIRONMENT_IS_WORKER no longer depends on this dummy symbol on Node.js:

ENVIRONMENT_IS_WORKER = !worker_threads.isMainThread;

(I can separate this change into its own PR if needed)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that ENVIRONMENT_IS_NODE is false on Deno. IIUC, Deno tends to favor standard Web Platform APIs over proprietary ones and wasn't originally designed to be a drop-in replacement for Node.js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants