From 61123b575e546371a72c10719cc47e6404d824cc Mon Sep 17 00:00:00 2001 From: Eduardo Rodrigues Date: Sat, 18 Feb 2023 22:48:04 +0100 Subject: [PATCH 01/10] feat: add wasi-common shim for browser and nodejs --- packages/wasi-common/browser/clocks.js | 47 ++++++ .../wasi-common/browser/default-clocks.js | 7 + packages/wasi-common/browser/exit.js | 3 + packages/wasi-common/browser/filesystem.js | 47 ++++++ packages/wasi-common/browser/index.js | 21 +++ packages/wasi-common/browser/io.js | 34 ++++ packages/wasi-common/browser/logging.js | 3 + packages/wasi-common/browser/poll.js | 3 + packages/wasi-common/browser/random.js | 19 +++ packages/wasi-common/browser/stderr.js | 3 + packages/wasi-common/index.d.ts | 9 ++ packages/wasi-common/index.js | 1 + packages/wasi-common/nodejs/clocks.js | 27 ++++ packages/wasi-common/nodejs/default-clocks.js | 7 + packages/wasi-common/nodejs/exit.js | 4 + packages/wasi-common/nodejs/filesystem.js | 58 +++++++ packages/wasi-common/nodejs/index.js | 21 +++ packages/wasi-common/nodejs/io.js | 33 ++++ packages/wasi-common/nodejs/logging.js | 3 + packages/wasi-common/nodejs/poll.js | 3 + packages/wasi-common/nodejs/random.js | 5 + packages/wasi-common/nodejs/stderr.js | 3 + packages/wasi-common/package.json | 18 +++ packages/wasi-common/types/wasi-clocks.d.ts | 11 ++ .../types/wasi-default-clocks.d.ts | 6 + packages/wasi-common/types/wasi-exit.d.ts | 3 + .../wasi-common/types/wasi-filesystem.d.ts | 150 ++++++++++++++++++ packages/wasi-common/types/wasi-io.d.ts | 10 ++ packages/wasi-common/types/wasi-poll.d.ts | 4 + packages/wasi-common/types/wasi-random.d.ts | 3 + packages/wasi-common/types/wasi-stderr.d.ts | 3 + 31 files changed, 569 insertions(+) create mode 100644 packages/wasi-common/browser/clocks.js create mode 100644 packages/wasi-common/browser/default-clocks.js create mode 100644 packages/wasi-common/browser/exit.js create mode 100644 packages/wasi-common/browser/filesystem.js create mode 100644 packages/wasi-common/browser/index.js create mode 100644 packages/wasi-common/browser/io.js create mode 100644 packages/wasi-common/browser/logging.js create mode 100644 packages/wasi-common/browser/poll.js create mode 100644 packages/wasi-common/browser/random.js create mode 100644 packages/wasi-common/browser/stderr.js create mode 100644 packages/wasi-common/index.d.ts create mode 100644 packages/wasi-common/index.js create mode 100644 packages/wasi-common/nodejs/clocks.js create mode 100644 packages/wasi-common/nodejs/default-clocks.js create mode 100644 packages/wasi-common/nodejs/exit.js create mode 100644 packages/wasi-common/nodejs/filesystem.js create mode 100644 packages/wasi-common/nodejs/index.js create mode 100644 packages/wasi-common/nodejs/io.js create mode 100644 packages/wasi-common/nodejs/logging.js create mode 100644 packages/wasi-common/nodejs/poll.js create mode 100644 packages/wasi-common/nodejs/random.js create mode 100644 packages/wasi-common/nodejs/stderr.js create mode 100644 packages/wasi-common/package.json create mode 100644 packages/wasi-common/types/wasi-clocks.d.ts create mode 100644 packages/wasi-common/types/wasi-default-clocks.d.ts create mode 100644 packages/wasi-common/types/wasi-exit.d.ts create mode 100644 packages/wasi-common/types/wasi-filesystem.d.ts create mode 100644 packages/wasi-common/types/wasi-io.d.ts create mode 100644 packages/wasi-common/types/wasi-poll.d.ts create mode 100644 packages/wasi-common/types/wasi-random.d.ts create mode 100644 packages/wasi-common/types/wasi-stderr.d.ts diff --git a/packages/wasi-common/browser/clocks.js b/packages/wasi-common/browser/clocks.js new file mode 100644 index 000000000..e62c29705 --- /dev/null +++ b/packages/wasi-common/browser/clocks.js @@ -0,0 +1,47 @@ +export function wallClockNow(clock) { + if (clock === 1) { + const seconds = BigInt(Math.floor(Date.now() / 1000)); + const nanoseconds = (Date.now() % 1000) * 1000 * 1000; + return { seconds, nanoseconds }; + } + console.log("[clocks] UNKNOWN CLOCK"); +} + +export function monotonicClockResolution(clock) { + console.log(`[clocks] Monotonic clock resolution ${clock}`); +} + +export function wallClockResolution(clock) { + console.log(`[clocks] Wall clock resolution ${clock}`); +} + +let hrStart = hrtimeBigint(); + +export function monotonicClockNow(clock) { + if (clock === 0) { + return hrtimeBigint() - hrStart; + } + console.log("UNKNOWN CLOCK"); +} + +function hrtime(previousTimestamp) { + const baseNow = Math.floor((Date.now() - performance.now()) * 1e-3); + const clocktime = performance.now() * 1e-3; + let seconds = Math.floor(clocktime) + baseNow; + let nanoseconds = Math.floor((clocktime % 1) * 1e9); + + if (previousTimestamp) { + seconds = seconds - previousTimestamp[0]; + nanoseconds = nanoseconds - previousTimestamp[1]; + if (nanoseconds < 0) { + seconds--; + nanoseconds += 1e9; + } + } + return [seconds, nanoseconds]; +} + +function hrtimeBigint(time) { + const diff = hrtime(time); + return BigInt(diff[0] * 1e9 + diff[1]); +} diff --git a/packages/wasi-common/browser/default-clocks.js b/packages/wasi-common/browser/default-clocks.js new file mode 100644 index 000000000..3a5854a62 --- /dev/null +++ b/packages/wasi-common/browser/default-clocks.js @@ -0,0 +1,7 @@ +export function defaultMonotonicClock() { + return 0; +} + +export function defaultWallClock() { + return 1; +} diff --git a/packages/wasi-common/browser/exit.js b/packages/wasi-common/browser/exit.js new file mode 100644 index 000000000..ca87ae19c --- /dev/null +++ b/packages/wasi-common/browser/exit.js @@ -0,0 +1,3 @@ +export function exit(status) { + console.log(`[exit] Exit: ${JSON.stringify(status)}`); +} diff --git a/packages/wasi-common/browser/filesystem.js b/packages/wasi-common/browser/filesystem.js new file mode 100644 index 000000000..54daf07ef --- /dev/null +++ b/packages/wasi-common/browser/filesystem.js @@ -0,0 +1,47 @@ +export function flags(fd) { + console.log(`[filesystem] FLAGS FOR ${fd}`); +} + +export function setFlags(fd, flags) { + console.log(`[filesystem] SET FLAGS ${fd} ${JSON.stringify(flags)}`); +} + +export function close(fd) { + console.log(`[filesystem] CLOSE: ${fd}`); +} + +export function removeDirectoryAt(fd, path) { + console.log(`[filesystem] RM DIR: ${fd} ${path}`); +} + +export function unlinkFileAt(fd, path) { + console.log(`[filesystem] UNLINK: ${fd} ${path}`); +} + +export function writeViaStream(fd, offset) { + console.log(`[filesystem] WRITE STREAM ${fd} ${offset}`); +} + +export function appendViaStream(fd, offset) { + console.log(`[filesystem] APPEND STREAM ${fd} ${offset}`); +} + +export function readViaStream(fd, offset) { + console.log(`[filesystem] READ STREAM ${fd} ${offset}`); +} + +export function openAt(fd, atFlags, path, offset) { + console.log(`[filesystem] OPEN AT ${fd}`); +} + +export function stat(fd) { + console.log(`[filesystem] STAT: ${fd}`); +} + +export function todoType(fd) { + console.log(`[filesystem] TODO TYPE: ${fd}`); +} + +export function closeDirEntryStream(s) { + console.log(`[filesystem] CLOSE DIR ENTRY STREAM`); +} diff --git a/packages/wasi-common/browser/index.js b/packages/wasi-common/browser/index.js new file mode 100644 index 000000000..18a399e35 --- /dev/null +++ b/packages/wasi-common/browser/index.js @@ -0,0 +1,21 @@ +import * as clocks from "./clocks.js"; +import * as defaultClocks from "./default-clocks.js"; +import * as exit from "./exit.js"; +import * as filesystem from "./filesystem.js"; +import * as io from "./io.js"; +import * as logging from "./logging.js"; +import * as poll from "./poll.js"; +import * as random from "./random.js"; +import * as stderr from "./stderr.js"; + +export const importObject = { + "wasi-clocks": clocks, + "wasi-default-clocks": defaultClocks, + "wasi-exit": exit, + "wasi-filesystem": filesystem, + "wasi-io": io, + "wasi-logging": logging, + "wasi-poll": poll, + "wasi-random": random, + "wasi-stderr": stderr, +}; diff --git a/packages/wasi-common/browser/io.js b/packages/wasi-common/browser/io.js new file mode 100644 index 000000000..50aea15e3 --- /dev/null +++ b/packages/wasi-common/browser/io.js @@ -0,0 +1,34 @@ +export function dropInputStream(f) { + console.log(`[io] Drop input stream ${f}`); +} + +export function dropOutputStream(f) { + console.log(`[io] Drop output stream ${f}`); +} + +export function read(src, len) { + console.log(`[io] Read ${src}`); +} + +export function write(dst, buf) { + switch (dst) { + case 0: + throw new Error(`TODO: write stdin`); + case 1: + const decoder = new TextDecoder(); + console.log(decoder.decode(buf)); + return BigInt(buf.byteLength); + case 2: + throw new Error(`TODO: write stdout`); + default: + throw new Error(`TODO: write ${dst}`); + } +} + +export function skip(src, len) { + console.log(`[io] Skip ${src}`); +} + +export function write_repeated(dst, byte, len) { + console.log(`[io] Write repeated ${dst}`); +} diff --git a/packages/wasi-common/browser/logging.js b/packages/wasi-common/browser/logging.js new file mode 100644 index 000000000..2cef561f8 --- /dev/null +++ b/packages/wasi-common/browser/logging.js @@ -0,0 +1,3 @@ +export function log(level, context, msg) { + console.log(`${level}: (${context}) ${msg}\n`); +} diff --git a/packages/wasi-common/browser/poll.js b/packages/wasi-common/browser/poll.js new file mode 100644 index 000000000..316afdd71 --- /dev/null +++ b/packages/wasi-common/browser/poll.js @@ -0,0 +1,3 @@ +export function pollOneoff(f) { + console.log(`[poll] Poll oneoff ${f}`); +} diff --git a/packages/wasi-common/browser/random.js b/packages/wasi-common/browser/random.js new file mode 100644 index 000000000..775ec5322 --- /dev/null +++ b/packages/wasi-common/browser/random.js @@ -0,0 +1,19 @@ +const MAX_BYTES = 65536; + +export function getRandomBytes(len) { + const bytes = new Uint8Array(len); + + if (len > MAX_BYTES) { + // this is the max bytes crypto.getRandomValues + // can do at once see https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues + for (var generated = 0; generated < len; generated += MAX_BYTES) { + // buffer.slice automatically checks if the end is past the end of + // the buffer so we don't have to here + crypto.getRandomValues(bytes.slice(generated, generated + MAX_BYTES)); + } + } else { + crypto.getRandomValues(bytes); + } + + return bytes; +} diff --git a/packages/wasi-common/browser/stderr.js b/packages/wasi-common/browser/stderr.js new file mode 100644 index 000000000..d9784ebaa --- /dev/null +++ b/packages/wasi-common/browser/stderr.js @@ -0,0 +1,3 @@ +export function print(message) { + console.error(`${message}\n`); +} diff --git a/packages/wasi-common/index.d.ts b/packages/wasi-common/index.d.ts new file mode 100644 index 000000000..48b3aa9f4 --- /dev/null +++ b/packages/wasi-common/index.d.ts @@ -0,0 +1,9 @@ +export * as clocks from "./types/wasi-clocks"; +export * as defaultClocks from "./types/wasi-default-clocks"; +export * as exit from "./types/wasi-exit"; +export * as filesystem from "./types/wasi-filesystem"; +export * as io from "./types/wasi-io"; +export * as logging from "./types/wasi-logging"; +export * as poll from "./types/wasi-poll"; +export * as random from "./types/wasi-random"; +export * as stderr from "./types/wasi-stderr"; diff --git a/packages/wasi-common/index.js b/packages/wasi-common/index.js new file mode 100644 index 000000000..a8af064ba --- /dev/null +++ b/packages/wasi-common/index.js @@ -0,0 +1 @@ +export * from "./nodejs/index.js"; diff --git a/packages/wasi-common/nodejs/clocks.js b/packages/wasi-common/nodejs/clocks.js new file mode 100644 index 000000000..2e81a44a5 --- /dev/null +++ b/packages/wasi-common/nodejs/clocks.js @@ -0,0 +1,27 @@ +import { hrtime } from "node:process"; + +export function wallClockNow(clock) { + if (clock === 1) { + const seconds = BigInt(Math.floor(Date.now() / 1000)); + const nanoseconds = (Date.now() % 1000) * 1000 * 1000; + return { seconds, nanoseconds }; + } + console.log("[clocks] UNKNOWN CLOCK"); +} + +export function monotonicClockResolution(clock) { + console.log(`[clocks] Monotonic clock resolution ${clock}`); +} + +export function wallClockResolution(clock) { + console.log(`[clocks] Wall clock resolution ${clock}`); +} + +let hrStart = hrtime.bigint(); + +export function monotonicClockNow(clock) { + if (clock === 0) { + return hrtime.bigint() - hrStart; + } + console.log("[clocks] UNKNOWN CLOCK"); +} diff --git a/packages/wasi-common/nodejs/default-clocks.js b/packages/wasi-common/nodejs/default-clocks.js new file mode 100644 index 000000000..3a5854a62 --- /dev/null +++ b/packages/wasi-common/nodejs/default-clocks.js @@ -0,0 +1,7 @@ +export function defaultMonotonicClock() { + return 0; +} + +export function defaultWallClock() { + return 1; +} diff --git a/packages/wasi-common/nodejs/exit.js b/packages/wasi-common/nodejs/exit.js new file mode 100644 index 000000000..a454c89bd --- /dev/null +++ b/packages/wasi-common/nodejs/exit.js @@ -0,0 +1,4 @@ +export function exit(status) { + console.log(`[exit] Exit: ${JSON.stringify(status)}`); + process.exit(1); +} diff --git a/packages/wasi-common/nodejs/filesystem.js b/packages/wasi-common/nodejs/filesystem.js new file mode 100644 index 000000000..b2c41dfa1 --- /dev/null +++ b/packages/wasi-common/nodejs/filesystem.js @@ -0,0 +1,58 @@ +// export interface DescriptorStat { +// dev: Device, +// ino: Inode, +// type: DescriptorType, +// nlink: Linkcount, +// size: Filesize, +// atim: Timestamp, +// mtim: Timestamp, +// ctim: Timestamp, +// } + +export function flags(fd) { + console.log(`[filesystem] FLAGS FOR ${fd}`); +} + +export function setFlags(fd, flags) { + console.log(`[filesystem] SET FLAGS ${fd} ${JSON.stringify(flags)}`); +} + +export function close(fd) { + console.log(`[filesystem] CLOSE: ${fd}`); +} + +export function removeDirectoryAt(fd, path) { + console.log(`[filesystem] RM DIR: ${fd} ${path}`); +} + +export function unlinkFileAt(fd, path) { + console.log(`[filesystem] UNLINK: ${fd} ${path}`); +} + +export function writeViaStream(fd, offset) { + console.log(`[filesystem] WRITE STREAM ${fd} ${offset}`); +} + +export function appendViaStream(fd, offset) { + console.log(`[filesystem] APPEND STREAM ${fd} ${offset}`); +} + +export function readViaStream(fd, offset) { + console.log(`[filesystem] READ STREAM ${fd} ${offset}`); +} + +export function openAt(fd, atFlags, path, offset) { + console.log(`[filesystem] OPEN AT ${fd}`); +} + +export function stat(fd) { + console.log(`[filesystem] STAT: ${fd}`); +} + +export function todoType(fd) { + console.log(`[filesystem] TODO TYPE: ${fd}`); +} + +export function closeDirEntryStream(s) { + console.log(`[filesystem] CLOSE DIR ENTRY STREAM`); +} diff --git a/packages/wasi-common/nodejs/index.js b/packages/wasi-common/nodejs/index.js new file mode 100644 index 000000000..18a399e35 --- /dev/null +++ b/packages/wasi-common/nodejs/index.js @@ -0,0 +1,21 @@ +import * as clocks from "./clocks.js"; +import * as defaultClocks from "./default-clocks.js"; +import * as exit from "./exit.js"; +import * as filesystem from "./filesystem.js"; +import * as io from "./io.js"; +import * as logging from "./logging.js"; +import * as poll from "./poll.js"; +import * as random from "./random.js"; +import * as stderr from "./stderr.js"; + +export const importObject = { + "wasi-clocks": clocks, + "wasi-default-clocks": defaultClocks, + "wasi-exit": exit, + "wasi-filesystem": filesystem, + "wasi-io": io, + "wasi-logging": logging, + "wasi-poll": poll, + "wasi-random": random, + "wasi-stderr": stderr, +}; diff --git a/packages/wasi-common/nodejs/io.js b/packages/wasi-common/nodejs/io.js new file mode 100644 index 000000000..178adc1ef --- /dev/null +++ b/packages/wasi-common/nodejs/io.js @@ -0,0 +1,33 @@ +export function dropInputStream(f) { + console.log(`[io] Drop input stream ${f}`); +} + +export function dropOutputStream(f) { + console.log(`[io] Drop output stream ${f}`); +} + +export function read(src, len) { + console.log(`[io] Read ${src}`); +} + +export function write(dst, buf) { + switch (dst) { + case 0: + throw new Error(`TODO: write stdin`); + case 1: + process.stdout.write(buf); + return BigInt(buf.byteLength); + case 2: + throw new Error(`TODO: write stdout`); + default: + throw new Error(`TODO: write ${dst}`); + } +} + +export function skip(src, len) { + console.log(`[io] Skip ${src}`); +} + +export function write_repeated(dst, byte, len) { + console.log(`[io] Write repeated ${dst}`); +} diff --git a/packages/wasi-common/nodejs/logging.js b/packages/wasi-common/nodejs/logging.js new file mode 100644 index 000000000..9b1860f60 --- /dev/null +++ b/packages/wasi-common/nodejs/logging.js @@ -0,0 +1,3 @@ +export function log(level, context, msg) { + process.stdout.write(`${level}: (${context}) ${msg}\n`); +} diff --git a/packages/wasi-common/nodejs/poll.js b/packages/wasi-common/nodejs/poll.js new file mode 100644 index 000000000..316afdd71 --- /dev/null +++ b/packages/wasi-common/nodejs/poll.js @@ -0,0 +1,3 @@ +export function pollOneoff(f) { + console.log(`[poll] Poll oneoff ${f}`); +} diff --git a/packages/wasi-common/nodejs/random.js b/packages/wasi-common/nodejs/random.js new file mode 100644 index 000000000..8f0a03f13 --- /dev/null +++ b/packages/wasi-common/nodejs/random.js @@ -0,0 +1,5 @@ +import { randomBytes } from "node:crypto"; + +export function getRandomBytes(len) { + return randomBytes(len); +} diff --git a/packages/wasi-common/nodejs/stderr.js b/packages/wasi-common/nodejs/stderr.js new file mode 100644 index 000000000..7a3eb082c --- /dev/null +++ b/packages/wasi-common/nodejs/stderr.js @@ -0,0 +1,3 @@ +export function print(message) { + process.stderr.write(`${message}\n`); +} diff --git a/packages/wasi-common/package.json b/packages/wasi-common/package.json new file mode 100644 index 000000000..3c8205f58 --- /dev/null +++ b/packages/wasi-common/package.json @@ -0,0 +1,18 @@ +{ + "name": "@bytecodealliance/wasi-common", + "version": "0.0.1", + "description": "WASI implementation in JavaScript for the Browser and Node.js", + "author": "Guy Bedford, Eduardo Rodrigues<16357187+eduardomourar@users.noreply.github.com>", + "type": "module", + "main": "./index.js", + "browser": "./browser/index.js", + "types": "index.d.ts", + "files": [ + "index.js", + "index.d.ts", + "browser/", + "nodejs/", + "types/" + ], + "dependencies": {} +} diff --git a/packages/wasi-common/types/wasi-clocks.d.ts b/packages/wasi-common/types/wasi-clocks.d.ts new file mode 100644 index 000000000..68aadaec5 --- /dev/null +++ b/packages/wasi-common/types/wasi-clocks.d.ts @@ -0,0 +1,11 @@ +export type MonotonicClock = number; +export type Instant = bigint; +export type WallClock = number; +export interface Datetime { + seconds: bigint, + nanoseconds: number, +} +export namespace WasiClocks { + export function monotonicClockNow(clock: MonotonicClock): Instant; + export function wallClockNow(clock: WallClock): Datetime; +} diff --git a/packages/wasi-common/types/wasi-default-clocks.d.ts b/packages/wasi-common/types/wasi-default-clocks.d.ts new file mode 100644 index 000000000..17d83411e --- /dev/null +++ b/packages/wasi-common/types/wasi-default-clocks.d.ts @@ -0,0 +1,6 @@ +export type MonotonicClock = MonotonicClock; +export type WallClock = WallClock; +export namespace WasiDefaultClocks { + export function defaultMonotonicClock(): MonotonicClock; + export function defaultWallClock(): WallClock; +} diff --git a/packages/wasi-common/types/wasi-exit.d.ts b/packages/wasi-common/types/wasi-exit.d.ts new file mode 100644 index 000000000..5a0b32c23 --- /dev/null +++ b/packages/wasi-common/types/wasi-exit.d.ts @@ -0,0 +1,3 @@ +export namespace WasiExit { + export function exit(status: Result): void; +} diff --git a/packages/wasi-common/types/wasi-filesystem.d.ts b/packages/wasi-common/types/wasi-filesystem.d.ts new file mode 100644 index 000000000..681ec11e7 --- /dev/null +++ b/packages/wasi-common/types/wasi-filesystem.d.ts @@ -0,0 +1,150 @@ +export type Descriptor = number; +export type Filesize = bigint; +export type InputStream = InputStream; +/** + * # Variants + * + * ## `"access"` + * + * ## `"again"` + * + * ## `"already"` + * + * ## `"badf"` + * + * ## `"busy"` + * + * ## `"deadlk"` + * + * ## `"dquot"` + * + * ## `"exist"` + * + * ## `"fbig"` + * + * ## `"ilseq"` + * + * ## `"inprogress"` + * + * ## `"intr"` + * + * ## `"inval"` + * + * ## `"io"` + * + * ## `"isdir"` + * + * ## `"loop"` + * + * ## `"mlink"` + * + * ## `"msgsize"` + * + * ## `"nametoolong"` + * + * ## `"nodev"` + * + * ## `"noent"` + * + * ## `"nolck"` + * + * ## `"nomem"` + * + * ## `"nospc"` + * + * ## `"nosys"` + * + * ## `"notdir"` + * + * ## `"notempty"` + * + * ## `"notrecoverable"` + * + * ## `"notsup"` + * + * ## `"notty"` + * + * ## `"nxio"` + * + * ## `"overflow"` + * + * ## `"perm"` + * + * ## `"pipe"` + * + * ## `"rofs"` + * + * ## `"spipe"` + * + * ## `"txtbsy"` + * + * ## `"xdev"` + */ +export type Errno = 'access' | 'again' | 'already' | 'badf' | 'busy' | 'deadlk' | 'dquot' | 'exist' | 'fbig' | 'ilseq' | 'inprogress' | 'intr' | 'inval' | 'io' | 'isdir' | 'loop' | 'mlink' | 'msgsize' | 'nametoolong' | 'nodev' | 'noent' | 'nolck' | 'nomem' | 'nospc' | 'nosys' | 'notdir' | 'notempty' | 'notrecoverable' | 'notsup' | 'notty' | 'nxio' | 'overflow' | 'perm' | 'pipe' | 'rofs' | 'spipe' | 'txtbsy' | 'xdev'; +export type OutputStream = OutputStream; +export type DirEntryStream = number; +export type Device = bigint; +export type Inode = bigint; +/** + * # Variants + * + * ## `"unknown"` + * + * ## `"block-device"` + * + * ## `"character-device"` + * + * ## `"directory"` + * + * ## `"fifo"` + * + * ## `"symbolic-link"` + * + * ## `"regular-file"` + * + * ## `"socket"` + */ +export type DescriptorType = 'unknown' | 'block-device' | 'character-device' | 'directory' | 'fifo' | 'symbolic-link' | 'regular-file' | 'socket'; +export type Linkcount = bigint; +export type Datetime = Datetime; +export interface DescriptorStat { + dev: Device, + ino: Inode, + type: DescriptorType, + nlink: Linkcount, + size: Filesize, + atim: Datetime, + mtim: Datetime, + ctim: Datetime, +} +export interface AtFlags { + symlinkFollow?: boolean, +} +export interface OFlags { + create?: boolean, + directory?: boolean, + excl?: boolean, + trunc?: boolean, +} +export interface DescriptorFlags { + read?: boolean, + write?: boolean, + dsync?: boolean, + nonblock?: boolean, + rsync?: boolean, + sync?: boolean, +} +export interface Mode { + readable?: boolean, + writeable?: boolean, + executable?: boolean, +} +export namespace WasiFilesystem { + export function readViaStream(fd: Descriptor, offset: Filesize): InputStream; + export function writeViaStream(fd: Descriptor, offset: Filesize): OutputStream; + export function appendViaStream(fd: Descriptor): OutputStream; + export function closeDirEntryStream(s: DirEntryStream): void; + export function stat(fd: Descriptor): DescriptorStat; + export function openAt(fd: Descriptor, atFlags: AtFlags, path: string, oFlags: OFlags, flags: DescriptorFlags, mode: Mode): Descriptor; + export function close(fd: Descriptor): void; +} diff --git a/packages/wasi-common/types/wasi-io.d.ts b/packages/wasi-common/types/wasi-io.d.ts new file mode 100644 index 000000000..5cd70ae10 --- /dev/null +++ b/packages/wasi-common/types/wasi-io.d.ts @@ -0,0 +1,10 @@ +export type InputStream = number; +export interface StreamError { +} +export type OutputStream = number; +export namespace WasiIo { + export function read(src: InputStream, len: bigint): [Uint8Array | ArrayBuffer, boolean]; + export function write(dst: OutputStream, buf: Uint8Array): bigint; + export function dropInputStream(f: InputStream): void; + export function dropOutputStream(f: OutputStream): void; +} diff --git a/packages/wasi-common/types/wasi-poll.d.ts b/packages/wasi-common/types/wasi-poll.d.ts new file mode 100644 index 000000000..f349f1a35 --- /dev/null +++ b/packages/wasi-common/types/wasi-poll.d.ts @@ -0,0 +1,4 @@ +export type Pollable = number; +export namespace WasiPoll { + export function pollOneoff(input: Pollable[]): Uint8Array; +} diff --git a/packages/wasi-common/types/wasi-random.d.ts b/packages/wasi-common/types/wasi-random.d.ts new file mode 100644 index 000000000..e9a642225 --- /dev/null +++ b/packages/wasi-common/types/wasi-random.d.ts @@ -0,0 +1,3 @@ +export namespace WasiRandom { + export function getRandomBytes(len: number): Uint8Array | ArrayBuffer; +} diff --git a/packages/wasi-common/types/wasi-stderr.d.ts b/packages/wasi-common/types/wasi-stderr.d.ts new file mode 100644 index 000000000..a959b8ebd --- /dev/null +++ b/packages/wasi-common/types/wasi-stderr.d.ts @@ -0,0 +1,3 @@ +export namespace WasiStderr { + export function print(message: string): void; +} From 4bf4912a35743ee6203daebf6d972acc29222a15 Mon Sep 17 00:00:00 2001 From: Eduardo Rodrigues Date: Sun, 19 Feb 2023 02:18:50 +0100 Subject: [PATCH 02/10] chore: implement experimental outbound http --- packages/wasi-common/browser/http.js | 28 ++++++++++++ packages/wasi-common/http/error.js | 11 +++++ packages/wasi-common/http/make-request.js | 29 ++++++++++++ packages/wasi-common/nodejs/http.js | 19 ++++++++ packages/wasi-common/package.json | 5 ++- packages/wasi-common/types/wasi-http.d.ts | 55 +++++++++++++++++++++++ 6 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 packages/wasi-common/browser/http.js create mode 100644 packages/wasi-common/http/error.js create mode 100644 packages/wasi-common/http/make-request.js create mode 100644 packages/wasi-common/nodejs/http.js create mode 100644 packages/wasi-common/types/wasi-http.d.ts diff --git a/packages/wasi-common/browser/http.js b/packages/wasi-common/browser/http.js new file mode 100644 index 000000000..c03653b55 --- /dev/null +++ b/packages/wasi-common/browser/http.js @@ -0,0 +1,28 @@ +import { UnexpectedError } from "../http/error.js"; + +/** + * @param {import("../types/wasi-http").Request} req + * @returns {string} + */ +export function send(req) { + console.log(`[http] Send (browser) ${req.uri}`); + try { + const xhr = new XMLHttpRequest(); + xhr.open(req.method.toString(), req.uri, false); + xhr.responseType = "arraybuffer"; + for (let [name, value] of req.headers) { + xhr.setRequestHeader(name, value); + } + xhr.send(req.body.length > 0 ? req.body : null); + return { + status: xhr.status, + headers: xhr + .getAllResponseHeaders() + .trim() + .split(/[\r\n]+/), + body: xhr.response.byteLength > 0 ? xhr.response : undefined, + }; + } catch (err) { + throw new UnexpectedError(err.message); + } +} diff --git a/packages/wasi-common/http/error.js b/packages/wasi-common/http/error.js new file mode 100644 index 000000000..d896b3651 --- /dev/null +++ b/packages/wasi-common/http/error.js @@ -0,0 +1,11 @@ +export class UnexpectedError extends Error { + /** @type { import("../types/wasi-http").HttpErrorUnexpectedError } */ + payload; + constructor(message = "unexpected-error") { + super(message); + this.payload = { + tag: "unexpected-error", + val: message, + }; + } +} diff --git a/packages/wasi-common/http/make-request.js b/packages/wasi-common/http/make-request.js new file mode 100644 index 000000000..0b3dba3ca --- /dev/null +++ b/packages/wasi-common/http/make-request.js @@ -0,0 +1,29 @@ +import { runAsWorker } from "synckit"; + +/** + * @param {import("../types/wasi-http").Request} req + * @returns {Promise} + */ +async function makeRequest(req) { + try { + let headers = new Headers(req.headers); + const resp = await fetch(req.uri, { + method: req.method.toString(), + headers, + body: req.body.length > 0 ? req.body : undefined, + }); + let arrayBuffer = await resp.arrayBuffer(); + return JSON.stringify({ + status: resp.status, + headers: resp.headers, + body: + arrayBuffer.byteLength > 0 + ? Buffer.from(arrayBuffer).toString("base64") + : undefined, + }); + } catch (err) { + return err.message; + } +} + +runAsWorker(makeRequest); diff --git a/packages/wasi-common/nodejs/http.js b/packages/wasi-common/nodejs/http.js new file mode 100644 index 000000000..e9591a8ec --- /dev/null +++ b/packages/wasi-common/nodejs/http.js @@ -0,0 +1,19 @@ +import { createSyncFn } from "synckit"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { UnexpectedError } from "../http/error.js"; + +export function send(req) { + console.log(`[http] Send (nodejs) ${req.uri}`); + const dirname = path.dirname(fileURLToPath(import.meta.url)); + const syncFn = createSyncFn(path.resolve(dirname, "../http/make-request.js")); + let rawResponse = syncFn(req); + let response = JSON.parse(rawResponse); + if (response.status) { + return { + ...response, + body: response.body ? Buffer.from(response.body, "base64") : undefined, + }; + } + throw new UnexpectedError(response); +} diff --git a/packages/wasi-common/package.json b/packages/wasi-common/package.json index 3c8205f58..3ef06ea30 100644 --- a/packages/wasi-common/package.json +++ b/packages/wasi-common/package.json @@ -11,8 +11,11 @@ "index.js", "index.d.ts", "browser/", + "http/", "nodejs/", "types/" ], - "dependencies": {} + "dependencies": { + "synckit": "^0.8.5" + } } diff --git a/packages/wasi-common/types/wasi-http.d.ts b/packages/wasi-common/types/wasi-http.d.ts new file mode 100644 index 000000000..80416d7dd --- /dev/null +++ b/packages/wasi-common/types/wasi-http.d.ts @@ -0,0 +1,55 @@ +/** + * # Variants + * + * ## `"get"` + * + * ## `"post"` + * + * ## `"put"` + * + * ## `"delete"` + * + * ## `"patch"` + * + * ## `"head"` + * + * ## `"options"` + */ +export type Method = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head' | 'options'; +export type Uri = string; +export type Headers = [string, string][]; +export type Params = [string, string][]; +export type Body = Uint8Array; +export interface Request { + method: Method, + uri: Uri, + headers: Headers, + params: Params, + body?: Body, +} +export type HttpStatus = number; +export interface Response { + status: HttpStatus, + headers?: Headers, + body?: Body, +} +export type HttpError = HttpErrorInvalidUrl | HttpErrorTimeoutError | HttpErrorProtocolError | HttpErrorUnexpectedError; +export interface HttpErrorInvalidUrl { + tag: 'invalid-url', + val: string, +} +export interface HttpErrorTimeoutError { + tag: 'timeout-error', + val: string, +} +export interface HttpErrorProtocolError { + tag: 'protocol-error', + val: string, +} +export interface HttpErrorUnexpectedError { + tag: 'unexpected-error', + val: string, +} +export namespace WasiHttp { + export function send(req: Request): Response; +} From 9c0ae3288ec94a4275160178cdc4afa7eecb7d61 Mon Sep 17 00:00:00 2001 From: Eduardo de Moura Rodrigues <16357187+eduardomourar@users.noreply.github.com> Date: Sun, 19 Feb 2023 02:23:38 +0100 Subject: [PATCH 03/10] chore: rename package to preview2-shim Co-authored-by: Guy Bedford --- packages/wasi-common/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasi-common/package.json b/packages/wasi-common/package.json index 3ef06ea30..d49a62362 100644 --- a/packages/wasi-common/package.json +++ b/packages/wasi-common/package.json @@ -1,5 +1,5 @@ { - "name": "@bytecodealliance/wasi-common", + "name": "@bytecodealliance/preview2-shim", "version": "0.0.1", "description": "WASI implementation in JavaScript for the Browser and Node.js", "author": "Guy Bedford, Eduardo Rodrigues<16357187+eduardomourar@users.noreply.github.com>", From 6b31310fa9f1da0bc40d0477cfd410dc6c6be0f2 Mon Sep 17 00:00:00 2001 From: Eduardo de Moura Rodrigues <16357187+eduardomourar@users.noreply.github.com> Date: Sun, 19 Feb 2023 02:29:03 +0100 Subject: [PATCH 04/10] chore: define result shape with tag property Co-authored-by: Guy Bedford --- packages/wasi-common/types/wasi-exit.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasi-common/types/wasi-exit.d.ts b/packages/wasi-common/types/wasi-exit.d.ts index 5a0b32c23..7c9a74ba7 100644 --- a/packages/wasi-common/types/wasi-exit.d.ts +++ b/packages/wasi-common/types/wasi-exit.d.ts @@ -1,3 +1,3 @@ export namespace WasiExit { - export function exit(status: Result): void; + export function exit(status: { tag: 'err' | 'ok' }): void; } From 6a49cf835a4b050c4c97c87d333950c76969d1a5 Mon Sep 17 00:00:00 2001 From: Eduardo de Moura Rodrigues <16357187+eduardomourar@users.noreply.github.com> Date: Sun, 19 Feb 2023 02:33:16 +0100 Subject: [PATCH 05/10] chore: exit with code-specific in case of either error or success Co-authored-by: Guy Bedford --- packages/wasi-common/nodejs/exit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasi-common/nodejs/exit.js b/packages/wasi-common/nodejs/exit.js index a454c89bd..2fea22774 100644 --- a/packages/wasi-common/nodejs/exit.js +++ b/packages/wasi-common/nodejs/exit.js @@ -1,4 +1,4 @@ export function exit(status) { console.log(`[exit] Exit: ${JSON.stringify(status)}`); - process.exit(1); + process.exit(status.tag === 'err' ? 1 : 0); } From 1fe0c10438f7a2bff764535dd21e7df651d76050 Mon Sep 17 00:00:00 2001 From: Eduardo de Moura Rodrigues <16357187+eduardomourar@users.noreply.github.com> Date: Sun, 19 Feb 2023 02:42:22 +0100 Subject: [PATCH 06/10] chore: use more modern exports in package json Co-authored-by: Guy Bedford --- packages/wasi-common/package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/wasi-common/package.json b/packages/wasi-common/package.json index d49a62362..c20706ad8 100644 --- a/packages/wasi-common/package.json +++ b/packages/wasi-common/package.json @@ -4,8 +4,10 @@ "description": "WASI implementation in JavaScript for the Browser and Node.js", "author": "Guy Bedford, Eduardo Rodrigues<16357187+eduardomourar@users.noreply.github.com>", "type": "module", - "main": "./index.js", - "browser": "./browser/index.js", + "exports": { + "node": "./nodejs/index.js", + "default": "./browser/index.js" + } "types": "index.d.ts", "files": [ "index.js", From 1fe855c49f64f4c3d3a0416ff29f61fcc50c0645 Mon Sep 17 00:00:00 2001 From: Eduardo Rodrigues Date: Sun, 19 Feb 2023 02:46:17 +0100 Subject: [PATCH 07/10] chore: update package description --- packages/wasi-common/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wasi-common/package.json b/packages/wasi-common/package.json index c20706ad8..bf2c0061b 100644 --- a/packages/wasi-common/package.json +++ b/packages/wasi-common/package.json @@ -1,7 +1,7 @@ { "name": "@bytecodealliance/preview2-shim", "version": "0.0.1", - "description": "WASI implementation in JavaScript for the Browser and Node.js", + "description": "WASI Preview2 shim in JavaScript for the Browser and Node.js", "author": "Guy Bedford, Eduardo Rodrigues<16357187+eduardomourar@users.noreply.github.com>", "type": "module", "exports": { From 6f1a90099442b3347c27fc33c2138ddf33c25a9e Mon Sep 17 00:00:00 2001 From: Eduardo Rodrigues Date: Sun, 19 Feb 2023 02:47:07 +0100 Subject: [PATCH 08/10] chore: rename folder --- packages/{wasi-common => preview2-shim}/browser/clocks.js | 0 packages/{wasi-common => preview2-shim}/browser/default-clocks.js | 0 packages/{wasi-common => preview2-shim}/browser/exit.js | 0 packages/{wasi-common => preview2-shim}/browser/filesystem.js | 0 packages/{wasi-common => preview2-shim}/browser/http.js | 0 packages/{wasi-common => preview2-shim}/browser/index.js | 0 packages/{wasi-common => preview2-shim}/browser/io.js | 0 packages/{wasi-common => preview2-shim}/browser/logging.js | 0 packages/{wasi-common => preview2-shim}/browser/poll.js | 0 packages/{wasi-common => preview2-shim}/browser/random.js | 0 packages/{wasi-common => preview2-shim}/browser/stderr.js | 0 packages/{wasi-common => preview2-shim}/http/error.js | 0 packages/{wasi-common => preview2-shim}/http/make-request.js | 0 packages/{wasi-common => preview2-shim}/index.d.ts | 0 packages/{wasi-common => preview2-shim}/index.js | 0 packages/{wasi-common => preview2-shim}/nodejs/clocks.js | 0 packages/{wasi-common => preview2-shim}/nodejs/default-clocks.js | 0 packages/{wasi-common => preview2-shim}/nodejs/exit.js | 0 packages/{wasi-common => preview2-shim}/nodejs/filesystem.js | 0 packages/{wasi-common => preview2-shim}/nodejs/http.js | 0 packages/{wasi-common => preview2-shim}/nodejs/index.js | 0 packages/{wasi-common => preview2-shim}/nodejs/io.js | 0 packages/{wasi-common => preview2-shim}/nodejs/logging.js | 0 packages/{wasi-common => preview2-shim}/nodejs/poll.js | 0 packages/{wasi-common => preview2-shim}/nodejs/random.js | 0 packages/{wasi-common => preview2-shim}/nodejs/stderr.js | 0 packages/{wasi-common => preview2-shim}/package.json | 0 packages/{wasi-common => preview2-shim}/types/wasi-clocks.d.ts | 0 .../{wasi-common => preview2-shim}/types/wasi-default-clocks.d.ts | 0 packages/{wasi-common => preview2-shim}/types/wasi-exit.d.ts | 0 .../{wasi-common => preview2-shim}/types/wasi-filesystem.d.ts | 0 packages/{wasi-common => preview2-shim}/types/wasi-http.d.ts | 0 packages/{wasi-common => preview2-shim}/types/wasi-io.d.ts | 0 packages/{wasi-common => preview2-shim}/types/wasi-poll.d.ts | 0 packages/{wasi-common => preview2-shim}/types/wasi-random.d.ts | 0 packages/{wasi-common => preview2-shim}/types/wasi-stderr.d.ts | 0 36 files changed, 0 insertions(+), 0 deletions(-) rename packages/{wasi-common => preview2-shim}/browser/clocks.js (100%) rename packages/{wasi-common => preview2-shim}/browser/default-clocks.js (100%) rename packages/{wasi-common => preview2-shim}/browser/exit.js (100%) rename packages/{wasi-common => preview2-shim}/browser/filesystem.js (100%) rename packages/{wasi-common => preview2-shim}/browser/http.js (100%) rename packages/{wasi-common => preview2-shim}/browser/index.js (100%) rename packages/{wasi-common => preview2-shim}/browser/io.js (100%) rename packages/{wasi-common => preview2-shim}/browser/logging.js (100%) rename packages/{wasi-common => preview2-shim}/browser/poll.js (100%) rename packages/{wasi-common => preview2-shim}/browser/random.js (100%) rename packages/{wasi-common => preview2-shim}/browser/stderr.js (100%) rename packages/{wasi-common => preview2-shim}/http/error.js (100%) rename packages/{wasi-common => preview2-shim}/http/make-request.js (100%) rename packages/{wasi-common => preview2-shim}/index.d.ts (100%) rename packages/{wasi-common => preview2-shim}/index.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/clocks.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/default-clocks.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/exit.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/filesystem.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/http.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/index.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/io.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/logging.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/poll.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/random.js (100%) rename packages/{wasi-common => preview2-shim}/nodejs/stderr.js (100%) rename packages/{wasi-common => preview2-shim}/package.json (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-clocks.d.ts (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-default-clocks.d.ts (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-exit.d.ts (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-filesystem.d.ts (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-http.d.ts (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-io.d.ts (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-poll.d.ts (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-random.d.ts (100%) rename packages/{wasi-common => preview2-shim}/types/wasi-stderr.d.ts (100%) diff --git a/packages/wasi-common/browser/clocks.js b/packages/preview2-shim/browser/clocks.js similarity index 100% rename from packages/wasi-common/browser/clocks.js rename to packages/preview2-shim/browser/clocks.js diff --git a/packages/wasi-common/browser/default-clocks.js b/packages/preview2-shim/browser/default-clocks.js similarity index 100% rename from packages/wasi-common/browser/default-clocks.js rename to packages/preview2-shim/browser/default-clocks.js diff --git a/packages/wasi-common/browser/exit.js b/packages/preview2-shim/browser/exit.js similarity index 100% rename from packages/wasi-common/browser/exit.js rename to packages/preview2-shim/browser/exit.js diff --git a/packages/wasi-common/browser/filesystem.js b/packages/preview2-shim/browser/filesystem.js similarity index 100% rename from packages/wasi-common/browser/filesystem.js rename to packages/preview2-shim/browser/filesystem.js diff --git a/packages/wasi-common/browser/http.js b/packages/preview2-shim/browser/http.js similarity index 100% rename from packages/wasi-common/browser/http.js rename to packages/preview2-shim/browser/http.js diff --git a/packages/wasi-common/browser/index.js b/packages/preview2-shim/browser/index.js similarity index 100% rename from packages/wasi-common/browser/index.js rename to packages/preview2-shim/browser/index.js diff --git a/packages/wasi-common/browser/io.js b/packages/preview2-shim/browser/io.js similarity index 100% rename from packages/wasi-common/browser/io.js rename to packages/preview2-shim/browser/io.js diff --git a/packages/wasi-common/browser/logging.js b/packages/preview2-shim/browser/logging.js similarity index 100% rename from packages/wasi-common/browser/logging.js rename to packages/preview2-shim/browser/logging.js diff --git a/packages/wasi-common/browser/poll.js b/packages/preview2-shim/browser/poll.js similarity index 100% rename from packages/wasi-common/browser/poll.js rename to packages/preview2-shim/browser/poll.js diff --git a/packages/wasi-common/browser/random.js b/packages/preview2-shim/browser/random.js similarity index 100% rename from packages/wasi-common/browser/random.js rename to packages/preview2-shim/browser/random.js diff --git a/packages/wasi-common/browser/stderr.js b/packages/preview2-shim/browser/stderr.js similarity index 100% rename from packages/wasi-common/browser/stderr.js rename to packages/preview2-shim/browser/stderr.js diff --git a/packages/wasi-common/http/error.js b/packages/preview2-shim/http/error.js similarity index 100% rename from packages/wasi-common/http/error.js rename to packages/preview2-shim/http/error.js diff --git a/packages/wasi-common/http/make-request.js b/packages/preview2-shim/http/make-request.js similarity index 100% rename from packages/wasi-common/http/make-request.js rename to packages/preview2-shim/http/make-request.js diff --git a/packages/wasi-common/index.d.ts b/packages/preview2-shim/index.d.ts similarity index 100% rename from packages/wasi-common/index.d.ts rename to packages/preview2-shim/index.d.ts diff --git a/packages/wasi-common/index.js b/packages/preview2-shim/index.js similarity index 100% rename from packages/wasi-common/index.js rename to packages/preview2-shim/index.js diff --git a/packages/wasi-common/nodejs/clocks.js b/packages/preview2-shim/nodejs/clocks.js similarity index 100% rename from packages/wasi-common/nodejs/clocks.js rename to packages/preview2-shim/nodejs/clocks.js diff --git a/packages/wasi-common/nodejs/default-clocks.js b/packages/preview2-shim/nodejs/default-clocks.js similarity index 100% rename from packages/wasi-common/nodejs/default-clocks.js rename to packages/preview2-shim/nodejs/default-clocks.js diff --git a/packages/wasi-common/nodejs/exit.js b/packages/preview2-shim/nodejs/exit.js similarity index 100% rename from packages/wasi-common/nodejs/exit.js rename to packages/preview2-shim/nodejs/exit.js diff --git a/packages/wasi-common/nodejs/filesystem.js b/packages/preview2-shim/nodejs/filesystem.js similarity index 100% rename from packages/wasi-common/nodejs/filesystem.js rename to packages/preview2-shim/nodejs/filesystem.js diff --git a/packages/wasi-common/nodejs/http.js b/packages/preview2-shim/nodejs/http.js similarity index 100% rename from packages/wasi-common/nodejs/http.js rename to packages/preview2-shim/nodejs/http.js diff --git a/packages/wasi-common/nodejs/index.js b/packages/preview2-shim/nodejs/index.js similarity index 100% rename from packages/wasi-common/nodejs/index.js rename to packages/preview2-shim/nodejs/index.js diff --git a/packages/wasi-common/nodejs/io.js b/packages/preview2-shim/nodejs/io.js similarity index 100% rename from packages/wasi-common/nodejs/io.js rename to packages/preview2-shim/nodejs/io.js diff --git a/packages/wasi-common/nodejs/logging.js b/packages/preview2-shim/nodejs/logging.js similarity index 100% rename from packages/wasi-common/nodejs/logging.js rename to packages/preview2-shim/nodejs/logging.js diff --git a/packages/wasi-common/nodejs/poll.js b/packages/preview2-shim/nodejs/poll.js similarity index 100% rename from packages/wasi-common/nodejs/poll.js rename to packages/preview2-shim/nodejs/poll.js diff --git a/packages/wasi-common/nodejs/random.js b/packages/preview2-shim/nodejs/random.js similarity index 100% rename from packages/wasi-common/nodejs/random.js rename to packages/preview2-shim/nodejs/random.js diff --git a/packages/wasi-common/nodejs/stderr.js b/packages/preview2-shim/nodejs/stderr.js similarity index 100% rename from packages/wasi-common/nodejs/stderr.js rename to packages/preview2-shim/nodejs/stderr.js diff --git a/packages/wasi-common/package.json b/packages/preview2-shim/package.json similarity index 100% rename from packages/wasi-common/package.json rename to packages/preview2-shim/package.json diff --git a/packages/wasi-common/types/wasi-clocks.d.ts b/packages/preview2-shim/types/wasi-clocks.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-clocks.d.ts rename to packages/preview2-shim/types/wasi-clocks.d.ts diff --git a/packages/wasi-common/types/wasi-default-clocks.d.ts b/packages/preview2-shim/types/wasi-default-clocks.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-default-clocks.d.ts rename to packages/preview2-shim/types/wasi-default-clocks.d.ts diff --git a/packages/wasi-common/types/wasi-exit.d.ts b/packages/preview2-shim/types/wasi-exit.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-exit.d.ts rename to packages/preview2-shim/types/wasi-exit.d.ts diff --git a/packages/wasi-common/types/wasi-filesystem.d.ts b/packages/preview2-shim/types/wasi-filesystem.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-filesystem.d.ts rename to packages/preview2-shim/types/wasi-filesystem.d.ts diff --git a/packages/wasi-common/types/wasi-http.d.ts b/packages/preview2-shim/types/wasi-http.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-http.d.ts rename to packages/preview2-shim/types/wasi-http.d.ts diff --git a/packages/wasi-common/types/wasi-io.d.ts b/packages/preview2-shim/types/wasi-io.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-io.d.ts rename to packages/preview2-shim/types/wasi-io.d.ts diff --git a/packages/wasi-common/types/wasi-poll.d.ts b/packages/preview2-shim/types/wasi-poll.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-poll.d.ts rename to packages/preview2-shim/types/wasi-poll.d.ts diff --git a/packages/wasi-common/types/wasi-random.d.ts b/packages/preview2-shim/types/wasi-random.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-random.d.ts rename to packages/preview2-shim/types/wasi-random.d.ts diff --git a/packages/wasi-common/types/wasi-stderr.d.ts b/packages/preview2-shim/types/wasi-stderr.d.ts similarity index 100% rename from packages/wasi-common/types/wasi-stderr.d.ts rename to packages/preview2-shim/types/wasi-stderr.d.ts From 79382a98aea59298d02ec60852ca62150320b4c6 Mon Sep 17 00:00:00 2001 From: Eduardo Rodrigues Date: Sun, 19 Feb 2023 02:57:30 +0100 Subject: [PATCH 09/10] chore: allow setting the log level --- packages/preview2-shim/browser/logging.js | 11 ++++++++++- packages/preview2-shim/nodejs/logging.js | 9 +++++++++ packages/preview2-shim/package.json | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/preview2-shim/browser/logging.js b/packages/preview2-shim/browser/logging.js index 2cef561f8..2d3f0890a 100644 --- a/packages/preview2-shim/browser/logging.js +++ b/packages/preview2-shim/browser/logging.js @@ -1,3 +1,12 @@ +const levels = ["trace", "debug", "info", "warn", "error"]; + +let logLevel = levels.indexOf("warn"); + +export function setLevel(level) { + logLevel = levels.indexOf(level); +} + export function log(level, context, msg) { - console.log(`${level}: (${context}) ${msg}\n`); + if (logLevel > levels.indexOf(level)) return; + console[level](`(${context}) ${msg}\n`); } diff --git a/packages/preview2-shim/nodejs/logging.js b/packages/preview2-shim/nodejs/logging.js index 9b1860f60..b19b831f8 100644 --- a/packages/preview2-shim/nodejs/logging.js +++ b/packages/preview2-shim/nodejs/logging.js @@ -1,3 +1,12 @@ +const levels = ["trace", "debug", "info", "warn", "error"]; + +let logLevel = levels.indexOf("warn"); + +export function setLevel(level) { + logLevel = levels.indexOf(level); +} + export function log(level, context, msg) { + if (logLevel > levels.indexOf(level)) return; process.stdout.write(`${level}: (${context}) ${msg}\n`); } diff --git a/packages/preview2-shim/package.json b/packages/preview2-shim/package.json index bf2c0061b..ca43e21e5 100644 --- a/packages/preview2-shim/package.json +++ b/packages/preview2-shim/package.json @@ -7,7 +7,7 @@ "exports": { "node": "./nodejs/index.js", "default": "./browser/index.js" - } + }, "types": "index.d.ts", "files": [ "index.js", From 85353dfc0103029122aef2d58e95d67327eebd6c Mon Sep 17 00:00:00 2001 From: Eduardo Rodrigues Date: Sun, 19 Feb 2023 03:20:24 +0100 Subject: [PATCH 10/10] chore: define exit errors for browser --- packages/preview2-shim/browser/exit.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/preview2-shim/browser/exit.js b/packages/preview2-shim/browser/exit.js index ca87ae19c..5509bdc65 100644 --- a/packages/preview2-shim/browser/exit.js +++ b/packages/preview2-shim/browser/exit.js @@ -1,3 +1,21 @@ +class FailureExit extends Error { + code = 1; + constructor() { + super("failure-exit"); + } +} + +class SuccessfulExit extends Error { + code = 0; + constructor() { + super("successful-exit"); + } +} + export function exit(status) { console.log(`[exit] Exit: ${JSON.stringify(status)}`); + if (status.tag === "err") { + throw new FailureExit(); + } + throw new SuccessfulExit(); }