gofront 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +35 -39
  2. package/package.json +37 -4
  3. package/src/backend/js/expressions.js +559 -144
  4. package/src/backend/js/index.js +174 -49
  5. package/src/backend/js/runtime.js +1518 -54
  6. package/src/backend/js/statements.js +91 -73
  7. package/src/backend/js/stdlib/base64.js +12 -0
  8. package/src/backend/js/stdlib/binary.js +102 -0
  9. package/src/backend/js/stdlib/bits.js +15 -1
  10. package/src/backend/js/stdlib/builder.js +28 -9
  11. package/src/backend/js/stdlib/bytes.js +75 -18
  12. package/src/backend/js/stdlib/errors.js +25 -1
  13. package/src/backend/js/stdlib/fmt.js +70 -13
  14. package/src/backend/js/stdlib/hex.js +17 -0
  15. package/src/backend/js/stdlib/html.js +1 -1
  16. package/src/backend/js/stdlib/index.js +28 -0
  17. package/src/backend/js/stdlib/io.js +105 -3
  18. package/src/backend/js/stdlib/json.js +972 -0
  19. package/src/backend/js/stdlib/math.js +13 -1
  20. package/src/backend/js/stdlib/path.js +18 -4
  21. package/src/backend/js/stdlib/rand.js +10 -5
  22. package/src/backend/js/stdlib/sha256.js +12 -0
  23. package/src/backend/js/stdlib/simd.js +24 -0
  24. package/src/backend/js/stdlib/slices.js +52 -26
  25. package/src/backend/js/stdlib/strconv.js +21 -5
  26. package/src/backend/js/stdlib/strings.js +148 -15
  27. package/src/backend/js/stdlib/sync.js +13 -0
  28. package/src/backend/js/stdlib/time.js +90 -19
  29. package/src/backend/js/stdlib/unicode.js +2 -2
  30. package/src/backend/wasm/boundary.js +1225 -41
  31. package/src/backend/wasm/const-fold.js +205 -0
  32. package/src/backend/wasm/emit-builtins.js +220 -76
  33. package/src/backend/wasm/emit-exprs.js +475 -276
  34. package/src/backend/wasm/emit-maps.js +144 -8
  35. package/src/backend/wasm/emit-stdlib.js +12 -3005
  36. package/src/backend/wasm/emit-stmts.js +264 -270
  37. package/src/backend/wasm/emit.js +124 -87
  38. package/src/backend/wasm/encode.js +140 -29
  39. package/src/backend/wasm/index.js +1001 -32
  40. package/src/backend/wasm/optimize.js +17 -6
  41. package/src/backend/wasm/stdlib/bytes.js +5039 -0
  42. package/src/backend/wasm/stdlib/core.js +8903 -0
  43. package/src/backend/wasm/stdlib/index.js +43 -0
  44. package/src/backend/wasm/stdlib/io.js +2161 -0
  45. package/src/backend/wasm/stdlib/packages.js +2400 -0
  46. package/src/backend/wasm/stdlib/pure.js +720 -0
  47. package/src/backend/wasm/stdlib/simd.js +234 -0
  48. package/src/backend/wasm/stdlib/time.js +1200 -0
  49. package/src/backend/wasm/types.js +174 -1
  50. package/src/backend/wasm/wat.js +37 -0
  51. package/src/cli-core.js +1 -1
  52. package/src/compiler.js +18 -4
  53. package/src/dts-parser.js +150 -140
  54. package/src/index.js +2 -6
  55. package/src/lexer.js +80 -29
  56. package/src/lower/boxing.js +1 -7
  57. package/src/lower/captures.js +2 -6
  58. package/src/lower/embedding.js +2 -1
  59. package/src/lower/ownership.js +30 -9
  60. package/src/minifier.js +20 -68
  61. package/src/parser/declarations.js +3 -6
  62. package/src/parser/expressions.js +3 -8
  63. package/src/parser/index.js +18 -3
  64. package/src/parser/statements.js +25 -38
  65. package/src/parser/struct-tag.js +144 -0
  66. package/src/parser/types.js +64 -8
  67. package/src/resolver.js +2 -27
  68. package/src/templ-lexer.js +29 -63
  69. package/src/templ-parser.js +22 -45
  70. package/src/typechecker/assignability.js +126 -13
  71. package/src/typechecker/expressions.js +168 -16
  72. package/src/typechecker/index.js +35 -8
  73. package/src/typechecker/resolve.js +187 -8
  74. package/src/typechecker/statements.js +68 -9
  75. package/src/typechecker/stdlib/core.js +280 -89
  76. package/src/typechecker/stdlib/extended.js +490 -1
  77. package/src/typechecker/stdlib/simd.js +73 -0
  78. package/src/typechecker/stdlib.js +2 -0
  79. package/src/typechecker/types.js +362 -9
  80. package/src/vendor.js +86 -11
