Skip to content

Commit 0c30c6f

Browse files
authored
Cloudflare worker support (#133)
* working wrangler demo * improve worker example code quality * add helpers for cloudflare support * document cloudflare, deno, esmodule * deno smoketest file * doc cleanup * expand loader docs * test minimal example in CI * rebuild docs * document minimal size
1 parent 2482607 commit 0c30c6f

File tree

152 files changed

+5863
-1145
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+5863
-1145
lines changed

.github/workflows/main.yml

+3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ jobs:
7878
- name: Build tarballs
7979
run: yarn tarball && du -h build/tar/*
8080

81+
- name: Test release with NodeJS minimal ESModule example
82+
run: ./scripts/smoketest-node-minimal.ts
83+
8184
- name: Test release with NodeJS/Typescript example
8285
run: ./scripts/smoketest-node.ts
8386

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
ts/generated
22
quickjs
33
.yarn
4+
.*
45
doc
56
json-generator-dot-com-1024-rows.json
67
dist

README.md

+125-24
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,13 @@ main()
5858
- [Async module loader](#async-module-loader)
5959
- [Async on host, sync in QuickJS](#async-on-host-sync-in-quickjs)
6060
- [Testing your code](#testing-your-code)
61-
- [Using in the browser without a build step](#using-in-the-browser-without-a-build-step)
62-
- [quickjs-emscripten-core, variants, and advanced packaging](#quickjs-emscripten-core-variants-and-advanced-packaging)
61+
- [Packaging](#packaging)
62+
- [Reducing package size](#reducing-package-size)
63+
- [WebAssembly loading](#webassembly-loading)
64+
- [Using in the browser without a build step](#using-in-the-browser-without-a-build-step)
6365
- [Debugging](#debugging)
66+
- [Supported Platforms](#supported-platforms)
6467
- [More Documentation](#more-documentation)
65-
- [Requirements](#requirements)
6668
- [Background](#background)
6769
- [Status \& Roadmap](#status--roadmap)
6870
- [Related](#related)
@@ -515,7 +517,105 @@ For more testing examples, please explore the typescript source of [quickjs-emsc
515517
[debug_sync]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/exports.md#debug_sync
516518
[testquickjswasmmodule]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/TestQuickJSWASMModule.md
517519

518-
### Using in the browser without a build step
520+
### Packaging
521+
522+
The main `quickjs-emscripten` package includes several build variants of the WebAssembly module:
523+
524+
- `RELEASE...` build variants should be used in production. They offer better performance and smaller file size compared to `DEBUG...` build variants.
525+
- `RELEASE_SYNC`: This is the default variant used when you don't explicitly provide one. It offers the fastest performance and smallest file size.
526+
- `RELEASE_ASYNC`: The default variant if you need [asyncify][] magic, which comes at a performance cost. See the asyncify docs for details.
527+
- `DEBUG...` build variants can be helpful during development and testing. They include source maps and assertions for catching bugs in your code. We recommend running your tests with _both_ a debug build variant and the release build variant you'll use in production.
528+
- `DEBUG_SYNC`: Instrumented to detect memory leaks, in addition to assertions and source maps.
529+
- `DEBUG_ASYNC`: An [asyncify][] variant with source maps.
530+
531+
To use a variant, call `newQuickJSWASMModule` or `newQuickJSAsyncWASMModule` with the variant object. These functions return a promise that resolves to a [QuickJSWASMModule](./doc/quickjs-emscripten/classes/QuickJSWASMModule.md), the same as `getQuickJS`.
532+
533+
```typescript
534+
import {
535+
newQuickJSWASMModule,
536+
newQuickJSAsyncWASMModule,
537+
RELEASE_SYNC,
538+
DEBUG_SYNC,
539+
RELEASE_ASYNC,
540+
DEBUG_ASYNC,
541+
} from "quickjs-emscripten"
542+
543+
const QuickJSReleaseSync = await newQuickJSWASMModule(RELEASE_SYNC)
544+
const QuickJSDebugSync = await newQuickJSWASMModule(DEBUG_SYNC)
545+
const QuickJSReleaseAsync = await newQuickJSAsyncWASMModule(RELEASE_ASYNC)
546+
const QuickJSDebugAsync = await newQuickJSAsyncWASMModule(DEBUG_ASYNC)
547+
548+
for (const quickjs of [
549+
QuickJSReleaseSync,
550+
QuickJSDebugSync,
551+
QuickJSReleaseAsync,
552+
QuickJSDebugAsync,
553+
]) {
554+
const vm = quickjs.newContext()
555+
const result = vm.unwrapResult(vm.evalCode("1 + 1")).consume(vm.getNumber)
556+
console.log(result)
557+
vm.dispose()
558+
quickjs.dispose()
559+
}
560+
```
561+
562+
#### Reducing package size
563+
564+
Including 4 different copies of the WebAssembly module in the main package gives it an install size of [about 9.04mb](https://packagephobia.com/result?p=quickjs-emscripten). If you're building a CLI package or library of your own, or otherwise don't need to include 4 different variants in your `node_modules`, you can switch to the `quickjs-emscripten-core` package, which contains only the Javascript code for this library, and install one (or more) variants a-la-carte as separate packages.
565+
566+
The most minimal setup would be to install `quickjs-emscripten-core` and `@jitl/quickjs-wasmfile-release-sync` (1.3mb total):
567+
568+
```bash
569+
yarn add quickjs-emscripten-core @jitl/quickjs-wasmfile-release-sync
570+
du -h node_modules
571+
# 640K node_modules/@jitl/quickjs-wasmfile-release-sync
572+
# 80K node_modules/@jitl/quickjs-ffi-types
573+
# 588K node_modules/quickjs-emscripten-core
574+
# 1.3M node_modules
575+
```
576+
577+
Then, you can use quickjs-emscripten-core's `newQuickJSWASMModuleFromVariant` to create a QuickJS module (see [the minimal example][minimal]):
578+
579+
```typescript
580+
// src/quickjs.mjs
581+
import { newQuickJSWASMModuleFromVariant } from "quickjs-emscripten-core"
582+
import RELEASE_SYNC from "@jitl/quickjs-wasmfile-release-sync"
583+
export const QuickJS = await newQuickJSWASMModuleFromVariant(RELEASE_SYNC)
584+
585+
// src/app.mjs
586+
import { QuickJS } from "./quickjs.mjs"
587+
console.log(QuickJS.evalCode("1 + 1"))
588+
```
589+
590+
See the [documentation of quickjs-emscripten-core][core] for more details and the list of variant packages.
591+
592+
[core]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten-core/README.md
593+
594+
#### WebAssembly loading
595+
596+
To run QuickJS, we need to load a WebAssembly module into the host Javascript runtime's memory (usually as an ArrayBuffer or TypedArray) and [compile it](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/instantiate_static) to a [WebAssembly.Module](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Module). This means we need to find the file path or URI of the WebAssembly module, and then read it using an API like `fetch` (browser) or `fs.readFile` (NodeJS). `quickjs-emscripten` tries to handle this automatically using patterns like `new URL('./local-path', import.meta.url)` that work in the browser or are handled automatically by bundlers, or `__dirname` in NodeJS, but you may need to configure this manually if these don't work in your environment, or you want more control about how the WebAssembly module is loaded.
597+
598+
To customize the loading of an existing variant, create a new variant with your loading settings using `newVariant`, passing [CustomizeVariantOptions][newVariant]. For example, you need to customize loading in Cloudflare Workers (see [the full example][cloudflare]).
599+
600+
```typescript
601+
import { newQuickJSWASMModule, DEBUG_SYNC as baseVariant, newVariant } from "quickjs-emscripten"
602+
import cloudflareWasmModule from "./DEBUG_SYNC.wasm"
603+
import cloudflareWasmModuleSourceMap from "./DEBUG_SYNC.wasm.map.txt"
604+
605+
/**
606+
* We need to make a new variant that directly passes the imported WebAssembly.Module
607+
* to Emscripten. Normally we'd load the wasm file as bytes from a URL, but
608+
* that's forbidden in Cloudflare workers.
609+
*/
610+
const cloudflareVariant = newVariant(baseVariant, {
611+
wasmModule: cloudflareWasmModule,
612+
wasmSourceMapData: cloudflareWasmModuleSourceMap,
613+
})
614+
```
615+
616+
[newVariant]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/interfaces/CustomizeVariantOptions.md
617+
618+
#### Using in the browser without a build step
519619

520620
You can use quickjs-emscripten directly from an HTML file in two ways:
521621

@@ -548,16 +648,6 @@ You can use quickjs-emscripten directly from an HTML file in two ways:
548648
</script>
549649
```
550650

551-
### quickjs-emscripten-core, variants, and advanced packaging
552-
553-
Them main `quickjs-emscripten` package includes several build variants of the WebAssembly module.
554-
If these variants are too large for you, you can instead use the `quickjs-emscripten-core` package,
555-
and manually select your own build variant.
556-
557-
See the [documentation of quickjs-emscripten-core][core] for more details.
558-
559-
[core]: https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten-core/README.md
560-
561651
### Debugging
562652

563653
- Switch to a DEBUG build variant of the WebAssembly module to see debug log messages from the C part of this library:
@@ -595,24 +685,35 @@ See the [documentation of quickjs-emscripten-core][core] for more details.
595685

596686
[setDebugMode]: doc/quickjs-emscripten/exports.md#setdebugmode
597687

598-
### More Documentation
599-
600-
[Github] | [NPM] | [API Documentation][api] | [Variants][core] | [Examples][tests]
601-
602-
### Requirements
688+
### Supported Platforms
603689

604690
`quickjs-emscripten` and related packages should work in any environment that supports ES2020.
605691

606-
- NodeJS: requires v16.0.0 or later for WebAssembly compatibility. Tested with node@18.
607-
- We estimate support for the following browsers:
692+
- Browsers: we estimate support for the following browser versions. See the [global-iife][iife] and [esmodule][esm-html] HTML examples.
608693
- Chrome 63+
609694
- Edge 79+
610695
- Safari 11.1+
611696
- Firefox 58+
697+
- NodeJS: requires v16.0.0 or later for WebAssembly compatibility. Tested with node@18. See the [node-typescript][tsx-example] and [node-minimal][minimal] examples.
698+
- Typescript: tested with [email protected] and [email protected]. See the [node-typescript example][tsx-example].
699+
- Vite: tested with [email protected]. See the [Vite/Vue example][vite].
700+
- Create react app: tested with [email protected]. See the [create-react-app example][cra].
612701
- Webpack: tested with [email protected] via create-react-app.
613-
- Vite: tested with [email protected].
614-
- Typescript: tested with [email protected] and [email protected].
615-
- Create react app: tested with [email protected].
702+
- Cloudflare Workers: tested with [email protected]. See the [Cloudflare Workers example][cloudflare].
703+
- Deno: tested with deno 1.39.1. See the [Deno example][deno].
704+
705+
[iife]: https://github.com/justjake/quickjs-emscripten/blob/main/examples/global-iife.html
706+
[esm-html]: https://github.com/justjake/quickjs-emscripten/blob/main/examples/esmodule.html
707+
[deno]: https://github.com/justjake/quickjs-emscripten/blob/main/examples/deno
708+
[vite]: https://github.com/justjake/quickjs-emscripten/blob/main/examples/vite-vue
709+
[cra]: https://github.com/justjake/quickjs-emscripten/blob/main/examples/create-react-app
710+
[cloudflare]: https://github.com/justjake/quickjs-emscripten/blob/main/examples/cloudflare-workers
711+
[tsx-example]: https://github.com/justjake/quickjs-emscripten/blob/main/examples/node-typescript
712+
[minimal]: https://github.com/justjake/quickjs-emscripten/blob/main/examples/node-minimal
713+
714+
### More Documentation
715+
716+
[Github] | [NPM] | [API Documentation][api] | [Variants][core] | [Examples][tests]
616717

617718
## Background
618719

doc/@jitl/quickjs-ffi-types/exports.md

+22-20
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@
3737

3838
- [EmscriptenModule](interfaces/EmscriptenModule.md)
3939
- [EmscriptenModuleLoader](interfaces/EmscriptenModuleLoader.md)
40+
- [EmscriptenModuleLoaderOptions](interfaces/EmscriptenModuleLoaderOptions.md)
4041
- [QuickJSAsyncEmscriptenModule](interfaces/QuickJSAsyncEmscriptenModule.md)
4142
- [QuickJSAsyncFFI](interfaces/QuickJSAsyncFFI.md)
4243
- [QuickJSAsyncVariant](interfaces/QuickJSAsyncVariant.md)
4344
- [QuickJSEmscriptenModule](interfaces/QuickJSEmscriptenModule.md)
4445
- [QuickJSFFI](interfaces/QuickJSFFI.md)
4546
- [QuickJSSyncVariant](interfaces/QuickJSSyncVariant.md)
47+
- [SourceMapData](interfaces/SourceMapData.md)
4648

4749
## Type Aliases
4850

@@ -55,7 +57,7 @@ for the Emscripten stack.
5557

5658
#### Source
5759

58-
[ffi-types.ts:77](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L77)
60+
[packages/quickjs-ffi-types/src/ffi-types.ts:77](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L77)
5961

6062
***
6163

@@ -65,7 +67,7 @@ for the Emscripten stack.
6567
6668
#### Source
6769

68-
[variant-types.ts:50](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/variant-types.ts#L50)
70+
[packages/quickjs-ffi-types/src/variant-types.ts:50](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/variant-types.ts#L50)
6971

7072
***
7173

@@ -75,7 +77,7 @@ for the Emscripten stack.
7577
7678
#### Source
7779

78-
[emscripten-types.ts:166](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/emscripten-types.ts#L166)
80+
[packages/quickjs-ffi-types/src/emscripten-types.ts:242](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/emscripten-types.ts#L242)
7981

8082
***
8183

@@ -88,7 +90,7 @@ for the Emscripten stack.
8890

8991
#### Source
9092

91-
[ffi-types.ts:89](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L89)
93+
[packages/quickjs-ffi-types/src/ffi-types.ts:89](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L89)
9294

9395
***
9496

@@ -100,7 +102,7 @@ for the Emscripten stack.
100102

101103
#### Source
102104

103-
[ffi-types.ts:19](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L19)
105+
[packages/quickjs-ffi-types/src/ffi-types.ts:19](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L19)
104106

105107
***
106108

@@ -112,7 +114,7 @@ for the Emscripten stack.
112114

113115
#### Source
114116

115-
[ffi-types.ts:24](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L24)
117+
[packages/quickjs-ffi-types/src/ffi-types.ts:24](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L24)
116118

117119
***
118120

@@ -124,7 +126,7 @@ for the Emscripten stack.
124126

125127
#### Source
126128

127-
[ffi-types.ts:29](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L29)
129+
[packages/quickjs-ffi-types/src/ffi-types.ts:29](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L29)
128130

129131
***
130132

@@ -136,7 +138,7 @@ for the Emscripten stack.
136138

137139
#### Source
138140

139-
[ffi-types.ts:14](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L14)
141+
[packages/quickjs-ffi-types/src/ffi-types.ts:14](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L14)
140142

141143
***
142144

@@ -149,7 +151,7 @@ See JSValueConst and StaticJSValue.
149151

150152
#### Source
151153

152-
[ffi-types.ts:41](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L41)
154+
[packages/quickjs-ffi-types/src/ffi-types.ts:41](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L41)
153155

154156
***
155157

@@ -161,7 +163,7 @@ Used internally for Javascript-to-C function calls.
161163

162164
#### Source
163165

164-
[ffi-types.ts:51](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L51)
166+
[packages/quickjs-ffi-types/src/ffi-types.ts:51](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L51)
165167

166168
***
167169

@@ -174,7 +176,7 @@ See JSValue.
174176

175177
#### Source
176178

177-
[ffi-types.ts:35](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L35)
179+
[packages/quickjs-ffi-types/src/ffi-types.ts:35](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L35)
178180

179181
***
180182

@@ -186,7 +188,7 @@ Used internally for Javascript-to-C function calls.
186188

187189
#### Source
188190

189-
[ffi-types.ts:46](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L46)
191+
[packages/quickjs-ffi-types/src/ffi-types.ts:46](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L46)
190192

191193
***
192194

@@ -198,7 +200,7 @@ Opaque pointer that was allocated by js_malloc.
198200

199201
#### Source
200202

201-
[ffi-types.ts:94](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L94)
203+
[packages/quickjs-ffi-types/src/ffi-types.ts:94](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L94)
202204

203205
***
204206

@@ -211,7 +213,7 @@ for the Emscripten stack.
211213

212214
#### Source
213215

214-
[ffi-types.ts:83](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L83)
216+
[packages/quickjs-ffi-types/src/ffi-types.ts:83](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L83)
215217

216218
***
217219

@@ -223,7 +225,7 @@ Used internally for C-to-Javascript function calls.
223225

224226
#### Source
225227

226-
[ffi-types.ts:61](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L61)
228+
[packages/quickjs-ffi-types/src/ffi-types.ts:61](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L61)
227229

228230
***
229231

@@ -235,7 +237,7 @@ Used internally for C-to-Javascript interrupt handlers.
235237

236238
#### Source
237239

238-
[ffi-types.ts:66](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L66)
240+
[packages/quickjs-ffi-types/src/ffi-types.ts:66](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L66)
239241

240242
***
241243

@@ -247,7 +249,7 @@ Used internally for C-to-Javascript module loading.
247249

248250
#### Source
249251

250-
[ffi-types.ts:71](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L71)
252+
[packages/quickjs-ffi-types/src/ffi-types.ts:71](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L71)
251253

252254
***
253255

@@ -257,7 +259,7 @@ Used internally for C-to-Javascript module loading.
257259
258260
#### Source
259261

260-
[variant-types.ts:49](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/variant-types.ts#L49)
262+
[packages/quickjs-ffi-types/src/variant-types.ts:49](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/variant-types.ts#L49)
261263

262264
## Variables
263265

@@ -325,7 +327,7 @@ module code
325327

326328
#### Source
327329

328-
[ffi-types.ts:99](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L99)
330+
[packages/quickjs-ffi-types/src/ffi-types.ts:99](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L99)
329331

330332
## Functions
331333

@@ -358,7 +360,7 @@ module code
358360
359361
#### Source
360362

361-
[ffi-types.ts:106](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L106)
363+
[packages/quickjs-ffi-types/src/ffi-types.ts:106](https://github.com/justjake/quickjs-emscripten/blob/main/packages/quickjs-ffi-types/src/ffi-types.ts#L106)
362364

363365
***
364366

0 commit comments

Comments
 (0)