mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
WASM test analyzer (#4043)
* wasm * WASM test scanner * Update Makefile * Update Makefile * Configurable heap limit * slightly better error * Update js_parser.zig * Update path.test.js * Update node.mjs --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
// @ts-nocheck
|
||||
import { ByteBuffer } from "peechy/bb";
|
||||
import {
|
||||
Loader as BunLoader,
|
||||
TestKind,
|
||||
decodeGetTestsResponse,
|
||||
decodeScanResult,
|
||||
decodeTransformResponse,
|
||||
encodeGetTestsRequest,
|
||||
encodeScan,
|
||||
encodeTransform,
|
||||
Loader as BunLoader,
|
||||
type ScanResult,
|
||||
type TransformResponse,
|
||||
} from "./schema";
|
||||
@@ -15,9 +18,13 @@ export enum Loader {
|
||||
tsx = BunLoader.tsx,
|
||||
ts = BunLoader.ts,
|
||||
}
|
||||
|
||||
const testKindMap = {
|
||||
[TestKind.describe_fn]: "describe",
|
||||
[TestKind.test_fn]: "test",
|
||||
};
|
||||
const capturedErrors = [];
|
||||
let captureErrors = false;
|
||||
export type { ScanResult, TransformResponse };
|
||||
|
||||
function normalizeLoader(file_name: string, loader?: Loader): BunLoader {
|
||||
return (
|
||||
(loader
|
||||
@@ -82,12 +89,22 @@ var scratch2: Uint8Array;
|
||||
|
||||
const env = {
|
||||
console_log(slice: number) {
|
||||
const text = Bun._wasmPtrLenToString(slice);
|
||||
if (captureErrors) {
|
||||
capturedErrors.push(text);
|
||||
return;
|
||||
}
|
||||
//@ts-ignore
|
||||
console.log(Bun._wasmPtrLenToString(slice));
|
||||
console.log(text);
|
||||
},
|
||||
console_error(slice: number) {
|
||||
//@ts-ignore
|
||||
console.error(Bun._wasmPtrLenToString(slice));
|
||||
const text = Bun._wasmPtrLenToString(slice);
|
||||
if (captureErrors) {
|
||||
capturedErrors.push(text);
|
||||
return;
|
||||
}
|
||||
console.error(text);
|
||||
},
|
||||
console_warn(slice: number) {
|
||||
//@ts-ignore
|
||||
@@ -148,7 +165,6 @@ const env = {
|
||||
},
|
||||
emscripten_notify_memory_growth() {},
|
||||
};
|
||||
|
||||
export class Bun {
|
||||
private static has_initialized = false;
|
||||
// @ts-ignore-line
|
||||
@@ -179,63 +195,115 @@ export class Bun {
|
||||
return Bun._decoder.decode(region);
|
||||
}
|
||||
|
||||
static async init(url, fetch = globalThis.fetch) {
|
||||
// globalThis.sucraseTransform = sucraseTransform;
|
||||
static async init(url, heapSize = 64_000_000, fetch = globalThis.fetch) {
|
||||
scratch = new Uint8Array(8096);
|
||||
|
||||
if (Bun.has_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (globalThis?.WebAssembly?.instantiateStreaming) {
|
||||
Bun.wasm_source = await globalThis.WebAssembly.instantiateStreaming(
|
||||
fetch(url),
|
||||
{ env: env, wasi_snapshot_preview1: Wasi },
|
||||
);
|
||||
} else if (typeof window !== "undefined") {
|
||||
const resp = await fetch(url);
|
||||
Bun.wasm_source = await globalThis.WebAssembly.instantiate(
|
||||
await resp.arrayBuffer(),
|
||||
{
|
||||
if (typeof process === "undefined") {
|
||||
if (globalThis?.WebAssembly?.instantiateStreaming) {
|
||||
Bun.wasm_source = await globalThis.WebAssembly.instantiateStreaming(fetch(url), {
|
||||
env: env,
|
||||
wasi_snapshot_preview1: Wasi,
|
||||
},
|
||||
);
|
||||
// is it node?
|
||||
});
|
||||
} else if (typeof window !== "undefined") {
|
||||
const resp = await fetch(url);
|
||||
Bun.wasm_source = await globalThis.WebAssembly.instantiate(await resp.arrayBuffer(), {
|
||||
env: env,
|
||||
wasi_snapshot_preview1: Wasi,
|
||||
});
|
||||
// is it node?
|
||||
}
|
||||
} else {
|
||||
//@ts-ignore
|
||||
const fs = await import("fs");
|
||||
|
||||
Bun.wasm_source = await globalThis.WebAssembly.instantiate(
|
||||
fs.readFileSync(url),
|
||||
{
|
||||
env: env,
|
||||
wasi_snapshot_preview1: Wasi,
|
||||
},
|
||||
);
|
||||
Bun.wasm_source = await globalThis.WebAssembly.instantiate(fs.readFileSync(url), {
|
||||
env: env,
|
||||
wasi_snapshot_preview1: Wasi,
|
||||
});
|
||||
}
|
||||
|
||||
const res = Bun.wasm_exports.init();
|
||||
const res = Bun.wasm_exports.init(heapSize);
|
||||
|
||||
if (res < 0) {
|
||||
throw `[Bun] Failed to initialize WASM module: code ${res}`;
|
||||
throw new Error(`[Bun] Failed to initialize WASM module: code ${res}`);
|
||||
}
|
||||
|
||||
Bun.has_initialized = true;
|
||||
}
|
||||
|
||||
static transformSync(
|
||||
content: Uint8Array | string,
|
||||
file_name: string,
|
||||
loader?: Loader,
|
||||
): TransformResponse {
|
||||
if (!Bun.has_initialized) {
|
||||
throw "Please run await Bun.init(wasm_url) before using this.";
|
||||
static getTests(content: Uint8Array | string, filename = "my.test.tsx") {
|
||||
const bb = new ByteBuffer(scratch);
|
||||
bb.length = 0;
|
||||
bb.index = 0;
|
||||
const contents_buffer = content;
|
||||
|
||||
encodeGetTestsRequest(
|
||||
{
|
||||
contents: contents_buffer,
|
||||
path: filename,
|
||||
},
|
||||
bb,
|
||||
);
|
||||
|
||||
const data = bb.toUint8Array();
|
||||
|
||||
const input_ptr = Bun.wasm_exports.bun_malloc(data.length);
|
||||
var buffer = Bun._wasmPtrToSlice(input_ptr);
|
||||
buffer.set(data);
|
||||
captureErrors = true;
|
||||
try {
|
||||
var resp_ptr = Bun.wasm_exports.getTests(input_ptr);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
captureErrors = false;
|
||||
Bun.wasm_exports.bun_free(input_ptr);
|
||||
}
|
||||
|
||||
// if (process.env.NODE_ENV === "development") {
|
||||
// console.time("[Bun] Transform " + file_name);
|
||||
// }
|
||||
if (Number(resp_ptr) === 0) {
|
||||
if (capturedErrors.length) {
|
||||
const err = capturedErrors.slice();
|
||||
capturedErrors.length = 0;
|
||||
throw new Error(err.join("\n").trim());
|
||||
}
|
||||
|
||||
throw new Error("Failed to parse");
|
||||
}
|
||||
|
||||
if (capturedErrors.length) {
|
||||
Bun.wasm_exports.bun_free(resp_ptr);
|
||||
const err = capturedErrors.slice();
|
||||
capturedErrors.length = 0;
|
||||
throw new Error(err.join("\n").trim());
|
||||
}
|
||||
|
||||
var _bb = new ByteBuffer(Bun._wasmPtrToSlice(resp_ptr));
|
||||
|
||||
const response = decodeGetTestsResponse(_bb);
|
||||
var tests = new Array(response.tests.length);
|
||||
|
||||
for (var i = 0; i < response.tests.length; i++) {
|
||||
tests[i] = {
|
||||
name: new TextDecoder().decode(
|
||||
response.contents.subarray(
|
||||
response.tests[i].label.offset,
|
||||
response.tests[i].label.offset + response.tests[i].label.length,
|
||||
),
|
||||
),
|
||||
byteOffset: response.tests[i].byteOffset,
|
||||
kind: testKindMap[response.tests[i].kind],
|
||||
};
|
||||
}
|
||||
|
||||
Bun.wasm_exports.bun_free(resp_ptr);
|
||||
|
||||
return tests;
|
||||
}
|
||||
|
||||
static transformSync(content: Uint8Array | string, file_name: string, loader?: Loader): TransformResponse {
|
||||
const bb = new ByteBuffer(scratch);
|
||||
bb.length = 0;
|
||||
bb.index = 0;
|
||||
@@ -274,28 +342,14 @@ export class Bun {
|
||||
buffer.set(data);
|
||||
|
||||
const resp_ptr = Bun.wasm_exports.transform(input_ptr);
|
||||
|
||||
var _bb = new ByteBuffer(Bun._wasmPtrToSlice(resp_ptr));
|
||||
|
||||
const response = decodeTransformResponse(_bb);
|
||||
Bun.wasm_exports.bun_free(input_ptr);
|
||||
scratch = bb.data;
|
||||
return response;
|
||||
}
|
||||
|
||||
static scan(
|
||||
content: Uint8Array | string,
|
||||
file_name: string,
|
||||
loader?: Loader,
|
||||
): ScanResult {
|
||||
if (!Bun.has_initialized) {
|
||||
throw "Please run await Bun.init(wasm_url) before using this.";
|
||||
}
|
||||
|
||||
// if (process.env.NODE_ENV === "development") {
|
||||
// console.time("[Bun] Transform " + file_name);
|
||||
// }
|
||||
scratch.fill(0);
|
||||
static scan(content: Uint8Array | string, file_name: string, loader?: Loader): ScanResult {
|
||||
const bb = new ByteBuffer(scratch);
|
||||
bb.length = 0;
|
||||
bb.index = 0;
|
||||
@@ -337,15 +391,5 @@ export class Bun {
|
||||
export const transformSync = Bun.transformSync;
|
||||
export const scan = Bun.scan;
|
||||
export const init = Bun.init;
|
||||
export const getTests = Bun.getTests;
|
||||
export default Bun;
|
||||
|
||||
if ("window" in globalThis && !("Bun" in globalThis)) {
|
||||
// @ts-ignore-line
|
||||
globalThis.Bun = Bun;
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
//@ts-ignore
|
||||
Bun.env = env;
|
||||
}
|
||||
|
||||
@@ -1,28 +1,7 @@
|
||||
// This is not released yet because there are some memory bugs with the WASM build
|
||||
// It causes syntax errors which don't make any sense
|
||||
// Most likely, this is an issue with some code expecting 64 bit pointers
|
||||
// That's also why this test just prints instead of using a test runner
|
||||
import * as Bun from "../index.mjs";
|
||||
import { readFileSync } from "fs";
|
||||
import { init, getTests } from "../index.mjs";
|
||||
|
||||
await Bun.init(new URL("../bun.wasm", import.meta.url));
|
||||
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 buf =
|
||||
(process.argv.length > 2 ? process.argv.at(-1) : "") ||
|
||||
new TextEncoder().encode(`
|
||||
|
||||
export function hi() {
|
||||
return <div>Hey</div>;
|
||||
}
|
||||
|
||||
`);
|
||||
const result = Bun.transformSync(buf, "hi.jsx", "jsx");
|
||||
if (result.errors?.length) {
|
||||
console.log(JSON.stringify(result.errors, null, 2));
|
||||
throw new Error("Failed");
|
||||
}
|
||||
|
||||
if (!result.files.length) {
|
||||
throw new Error("unexpectedly empty");
|
||||
}
|
||||
|
||||
process.stdout.write(result.files[0].data);
|
||||
console.log(getTests(buf));
|
||||
|
||||
Reference in New Issue
Block a user