Skip to content

wasm_exec.js doesn't play well with CloudFlare workers #5370

@TPXP

Description

@TPXP

Summary

Trying to import https://github.com/tinygo-org/tinygo/blob/dev/targets/wasm_exec.js in a cloudflare worker results in a weird error

✘ [ERROR] service core:user:my-first-worker: Uncaught RangeError: Maximum call stack size exceeded

    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get
    at null.<anonymous> (index.js:1:1) in get

Minimal reproduction

Create a basic CloudFlare worker
npm create cloudflare@latest -- my-first-worker

> npx
> "create-cloudflare" my-first-worker

─────────────────────────────────────────────────────────────────
👋 Welcome to create-cloudflare v2.68.0!
🧡 Let's get started.
📊 Cloudflare collects telemetry about your usage of Create-Cloudflare.

Learn more at: https://github.com/cloudflare/workers-sdk/blob/main/packages/create-cloudflare/telemetry.md
─────────────────────────────────────────────────────────────────
╭ Create an application with Cloudflare Step 1 of 3
│
├ In which directory do you want to create your application?
│ dir ./my-first-worker
│
├ What would you like to start with?
│ category Hello World example
│
├ Which template would you like to use?
│ type Worker only
│
├ Which language do you want to use?
│ lang TypeScript
│
├ Copying template files
│ files copied to project directory
│
├ Updating name in `package.json`
│ updated `package.json`
│
├ Installing dependencies
│ installed via `npm install`
│
├ Do you want to add an AGENTS.md file to help AI coding tools understand Cloudflare APIs?
│ no agents
│
╰ Application created

╭ Configuring your application for Cloudflare Step 2 of 3
│
├ Installing wrangler A command line tool for building Cloudflare Workers
│ installed via `npm install wrangler --save-dev`
│
├ Retrieving current workerd compatibility date
│ compatibility date 2026-05-05
│
├ Generating types for your application
│ generated to `./worker-configuration.d.ts` via `npm run cf-typegen`
│
├ Installing @types/node
│ installed via npm
│
├ Do you want to use git for version control?
│ yes git
│
├ Initializing git repo
│ initialized git
│
├ Committing new files
│ git commit
│
╰ Application configured

╭ Deploy with Cloudflare Step 3 of 3
│
├ Do you want to deploy your application?
│ no deploy via `npm run deploy`
│
╰ Done

Add wasm_exec.js

cd my-first-worker
wget https://github.com/tinygo-org/tinygo/raw/refs/heads/dev/targets/wasm_exec.js

Update index.ts to load wasm_exec.js

bat src/index.ts
───────┬───────────────────────────────────────────────────────────────────────
       │ File: src/index.ts
───────┼───────────────────────────────────────────────────────────────────────
   1   │ /**
   2   │  * Welcome to Cloudflare Workers! This is your first worker.
   3   │  *
   4   │  * - Run `npm run dev` in your terminal to start a development server
   5   │  * - Open a browser tab at http://localhost:8787/ to see your worker in action
   6   │  * - Run `npm run deploy` to publish your worker
   7   │  *
   8   │  * Bind resources to your worker in `wrangler.jsonc`. After adding bindings, a type definition for the
   9   │  * `Env` object can be regenerated with `npm run cf-typegen`.
  10   │  *
  11   │  * Learn more at https://developers.cloudflare.com/workers/
  12   │  */
  13   │
  14 + │ import '../wasm_exec.js';
  15 + │
  16   │ export default {
  17   │     async fetch(request, env, ctx): Promise<Response> {
  18   │         return new Response("Hello World!");
  19   │     },
  20   │ } satisfies ExportedHandler<Env>;

Try to run it with npm run dev. Error above appears

Analysis and workarounds

The error seems to originate from the global.require = require; assignment. Commenting it avoids the issue, and we can replace global.require usages in the file (notably https://github.com/tinygo-org/tinygo/blob/dev/targets/wasm_exec.js#L31 and https://github.com/tinygo-org/tinygo/blob/dev/targets/wasm_exec.js#L539-L540) to use require directly without issues.

A Go package designed to use go in cloudflare workers has implemented similar workarounds, commenting out the sections causing issues https://github.com/syumai/workers/blob/main/cmd/workers-assets-gen/assets/wasm_exec_tinygo.js

Suggested solution

Golang's version has evolved to rely on globalThis instead of the global object, I think TinyGo should make these changes too golang/go@680caf1

Here's a patched file (tested in cloudflare workers) https://gist.github.com/TPXP/9a53501c459f22e3535a8af1b1bbe557

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions