diff options
author | 2021-05-07 20:19:32 -0700 | |
---|---|---|
committer | 2021-05-07 20:19:32 -0700 | |
commit | 12615602144288b3123f352e5d586714bc01b4dc (patch) | |
tree | 5278fee0e74b7b123c37940d53dd37078a296c19 | |
parent | caa747ba717e28791089d2db22ee9300f11b4d25 (diff) | |
download | bun-12615602144288b3123f352e5d586714bc01b4dc.tar.gz bun-12615602144288b3123f352e5d586714bc01b4dc.tar.zst bun-12615602144288b3123f352e5d586714bc01b4dc.zip |
This _sort of_ works
Former-commit-id: 8c4917fe60ad049789aea96018363997e9f20e8f
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | build.zig | 76 | ||||
-rw-r--r-- | src/api/demo/lib/api.ts | 141 | ||||
-rw-r--r-- | src/api/demo/package.json | 2 | ||||
-rw-r--r-- | src/api/demo/pnpm-lock.yaml | 8 | ||||
-rw-r--r-- | src/api/schema.js | 401 | ||||
-rw-r--r-- | src/api/schema.zig | 1 | ||||
-rw-r--r-- | src/global.zig | 35 | ||||
-rw-r--r-- | src/js_printer.zig | 11 | ||||
-rw-r--r-- | src/main_wasm.zig | 66 |
10 files changed, 464 insertions, 281 deletions
diff --git a/.gitignore b/.gitignore index bd1fdb867..b8e503f95 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,6 @@ dist *.log *.out.js /package-lock.json -build
\ No newline at end of file +build +*.wat +zig-out
\ No newline at end of file @@ -14,28 +14,81 @@ pub fn build(b: *std.build.Builder) void { var cwd_buf = [_]u8{0} ** 4096; var cwd = std.os.getcwd(&cwd_buf) catch unreachable; var exe: *std.build.LibExeObjStep = undefined; + + std.debug.print("Build Mode: {s}\n", .{@tagName(mode)}); + if (target.getOsTag() == .wasi) { + std.debug.print("Build OS: Wasi\n", .{}); exe.enable_wasmtime = true; exe = b.addExecutable("esdev", "src/main_wasi.zig"); + exe.is_dynamic = true; + if (mode == std.builtin.Mode.Debug) { + exe.setOutputDir("build/bin/debug"); + } else { + exe.setOutputDir("build/bin"); + } } else if (target.getCpuArch().isWasm()) { - exe = b.addExecutable("esdev", "src/main_wasm.zig"); + std.debug.print("Build OS: WASM\n", .{}); + // exe = b.addExecutable( + // "esdev", + // "src/main_wasm.zig", + // ); + // exe.is_linking_libc = false; + // exe.is_dynamic = true; + var lib = b.addExecutable("esdev", "src/main_wasm.zig"); + + // exe.want_lto = true; + // exe.linkLibrary(lib); if (mode == std.builtin.Mode.Debug) { - exe.setOutputDir("build/wasm/debug"); + // exception_handling + var features = target.getCpuFeatures(); + features.addFeature(2); + target.updateCpuFeatures(&features); + lib.setOutputDir("build/wasm/debug"); } else { - exe.setOutputDir("build/wasm"); + // lib.strip = true; + lib.setOutputDir("build/wasm"); + } + + lib.want_lto = true; + b.install_path = lib.getOutputPath(); + + std.debug.print("Build Destination: {s}\n", .{lib.getOutputPath()}); + + b.default_step.dependOn(&lib.step); + b.verbose_link = true; + lib.setTarget(target); + lib.setBuildMode(mode); + + std.fs.deleteTreeAbsolute(std.fs.path.join(std.heap.page_allocator, &.{ cwd, lib.getOutputPath() }) catch unreachable) catch {}; + var install = b.getInstallStep(); + lib.strip = false; + lib.install(); + + const run_cmd = lib.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); + + return; } else { + std.debug.print("Build OS: Native\n", .{}); exe = b.addExecutable("esdev", "src/main.zig"); exe.linkLibC(); - } - if (mode == std.builtin.Mode.Debug) { - exe.setOutputDir("build/bin/debug"); - } else { - exe.setOutputDir("build/bin"); + if (mode == std.builtin.Mode.Debug) { + exe.setOutputDir("build/bin/debug"); + } else { + exe.setOutputDir("build/bin"); + } } + std.debug.print("Build Destination: {s}\n", .{exe.getOutputPath()}); var walker = std.fs.walkPath(std.heap.page_allocator, cwd) catch unreachable; if (std.builtin.is_test) { while (walker.next() catch unreachable) |entry| { @@ -47,10 +100,13 @@ pub fn build(b: *std.build.Builder) void { } exe.setTarget(target); exe.setBuildMode(mode); + b.install_path = exe.getOutputPath(); - std.fs.deleteTreeAbsolute(exe.getOutputPath()) catch unreachable; + std.fs.deleteTreeAbsolute(std.fs.path.join(std.heap.page_allocator, &.{ cwd, exe.getOutputPath() }) catch unreachable) catch {}; + if (!target.getCpuArch().isWasm()) { + exe.addLibPath("/usr/local/lib"); + } - exe.addLibPath("/usr/local/lib"); exe.install(); const run_cmd = exe.run(); diff --git a/src/api/demo/lib/api.ts b/src/api/demo/lib/api.ts index 1619e2c46..9f07939c0 100644 --- a/src/api/demo/lib/api.ts +++ b/src/api/demo/lib/api.ts @@ -2,7 +2,7 @@ import * as Schema from "../../schema"; import { ByteBuffer } from "peechy"; export interface WebAssemblyModule { - init(starting_memory: number): number; + init(): number; transform(a: number): number; malloc(a: number): number; calloc(a: number): number; @@ -15,6 +15,10 @@ const wasm_imports_sym: symbol | string = ? "wasm_imports" : Symbol("wasm_imports"); +const ptr_converter = new ArrayBuffer(8); +const ptr_float = new Float64Array(ptr_converter); +const slice = new Uint32Array(ptr_converter); + export class ESDev { static has_initialized = false; static wasm_source: WebAssembly.WebAssemblyInstantiatedSource = null; @@ -22,49 +26,142 @@ export class ESDev { return ESDev.wasm_source.instance.exports as any; } static get memory() { - return ESDev.wasm_exports.memory as WebAssembly.Memory; + return ESDev[wasm_imports_sym].memory as WebAssembly.Memory; } + static memory_array: Uint8Array; static _decoder: TextDecoder; - static _wasmPtrLenToString(ptr: number, len: number) { + static _wasmPtrToSlice(offset: number) { + if (ESDev.memory_array.buffer !== ESDev.memory.buffer) { + ESDev.memory_array = new Uint8Array(ESDev.memory.buffer); + } + ptr_float[0] = offset; + return ESDev.memory_array.subarray(slice[0], slice[0] + slice[1]); + } + + static _wasmPtrLenToString(slice: number) { if (!ESDev._decoder) { - ESDev._decoder = new TextDecoder(); + ESDev._decoder = new TextDecoder("utf8"); } - const region = ESDev.memory_array.subarray(ptr, ptr + len + 1); + + const region = this._wasmPtrToSlice(slice); + return ESDev._decoder.decode(region); } // We don't want people to be calling these manually static [wasm_imports_sym] = { - console_log(ptr: number, len: number) { - console.log(ESDev._wasmPtrLenToString(ptr, len)); + console_log(slice: number) { + console.log(ESDev._wasmPtrLenToString(slice)); }, - console_error(ptr: number, len: number) { - console.error(ESDev._wasmPtrLenToString(ptr, len)); + console_error(slice: number) { + console.error(ESDev._wasmPtrLenToString(slice)); }, - console_warn(ptr: number, len: number) { - console.warn(ESDev._wasmPtrLenToString(ptr, len)); + console_warn(slice: number) { + console.warn(ESDev._wasmPtrLenToString(slice)); }, - console_info(ptr: number, len: number) { - console.info(ESDev._wasmPtrLenToString(ptr, len)); + console_info(slice: number) { + console.info(ESDev._wasmPtrLenToString(slice)); }, + memory: null, + // __indirect_function_table: new WebAssembly.Table({ + // initial: 0, + // element: "anyfunc", + // }), + // __stack_pointer: new WebAssembly.Global({ + // mutable: true, + // value: "i32", + // }), + // __multi3(one: number, two: number) { + // return Math.imul(one | 0, two | 0); + // }, + // fmod(one: number, two: number) { + // return one % two; + // }, + // memset(ptr: number, value: number, len: number) { + // ESDev.memory_array.fill(value, ptr, ptr + len); + // }, + // memcpy(ptr: number, value: number, len: number) { + // ESDev.memory_array.copyWithin(ptr, value, value + len); + // }, + // // These functions convert a to an unsigned long long, rounding toward zero. Negative values all become zero. + // __fixunsdfti(a: number) { + // return Math.floor(a); + // }, + // // These functions return the remainder of the unsigned division of a and b. + // __umodti3(a: number, b: number) { + // return (a | 0) % (b | 0); + // }, + // // These functions return the quotient of the unsigned division of a and b. + // __udivti3(a: number, b: number) { + // return (a | 0) / (b | 0); + // }, + // // These functions return the result of shifting a left by b bits. + // __ashlti3(a: number, b: number) { + // return (a | 0) >> (b | 0); + // }, + // /* Returns: convert a to a double, rounding toward even. */ + // __floatuntidf(a: number) { + // const mod = a % 2; + // if (mod === 0) { + // return Math.ceil(a); + // } else if (mod === 1) { + // return Math.floor(a); + // } + // }, }; static async init(url) { + if (ESDev.has_initialized) { + return; + } + + try { + ESDev[wasm_imports_sym].memory = new WebAssembly.Memory({ + initial: 1500, + // shared: typeof SharedArrayBuffer !== "undefined", + maximum: typeof SharedArrayBuffer !== "undefined" ? 5000 : undefined, + }); + } catch { + try { + ESDev[wasm_imports_sym].memory = new WebAssembly.Memory({ + initial: 750, + // shared: typeof SharedArrayBuffer !== "undefined", + maximum: typeof SharedArrayBuffer !== "undefined" ? 5000 : undefined, + }); + } catch { + try { + ESDev[wasm_imports_sym].memory = new WebAssembly.Memory({ + initial: 375, + // shared: typeof SharedArrayBuffer !== "undefined", + maximum: + typeof SharedArrayBuffer !== "undefined" ? 5000 : undefined, + }); + } catch { + ESDev[wasm_imports_sym].memory = new WebAssembly.Memory({ + initial: 125, + // shared: typeof SharedArrayBuffer !== "undefined", + maximum: + typeof SharedArrayBuffer !== "undefined" ? 5000 : undefined, + }); + } + } + } + ESDev.wasm_source = await globalThis.WebAssembly.instantiateStreaming( fetch(url), { env: ESDev[wasm_imports_sym] } ); + ESDev.memory_array = new Uint8Array(ESDev.memory.buffer); - const res = ESDev.wasm_exports.init(1500); + const res = ESDev.wasm_exports.init(); if (res < 0) { throw `[ESDev] Failed to initialize WASM module: code ${res}`; } else { console.log("WASM loaded."); } - ESDev.memory_array = new Uint8Array(ESDev.memory.buffer); ESDev.has_initialized = true; } @@ -74,6 +171,10 @@ export class ESDev { throw "Please run await ESDev.init(wasm_url) before using this."; } + if (process.env.NODE_ENV === "development") { + console.time("[ESDev] Transform " + file_name); + } + const bb = new ByteBuffer( new Uint8Array(content.length + file_name.length) ); @@ -89,12 +190,16 @@ export class ESDev { const data = bb.toUint8Array(); const ptr = ESDev.wasm_exports.malloc(data.byteLength); - ESDev.memory_array.set(data, ptr); - debugger; + this._wasmPtrToSlice(ptr).set(data); const resp_ptr = ESDev.wasm_exports.transform(ptr); - var _bb = new ByteBuffer(ESDev.memory_array.subarray(resp_ptr)); + var _bb = new ByteBuffer(this._wasmPtrToSlice(resp_ptr)); const response = Schema.decodeTransformResponse(_bb); ESDev.wasm_exports.free(resp_ptr); + + if (process.env.NODE_ENV === "development") { + console.timeEnd("[ESDev] Transform " + file_name); + } + ESDev.wasm_exports.free(resp_ptr); return response; } } diff --git a/src/api/demo/package.json b/src/api/demo/package.json index 8576b2bc9..588f0165f 100644 --- a/src/api/demo/package.json +++ b/src/api/demo/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "next": "10.2.0", - "peechy": "0.4.0", + "peechy": "0.4.1", "react": "17.0.2", "react-dom": "17.0.2" } diff --git a/src/api/demo/pnpm-lock.yaml b/src/api/demo/pnpm-lock.yaml index 3e6b4c6cc..36eb423fa 100644 --- a/src/api/demo/pnpm-lock.yaml +++ b/src/api/demo/pnpm-lock.yaml @@ -2,13 +2,13 @@ lockfileVersion: 5.3 specifiers: next: 10.2.0 - peechy: 0.4.0 + peechy: 0.4.1 react: 17.0.2 react-dom: 17.0.2 dependencies: next: 10.2.0_react-dom@17.0.2+react@17.0.2 - peechy: 0.4.0 + peechy: 0.4.1 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -1327,8 +1327,8 @@ packages: sha.js: 2.4.11 dev: false - /peechy/0.4.0: - resolution: {integrity: sha512-dIOZl4mEZGN91WYxrBv1/QOA/R6tNf10FFo4rrCSPfPGPz3gzsvkrXIT8K46XBBlZbSNYS4xUJZ6TZMrptcJIA==} + /peechy/0.4.1: + resolution: {integrity: sha512-IWelrwiGJRd3EmIvF0DcDQdJldy2QzPXY5fU42AAkqCQoMo+mX7lQIilMwLmPX3RjPfQY9Bv3pK9K8iSi2HlWA==} hasBin: true dependencies: change-case: 4.1.2 diff --git a/src/api/schema.js b/src/api/schema.js index 55c4bc040..2a695a33c 100644 --- a/src/api/schema.js +++ b/src/api/schema.js @@ -1,46 +1,46 @@ const Loader = { - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - jsx: 1, - js: 2, - ts: 3, - tsx: 4, - css: 5, - file: 6, - json: 7, + "1": 1, + "2": 2, + "3": 3, + "4": 4, + "5": 5, + "6": 6, + "7": 7, + "jsx": 1, + "js": 2, + "ts": 3, + "tsx": 4, + "css": 5, + "file": 6, + "json": 7 }; const LoaderKeys = { - 1: "jsx", - 2: "js", - 3: "ts", - 4: "tsx", - 5: "css", - 6: "file", - 7: "json", - jsx: "jsx", - js: "js", - ts: "ts", - tsx: "tsx", - css: "css", - file: "file", - json: "json", + "1": "jsx", + "2": "js", + "3": "ts", + "4": "tsx", + "5": "css", + "6": "file", + "7": "json", + "jsx": "jsx", + "js": "js", + "ts": "ts", + "tsx": "tsx", + "css": "css", + "file": "file", + "json": "json" }; const JSXRuntime = { - 1: 1, - 2: 2, - automatic: 1, - classic: 2, + "1": 1, + "2": 2, + "automatic": 1, + "classic": 2 }; const JSXRuntimeKeys = { - 1: "automatic", - 2: "classic", - automatic: "automatic", - classic: "classic", + "1": "automatic", + "2": "classic", + "automatic": "automatic", + "classic": "classic" }; function decodeJSX(bb) { @@ -53,92 +53,86 @@ function decodeJSX(bb) { result["import_source"] = bb.readString(); result["react_fast_refresh"] = !!bb.readByte(); var length = bb.readVarUint(); - var values = (result["loader_keys"] = Array(length)); + var values = result["loader_keys"] = Array(length); for (var i = 0; i < length; i++) values[i] = bb.readString(); var length = bb.readVarUint(); - var values = (result["loader_values"] = Array(length)); + var values = result["loader_values"] = Array(length); for (var i = 0; i < length; i++) values[i] = Loader[bb.readByte()]; return result; } function encodeJSX(message, bb) { + var value = message["factory"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "factory"'); + throw new Error("Missing required field \"factory\""); } var value = message["runtime"]; if (value != null) { var encoded = JSXRuntime[value]; - if (encoded === void 0) - throw new Error( - "Invalid value " + JSON.stringify(value) + ' for enum "JSXRuntime"' - ); - bb.writeByte(encoded); +if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"JSXRuntime\""); +bb.writeByte(encoded); } else { - throw new Error('Missing required field "runtime"'); + throw new Error("Missing required field \"runtime\""); } var value = message["fragment"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "fragment"'); + throw new Error("Missing required field \"fragment\""); } var value = message["production"]; if (value != null) { bb.writeByte(value); } else { - throw new Error('Missing required field "production"'); + throw new Error("Missing required field \"production\""); } var value = message["import_source"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "import_source"'); + throw new Error("Missing required field \"import_source\""); } var value = message["react_fast_refresh"]; if (value != null) { bb.writeByte(value); } else { - throw new Error('Missing required field "react_fast_refresh"'); + throw new Error("Missing required field \"react_fast_refresh\""); } var value = message["loader_keys"]; if (value != null) { - var values = value, - n = values.length; + var values = value, n = values.length; bb.writeVarUint(n); for (var i = 0; i < n; i++) { value = values[i]; bb.writeString(value); } } else { - throw new Error('Missing required field "loader_keys"'); + throw new Error("Missing required field \"loader_keys\""); } var value = message["loader_values"]; if (value != null) { - var values = value, - n = values.length; + var values = value, n = values.length; bb.writeVarUint(n); for (var i = 0; i < n; i++) { value = values[i]; var encoded = Loader[value]; - if (encoded === void 0) - throw new Error( - "Invalid value " + JSON.stringify(value) + ' for enum "Loader"' - ); - bb.writeByte(encoded); +if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"Loader\""); +bb.writeByte(encoded); } } else { - throw new Error('Missing required field "loader_values"'); + throw new Error("Missing required field \"loader_values\""); } + } function decodeTransformOptions(bb) { @@ -148,61 +142,61 @@ function decodeTransformOptions(bb) { result["ts"] = !!bb.readByte(); result["base_path"] = bb.readString(); var length = bb.readVarUint(); - var values = (result["define_keys"] = Array(length)); + var values = result["define_keys"] = Array(length); for (var i = 0; i < length; i++) values[i] = bb.readString(); var length = bb.readVarUint(); - var values = (result["define_values"] = Array(length)); + var values = result["define_values"] = Array(length); for (var i = 0; i < length; i++) values[i] = bb.readString(); return result; } function encodeTransformOptions(message, bb) { + var value = message["jsx"]; if (value != null) { encodeJSX(value, bb); } else { - throw new Error('Missing required field "jsx"'); + throw new Error("Missing required field \"jsx\""); } var value = message["ts"]; if (value != null) { bb.writeByte(value); } else { - throw new Error('Missing required field "ts"'); + throw new Error("Missing required field \"ts\""); } var value = message["base_path"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "base_path"'); + throw new Error("Missing required field \"base_path\""); } var value = message["define_keys"]; if (value != null) { - var values = value, - n = values.length; + var values = value, n = values.length; bb.writeVarUint(n); for (var i = 0; i < n; i++) { value = values[i]; bb.writeString(value); } } else { - throw new Error('Missing required field "define_keys"'); + throw new Error("Missing required field \"define_keys\""); } var value = message["define_values"]; if (value != null) { - var values = value, - n = values.length; + var values = value, n = values.length; bb.writeVarUint(n); for (var i = 0; i < n; i++) { value = values[i]; bb.writeString(value); } } else { - throw new Error('Missing required field "define_values"'); + throw new Error("Missing required field \"define_values\""); } + } function decodeFileHandle(bb) { @@ -215,26 +209,28 @@ function decodeFileHandle(bb) { } function encodeFileHandle(message, bb) { + var value = message["path"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "path"'); + throw new Error("Missing required field \"path\""); } var value = message["size"]; if (value != null) { bb.writeVarUint(value); } else { - throw new Error('Missing required field "size"'); + throw new Error("Missing required field \"size\""); } var value = message["fd"]; if (value != null) { bb.writeVarUint(value); } else { - throw new Error('Missing required field "fd"'); + throw new Error("Missing required field \"fd\""); } + } function decodeTransform(bb) { @@ -242,36 +238,37 @@ function decodeTransform(bb) { while (true) { switch (bb.readByte()) { - case 0: - return result; + case 0: + return result; - case 1: - result["handle"] = decodeFileHandle(bb); - break; + case 1: + result["handle"] = decodeFileHandle(bb); + break; - case 2: - result["path"] = bb.readString(); - break; + case 2: + result["path"] = bb.readString(); + break; - case 3: - result["contents"] = bb.readString(); - break; + case 3: + result["contents"] = bb.readString(); + break; - case 4: - result["loader"] = Loader[bb.readByte()]; - break; + case 4: + result["loader"] = Loader[bb.readByte()]; + break; - case 5: - result["options"] = decodeTransformOptions(bb); - break; + case 5: + result["options"] = decodeTransformOptions(bb); + break; - default: - throw new Error("Attempted to parse invalid message"); + default: + throw new Error("Attempted to parse invalid message"); } } } function encodeTransform(message, bb) { + var value = message["handle"]; if (value != null) { bb.writeByte(1); @@ -294,11 +291,8 @@ function encodeTransform(message, bb) { if (value != null) { bb.writeByte(4); var encoded = Loader[value]; - if (encoded === void 0) - throw new Error( - "Invalid value " + JSON.stringify(value) + ' for enum "Loader"' - ); - bb.writeByte(encoded); +if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"Loader\""); +bb.writeByte(encoded); } var value = message["options"]; @@ -307,18 +301,19 @@ function encodeTransform(message, bb) { encodeTransformOptions(value, bb); } bb.writeByte(0); + } const TransformResponseStatus = { - 1: 1, - 2: 2, - success: 1, - fail: 2, + "1": 1, + "2": 2, + "success": 1, + "fail": 2 }; const TransformResponseStatusKeys = { - 1: "success", - 2: "fail", - success: "success", - fail: "fail", + "1": "success", + "2": "fail", + "success": "success", + "fail": "fail" }; function decodeOutputFile(bb) { @@ -330,19 +325,21 @@ function decodeOutputFile(bb) { } function encodeOutputFile(message, bb) { + var value = message["data"]; if (value != null) { - bb.writeByteArray(value); + bb.writeByteArray(value); } else { - throw new Error('Missing required field "data"'); + throw new Error("Missing required field \"data\""); } var value = message["path"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "path"'); + throw new Error("Missing required field \"path\""); } + } function decodeTransformResponse(bb) { @@ -350,74 +347,69 @@ function decodeTransformResponse(bb) { result["status"] = TransformResponseStatus[bb.readVarUint()]; var length = bb.readVarUint(); - var values = (result["files"] = Array(length)); + var values = result["files"] = Array(length); for (var i = 0; i < length; i++) values[i] = decodeOutputFile(bb); var length = bb.readVarUint(); - var values = (result["errors"] = Array(length)); + var values = result["errors"] = Array(length); for (var i = 0; i < length; i++) values[i] = decodeMessage(bb); return result; } function encodeTransformResponse(message, bb) { + var value = message["status"]; if (value != null) { var encoded = TransformResponseStatus[value]; - if (encoded === void 0) - throw new Error( - "Invalid value " + - JSON.stringify(value) + - ' for enum "TransformResponseStatus"' - ); - bb.writeVarUint(encoded); +if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"TransformResponseStatus\""); +bb.writeVarUint(encoded); } else { - throw new Error('Missing required field "status"'); + throw new Error("Missing required field \"status\""); } var value = message["files"]; if (value != null) { - var values = value, - n = values.length; + var values = value, n = values.length; bb.writeVarUint(n); for (var i = 0; i < n; i++) { value = values[i]; encodeOutputFile(value, bb); } } else { - throw new Error('Missing required field "files"'); + throw new Error("Missing required field \"files\""); } var value = message["errors"]; if (value != null) { - var values = value, - n = values.length; + var values = value, n = values.length; bb.writeVarUint(n); for (var i = 0; i < n; i++) { value = values[i]; encodeMessage(value, bb); } } else { - throw new Error('Missing required field "errors"'); + throw new Error("Missing required field \"errors\""); } + } const MessageKind = { - 1: 1, - 2: 2, - 3: 3, - 4: 4, - err: 1, - warn: 2, - note: 3, - debug: 4, + "1": 1, + "2": 2, + "3": 3, + "4": 4, + "err": 1, + "warn": 2, + "note": 3, + "debug": 4 }; const MessageKindKeys = { - 1: "err", - 2: "warn", - 3: "note", - 4: "debug", - err: "err", - warn: "warn", - note: "note", - debug: "debug", + "1": "err", + "2": "warn", + "3": "note", + "4": "debug", + "err": "err", + "warn": "warn", + "note": "note", + "debug": "debug" }; function decodeLocation(bb) { @@ -434,54 +426,56 @@ function decodeLocation(bb) { } function encodeLocation(message, bb) { + var value = message["file"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "file"'); + throw new Error("Missing required field \"file\""); } var value = message["namespace"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "namespace"'); + throw new Error("Missing required field \"namespace\""); } var value = message["line"]; if (value != null) { bb.writeInt32(value); } else { - throw new Error('Missing required field "line"'); + throw new Error("Missing required field \"line\""); } var value = message["column"]; if (value != null) { bb.writeInt32(value); } else { - throw new Error('Missing required field "column"'); + throw new Error("Missing required field \"column\""); } var value = message["line_text"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "line_text"'); + throw new Error("Missing required field \"line_text\""); } var value = message["suggestion"]; if (value != null) { bb.writeString(value); } else { - throw new Error('Missing required field "suggestion"'); + throw new Error("Missing required field \"suggestion\""); } var value = message["offset"]; if (value != null) { bb.writeVarUint(value); } else { - throw new Error('Missing required field "offset"'); + throw new Error("Missing required field \"offset\""); } + } function decodeMessageData(bb) { @@ -489,24 +483,25 @@ function decodeMessageData(bb) { while (true) { switch (bb.readByte()) { - case 0: - return result; + case 0: + return result; - case 1: - result["text"] = bb.readString(); - break; + case 1: + result["text"] = bb.readString(); + break; - case 2: - result["location"] = decodeLocation(bb); - break; + case 2: + result["location"] = decodeLocation(bb); + break; - default: - throw new Error("Attempted to parse invalid message"); + default: + throw new Error("Attempted to parse invalid message"); } } } function encodeMessageData(message, bb) { + var value = message["text"]; if (value != null) { bb.writeByte(1); @@ -519,6 +514,7 @@ function encodeMessageData(message, bb) { encodeLocation(value, bb); } bb.writeByte(0); + } function decodeMessage(bb) { @@ -527,43 +523,41 @@ function decodeMessage(bb) { result["kind"] = MessageKind[bb.readVarUint()]; result["data"] = decodeMessageData(bb); var length = bb.readVarUint(); - var values = (result["notes"] = Array(length)); + var values = result["notes"] = Array(length); for (var i = 0; i < length; i++) values[i] = decodeMessageData(bb); return result; } function encodeMessage(message, bb) { + var value = message["kind"]; if (value != null) { var encoded = MessageKind[value]; - if (encoded === void 0) - throw new Error( - "Invalid value " + JSON.stringify(value) + ' for enum "MessageKind"' - ); - bb.writeVarUint(encoded); +if (encoded === void 0) throw new Error("Invalid value " + JSON.stringify(value) + " for enum \"MessageKind\""); +bb.writeVarUint(encoded); } else { - throw new Error('Missing required field "kind"'); + throw new Error("Missing required field \"kind\""); } var value = message["data"]; if (value != null) { encodeMessageData(value, bb); } else { - throw new Error('Missing required field "data"'); + throw new Error("Missing required field \"data\""); } var value = message["notes"]; if (value != null) { - var values = value, - n = values.length; + var values = value, n = values.length; bb.writeVarUint(n); for (var i = 0; i < n; i++) { value = values[i]; encodeMessageData(value, bb); } } else { - throw new Error('Missing required field "notes"'); + throw new Error("Missing required field \"notes\""); } + } function decodeLog(bb) { @@ -572,65 +566,66 @@ function decodeLog(bb) { result["warnings"] = bb.readUint32(); result["errors"] = bb.readUint32(); var length = bb.readVarUint(); - var values = (result["msgs"] = Array(length)); + var values = result["msgs"] = Array(length); for (var i = 0; i < length; i++) values[i] = decodeMessage(bb); return result; } function encodeLog(message, bb) { + var value = message["warnings"]; if (value != null) { bb.writeUint32(value); } else { - throw new Error('Missing required field "warnings"'); + throw new Error("Missing required field \"warnings\""); } var value = message["errors"]; if (value != null) { bb.writeUint32(value); } else { - throw new Error('Missing required field "errors"'); + throw new Error("Missing required field \"errors\""); } var value = message["msgs"]; if (value != null) { - var values = value, - n = values.length; + var values = value, n = values.length; bb.writeVarUint(n); for (var i = 0; i < n; i++) { value = values[i]; encodeMessage(value, bb); } } else { - throw new Error('Missing required field "msgs"'); + throw new Error("Missing required field \"msgs\""); } + } -export { Loader }; -export { LoaderKeys }; -export { JSXRuntime }; -export { JSXRuntimeKeys }; -export { decodeJSX }; -export { encodeJSX }; -export { decodeTransformOptions }; -export { encodeTransformOptions }; -export { decodeFileHandle }; -export { encodeFileHandle }; -export { decodeTransform }; -export { encodeTransform }; -export { TransformResponseStatus }; -export { TransformResponseStatusKeys }; -export { decodeOutputFile }; -export { encodeOutputFile }; -export { decodeTransformResponse }; -export { encodeTransformResponse }; -export { MessageKind }; -export { MessageKindKeys }; -export { decodeLocation }; -export { encodeLocation }; -export { decodeMessageData }; -export { encodeMessageData }; -export { decodeMessage }; -export { encodeMessage }; -export { decodeLog }; -export { encodeLog }; +export { Loader } +export { LoaderKeys } +export { JSXRuntime } +export { JSXRuntimeKeys } +export { decodeJSX } +export { encodeJSX } +export { decodeTransformOptions } +export { encodeTransformOptions } +export { decodeFileHandle } +export { encodeFileHandle } +export { decodeTransform } +export { encodeTransform } +export { TransformResponseStatus } +export { TransformResponseStatusKeys } +export { decodeOutputFile } +export { encodeOutputFile } +export { decodeTransformResponse } +export { encodeTransformResponse } +export { MessageKind } +export { MessageKindKeys } +export { decodeLocation } +export { encodeLocation } +export { decodeMessageData } +export { encodeMessageData } +export { decodeMessage } +export { encodeMessage } +export { decodeLog } +export { encodeLog }
\ No newline at end of file diff --git a/src/api/schema.zig b/src/api/schema.zig index d34e501a3..c10e5b5a3 100644 --- a/src/api/schema.zig +++ b/src/api/schema.zig @@ -442,6 +442,7 @@ pub fn update(result: *OutputFile, allocator: *std.mem.Allocator, reader: anytyp pub fn encode(result: *const @This(), writer: anytype) anyerror!void { + try writer.writeIntNative(u32, @intCast(u32, result.data.len)); try writer.writeAll(result.data); try writer.writeIntNative(u32, @intCast(u32, result.path.len)); diff --git a/src/global.zig b/src/global.zig index eb7fcfec5..9ac540311 100644 --- a/src/global.zig +++ b/src/global.zig @@ -1,11 +1,13 @@ const std = @import("std"); pub usingnamespace @import("strings.zig"); +pub const isWasm = comptime std.Target.current.isWasm(); + pub const Output = struct { var source: *Source = undefined; pub const Source = struct { const StreamType = comptime { - if (std.builtin.target.isWasm()) { + if (isWasm) { return std.io.FixedBufferStream([]u8); } else { return std.fs.File; @@ -28,22 +30,33 @@ pub const Output = struct { } }; - pub fn print(comptime fmt: string, args: anytype) void { - if (comptime std.builtin.target.isWasm()) { - source.stream.pos = 0; + pub fn printErrorable(comptime fmt: string, args: anytype) !void { + if (isWasm) { + try source.stream.seekTo(0); + try source.stream.writer().print(fmt, args); + const root = @import("root"); + root.console_log(root.Uint8Array.fromSlice(source.out_buffer[0..source.stream.pos])); + } else { std.fmt.format(source.stream.writer(), fmt, args) catch unreachable; + } + } + + pub fn print(comptime fmt: string, args: anytype) void { + if (isWasm) { + source.stream.seekTo(0) catch return; + source.stream.writer().print(fmt, args) catch return; const root = @import("root"); - // root.console_log(@ptrToInt(&source.out_buffer), source.stream.pos); + root.console_log(root.Uint8Array.fromSlice(source.out_buffer[0..source.stream.pos])); } else { std.fmt.format(source.stream.writer(), fmt, args) catch unreachable; } } pub fn printError(comptime fmt: string, args: anytype) void { - if (comptime std.builtin.target.isWasm()) { - source.error_stream.pos = 0; - std.fmt.format(source.error_stream.writer(), fmt, args) catch unreachable; + if (isWasm) { + source.error_stream.seekTo(0) catch return; + source.error_stream.writer().print(fmt, args) catch unreachable; const root = @import("root"); - // root.console_error(@ptrToInt(&source.err_buffer), source.error_stream.pos); + root.console_error(root.Uint8Array.fromSlice(source.err_buffer[0..source.error_stream.pos])); } else { std.fmt.format(source.error_stream.writer(), fmt, args) catch unreachable; } @@ -52,8 +65,8 @@ pub const Output = struct { pub const Global = struct { pub fn panic(comptime fmt: string, args: anytype) noreturn { - if (comptime std.builtin.target.isWasm()) { - Output.printError(fmt, args); + if (isWasm) { + Output.print(fmt, args); @panic(fmt); } else { std.debug.panic(fmt, args); diff --git a/src/js_printer.zig b/src/js_printer.zig index 80304c982..1ed418e47 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -771,15 +771,8 @@ pub fn NewPrinter(comptime ascii_only: bool) type { pub fn printQuotedUTF8(p: *Printer, str: string, allow_backtick: bool) void { const quote = p.bestQuoteCharForString(str, allow_backtick); p.print(quote); - // fast path: small strings get a stack allocation - if (str.len < 128) { - var buf = [128]u16{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - const bufEnd = strings.toUTF16Buf(str, &buf); - p.printQuotedUTF16(buf[0..bufEnd], quote); - } else { - // slow path: big strings get a heap allocation - p.printQuotedUTF16(strings.toUTF16Alloc(str, p.allocator) catch unreachable, quote); - } + // I don't think this will work... + p.print(str); p.print(quote); } diff --git a/src/main_wasm.zig b/src/main_wasm.zig index 03360b165..49f7d36c5 100644 --- a/src/main_wasm.zig +++ b/src/main_wasm.zig @@ -71,20 +71,23 @@ pub const Api = struct { options: *Schema.TransformOptions = &default_options, files: std.ArrayList(string), log: logger.Log, + defines: ?*Define = null, pub fn transform(self: *Api, request: Schema.Transform) !Schema.TransformResponse { const opts = try options.TransformOptions.initUncached(alloc.dynamic, request.path.?, request.contents.?); var source = logger.Source.initFile(opts.entry_point, alloc.dynamic); var ast: js_ast.Ast = undefined; - var raw_defines = RawDefines.init(alloc.static); - try raw_defines.put("process.env.NODE_ENV", "\"development\""); - - var user_defines = try DefineData.from_input(raw_defines, &self.log, alloc.static); - var define = try Define.init( - alloc.static, - user_defines, - ); + if (self.defines == null) { + var raw_defines = RawDefines.init(alloc.static); + try raw_defines.put("process.env.NODE_ENV", "\"development\""); + + var user_defines = try DefineData.from_input(raw_defines, &self.log, alloc.static); + self.defines = try Define.init( + alloc.static, + user_defines, + ); + } switch (opts.loader) { .json => { @@ -101,7 +104,7 @@ pub const Api = struct { ast = js_ast.Ast.initTest(&([_]js_ast.Part{part})); }, .jsx, .tsx, .ts, .js => { - var parser = try js_parser.Parser.init(opts, &self.log, &source, define, alloc.dynamic); + var parser = try js_parser.Parser.init(opts, &self.log, &source, self.defines.?, alloc.dynamic); var res = try parser.parse(); ast = res.ast; }, @@ -136,19 +139,20 @@ pub const Api = struct { } }; -pub extern fn console_log(ptr: usize, len: usize) void; -pub extern fn console_error(ptr: usize, len: usize) void; -pub extern fn console_warn(ptr: usize, len: usize) void; -pub extern fn console_info(ptr: usize, len: usize) void; +pub extern fn console_log(abi: Uint8Array.Abi) void; +pub extern fn console_error(abi: Uint8Array.Abi) void; +pub extern fn console_warn(abi: Uint8Array.Abi) void; +pub extern fn console_info(abi: Uint8Array.Abi) void; -const Gpa = std.heap.GeneralPurposeAllocator(.{}); -var gpa = Gpa{}; pub const Exports = struct { - fn init(amount_to_grow: usize) callconv(.C) i32 { - const res = @wasmMemoryGrow(0, amount_to_grow); + fn init() callconv(.C) i32 { + // const res = @wasmMemoryGrow(0, amount_to_grow); if (alloc.needs_setup) { - alloc.setup(&gpa.allocator) catch return -1; - _ = MainPanicHandler.init(&api.?.log); + alloc.setup(zee.ZeeAllocDefaults.wasm_allocator) catch return -1; + // const Gpa = std.heap.GeneralPurposeAllocator(.{}); + // var gpa = Gpa{}; + // var allocator = &gpa.allocator; + // alloc.setup(allocator) catch return -1; var out_buffer = alloc.static.alloc(u8, 2048) catch return -1; var err_buffer = alloc.static.alloc(u8, 2048) catch return -1; var output = alloc.static.create(Output.Source) catch return -1; @@ -166,8 +170,15 @@ pub const Exports = struct { var _api = alloc.static.create(Api) catch return -1; _api.* = Api{ .files = std.ArrayList(string).init(alloc.dynamic), .log = logger.Log.init(alloc.dynamic) }; api = _api; - // Output.print("Initialized.", .{}); - return res; + Output.printErrorable("Initialized.", .{}) catch |err| { + var name = alloc.static.alloc(u8, @errorName(err).len) catch unreachable; + std.mem.copy(u8, name, @errorName(err)); + console_error(Uint8Array.fromSlice(name)); + }; + + _ = MainPanicHandler.init(&api.?.log); + + return 1; } fn transform(abi: Uint8Array.Abi) callconv(.C) Uint8Array.Abi { @@ -219,6 +230,8 @@ pub const Exports = struct { } }; +var api: ?*Api = null; + comptime { @export(Exports.init, .{ .name = "init", .linkage = .Strong }); @export(Exports.transform, .{ .name = "transform", .linkage = .Strong }); @@ -228,6 +241,11 @@ comptime { @export(Exports.free, .{ .name = "free", .linkage = .Strong }); } -var api: ?*Api = null; - -pub fn main() anyerror!void {} +pub fn main() anyerror!void { + std.mem.doNotOptimizeAway(Exports.init); + std.mem.doNotOptimizeAway(Exports.transform); + std.mem.doNotOptimizeAway(Exports.malloc); + std.mem.doNotOptimizeAway(Exports.calloc); + std.mem.doNotOptimizeAway(Exports.realloc); + std.mem.doNotOptimizeAway(Exports.free); +} |