Skip to content

Commit

Permalink
feat(jsonwebtoken): support wasm32-wasi target (#798)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn authored Feb 29, 2024
1 parent 3f1c657 commit b23382d
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:
build: yarn build --target aarch64-pc-windows-msvc
- host: ubuntu-latest
target: 'wasm32-wasi-preview1-threads'
build: yarn workspaces foreach -A --no-private -j 1 --exclude "@node-rs/{jsonwebtoken,deno-lint}" run build --target wasm32-wasi-preview1-threads
build: yarn workspaces foreach -A --no-private -j 1 --exclude "@node-rs/deno-lint" run build --target wasm32-wasi-preview1-threads

name: stable - ${{ matrix.settings.target }} - node@20
runs-on: ${{ matrix.settings.host }}
Expand Down
1 change: 1 addition & 0 deletions packages/jsonwebtoken/browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '@node-rs/jsonwebtoken-wasm32-wasi'
75 changes: 75 additions & 0 deletions packages/jsonwebtoken/jsonwebtoken.wasi-browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync,
getDefaultContext as __emnapiGetDefaultContext,
WASI as __WASI,
} from '@napi-rs/wasm-runtime'
import { Volume as __Volume, createFsFromVolume as __createFsFromVolume } from '@napi-rs/wasm-runtime/fs'

import __wasmUrl from './jsonwebtoken.wasm32-wasi.wasm?url'

const __fs = __createFsFromVolume(
__Volume.fromJSON({
'/': null,
}),
)

const __wasi = new __WASI({
version: 'preview1',
fs: __fs,
})

const __emnapiContext = __emnapiGetDefaultContext()

const __sharedMemory = new WebAssembly.Memory({
initial: 1024,
maximum: 10240,
shared: true,
})

const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())

const {
instance: __napiInstance,
module: __wasiModule,
napiModule: __napiModule,
} = __emnapiInstantiateNapiModuleSync(__wasmFile, {
context: __emnapiContext,
asyncWorkPoolSize: 4,
wasi: __wasi,
onCreateWorker() {
return new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {
type: 'module',
})
},
overwriteImports(importObject) {
importObject.env = {
...importObject.env,
...importObject.napi,
...importObject.emnapi,
memory: __sharedMemory,
}
return importObject
},
beforeInit({ instance }) {
__napi_rs_initialize_modules(instance)
},
})

function __napi_rs_initialize_modules(__napiInstance) {
__napiInstance.exports['__napi_register__Algorithm_0']?.()
__napiInstance.exports['__napi_register__decode_header_1']?.()
__napiInstance.exports['__napi_register__Header_struct_2']?.()
__napiInstance.exports['__napi_register__SignTask_impl_3']?.()
__napiInstance.exports['__napi_register__sign_4']?.()
__napiInstance.exports['__napi_register__sign_sync_5']?.()
__napiInstance.exports['__napi_register__Validation_struct_6']?.()
__napiInstance.exports['__napi_register__VerifyTask_impl_7']?.()
__napiInstance.exports['__napi_register__verify_8']?.()
__napiInstance.exports['__napi_register__verify_sync_9']?.()
}
export const Algorithm = __napiModule.exports.Algorithm
export const decodeHeader = __napiModule.exports.decodeHeader
export const sign = __napiModule.exports.sign
export const signSync = __napiModule.exports.signSync
export const verify = __napiModule.exports.verify
export const verifySync = __napiModule.exports.verifySync
91 changes: 91 additions & 0 deletions packages/jsonwebtoken/jsonwebtoken.wasi.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-disable */
/* prettier-ignore */

/* auto-generated by NAPI-RS */

const __nodeFs= require('node:fs')
const __nodePath = require('node:path')
const { WASI: __nodeWASI } = require('node:wasi')
const { Worker } = require('node:worker_threads')

const {
instantiateNapiModuleSync: __emnapiInstantiateNapiModuleSync,
getDefaultContext: __emnapiGetDefaultContext,
} = require('@napi-rs/wasm-runtime')

const __wasi = new __nodeWASI({
version: 'preview1',
env: process.env,
preopens: {
'/': '/'
}
})

const __emnapiContext = __emnapiGetDefaultContext()

const __sharedMemory = new WebAssembly.Memory({
initial: 1024,
maximum: 10240,
shared: true,
})

let __wasmFilePath = __nodePath.join(__dirname, 'jsonwebtoken.wasm32-wasi.wasm')

if (!__nodeFs.existsSync(__wasmFilePath)) {
try {
__wasmFilePath = __nodePath.resolve('@node-rs/jsonwebtoken-wasm32-wasi')
} catch {
throw new Error('Cannot find jsonwebtoken.wasm32-wasi.wasm file, and @node-rs/jsonwebtoken-wasm32-wasi package is not installed.')
}
}

const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = __emnapiInstantiateNapiModuleSync(__nodeFs.readFileSync(__wasmFilePath), {
context: __emnapiContext,
asyncWorkPoolSize: (function() {
const threadsSizeFromEnv = Number(process.env.NAPI_RS_ASYNC_WORK_POOL_SIZE ?? process.env.UV_THREADPOOL_SIZE)
// NaN > 0 is false
if (threadsSizeFromEnv > 0) {
return threadsSizeFromEnv
} else {
return 4
}
})(),
wasi: __wasi,
onCreateWorker() {
return new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), {
env: process.env,
execArgv: ['--experimental-wasi-unstable-preview1'],
})
},
overwriteImports(importObject) {
importObject.env = {
...importObject.env,
...importObject.napi,
...importObject.emnapi,
memory: __sharedMemory,
}
return importObject
},
beforeInit({ instance }) {
__napi_rs_initialize_modules(instance)
}
})