@@ -3,16 +3,30 @@
3
3
  /** @typedef {import('../index.js').CodeGen} CodeGen */
4
4
 
5
5
  const _SSCAN_LOOP =
6
- `let n = 0; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { ` +
7
- `const t = tokens[i]; const p = ptrs[i]; ` +
8
- `if (typeof p.value === "number") p.value = Number(t); ` +
9
- `else if (typeof p.value === "boolean") p.value = t === "true"; ` +
6
+ `let n = 0, err = null; for (let i = 0; i < ptrs.length && i < tokens.length; i++) { ` +
7
+ `const item = tokens[i]; const t = typeof item === "object" && item !== null ? item.t : item; const verb = item?.verb; const p = ptrs[i]; ` +
8
+ `if (verb === "%c") { p.value = t.codePointAt ? t.codePointAt(0) : t; } ` +
9
+ `else if (verb === "%x" || verb === "%X") { const clean = t.replace(/^0[xX]/, ""); const v = parseInt(clean, 16); if (isNaN(v)) { err = __error("expected hex number"); break; } p.value = typeof p.value === "bigint" ? BigInt("0x" + clean) : v; } ` +
10
+ `else if (verb === "%o") { const clean = t.replace(/^0[oO]?/, ""); const v = parseInt(clean, 8); if (isNaN(v)) { err = __error("expected octal number"); break; } p.value = typeof p.value === "bigint" ? BigInt("0o" + clean) : v; } ` +
11
+ `else if (verb === "%b") { const clean = t.replace(/^0[bB]/, ""); const v = parseInt(clean, 2); if (isNaN(v)) { err = __error("expected binary number"); break; } p.value = typeof p.value === "bigint" ? BigInt("0b" + clean) : v; } ` +
12
+ `else if (typeof p.value === "number") { const v = Number(t); if (Number.isNaN(v) || !/^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?$/.test(t)) { err = __error("expected number"); break; } p.value = v; } ` +
13
+ `else if (typeof p.value === "bigint") { try { if (!/^[+-]?\\d+$/.test(t)) throw 1; p.value = BigInt(t); } catch { err = __error("expected integer"); break; } } ` +
14
+ `else if (typeof p.value === "boolean") { const tl = String(t).toLowerCase(); if (tl === "true" || tl === "1" || tl === "t") p.value = true; else if (tl === "false" || tl === "0" || tl === "f") p.value = false; else { err = __error("expected boolean"); break; } } ` +
10
15
  `else p.value = t; n++; }`;
11
16
 
12
17
  /** @type {ThisType<CodeGen>} */
