豫言 / 豫言操作系统网页编译 @ 0.1.0

在浏览器里本地编译一组豫言源文件,进度与结果进入统一事件队列,可停止。

源码浏览已生成;不能解析的文件以纯文本展示,不表示通过类型检查。

规范.汉语.md

# 网页编译接口规范 0.1.0

本包让浏览器里的豫言应用**在本机编译一组豫言源文件**:源文件由应用给出,编译在后台工作线程里由浏览器版豫言编译器(WasmGC+JSPI)完成,输出、诊断和阶段进度作为事件进入统一事件队列(见[网页事件接口规范](../网页事件/规范.汉语.md)),最终结果以“完成”事件报告。用途是云控制台的“本地编译”:源码在云端,编译在用户浏览器,结果与日志回传云端。应用依赖本包后,全部函数都必须实现。

本包只规定**编译**(源文件 → 编译是否通过、标准输出与标准错误、产物摘要),不规定运行编译产物、也不规定编译器资源的发布方式。

## 编译客户端

宿主通过一个“编译客户端”模块执行编译,默认从**页面基址目录下的 `编译/客户端.mjs`** 动态加载(例如页面 `/cloud/` 加载 `/cloud/编译/客户端.mjs`);创建宿主时可用选项 `编译客户端` 换成别的模块地址或已加载的对象(测试用)。模块须导出两个函数:

- `浏览器编译(输入, 仅编译, 报告)`:`输入` 是 `{"files":{路径:内容}}`;返回 Promise,解析为结果对象 `{ok, stdout, stderr, error, phase, artifact:{sha256}}`;过程中用 `报告(事件)` 回报 `{type:"stage",phase,label}`、`{type:"output",stream,text}`、`{type:"diagnostic",text}`。
- `停止编译()`:终止当前编译(客户端负责让上面的 Promise 以 `{ok:false,error:"已停止"}` 结束)。

语言仓的 `宿主/浏览器/编译器/` 是这两个函数的参考实现(主线程计时器、Worker、90 秒编译时限、5 秒运行时限均由它负责)。

## 函数

### `本地编译可用 : 有 → 爻`

浏览器同时具备 `WebAssembly.promising`(JSPI)、`Worker`、`DecompressionStream` 时返回阳,否则返回阴。它只查浏览器能力,**不检查编译客户端与编译资源是否能加载**;加载失败在启动之后以“完成”事件报告。可用来决定界面上是否提供“本地编译”选项。

### `启动本地编译 : 字符串(文件 JSON) → 整数`

参数是 JSON 对象,键是文件路径,值是文件内容(字符串):`{"入口。豫":"…","库/甲。豫":"…"}`。至多 4096 个文件;路径 1 至 512 个 UTF-16 码元,不含 NUL;内容总量至多 32 MiB(UTF-8 字节)。返回**编译号**(正整数,实例内递增,不复用),编译在后台进行。**同一时刻只允许一个编译**:已有编译在运行时抛事故;参数不合规或超限同样抛事故。

### `停止本地编译 : 有 → 爻`

停止正在运行的编译。确有编译在运行时返回阳,随后会投递一个“完成”事件(`成` 为假,`错误` 为 `已停止`);没有编译在运行时返回阴。

## 事件

类型 `编译`,`订阅号` = 编译号,同一编译的事件保持先后,最后一个总是“完成”。

### 名称 `进度`

```json
{"批":[{"类":"阶段","阶段":"load","标签":"正在加载浏览器编译器与标准库"},
       {"类":"输出","流":"stderr","文字":"正在编译:/库/标准库.豫\n"},
       {"类":"诊断","文字":"错误:…"}]}
```

宿主把 50 毫秒内到达的进度合成一批(1 至 64 项,一批总量至多约 1 MiB,更大的单项自成一批)。`类` 为 `阶段`(只带 `阶段` 与 `标签` 字段)、`输出`(只带 `流` 与 `文字`,`流` 为 `stdout` 或 `stderr`)、`诊断`(只带 `文字`);客户端没给的值为空文字;客户端报告的其他类型被忽略。**编译器把正常的编译进度也写到标准错误**,应用不能凭 `流` 为 `stderr` 判断失败,应看 `完成` 的 `成`。进度事件不会丢失:宿主在队列里该编译的进度积压过多时暂缓合批的投递,直到应用取走(编译线程本身不受影响,时限由客户端负责)。