function __napi_rs_initialize_modules(__napiInstance) {
__napiInstance.exports['__napi_register__Algorithm_0']?.()
__napiInstance.exports['__napi_register__decode_header_1']?.()
__napiInstance.exports['__napi_register__Header_struct_2']?.()
__napiInstance.exports['__napi_register__SignTask_impl_3']?.()
__napiInstance.exports['__napi_register__sign_4']?.()
__napiInstance.exports['__napi_register__sign_sync_5']?.()
__napiInstance.exports['__napi_register__Validation_struct_6']?.()
__napiInstance.exports['__napi_register__VerifyTask_impl_7']?.()
__napiInstance.exports['__napi_register__verify_8']?.()
__napiInstance.exports['__napi_register__verify_sync_9']?.()
}
module.exports.Algorithm = __napiModule.exports.Algorithm
module.exports.decodeHeader = __napiModule.exports.decodeHeader
module.exports.sign = __napiModule.exports.sign
module.exports.signSync = __napiModule.exports.signSync
module.exports.verify = __napiModule.exports.verify
module.exports.verifySync = __napiModule.exports.verifySync
3 changes: 3 additions & 0 deletions packages/jsonwebtoken/npm/wasm32-wasi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `@node-rs/jsonwebtoken-wasm32-wasi`

This is the **wasm32-wasi-preview1-threads** binary for `@node-rs/jsonwebtoken`
47 changes: 47 additions & 0 deletions packages/jsonwebtoken/npm/wasm32-wasi/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@node-rs/jsonwebtoken-wasm32-wasi",
"version": "0.4.0",
"cpu": [
"wasm32"
],
"main": "jsonwebtoken.wasi.cjs",
"files": [
"jsonwebtoken.wasm32-wasi.wasm",
"jsonwebtoken.wasi.cjs",
"jsonwebtoken.wasi-browser.js",
"wasi-worker.mjs",
"wasi-worker-browser.mjs"
],
"description": "Rust jsonwebtoken binding for Node.js",
"keywords": [
"jsonwebtoken",
"jwt",
"napi-rs",
"node-rs"
],
"author": {
"name": "Francesco Benedetto",
"url": "https://github.com/nebarf",
"email": "[email protected]"
},
"homepage": "https://github.com/napi-rs/node-rs#readme",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/napi-rs/node-rs.git"
},
"bugs": {
"url": "https://github.com/napi-rs/node-rs/issues"
},
"browser": "jsonwebtoken.wasi-browser.js",
"dependencies": {
"@napi-rs/wasm-runtime": "^0.1.1"
}
}
3 changes: 2 additions & 1 deletion packages/jsonwebtoken/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"x86_64-unknown-linux-musl",
"x86_64-unknown-freebsd",
"i686-pc-windows-msvc",
"armv7-linux-androideabi"
"armv7-linux-androideabi",
"wasm32-wasi-preview1-threads"
]
},
"repository": {
Expand Down
40 changes: 40 additions & 0 deletions packages/jsonwebtoken/wasi-worker-browser.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { instantiateNapiModuleSync, MessageHandler, WASI } from '@napi-rs/wasm-runtime'
import { Volume, createFsFromVolume } from '@napi-rs/wasm-runtime/fs'

const fs = createFsFromVolume(
Volume.fromJSON({
'/': null,
}),
)

const handler = new MessageHandler({
onLoad({ wasmModule, wasmMemory }) {
const wasi = new WASI({
fs,
print: function () {
// eslint-disable-next-line no-console
console.log.apply(console, arguments)
},
printErr: function() {
// eslint-disable-next-line no-console
console.error.apply(console, arguments)
},
})
return instantiateNapiModuleSync(wasmModule, {
childThread: true,
wasi,
overwriteImports(importObject) {
importObject.env = {
...importObject.env,
...importObject.napi,
...importObject.emnapi,
memory: wasmMemory,
}
},
})
},
})

globalThis.onmessage = function (e) {
handler.handle(e)
}
50 changes: 50 additions & 0 deletions packages/jsonwebtoken/wasi-worker.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import fs from "node:fs";
import { createRequire } from "node:module";
import { parentPort, Worker } from "node:worker_threads";

import { instantiateNapiModuleSync, MessageHandler, WASI } from "@napi-rs/wasm-runtime";

const require = createRequire(import.meta.url);

if (parentPort) {
parentPort.on("message", (data) => {
globalThis.onmessage({ data });
});
}

Object.assign(globalThis, {
self: globalThis,
require,
Worker,
importScripts: function (f) {
;(0, eval)(fs.readFileSync(f, "utf8") + "//# sourceURL=" + f);
},
postMessage: function (msg) {
if (parentPort) {
parentPort.postMessage(msg);
}
},
});

const handler = new MessageHandler({
onLoad({ wasmModule, wasmMemory }) {
const wasi = new WASI({ fs });

return instantiateNapiModuleSync(wasmModule, {
childThread: true,
wasi,
overwriteImports(importObject) {
importObject.env = {
...importObject.env,
...importObject.napi,
...importObject.emnapi,
memory: wasmMemory
};
},
});
},
});

globalThis.onmessage = function (e) {
handler.handle(e);
};

0 comments on commit b23382d

Please sign in to comment.