diff options
author | 2023-08-11 22:20:21 -0300 | |
---|---|---|
committer | 2023-08-11 18:20:21 -0700 | |
commit | 117cee5ca5c36f78ae75a0dee3178620bba73968 (patch) | |
tree | e295c758d3873b8ff904cd705235cd0d51648391 | |
parent | 43ebffedcdc47da9b9f89a07c9a5d21a7e303722 (diff) | |
download | bun-117cee5ca5c36f78ae75a0dee3178620bba73968.tar.gz bun-117cee5ca5c36f78ae75a0dee3178620bba73968.tar.zst bun-117cee5ca5c36f78ae75a0dee3178620bba73968.zip |
`bun-wasm` fixes & improvements (#4126)
* automate Bun.version & revision polyfills
* polyfill Bun.gc
* bun:jsc module initial polyfills
* fixes & improvements to bun-wasm
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | packages/bun-polyfills/package.json | 3 | ||||
-rw-r--r-- | packages/bun-polyfills/src/modules/bun.ts | 12 | ||||
-rw-r--r-- | packages/bun-polyfills/src/modules/jsc.ts | 111 | ||||
-rw-r--r-- | packages/bun-polyfills/src/repl.ts | 4 | ||||
-rw-r--r-- | packages/bun-polyfills/src/types/sync.d.ts | 15 | ||||
-rw-r--r-- | packages/bun-polyfills/src/utils/errors.ts | 9 | ||||
-rw-r--r-- | packages/bun-polyfills/tools/updateversions.ts | 41 | ||||
-rwxr-xr-x | packages/bun-wasm/bun.lockb | bin | 7189 -> 8473 bytes | |||
-rw-r--r-- | packages/bun-wasm/index.ts | 71 | ||||
-rw-r--r-- | packages/bun-wasm/package.json | 7 | ||||
-rw-r--r-- | packages/bun-wasm/test/node.mjs | 7 | ||||
-rw-r--r-- | packages/bun-wasm/tsconfig.json | 4 |
14 files changed, 252 insertions, 44 deletions
diff --git a/.gitignore b/.gitignore index f5823c788..5d4da2f88 100644 --- a/.gitignore +++ b/.gitignore @@ -96,6 +96,8 @@ packages/bun-wasm/*.cjs packages/bun-wasm/*.map packages/bun-wasm/*.js packages/bun-wasm/*.d.ts +packages/bun-wasm/*.d.cts +packages/bun-wasm/*.d.mts *.bc src/fallback.version @@ -705,7 +705,7 @@ dev-build-obj-wasm: dev-wasm: dev-build-obj-wasm emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \ -g2 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \ - $(BUN_DEPS_DIR)/libmimalloc.a.wasm \ + $(BUN_DEPS_DIR)/$(MIMALLOC_FILE).wasm \ packages/debug-bun-freestanding-wasm32/bun-wasm.o --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \ -o packages/debug-bun-freestanding-wasm32/bun-wasm.wasm cp packages/debug-bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm @@ -715,7 +715,7 @@ build-obj-wasm: $(ZIG) build bun-wasm -Doptimize=ReleaseFast -Dtarget=wasm32-freestanding emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \ -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \ - $(BUN_DEPS_DIR)/libmimalloc.a.wasm \ + $(BUN_DEPS_DIR)/$(MIMALLOC_FILE).wasm \ packages/bun-freestanding-wasm32/bun-wasm.o $(OPTIMIZATION_LEVEL) --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \ -o packages/bun-freestanding-wasm32/bun-wasm.wasm cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm @@ -725,18 +725,20 @@ build-obj-wasm-small: $(ZIG) build bun-wasm -Doptimize=ReleaseFast -Dtarget=wasm32-freestanding emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init', '_getTests']" \ -Oz -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \ - $(BUN_DEPS_DIR)/libmimalloc.a.wasm \ + $(BUN_DEPS_DIR)/$(MIMALLOC_FILE).wasm \ packages/bun-freestanding-wasm32/bun-wasm.o -Oz --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \ -o packages/bun-freestanding-wasm32/bun-wasm.wasm cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm .PHONY: wasm wasm: api mimalloc-wasm build-obj-wasm-small - @rm -rf packages/bun-wasm/*.{d.ts,js,wasm,cjs,mjs,tsbuildinfo} + @rm -rf packages/bun-wasm/*.{d.ts,d.cts,d.mts,js,wasm,cjs,mjs,tsbuildinfo} @cp packages/bun-freestanding-wasm32/bun-wasm.wasm packages/bun-wasm/bun.wasm @cp src/api/schema.d.ts packages/bun-wasm/schema.d.ts @cp src/api/schema.js packages/bun-wasm/schema.js @cd packages/bun-wasm && $(NPM_CLIENT) run tsc -- -p . + @cp packages/bun-wasm/index.d.ts packages/bun-wasm/index.d.cts + @mv packages/bun-wasm/index.d.ts packages/bun-wasm/index.d.mts @bun build --sourcemap=external --external=fs --outdir=packages/bun-wasm --target=browser --minify ./packages/bun-wasm/index.ts @mv packages/bun-wasm/index.js packages/bun-wasm/index.mjs @mv packages/bun-wasm/index.js.map packages/bun-wasm/index.mjs.map diff --git a/packages/bun-polyfills/package.json b/packages/bun-polyfills/package.json index e1852eddc..f08452c3d 100644 --- a/packages/bun-polyfills/package.json +++ b/packages/bun-polyfills/package.json @@ -14,7 +14,8 @@ "scripts": { "node": "node --enable-source-maps --import ./dist/src/repl.js", "clean": "rm -rf dist", - "build": "bun run clean && bunx tsc && bunx copyfiles \"./**/*.wasm\" dist", + "preprocess": "bun tools/updateversions.ts", + "build": "bun run clean && bun run preprocess && bunx tsc && bunx copyfiles \"./**/*.wasm\" dist", "build/wasm": "bun run build/zighash", "build/zighash": "cd lib/zighash && bun run build && cd ../.." }, diff --git a/packages/bun-polyfills/src/modules/bun.ts b/packages/bun-polyfills/src/modules/bun.ts index ce0f6f6be..432daea95 100644 --- a/packages/bun-polyfills/src/modules/bun.ts +++ b/packages/bun-polyfills/src/modules/bun.ts @@ -30,8 +30,16 @@ import openEditor from 'open-editor'; export const main = path.resolve(process.cwd(), process.argv[1] ?? 'repl') satisfies typeof Bun.main;
-export const version = '0.7.1' satisfies typeof Bun.version; // TODO: This can probably be fetched from somewhere in the repo
-export const revision = '0'.repeat(39) + '1' satisfies typeof Bun.revision;
+//? These are automatically updated on build by tools/updateversions.ts, do not edit manually.
+export const version = '0.7.4' satisfies typeof Bun.version;
+export const revision = '7088d7e182635a58a50860302da0b1abc42c7ce7' satisfies typeof Bun.revision;
+
+export const gc = (globalThis.gc ? (() => (globalThis.gc!(), process.memoryUsage().heapUsed)) : (() => {
+ const err = new Error('[bun-polyfills] Garbage collection polyfills are only available when Node.js is ran with the --expose-gc flag.');
+ Error.captureStackTrace(err, gc);
+ throw err;
+})) satisfies typeof Bun.gc;
+
//getter(bun, 'cwd', proc.cwd); //! Can't named export a getter
export const origin = '' satisfies typeof Bun.origin;
// @ts-expect-error ---
diff --git a/packages/bun-polyfills/src/modules/jsc.ts b/packages/bun-polyfills/src/modules/jsc.ts new file mode 100644 index 000000000..45062d339 --- /dev/null +++ b/packages/bun-polyfills/src/modules/jsc.ts @@ -0,0 +1,111 @@ +import type jsc from 'bun:jsc'; +import v8 from 'node:v8'; +//import { setRandomSeed, getRandomSeed } from './mathrandom.js'; +import { NotImplementedError, getCallSites } from '../utils/errors.js'; +import { gc } from './bun.js'; + +const STUB = () => void 0; + +function jscSerialize(value: any, options?: { binaryType: 'nodebuffer'; }): Buffer; +function jscSerialize(value: any, options?: { binaryType?: 'arraybuffer'; }): SharedArrayBuffer; +function jscSerialize(value: any, options?: { binaryType?: string }): Buffer | SharedArrayBuffer { + const serialized = v8.serialize(value); + if (options?.binaryType === 'nodebuffer') return serialized; + else return new SharedArrayBuffer(serialized.byteLength); +} +// TODO: Investigate ways of making these the actual JSC serialization format (probably Bun WASM) +// TODO: whilst this works for common use-cases like Node <-> Node it still does not make it +// TODO: possible for Node <-> Bun transfers of this kind of data, which might be interesting to have. +export const serialize = jscSerialize satisfies typeof jsc.serialize; +export const deserialize = (value => { + if (value instanceof ArrayBuffer || value instanceof SharedArrayBuffer) return v8.deserialize(Buffer.from(value)); + else return v8.deserialize(value); +}) satisfies typeof jsc.deserialize; + +export const setTimeZone = ((timeZone: string) => { + const resolvedTZ = Intl.DateTimeFormat(undefined, { timeZone }).resolvedOptions().timeZone; + return process.env.TZ = resolvedTZ; +}) satisfies typeof jsc.setTimeZone; + +export const callerSourceOrigin = (() => { + const callsites: NodeJS.CallSite[] = getCallSites(2); + // This may be inaccurate with async code. Needs more testing. + let lastSeenURL = ''; + for (const callsite of callsites) { + const sourceURL = callsite.getScriptNameOrSourceURL(); + if (sourceURL.startsWith('file://')) lastSeenURL = sourceURL; + } + return lastSeenURL; +}) satisfies typeof jsc.callerSourceOrigin; + +// TODO: Like with jsc.serialize/deserialize, these may be possible with Bun WASM. +export const jscDescribe = (() => { throw new NotImplementedError('jsc.jscDescribe', STUB); }) satisfies typeof jsc.jscDescribe; +export const jscDescribeArray = (() => { throw new NotImplementedError('jsc.jscDescribeArray', STUB); }) satisfies typeof jsc.jscDescribeArray; +// These are no longer documented but still exist. +export const describe = jscDescribe; +export const describeArray = jscDescribeArray; + +// Node.js only provides a singular non-configurable global GC function, so we have to make do with that. +export const edenGC = gc satisfies typeof jsc.edenGC; +export const fullGC = gc satisfies typeof jsc.fullGC; +export const gcAndSweep = gc satisfies typeof jsc.gcAndSweep; + +export const drainMicrotasks = STUB satisfies typeof jsc.drainMicrotasks; // no-op +export const releaseWeakRefs = STUB satisfies typeof jsc.releaseWeakRefs; // no-op +export const startSamplingProfiler = STUB satisfies typeof jsc.startSamplingProfiler; // no-op +//! likely broken but needs more testing +export const startRemoteDebugger = STUB satisfies typeof jsc.startRemoteDebugger; // no-op + +//! this is a really poor polyfill but it's better than nothing +export const getProtectedObjects = (() => { return [globalThis]; }) satisfies typeof jsc.getProtectedObjects; + +export const getRandomSeed = 0; // TODO +export const setRandomSeed = 0; // TODO + +export const heapSize = (() => { return v8.getHeapStatistics().used_heap_size; }) satisfies typeof jsc.heapSize; +export const heapStats = (() => { + const stats = v8.getHeapStatistics(); + return { + heapSize: stats.used_heap_size, + heapCapacity: stats.total_available_size, + extraMemorySize: stats.external_memory ?? 0, + objectCount: 1, // TODO: how to get this in node? + protectedObjectCount: getProtectedObjects().length, + globalObjectCount: 2, // TODO: this one is probably fine hardcoded but is there a way to get this in node? + protectedGlobalObjectCount: 1, // TODO: ^ + objectTypeCounts: {}, //! can't really throw an error here, so just return an empty object (TODO: how to get this in node?) + protectedObjectTypeCounts: {} //! can't really throw an error here, so just return an empty object (TODO: how to get this in node?) + }; +}) satisfies typeof jsc.heapStats; + +//! doubtful anyone relies on the return of this for anything besides debugging +export const isRope = (() => false) satisfies typeof jsc.isRope; + +export const memoryUsage = (() => { + const stats = v8.getHeapStatistics(); + const resUse = process.resourceUsage(); + return { + current: stats.malloced_memory, + peak: stats.peak_malloced_memory, + currentCommit: stats.malloced_memory, + peakCommit: stats.malloced_memory, + pageFaults: resUse.minorPageFault + resUse.majorPageFault + }; +}) satisfies typeof jsc.memoryUsage; + +//! these are likely broken, seemingly always returning undefined which does not match the documented return types +export const noFTL = (() => { return void 0 as unknown as Function; }) satisfies typeof jsc.noFTL; +export const noOSRExitFuzzing = (() => { return void 0 as unknown as Function; }) satisfies typeof jsc.noOSRExitFuzzing; +//! likely broken, seems to always returns zero +export const totalCompileTime = (() => 0) satisfies typeof jsc.totalCompileTime; +//! likely broken, seem to always returns 0 if any arguments are passed, undefined otherwise +export const numberOfDFGCompiles = ((...args) => args.length ? 0 : void 0 as unknown as number) satisfies typeof jsc.numberOfDFGCompiles; +export const reoptimizationRetryCount = ((...args) => args.length ? 0 : void 0 as unknown as number) satisfies typeof jsc.reoptimizationRetryCount; + +//! The following are very likely impossible to ever polyfill. +export const profile = (() => { + throw new NotImplementedError('jsc.profile is not polyfillable', STUB, true); +}) satisfies typeof jsc.profile; +export const optimizeNextInvocation = (() => { + throw new NotImplementedError('jsc.optimizeNextInvocation is not polyfillable', STUB, true); +}) satisfies typeof jsc.optimizeNextInvocation; diff --git a/packages/bun-polyfills/src/repl.ts b/packages/bun-polyfills/src/repl.ts index 5cf673701..030e479b0 100644 --- a/packages/bun-polyfills/src/repl.ts +++ b/packages/bun-polyfills/src/repl.ts @@ -1,4 +1,5 @@ import bun from './index.js'; +import * as jsc from './modules/jsc.js'; // This file serves two purposes: // 1. It is the entry point for using the Bun global in the REPL. (--import this file) @@ -12,7 +13,6 @@ globalThis.Bun = bun as typeof bun & { deepMatch: typeof import('bun').deepMatch; build: typeof import('bun').build; mmap: typeof import('bun').mmap; - gc: typeof import('bun').gc; connect: typeof import('bun').connect; listen: typeof import('bun').listen; Transpiler: typeof import('bun').Transpiler; @@ -27,3 +27,5 @@ globalThis.Bun = bun as typeof bun & { stderr: typeof import('bun').stderr; stdin: typeof import('bun').stdin; }; + +Reflect.set(globalThis, 'jsc', jsc); diff --git a/packages/bun-polyfills/src/types/sync.d.ts b/packages/bun-polyfills/src/types/sync.d.ts index 87e6794e0..11ed63a17 100644 --- a/packages/bun-polyfills/src/types/sync.d.ts +++ b/packages/bun-polyfills/src/types/sync.d.ts @@ -12,4 +12,19 @@ declare module 'stream/web' { declare global { var performance: typeof import('perf_hooks').performance; + + // TODO: These should be contributed to @types/node upstream + namespace NodeJS { + interface CallSite { + getScriptNameOrSourceURL(): string; + getEnclosingColumnNumber(): number; + getEnclosingLineNumber(): number; + getPosition(): number; + getPromiseIndex(): number; + getScriptHash(): string; + isAsync(): boolean; + isPromiseAll(): boolean; + toString(): string; + } + } } diff --git a/packages/bun-polyfills/src/utils/errors.ts b/packages/bun-polyfills/src/utils/errors.ts index cc82efdf0..35b967436 100644 --- a/packages/bun-polyfills/src/utils/errors.ts +++ b/packages/bun-polyfills/src/utils/errors.ts @@ -1,6 +1,15 @@ type PosixErrNo = MapKeysType<ReturnType<typeof getPosixSystemErrorMap>>;
type Win32ErrNo = MapKeysType<ReturnType<typeof getWin32SystemErrorMap>>;
+export function getCallSites(sliceOff = 1) {
+ const originalPST = Error.prepareStackTrace;
+ Error.prepareStackTrace = (error, stack) => stack;
+ const { stack } = new Error();
+ if (stack?.constructor.name !== 'Array') throw new Error('Failed to acquire structured JS stack trace');
+ Error.prepareStackTrace = originalPST;
+ return (stack as unknown as NodeJS.CallSite[]).slice(sliceOff);
+}
+
export function getPosixSystemErrorMap() {
return new Map([
[ -7, [ 'E2BIG', 'argument list too long' ] ],
diff --git a/packages/bun-polyfills/tools/updateversions.ts b/packages/bun-polyfills/tools/updateversions.ts new file mode 100644 index 000000000..bf838ac55 --- /dev/null +++ b/packages/bun-polyfills/tools/updateversions.ts @@ -0,0 +1,41 @@ +import path from 'path'; + +const abort = (...msg: string[]): never => (console.error(...msg), process.exit(1)); + +const makefilePath = path.resolve(import.meta.dir, '../../../Makefile'); +const makefile = Bun.file(makefilePath); +if (!await makefile.exists()) abort('Makefile not found at', makefilePath); + +const makefileContent = await makefile.text(); +const matched = makefileContent.match(/^BUN_BASE_VERSION\s*=\s*(\d+.\d+)/m); +if (!matched) abort('Could not find BUN_BASE_VERSION in Makefile'); + +const buildidPath = path.resolve(import.meta.dir, '../../../src/build-id'); +const buildid = Bun.file(buildidPath); +if (!await buildid.exists()) abort('Build ID file not found at', buildidPath); + +const [, BUN_BASE_VERSION] = matched!; +const BUN_VERSION = `${BUN_BASE_VERSION}.${await buildid.text()}`.trim(); + +const bunTsPath = path.resolve(import.meta.dir, '../src/modules/bun.ts'); +const bunTs = Bun.file(bunTsPath); +if (!await bunTs.exists()) abort('bun.ts source file not found at', bunTsPath); + +const bunTsContent = await bunTs.text(); +const bunTsContentNew = bunTsContent.replace( + /^export const version = '.+' satisfies typeof Bun.version;$/m, + `export const version = '${BUN_VERSION}' satisfies typeof Bun.version;` +); +if (bunTsContentNew !== bunTsContent) console.info('Updated Bun.version polyfill to', BUN_VERSION); + +const git = Bun.spawnSync({ cmd: ['git', 'rev-parse', 'HEAD'] }); +if (!git.success) abort('Could not get git HEAD commit hash'); +const BUN_REVISION = git.stdout.toString('utf8').trim(); + +const bunTsContentNewer = bunTsContentNew.replace( + /^export const revision = '.+' satisfies typeof Bun.revision;$/m, + `export const revision = '${BUN_REVISION}' satisfies typeof Bun.revision;` +); +if (bunTsContentNewer !== bunTsContentNew) console.info('Updated Bun.revision polyfill to', BUN_REVISION); + +Bun.write(bunTs, bunTsContentNewer); diff --git a/packages/bun-wasm/bun.lockb b/packages/bun-wasm/bun.lockb Binary files differindex fdaf01b1f..d77107312 100755 --- a/packages/bun-wasm/bun.lockb +++ b/packages/bun-wasm/bun.lockb diff --git a/packages/bun-wasm/index.ts b/packages/bun-wasm/index.ts index 10a7b3aa4..72eed5220 100644 --- a/packages/bun-wasm/index.ts +++ b/packages/bun-wasm/index.ts @@ -1,4 +1,3 @@ -// @ts-nocheck import { ByteBuffer } from "peechy/bb"; import { Loader as BunLoader, @@ -12,20 +11,28 @@ import { type ScanResult, type TransformResponse, } from "./schema"; + export enum Loader { jsx = BunLoader.jsx, js = BunLoader.js, tsx = BunLoader.tsx, ts = BunLoader.ts, } +export interface TestReference { + name: string, + byteOffset: number, + kind: 'test' | 'describe', +} +export type { ScanResult, TransformResponse }; + const testKindMap = { [TestKind.describe_fn]: "describe", [TestKind.test_fn]: "test", }; -const capturedErrors = []; +const capturedErrors: string[] = []; let captureErrors = false; -export type { ScanResult, TransformResponse }; -function normalizeLoader(file_name: string, loader?: Loader): BunLoader { + +function normalizeLoader(file_name: string, loader?: keyof typeof Loader): BunLoader { return ( (loader ? { @@ -46,11 +53,12 @@ function normalizeLoader(file_name: string, loader?: Loader): BunLoader { } interface WebAssemblyModule { - init(): number; + init(heapSize: number): number; transform(a: number): number; bun_malloc(a: number): number; bun_free(a: number): number; scan(a: number): number; + getTests(a: number): number; } const ptr_converter = new ArrayBuffer(16); @@ -58,28 +66,28 @@ const ptr_float = new BigUint64Array(ptr_converter); const slice = new Uint32Array(ptr_converter); const Wasi = { - clock_time_get(clk_id, tp) { + clock_time_get(clk_id: unknown, tp: unknown) { return Date.now(); }, environ_sizes_get() { debugger; return 0; }, - environ_get(__environ, environ_buf) { + environ_get(__environ: unknown, environ_buf: unknown) { debugger; return 0; }, - fd_close(fd) { + fd_close(fd: number) { debugger; return 0; }, proc_exit() {}, - fd_seek(fd, offset_bigint, whence, newOffset) { + fd_seek(fd: number, offset_bigint: bigint, whence: unknown, newOffset: unknown) { debugger; }, - fd_write(fd, iov, iovcnt, pnum) { + fd_write(fd: unknown, iov: unknown, iovcnt: unknown, pnum: unknown) { debugger; }, }; @@ -89,16 +97,16 @@ var scratch2: Uint8Array; const env = { console_log(slice: number) { + // @ts-expect-error const text = Bun._wasmPtrLenToString(slice); if (captureErrors) { capturedErrors.push(text); return; } - //@ts-ignore console.log(text); }, console_error(slice: number) { - //@ts-ignore + // @ts-expect-error const text = Bun._wasmPtrLenToString(slice); if (captureErrors) { capturedErrors.push(text); @@ -107,19 +115,17 @@ const env = { console.error(text); }, console_warn(slice: number) { - //@ts-ignore + // @ts-expect-error console.warn(Bun._wasmPtrLenToString(slice)); }, console_info(slice: number) { - //@ts-ignore + // @ts-expect-error console.info(Bun._wasmPtrLenToString(slice)); }, - // @ts-ignore-line __indirect_function_table: new WebAssembly.Table({ initial: 0, element: "anyfunc", }), - // @ts-ignore-line __stack_pointer: new WebAssembly.Global({ mutable: true, value: "i32", @@ -131,11 +137,11 @@ const env = { return one % two; }, memset(ptr: number, value: number, len: number) { - //@ts-ignore + // @ts-expect-error Bun.memory_array.fill(value, ptr, ptr + len); }, memcpy(ptr: number, value: number, len: number) { - //@ts-ignore + // @ts-expect-error Bun.memory_array.copyWithin(ptr, value, value + len); }, // These functions convert a to an unsigned long long, rounding toward zero. Negative values all become zero. @@ -167,14 +173,13 @@ const env = { }; export class Bun { private static has_initialized = false; - // @ts-ignore-line - private static wasm_source: WebAssembly.WebAssemblyInstantiatedSource = null; + private static wasm_source: WebAssembly.WebAssemblyInstantiatedSource; private static get wasm_exports(): WebAssemblyModule { - return Bun.wasm_source.instance.exports as any; + return Bun.wasm_source.instance.exports as unknown as WebAssemblyModule; } - // @ts-ignore-line + private static get memory(): WebAssembly.Memory { - return Bun.wasm_source.instance.exports.memory as any; + return Bun.wasm_source.instance.exports.memory as WebAssembly.Memory; } private static memory_array: Uint8Array; @@ -195,7 +200,8 @@ export class Bun { return Bun._decoder.decode(region); } - static async init(url, heapSize = 64_000_000, fetch = globalThis.fetch) { + static async init(url?: URL | string | null, heapSize = 64_000_000, fetch = globalThis.fetch) { + url ??= new URL("./bun.wasm", import.meta.url); scratch = new Uint8Array(8096); if (Bun.has_initialized) { @@ -216,9 +222,12 @@ export class Bun { // is it node? } } else { - //@ts-ignore const fs = await import("fs"); + if (typeof url === 'string' && url.startsWith('file://')) { + url = new URL(url); // fs.readFileSync cannot consume URL strings, only URL objects + } + Bun.wasm_source = await globalThis.WebAssembly.instantiate(fs.readFileSync(url), { env: env, wasi_snapshot_preview1: Wasi, @@ -234,7 +243,7 @@ export class Bun { Bun.has_initialized = true; } - static getTests(content: Uint8Array | string, filename = "my.test.tsx") { + static getTests(content: Uint8Array, filename = "my.test.tsx") { const bb = new ByteBuffer(scratch); bb.length = 0; bb.index = 0; @@ -283,7 +292,7 @@ export class Bun { var _bb = new ByteBuffer(Bun._wasmPtrToSlice(resp_ptr)); const response = decodeGetTestsResponse(_bb); - var tests = new Array(response.tests.length); + var tests: TestReference[] = new Array(response.tests.length); for (var i = 0; i < response.tests.length; i++) { tests[i] = { @@ -294,7 +303,7 @@ export class Bun { ), ), byteOffset: response.tests[i].byteOffset, - kind: testKindMap[response.tests[i].kind], + kind: testKindMap[response.tests[i].kind] as 'test' | 'describe', }; } @@ -303,7 +312,7 @@ export class Bun { return tests; } - static transformSync(content: Uint8Array | string, file_name: string, loader?: Loader): TransformResponse { + static transformSync(content: Uint8Array | string, file_name: string, loader?: keyof typeof Loader): TransformResponse { const bb = new ByteBuffer(scratch); bb.length = 0; bb.index = 0; @@ -330,7 +339,6 @@ export class Bun { { contents: contents_buffer, path: file_name, - // @ts-ignore loader: normalizeLoader(file_name, loader), }, bb, @@ -349,7 +357,7 @@ export class Bun { return response; } - static scan(content: Uint8Array | string, file_name: string, loader?: Loader): ScanResult { + static scan(content: Uint8Array | string, file_name: string, loader?: keyof typeof Loader): ScanResult { const bb = new ByteBuffer(scratch); bb.length = 0; bb.index = 0; @@ -368,7 +376,6 @@ export class Bun { { contents: contents_buffer, path: file_name, - // @ts-ignore loader: normalizeLoader(file_name, loader), }, bb, diff --git a/packages/bun-wasm/package.json b/packages/bun-wasm/package.json index 5f3234e40..54eb646fa 100644 --- a/packages/bun-wasm/package.json +++ b/packages/bun-wasm/package.json @@ -1,7 +1,12 @@ { "name": "bun-wasm", "version": "0.0.79", + "scripts": { + "build": "cd ../.. && make wasm", + "dev": "cd ../.. && make dev-wasm" + }, "devDependencies": { + "@types/node": "^20.4.10", "peechy": "0.4.32", "typescript": "latest" }, @@ -16,7 +21,7 @@ "schema.js" ], "type": "module", - "types": "index.d.ts", + "types": "index.d.mts", "exports": { ".": { "import": "./index.mjs", diff --git a/packages/bun-wasm/test/node.mjs b/packages/bun-wasm/test/node.mjs index 2699a1dad..9c2f503d4 100644 --- a/packages/bun-wasm/test/node.mjs +++ b/packages/bun-wasm/test/node.mjs @@ -1,7 +1,10 @@ import { readFileSync } from "fs"; import { init, getTests } from "../index.mjs"; -const buf = (process.argv.length > 2 ? readFileSync(process.argv.at(-1)) : "") || readFileSync(import.meta.url); -await init(new URL("../bun.wasm", import.meta.url)); +const filePath = process.argv[2]; +if (!filePath) throw new Error("Usage: node node.mjs <file>"); + +const buf = readFileSync(filePath); +await init(); console.log(getTests(buf)); diff --git a/packages/bun-wasm/tsconfig.json b/packages/bun-wasm/tsconfig.json index cb966c684..9b5b9eb0c 100644 --- a/packages/bun-wasm/tsconfig.json +++ b/packages/bun-wasm/tsconfig.json @@ -8,8 +8,10 @@ "isolatedModules": false, "skipLibCheck": true, "emitDeclarationOnly": true, + "strict": true, "outDir": ".", - "baseUrl": "." + "baseUrl": ".", + "types": ["node"] }, "include": [ "./node_modules/peechy", |