### 名称 `完成`

```json
{"成":true,"标准输出":"…","标准错误":"…","错误":"","阶段":"compile","产物摘要":"e3b0…"}
```

`成` 为编译是否通过;`标准输出`、`标准错误` 是完整输出(宿主**不截断**,应用上报云端时自行限长);`错误` 是失败说明(例如 `已停止`、`加载或编译超过九十秒时限`、`编译客户端不可用:…`),成功时为空文字;`阶段` 是失败发生的阶段(`load`、`compile`、`run`),可为空;`产物摘要` 是编译产物的 SHA-256 十六进制,没有产物为空文字。“完成”之前,该编译所有已收到的进度先投递完。

## 限额与失败分类

| 项 | 限额 |
| --- | --- |
| 同时运行的编译 | 1 |
| 文件数 | 4096 |
| 路径 | 512 个 UTF-16 码元 |
| 内容总量 | 32 MiB(UTF-8) |
| 一批进度 | 64 项且约 1 MiB |

违规调用(文件 JSON 不合规、超限、已有编译在运行、宿主已关闭)抛豫言事故;编译失败、超时、客户端加载失败都通过“完成”事件(`成` 为假)报告,不抛事故。浏览器不具备所需能力时,`启动本地编译` 仍可调用,随即以 `完成`(`成` 为假,`错误` 说明缺少的能力)结束。

## 一致性样例

1. 对一个简单源文件 `启动本地编译`:依次收到若干 `进度` 事件(含 `阶段` 项)和一个 `完成`,`成` 为真,`产物摘要` 是 64 位十六进制文字。
2. 源文件含语法错误:`完成` 的 `成` 为假,`标准错误` 或 `错误` 含诊断,`进度` 里出现 `诊断` 项或标准错误输出。
3. 编译中途 `停止本地编译`:返回阳;收到 `完成`,`成` 为假,`错误` 为 `已停止`;随后可以再 `启动本地编译`。
4. 编译在运行时再次 `启动本地编译`:抛事故。
5. 编译客户端模块不存在:`启动本地编译` 返回编译号,随后 `完成` 的 `成` 为假,`错误` 以 `编译客户端不可用` 开头。
6. 客户端报告 100 条输出:应用收到的所有 `进度` 批里按顺序恰好 100 条 `输出` 项。

## 边界

本包不规定:运行编译产物、增量编译与缓存、编译器资源(编译器 Wasm、标准库资料、Binaryen)的发布与版本核对、多编译并行、`仅编译` 以外的模式、把产物写入文件。

规范.文言.md

# 网页编译之约 0.1.0

此包令浏览器中豫言之客**于本机编译一组豫言源文件**:源文件由客授之,编译于后台工作线程中由浏览器版豫言编译器(WasmGC 加 JSPI)为之,输出、诊断与阶段之进度,皆作事而入统一事列(见[网页事件之约](../网页事件/规范.文言.md)),终果以“完成”之事报之。用于云控制台之“本地编译”:源在云端,编于用户之浏览器,果与日志回传云端。客依此包,诸术皆当具。

此包**惟定编译**(源文件 → 编译通否、标准输出与标准错误、产物之摘要),不定运行编译之产物,亦不定编译器资源如何发布。

## 编译客户端

宿主凭一“编译客户端”模块行编译,默认自**页面基址目录下之“编译/客户端.mjs”**动态载之(如页 `/cloud/` 载 `/cloud/编译/客户端.mjs`);创宿主时可以选项“编译客户端”易为他模块之址或已载之物(测试之用)。模块须出二函数:

- `浏览器编译(输入, 仅编译, 报告)`:输入为 `{"files":{路径:内容}}`;返 Promise,解为果之物 `{ok, stdout, stderr, error, phase, artifact:{sha256}}`;过程中以“报告(事)”回报 `{type:"stage",phase,label}`、`{type:"output",stream,text}`、`{type:"diagnostic",text}`。
- `停止编译()`:终止当前编译(客户端使上述 Promise 以 `{ok:false,error:"已停止"}` 而终)。

语言仓之“宿主/浏览器/编译器/”乃此二函数之参考实现(主线程之计时、Worker、九十秒编译之限、五秒运行之限,皆由其负责)。

