# webcs **Repository Path**: lightsever/webcs ## Basic Information - **Project Name**: webcs - **Description**: 探索性项目,用于把c#代码编译为 ts 和 wasm,用于web和小游戏等开发环境。 以ts为主,方便调试。 wasm为辅,对数据密集型业务,提高操作性能。 你可以理解为像burst 一样,只把性能关键的代码编译为wasm - **Primary Language**: C# - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2026-04-27 - **Last Updated**: 2026-05-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # WebCS **C# → JavaScript 转译器**。基于 Roslyn 解析 C# 源码,直接生成可在浏览器运行的 JavaScript。无需 WebAssembly,无需 GC 运行时,调试友好。 ## 特性一览 - 完整的 C# 语法支持:类、结构体、枚举、async/await、泛型、元组、Lambda、运算符重载、扩展方法、事件 - **struct 值语义模拟**:自动生成 `_clone()`,赋值/传参/返回自动克隆 - **[JSMemoryFlat]** 结构体二进制序列化,直接读写 DataView,适用于 WebGL 顶点填充 - **[JSModule]** 引用任意 JS 库,用 C# 接口描述 JS 对象结构,自然调用 - TypedArray 映射:`int[]` → `Int32Array`,`float[]` → `Float32Array` - 内置浏览器 API 绑定:DOM、Canvas、WebGL、Fetch、Storage、事件系统 - Source Map v3 生成,嵌入 C# 源码,浏览器直接调试 ## 快速开始 ### 构建 ```bash git clone webcs cd webcs dotnet build ``` ### CLI 用法 ```bash # 转译 C# 项目为 JS dotnet run --project src/webcs.builder -- conv <项目目录> <输出目录> # 打开 Edge 浏览器预览 dotnet run --project src/webcs.builder -- openedge <输出目录> ``` ### HelloWorld 示例 ```bash cd samples/HelloWorld dotnet build ``` 构建自动触发转译,输出到 `dist/`: ``` dist/ ├── HelloWorld.js # 转译后的 JS ├── HelloWorld.js.map # Source Map ├── index.html # 入口页面 ├── webcslib.math.js # 引用的库模块 ├── webcslib.math.d.ts # 库类型声明 ├── js/ # JS 库文件(从引用项目复制) │ ├── gifuct-js.js │ ├── png-codec.mjs │ └── pako.js └── img/ # 静态资源 ``` 在 VS / VS Code 中选择 **"Open Browser"** 配置点运行,即可在浏览器中查看效果。 ## struct 值语义 JS 没有值类型,WebCS 通过自动克隆模拟 struct 语义: ```csharp public struct Point { public double x; public double y; public double Length => Math.Sqrt(x * x + y * y); } ``` 转译结果: ```javascript class Point { x; y; static _new(x, y) { const self = new Point(); self.x = x; self.y = y; return self; } static _clone(self) { const c = new Point(); c.x = self.x; c.y = self.y; return c; } // self.Length -> Math.sqrt(self.x * self.x + self.y * self.y) } // 赋值自动克隆:let a = Point._clone(b); ``` ### [JSMemoryFlat] 二进制序列化 用于 WebGL 等需要直接操作内存的场景: ```csharp [JSMemoryFlat] public struct Vertex { public float x, y, z; // 12 bytes public byte r, g, b, a; // 4 bytes } // 共 16 bytes ``` 自动生成 `_Size()`、`_ReadFromDataView()`、`_WriteToDataView()`: ```javascript Vertex._Size() // -> 16 Vertex._ReadFromDataView(self, dv, offset) // 从 DataView 读取 Vertex._WriteToDataView(dv, offset, self) // 写入 DataView ``` ## 引用 JS 库 用 `[JSModule]` 导入任意 JS 库,`[JSType]` 接口描述返回值结构: ```csharp using Webcs; using System.Threading.Tasks; namespace Webcs.ImgDec; [JSType] public interface IDecodedPng { IPngImage image { get; } IPngDetails details { get; } } [JSType] public interface IPngImage { int width { get; } int height { get; } } [JSModule(Path = "./js/png-codec.mjs")] [JSType] public static class PngParser { [JSAPI(Name = "decodePng")] public static Task decodePng(byte[] data) => null; } ``` 调用时自动生成 ES6 import + 直接函数调用: ```csharp var resp = await JS.fetch("img/photo.png"); var buf = await resp.arrayBuffer(); var decoded = await PngParser.decodePng(buf.ToArray()); Console.log($"PNG: {decoded.image.width}x{decoded.image.height}"); ``` 转译结果: ```javascript import { decodePng } from './js/png-codec.mjs'; // ... let decoded = await decodePng(new Uint8Array(buf)); console.log(`PNG: ${decoded.image.width}x${decoded.image.height}`); ``` ## 浏览器 API 内置 DOM、Canvas、WebGL、Fetch 等常用 API 绑定: ```csharp using Webcs; using Webcs.Browser; // DOM 操作 var title = (IHTMLElement)Document.createElement("h1"); title.textContent = "Hello WebCS!"; Document.body.appendChild(title); // 事件 title.addEventListener("click", (IEvent e) => { Console.log("clicked!"); }); // Canvas var canvas = (IHTMLCanvasElement)Document.createElement("canvas"); canvas.width = 800; canvas.height = 600; var ctx = (ICanvasRenderingContext2D)canvas.getContext("2d"); ctx.fillStyle = "#e94560"; ctx.fillRect(10, 10, 100, 50); // Fetch var resp = await JS.fetch("/api/data"); var json = await resp.text(); // XMLHttpRequest var req = new WebRequest(); req.open("GET", "/api/data"); req.responseType = "arraybuffer"; req.addEventListener("load", (IEvent e) => { var buf = (ArrayBuffer)req.response; }); req.send(); ``` ## 类型映射 | C# | JavaScript | |---|---| | `int`, `short`, `byte` | `number`(运算自动 `\| 0` 截断) | | `double`, `float` | `number` | | `bool` | `boolean` | | `string` | `string` | | `int[]` | `Int32Array` | | `float[]` | `Float32Array` | | `byte[]` | `Uint8Array` | | `List` | `Array` | | `Dictionary` | `Map` | | `Task` | `Promise`(async/await 直译) | | `ArrayBuffer` | `ArrayBuffer` | ## 文档 - [语法支持说明](docs/syntax-support.md) — C# 特性支持/不支持分类列表 - [JS 导出方法文档](docs/js-export.md) — Attribute 用法、JS 对象映射、DOM/WebGL 接口列表 - [struct 转译说明](docs/struct.md) — struct 值语义模拟、clone、JSMemoryFlat 二进制序列化 - [开发历史](history.md) — 按时间倒序的开发记录 ## 架构 ``` C# 源码 → Roslyn AST (CSharpCompilation) → SyntaxTranslator 遍历 → JavaScript 文本 ``` ``` src/ ├── webcs.builder/ # 转译器核心 │ ├── Analysis/ # 源码分析层 │ │ ├── SourceAnalyzer # Roslyn 解析、项目引用解析 │ │ └── SyntaxTranslator # 核心:AST → JS 转译 │ └── Generation/ # 文件生成层 │ ├── TypeScriptEmitter # 编排器(入口项目) │ ├── ModuleEmitter # 库项目 ES6 模块 │ ├── TypeDeclEmitter # .d.ts 声明文件 │ └── SourceMapWriter # Source Map v3 ├── webcsapi/ # 核心 API 绑定(DOM、事件、Canvas) ├── webcsapi.browser/ # 浏览器扩展 API(Fetch、Storage、WebGL) ├── webcslib.math/ # 数学库(Vector3、Color32 等) └── webcslib.imgdec/ # 图像解码库(PNG/GIF JSModule 绑定) ``` 技术栈:.NET 10.0、Roslyn (`Microsoft.CodeAnalysis.CSharp` 4.*) ## License MIT