13
18
  export const fmtMethods = {
19
+ _fmtArgJs(e) {
20
+ const js = this.genExpr(e);
21
+ const base =
22
+ e?._type?.kind === "named" ? (e._type.underlying ?? e._type) : e?._type;
23
+ return base?.kind === "slice" ? `(${js} ?? [])` : js;
24
+ },
25
+
14
26
  _genFmt(fn, _a, expr) {
15
- const fmtArgs = expr.args.map((e) => this.genExpr(e)).join(", ");
27
+ const fmtArgs = expr.args
28
+ .map((e, idx) => (idx === 0 ? this.genExpr(e) : this._fmtArgJs(e)))
29
+ .join(", ");
16
30
  switch (fn) {
17
31
  case "Sprintf":
18
32
  this.useHelper("sprintf");
@@ -42,29 +56,72 @@ export const fmtMethods = {
42
56
  case "Fprint":
43
57
  return this._genFmtFprint(fn, expr);
44
58
  case "Sscan": {
59
+ this.useHelper("error");
45
60
  const strArg = this.genExpr(expr.args[0]);
46
61
  const restArgs = expr.args
47
62
  .slice(1)
48
63
  .map((e) => this.genExpr(e))
49
64
  .join(", ");
50
- return `((str, ...ptrs) => { const tokens = str.trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, n < ptrs.length ? "unexpected EOF" : null]; })(${strArg}, ${restArgs})`;
65
+ return `((str, ...ptrs) => { const tokens = str.trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, err ? err : (n < ptrs.length ? __error("unexpected EOF") : null)]; })(${strArg}, ${restArgs})`;
51
66
  }
52
67
  case "Sscanln": {
68
+ this.useHelper("error");
53
69
  const strArg = this.genExpr(expr.args[0]);
54
70
  const restArgs = expr.args
55
71
  .slice(1)
56
72
  .map((e) => this.genExpr(e))
57
73
  .join(", ");
58
- return `((str, ...ptrs) => { const tokens = str.split("\\n")[0].trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, n < ptrs.length ? "unexpected EOF" : null]; })(${strArg}, ${restArgs})`;
74
+ return `((str, ...ptrs) => { const tokens = str.split("\\n")[0].trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, err ? err : (n < ptrs.length ? __error("unexpected EOF") : null)]; })(${strArg}, ${restArgs})`;
59
75
  }
60
76
  case "Sscanf": {
77
+ this.useHelper("error");
61
78
  const strArg = this.genExpr(expr.args[0]);
62
79
  const fmtArg = this.genExpr(expr.args[1]);
63
80
  const restArgs = expr.args
64
81
  .slice(2)
65
82
  .map((e) => this.genExpr(e))
66
83
  .join(", ");
67
- return `((str, _fmt, ...ptrs) => { const tokens = str.trim().split(/\\s+/).filter(Boolean); ${_SSCAN_LOOP} return [n, n < ptrs.length ? "input does not match format" : null]; })(${strArg}, ${fmtArg}, ${restArgs})`;
84
+ return (
85
+ `((str, fmt, ...ptrs) => { ` +
86
+ `const s = String(str); const f = String(fmt); ` +
87
+ `let si = 0, fi = 0; const tokens = []; let parseErr = null; ` +
88
+ `while (fi < f.length) { ` +
89
+ `if (/\\s/.test(f[fi])) { ` +
90
+ `while (fi < f.length && /\\s/.test(f[fi])) fi++; ` +
91
+ `while (si < s.length && /\\s/.test(s[si])) si++; ` +
92
+ `continue; ` +
93
+ `} ` +
94
+ `if (f[fi] === "%") { ` +
95
+ `if (fi + 1 < f.length && f[fi + 1] === "%") { ` +
96
+ `if (s[si] !== "%") { parseErr = __error("input does not match format"); break; } ` +
97
+ `si++; fi += 2; continue; ` +
98
+ `} ` +
99
+ `const vm = f.slice(fi).match(/^%[vdsfqtxXbcoeEfFgG]/); ` +
100
+ `if (vm) { ` +
101
+ `const verb = vm[0]; fi += verb.length; ` +
102
+ `if (verb !== "%c") { while (si < s.length && /\\s/.test(s[si])) si++; } ` +
103
+ `if (si >= s.length) break; ` +
104
+ `let tokRe = /^\\S+/; ` +
105
+ `if (verb === "%d" || verb === "%i") tokRe = /^[+-]?\\d+/; ` +
106
+ `else if (verb === "%o") tokRe = /^[+-]?(?:0[oO])?[0-7]+/; ` +
107
+ `else if (verb === "%b") tokRe = /^[+-]?(?:0[bB])?[01]+/; ` +
108
+ `else if (verb === "%f" || verb === "%F" || verb === "%e" || verb === "%E" || verb === "%g" || verb === "%G") tokRe = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?/; ` +
109
+ `else if (verb === "%t") tokRe = /^(?:true|false|1|0|t|f|T|F|TRUE|FALSE)/; ` +
110
+ `else if (verb === "%x" || verb === "%X") tokRe = /^[+-]?(?:0x)?[0-9a-fA-F]+/; ` +
111
+ `else if (verb === "%c") tokRe = /^[\\s\\S]/; ` +
112
+ `const m = s.slice(si).match(tokRe); ` +
113
+ `if (!m) { parseErr = __error("input does not match format"); break; } ` +
114
+ `tokens.push({ t: m[0], verb }); si += m[0].length; continue; ` +
115
+ `} ` +
116
+ `} ` +
117
+ `if (si >= s.length) break; ` +
118
+ `if (s[si] !== f[fi]) { parseErr = __error("input does not match format"); break; } ` +
119
+ `si++; fi++; ` +
120
+ `} ` +
121
+ `${_SSCAN_LOOP} ` +
122
+ `return [n, parseErr || err || (n < ptrs.length ? __error("unexpected EOF") : null)]; ` +
123
+ `})(${strArg}, ${fmtArg}, ${restArgs})`
124
+ );
68
125
  }
69
126
  default:
70
127
  return undefined;
@@ -75,7 +132,7 @@ export const fmtMethods = {
75
132
  this.useHelper("sprintf");
76
133
  const writerArg = expr.args[0];
77
134
  const rest = expr.args.slice(1);
78
- const restJs = rest.map((e) => this.genExpr(e)).join(", ");
135
+ const restJs = rest.map((e) => this._fmtArgJs(e)).join(", ");
79
136
  const writerType = writerArg._type;
80
137
  const targetTypeName =
81
138
  writerType?.name ??
@@ -84,16 +141,16 @@ export const fmtMethods = {
84
141
  if (targetTypeName === "strings.Builder") {
85
142
  const w = this.genExpr(writerArg);
86
143
  const base = this._unboxWriter(w);
87
- return `(${base}._buf += ${sprintfCall})`;
144
+ return `((__b, __s) => { __b._buf += __s; return [__s.length, null]; })(${base}, ${sprintfCall})`;
88
145
  }
89
146
  if (targetTypeName === "bytes.Buffer") {
90
147
  const w = this.genExpr(writerArg);
91
148
  const base = this._unboxWriter(w);
92
- return `((__b,__s)=>{ __b._buf.push(...new TextEncoder().encode(__s)); })(${base}, ${sprintfCall})`;
149
+ return `((__b, __s) => { const __bytes = new TextEncoder().encode(__s); for (let i = 0; i < __bytes.length; i++) __b._buf.push(__bytes[i]); return [__bytes.length, null]; })(${base}, ${sprintfCall})`;
93
150
  }
94
151
  // Generic io.Writer fallback — call .WriteString if available
95
152
  const w = this.genExpr(writerArg);
96
- return `${w}.WriteString(${sprintfCall})`;
153
+ return `((__w, __s) => typeof __w.WriteString === "function" ? __w.WriteString(__s) : __w.Write(new TextEncoder().encode(__s)))(${w}, ${sprintfCall})`;
97
154
  },
98
155
 
99
156
  _genStdoutWrite(strJs) {
@@ -106,7 +163,7 @@ export const fmtMethods = {
106
163
  const argc = expr.args.length;
107
164
  if (argc === 0) return JSON.stringify(suffix);
108
165
  const fmt = Array(argc).fill("%v").join(sep) + suffix;
109
- const args = expr.args.map((e) => this.genExpr(e)).join(", ");
166
+ const args = expr.args.map((e) => this._fmtArgJs(e)).join(", ");
110
167
  return `__sprintf(${JSON.stringify(fmt)}, ${args})`;
111
168
  },
112
169
 
@@ -0,0 +1,17 @@
1
+ // src/backend/js/stdlib/hex.js
2
+ // CodeGen for Go encoding/hex package.
3
+
4
+ export const hexMethods = {
5
+ _genHex(fn, a) {
6
+ this.useHelper("hex");
7
+ this.useHelper("error");
8
+ const args = a();
9
+ if (fn === "EncodeToString") return `__hex_encode_to_string(${args[0]})`;
10
+ if (fn === "DecodeString") return `__hex_decode_string(${args[0]})`;
11
+ if (fn === "Encode") return `__hex_encode(${args[0]}, ${args[1]})`;
12
+ if (fn === "Decode") return `__hex_decode(${args[0]}, ${args[1]})`;
13
+ if (fn === "EncodedLen") return `(${args[0]} * 2)`;
14
+ if (fn === "DecodedLen") return `Math.floor(${args[0]} / 2)`;
15
+ return undefined;
16
+ },
17
+ };
@@ -12,7 +12,7 @@ export const htmlMethods = {
12
12
  }
13
13
  case "UnescapeString": {
14
14
  const [s] = a();
15
- return `${s}.replace(/&#39;/g,"'").replace(/&#34;/g,'"').replace(/&gt;/g,">").replace(/&lt;/g,"<").replace(/&amp;/g,"&")`;
15
+ return `(${s}).replace(/&(?:quot|apos|#39|#34|gt|lt|amp|#(?:[0-9]+|[xX][0-9a-fA-F]+));/g, m => { switch (m) { case "&quot;": case "&#34;": return '"'; case "&apos;": case "&#39;": return "'"; case "&gt;": return ">"; case "&lt;": return "<"; case "&amp;": return "&"; default: { if (m.startsWith("&#")) { const raw = m.slice(2, -1); const cp = (raw.startsWith("x") || raw.startsWith("X")) ? parseInt(raw.slice(1), 16) : parseInt(raw, 10); return (cp >= 0 && cp <= 0x10FFFF && !(cp >= 0xD800 && cp <= 0xDFFF)) ? String.fromCodePoint(cp) : "\\uFFFD"; } return m; } } })`;
16
16
  }
17
17
  }
18
18
  return undefined;
@@ -1,25 +1,32 @@
1
1
  // CodeGen stdlib call generation — installed as a mixin on CodeGen.prototype.
2
2
  // One file per Go package under ./stdlib/. This index merges them.
3
3
 
4
+ import { base64Methods } from "./base64.js";
5
+ import { binaryMethods } from "./binary.js";
4
6
  import { bitsMethods } from "./bits.js";
5
7
  import { builderMethods } from "./builder.js";
6
8
  import { bytesMethods } from "./bytes.js";
7
9
  import { errorsMethods } from "./errors.js";
8
10
  import { fmtMethods } from "./fmt.js";
9
11
  import { gomMethods } from "./gom.js";
12
+ import { hexMethods } from "./hex.js";
10
13
  import { htmlMethods } from "./html.js";
11
14
  import { ioMethods } from "./io.js";
15
+ import { jsonMethods } from "./json.js";
12
16
  import { mapsMethods } from "./maps.js";
13
17
  import { mathMethods } from "./math.js";
14
18
  import { osMethods } from "./os.js";
15
19
  import { pathMethods } from "./path.js";
16
20
  import { randMethods } from "./rand.js";
17
21
  import { regexpMethods } from "./regexp.js";
22
+ import { sha256Methods } from "./sha256.js";
18
23
  import { sharedMethods } from "./shared.js";
24
+ import { simdMethods } from "./simd.js";
19
25
  import { slicesMethods } from "./slices.js";
20
26
  import { sortMethods } from "./sort.js";
21
27
  import { strconvMethods } from "./strconv.js";
22
28
  import { stringsMethods } from "./strings.js";
29
+ import { syncMethods } from "./sync.js";
23
30
  import { testingMethods } from "./testing.js";
24
31
  import { timeMethods } from "./time.js";
25
32
  import { unicodeMethods } from "./unicode.js";
@@ -49,8 +56,16 @@ const STDLIB_METHOD_MAP = {
49
56
  rand: "_genRand",
50
57
  utf8: "_genUtf8",
51
58
  path: "_genPath",
59
+ filepath: "_genPath",
52
60
  testing: "_genTesting",
53
61
  shared: "_genShared",
62
+ sync: "_genSync",
63
+ sha256: "_genSha256",
64
+ binary: "_genBinary",
65
+ hex: "_genHex",
66
+ base64: "_genBase64",
67
+ json: "_genJson",
68
+ simd: "_genSimd",
54
69
  };
55
70
 
56
71
  const dispatchMethods = {
@@ -71,6 +86,12 @@ const dispatchMethods = {
71
86
  // Dispatch table for stdlib namespace calls (pkg.Func → inline JS).
72
87
  // Returns the generated JS string, or undefined if not handled.
73
88
  _genStdlibCall(ns, fn, expr) {
89
+ // Stdlib shims take raw values; only fmt and errors use the interface box
90
+ // of a named value (Error() dispatch, error comparisons).
91
+ const isNamespace = expr.func?.expr?._type?.kind === "namespace";
92
+ if (isNamespace && ns !== "fmt" && ns !== "errors") {
93
+ for (const e of expr.args) if (e) e._noNamedBox = true;
94
+ }
74
95
  const a = () => expr.args.map((e) => this.genExpr(e));
75
96
  if (ns === "gom") return this._genGom(fn, expr);
76
97
  const method = STDLIB_METHOD_MAP[ns];
@@ -95,6 +116,7 @@ export const stdlibGenMethods = {
95
116
  ...randMethods,
96
117
  ...regexpMethods,
97
118
  ...sharedMethods,
119
+ ...simdMethods,
98
120
  ...slicesMethods,
99
121
  ...sortMethods,
100
122
  ...strconvMethods,
@@ -103,5 +125,11 @@ export const stdlibGenMethods = {
103
125
  ...unicodeMethods,
104
126
  ...utf8Methods,
105
127
  ...testingMethods,
128
+ ...syncMethods,
129
+ ...sha256Methods,
130
+ ...binaryMethods,
131
+ ...hexMethods,
132
+ ...base64Methods,
133
+ ...jsonMethods,
106
134
  ...dispatchMethods,
107
135
  };
@@ -5,6 +5,7 @@
5
5
  /** @type {ThisType<CodeGen>} */
6
6
  export const ioMethods = {
7
7
  _genIo(fn, _a, expr) {
8
+ if (fn === "ReadAll") this.useHelper("error");
8
9
  switch (fn) {
9
10
  case "WriteString": {
10
11
  const writerArg = expr.args[0];
@@ -19,15 +20,116 @@ export const ioMethods = {
19
20
  return `((b,s) => { b._buf += s; return [s.length, null]; })(${base}, ${s})`;
20
21
  }
21
22
  if (typeName === "bytes.Buffer") {
22
- return `((b,s) => { b._buf.push(...new TextEncoder().encode(s)); return [s.length, null]; })(${base}, ${s})`;
23
+ return `((b,s) => { const bytes = new TextEncoder().encode(s); for (let i = 0; i < bytes.length; i++) b._buf.push(bytes[i]); return [bytes.length, null]; })(${base}, ${s})`;
23
24
  }
24
25
  // Generic: auto-dereference pointer, then dispatch on concrete writer type.
25
26
  // strings.Builder has { _buf: string }, bytes.Buffer has { _buf: [] }.
26
- return `((b,s) => { const w = b?.value ?? b; if (typeof w.WriteString === "function") return [w.WriteString(s), null]; if (typeof w._buf === "string") { w._buf += s; return [s.length, null]; } if (Array.isArray(w._buf)) { w._buf.push(...new TextEncoder().encode(s)); return [s.length, null]; } return [0, "io.WriteString: unsupported writer"]; })(${w}, ${s})`;
27
+ return `((b,s) => { const w = b?.value ?? b; if (typeof w.WriteString === "function") return w.WriteString(s); if (typeof w._buf === "string") { w._buf += s; return [s.length, null]; } if (Array.isArray(w._buf)) { const bytes = new TextEncoder().encode(s); for (let i = 0; i < bytes.length; i++) w._buf.push(bytes[i]); return [bytes.length, null]; } if (typeof w.Write === "function") return w.Write(new TextEncoder().encode(s)); return [0, "io.WriteString: unsupported writer"]; })(${w}, ${s})`;
27
28
  }
28
29
  case "ReadAll": {
30
+ this.useHelper("ioEOF");
29
31
  const r = this.genExpr(expr.args[0]);
30
- return `((r) => { const w = r?.value ?? r; if (typeof w._src === "string") { const s = w._src.slice(w._pos); w._pos = w._src.length; return [[...s].map(c => c.charCodeAt(0)), null]; } if (Array.isArray(w._src)) { const b = w._src.slice(w._pos); w._pos = w._src.length; return [b, null]; } const chunks = []; const buf = new Array(4096); let err = null; while (!err) { const [n, e] = w.Read(buf); if (n > 0) chunks.push(...buf.slice(0, n)); err = e; } return [chunks, err === "EOF" ? null : err]; })(${r})`;
32
+ return `((r) => { const w = r?.value ?? r; const chunks = []; const buf = new Uint8Array(512); let err = null; while (!err) { const [n, e] = w.Read(buf); if (n > 0) { for (let i = 0; i < n; i++) chunks.push(buf[i]); } if (n === 0 && !e) break; err = e; } return [new Uint8Array(chunks), (err === "EOF" || err === __io_eof || err?._msg === "EOF") ? null : err]; })(${r})`;
33
+ }
34
+ case "LimitReader": {
35
+ this.useHelper("ioEOF");
36
+ const r = this.genExpr(expr.args[0]);
37
+ const n = this.genExpr(expr.args[1]);
38
+ return `((r, n) => {
39
+ let rem = typeof n === "bigint" ? Number(n) : Number(n);
40
+ const reader = r?.value ?? r;
41
+ return {
42
+ Read(buf) {
43
+ if (rem <= 0) return [0, __io_eof];
44
+ const max = buf.length > rem ? rem : buf.length;
45
+ const slice = buf.subarray ? buf.subarray(0, max) : buf.slice(0, max);
46
+ const [readN, err] = reader.Read(slice);
47
+ if (readN > 0) {
48
+ if (buf.set && slice !== buf) buf.set(slice.subarray(0, readN), 0);
49
+ rem -= readN;
50
+ }
51
+ return [readN, err];
52
+ }
53
+ };
54
+ })(${r}, ${n})`;
55
+ }
56
+ case "Copy": {
57
+ this.useHelper("ioEOF");
58
+ const dst = this.genExpr(expr.args[0]);
59
+ const src = this.genExpr(expr.args[1]);
60
+ return `((dst, src) => {
61
+ const w = dst?.value ?? dst;
62
+ const r = src?.value ?? src;
63
+ const writeChunk = (chunk) => {
64
+ if (typeof w?.Write === "function") return w.Write(chunk);
65
+ if (Array.isArray(w?._buf)) {
66
+ for (let i = 0; i < chunk.length; i++) w._buf.push(chunk[i]);
67
+ return [chunk.length, null];
68
+ }
69
+ if (typeof w?._buf === "string") {
70
+ w._buf += new TextDecoder().decode(chunk);
71
+ return [chunk.length, null];
72
+ }
73
+ return [0, "unsupported writer"];
74
+ };
75
+ const buf = new Uint8Array(32 * 1024);
76
+ let total = 0;
77
+ while (true) {
78
+ const [n, rerr] = r.Read(buf);
79
+ if (n > 0) {
80
+ const chunk = buf.subarray(0, n);
81
+ const [wn, werr] = writeChunk(chunk);
82
+ total += wn;
83
+ if (werr) return [total, werr];
84
+ }
85
+ if (rerr) {
86
+ if (rerr === "EOF" || rerr === __io_eof || rerr?._msg === "EOF") return [total, null];
87
+ return [total, rerr];
88
+ }
89
+ }
90
+ })(${dst}, ${src})`;
91
+ }
92
+ case "CopyN": {
93
+ this.useHelper("ioEOF");
94
+ const dst = this.genExpr(expr.args[0]);
95
+ const src = this.genExpr(expr.args[1]);
96
+ const n = this.genExpr(expr.args[2]);
97
+ return `((dst, src, n) => {
98
+ const w = dst?.value ?? dst;
99
+ const r = src?.value ?? src;
100
+ const writeChunk = (chunk) => {
101
+ if (typeof w?.Write === "function") return w.Write(chunk);
102
+ if (Array.isArray(w?._buf)) {
103
+ for (let i = 0; i < chunk.length; i++) w._buf.push(chunk[i]);
104
+ return [chunk.length, null];
105
+ }
106
+ if (typeof w?._buf === "string") {
107
+ w._buf += new TextDecoder().decode(chunk);
108
+ return [chunk.length, null];
109
+ }
110
+ return [0, "unsupported writer"];
111
+ };
112
+ let rem = typeof n === "bigint" ? Number(n) : Number(n);
113
+ let total = 0;
114
+ const buf = new Uint8Array(32 * 1024);
115
+ while (rem > 0) {
116
+ const toRead = rem < buf.length ? rem : buf.length;
117
+ const [rn, rerr] = r.Read(buf.subarray(0, toRead));
118
+ if (rn > 0) {
119
+ const [wn, werr] = writeChunk(buf.subarray(0, rn));
120
+ total += wn;
121
+ rem -= wn;
122
+ if (werr) return [total, werr];
123
+ }
124
+ if (rerr) {
125
+ if ((rerr === "EOF" || rerr === __io_eof || rerr?._msg === "EOF") && rem === 0) {
126
+ return [total, null];
127
+ }
128
+ return [total, rerr];
129
+ }
130
+ }
131
+ return [total, null];
132
+ })(${dst}, ${src}, ${n})`;
31
133
  }
32
134
  }
33
135
  return undefined;