## 诸术

### 本地编译可用:有,返爻

浏览器兼有 `WebAssembly.promising`(JSPI)、Worker、DecompressionStream 则返阳,否则返阴。惟察浏览器之能,**不验编译客户端与编译资源可载否**;载败则于启动之后以“完成”事报之。可用以定界面上有无“本地编译”之选。

### 启动本地编译:字符串(文件癸象文),返整数

参数乃癸象对象,键为文件之径,值为文件之内容(字符串):`{"入口。豫":"…","库/甲。豫":"…"}`。至多四千零九十六文件;径一至五百一十二 UTF-16 码元,无 NUL;内容总量至多三十二 MiB(UTF-8 字节)。返**编译号**(正整数,实例内递增,不复用),编译于后台行。**同一时刻惟许一编译**:已有编译在行则发事故;参数不合或逾限亦发事故。

### 停止本地编译:有,返爻

止在行之编译。确有编译在行则返阳,随后投一“完成”事(成为假,错误曰“已停止”);无编译在行则返阴。

## 事

类曰“编译”,订阅号即编译号,同一编译之事保先后,末者恒为“完成”。

### 名“进度”

```json
{"批":[{"类":"阶段","阶段":"load","标签":"正在加载浏览器编译器与标准库"},
       {"类":"输出","流":"stderr","文字":"正在编译:/库/标准库.豫\n"},
       {"类":"诊断","文字":"错误:…"}]}
```

宿主合五十毫秒内所至之进度为一批(一至六十四项,一批总量至多约一 MiB,更大之单项自成一批)。“类”曰“阶段”(惟带“阶段”与“标签”)、“输出”(惟带“流”与“文字”,“流”为 stdout 或 stderr)、“诊断”(惟带“文字”);客户端未给之值为空文;客户端所报之他类,略之。**编译器亦以标准错误书常规之编译进度**,客不可因“流”为 stderr 即断其败,当观“完成”之“成”。进度之事不失:宿主于列中此编译之进度积压过多时,缓其合批之投,待客取后再续(编译线程自身不受影响,时限由客户端负责)。

### 名“完成”

```json
{"成":true,"标准输出":"…","标准错误":"…","错误":"","阶段":"compile","产物摘要":"e3b0…"}
```

“成”乃编译通否;“标准输出”“标准错误”乃完整之输出(宿主**不截断**,客上报云端时自限其长);“错误”乃败之释(如“已停止”“加载或编译超过九十秒时限”“编译客户端不可用:…”),成则空文;“阶段”乃败所发之阶段(load、compile、run),可空;“产物摘要”乃产物之 SHA-256 十六进制,无产物则空文。“完成”之前,此编译已收之进度必先投毕。

## 限额与败之类

| 项 | 限 |
| --- | --- |
| 同时行之编译 | 一 |
| 文件数 | 四千零九十六 |
| 径 | 五百一十二 UTF-16 码元 |
| 内容总量 | 三十二 MiB(UTF-8) |
| 一批进度 | 六十四项且约一 MiB |

违约之调用(文件癸象文不合、逾限、已有编译在行、宿主已闭)发豫言事故;编译败、超时、客户端载败,皆以“完成”事(成为假)报之,不发事故。浏览器不备所需之能,启动本地编译仍可调用,旋以“完成”(成为假,错误言所缺之能)而终。

## 一致性之例

1. 于一简源文件启动本地编译:依次收若干“进度”事(含“阶段”项)与一“完成”,成为真,产物摘要为六十四位十六进制文。
2. 源文件含语法之误:“完成”之成为假,标准错误或错误含诊断,“进度”中现“诊断”项或标准错误之输出。
3. 编译中途停止本地编译:返阳;收“完成”,成为假,错误曰“已停止”;其后可再启动本地编译。
4. 编译在行时再启动本地编译:发事故。
5. 编译客户端模块不存:启动本地编译返编译号,随后“完成”之成为假,错误以“编译客户端不可用”首。
6. 客户端报告一百条输出:客所收诸“进度”批中依序恰有一百条“输出”项。

## 界

此包不定:运行编译之产物、增量编译与缓存、编译器资源(编译器 Wasm、标准库资料、Binaryen)之发布与版本核对、多编译并行、“仅编译”以外之模式、写产物于文件。