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
@@ -8,8 +8,16 @@ import { BuiltinsEmitter } from "./emit-builtins.js";
8
8
  import { ExprsEmitter } from "./emit-exprs.js";
9
9
  import { MapsEmitter } from "./emit-maps.js";
10
10
  import { SharedEmitter } from "./emit-shared.js";
11
- import { StdlibEmitter } from "./emit-stdlib.js";
12
11
  import { StmtsEmitter } from "./emit-stmts.js";
12
+ import {
13
+ BytesEmitter,
14
+ ExtendedPackagesEmitter,
15
+ IoEmitter,
16
+ PurePackagesEmitter,
17
+ SimdEmitter,
18
+ StdlibCoreEmitter,
19
+ TimeEmitter,
20
+ } from "./stdlib/index.js";
13
21
  import {
14
22
  isArrayType,
15
23
  isPointerToStruct,
@@ -34,7 +42,14 @@ export class FunctionEmitter {
34
42
  this.mod.lowerResult?.captures?.get(
35
43
  this.rootFuncDecl._sourceDecl ?? this.rootFuncDecl,
36
44
  ) ?? null;
37
- this.mutatedCaptures = this.captureAnalysis?.mutatedCaptures ?? new Set();
45
+ this.mutatedCaptures = new Set(this.captureAnalysis?.mutatedCaptures ?? []);
46
+ const lowerBoxed =
47
+ this.mod.lowerResult?.boxedVars?.get(
48
+ this.rootFuncDecl._sourceDecl ?? this.rootFuncDecl,
49
+ ) ?? [];
50
+ for (const name of lowerBoxed) {
51
+ this.mutatedCaptures.add(name);
52
+ }
38
53
 
39
54
  this.capturedNames = this.funcDecl._funcLit
40
55
  ? Array.from(
@@ -126,33 +141,7 @@ export class FunctionEmitter {
126
141
  return;
127
142
  }
128
143
 
129
- const namedReturns = this.funcDecl.returnType?._namedReturns;
130
- if (namedReturns && namedReturns.length > 0) {
131
- this.namedReturnVars = [];
132
- for (let i = 0; i < namedReturns.length; i++) {
133
- const r = namedReturns[i];
134
- const isBlank = !r.name || r.name === "_";
135
- const varName = isBlank ? `__ret_blank$${i}` : r.name;
136
- const wType = this.toWasmType(r.type);
137
- const localIdx = this.allocLocal(varName, wType, r.type, isBlank);
138
- this.namedReturnVars.push({
139
- name: varName,
140
- localIdx,
141
- type: wType,
142
- goType: r.type,
143
- isBlank,
144
- });
145
- this.emitZeroValue(r.type, wType);
146
- const localInfo = this.locals.get(varName);
147
- if (localInfo?.isBoxed) {
148
- this.pushInstruction({
149
- op: "struct.new",
150
- typeIndex: localInfo.boxInfo.typeIndex,
151
- });
152
- }
153
- this.pushInstruction({ op: "local.set", index: localIdx });
154
- }
155
- }
144
+ this._initNamedReturns();
156
145
 
157
146
  const needsOobBlock = this._needsOobBlock(body);
158
147
  if (needsOobBlock) {
@@ -181,34 +170,38 @@ export class FunctionEmitter {
181
170
  }
182
171
  }
183
172
 
184
- _emitFunctionBodyWithDefer(body) {
173
+ _initNamedReturns() {
185
174
  const namedReturns = this.funcDecl.returnType?._namedReturns;
186
- if (namedReturns && namedReturns.length > 0) {
187
- this.namedReturnVars = [];
188
- for (let i = 0; i < namedReturns.length; i++) {
189
- const r = namedReturns[i];
190
- const isBlank = !r.name || r.name === "_";
191
- const varName = isBlank ? `__ret_blank$${i}` : r.name;
192
- const wType = this.toWasmType(r.type);
193
- const localIdx = this.allocLocal(varName, wType, r.type, isBlank);
194
- this.namedReturnVars.push({
195
- name: varName,
196
- localIdx,
197
- type: wType,
198
- goType: r.type,
199
- isBlank,
175
+ if (!namedReturns?.length) return false;
176
+ this.namedReturnVars = [];
177
+ for (let i = 0; i < namedReturns.length; i++) {
178
+ const r = namedReturns[i];
179
+ const isBlank = !r.name || r.name === "_";
180
+ const varName = isBlank ? `__ret_blank$${i}` : r.name;
181
+ const wType = this.toWasmType(r.type);
182
+ const localIdx = this.allocLocal(varName, wType, r.type, isBlank);
183
+ this.namedReturnVars.push({
184
+ name: varName,
185
+ localIdx,
186
+ type: wType,
187
+ goType: r.type,
188
+ isBlank,
189
+ });
190
+ this.emitZeroValue(r.type, wType);
191
+ const localInfo = this.locals.get(varName);
192
+ if (localInfo?.isBoxed) {
193
+ this.pushInstruction({
194
+ op: "struct.new",
195
+ typeIndex: localInfo.boxInfo.typeIndex,
200
196
  });
201
- this.emitZeroValue(r.type, wType);
202
- const localInfo = this.locals.get(varName);
203
- if (localInfo?.isBoxed) {
204
- this.pushInstruction({
205
- op: "struct.new",
206
- typeIndex: localInfo.boxInfo.typeIndex,
207
- });
208
- }
209
- this.pushInstruction({ op: "local.set", index: localIdx });
210
197
  }
211
- } else if (this.returnTypes.length > 0) {
198
+ this.pushInstruction({ op: "local.set", index: localIdx });
199
+ }
200
+ return true;
201
+ }
202
+
203
+ _emitFunctionBodyWithDefer(body) {
204
+ if (!this._initNamedReturns() && this.returnTypes.length > 0) {
212
205
  this.returnTempLocals = [];
213
206
  for (let i = 0; i < this.returnTypes.length; i++) {
214
207
  const wType = this.returnTypes[i];
@@ -662,36 +655,27 @@ export class FunctionEmitter {
662
655
  return null;
663
656
  }
664
657
 
665
- _unpackClosureEnv() {
658
+ _buildEnvFields(capturedNames) {
666
659
  const envFields = [];
667
- for (const name of this.capturedNames) {
660
+ for (const name of capturedNames) {
668
661
  const isBoxed = this.mutatedCaptures.has(name);
669
662
  const goType = this._findCapturedVarGoType(name);
670
- if (isBoxed) {
671
- const boxInfo = this.mod.getBoxType(goType);
672
- envFields.push({
673
- name,
674
- goType,
675
- isBoxed: true,
676
- boxInfo,
677
- wType: {
678
- kind: "ref",
679
- nullable: true,
680
- typeIndex: boxInfo.typeIndex,
681
- },
682
- });
683
- } else {
684
- const wType = this.toWasmType(goType);
685
- envFields.push({
686
- name,
687
- goType,
688
- isBoxed: false,
689
- boxInfo: null,
690
- wType,
691
- });
692
- }
663
+ const boxInfo = isBoxed ? this.mod.getBoxType(goType) : null;
664
+ envFields.push({
665
+ name,
666
+ goType,
667
+ isBoxed,
668
+ boxInfo,
669
+ wType: isBoxed
670
+ ? { kind: "ref", nullable: true, typeIndex: boxInfo.typeIndex }
671
+ : this.toWasmType(goType),
672
+ });
693
673
  }
674
+ return envFields;
675
+ }
694
676
 
677
+ _unpackClosureEnv() {
678
+ const envFields = this._buildEnvFields(this.capturedNames);
695
679
  const envInfo = this.mod.getEnvType(envFields);
696
680
  this.envInfo = envInfo;
697
681
  this.envFields = envFields;
@@ -873,6 +857,21 @@ export class FunctionEmitter {
873
857
  if (this.mod.structTypes.has(t.name))
874
858
  return this.mod.structTypes.get(t.name);
875
859
  }
860
+ if (t.kind === "struct" || t.kind === "StructType") {
861
+ const rawFields = [];
862
+ if (t.fields instanceof Map) {
863
+ for (const [k, v] of t.fields.entries())
864
+ rawFields.push({ name: k, goType: v });
865
+ } else if (Array.isArray(t.fields)) {
866
+ for (const f of t.fields) {
867
+ const names = f.names ?? (f.name ? [f.name] : []);
868
+ for (const n of names) rawFields.push({ name: n, goType: f.type });
869
+ }
870
+ }
871
+ if (rawFields.length > 0 && this.mod.getAnonStructType) {
872
+ return this.mod.getAnonStructType(rawFields);
873
+ }
874
+ }
876
875
  return null;
877
876
  }
878
877
 
@@ -930,6 +929,7 @@ export class FunctionEmitter {
930
929
  return;
931
930
  if (
932
931
  node.kind === "CompositeLit" ||
932
+ node.kind === "CallExpr" ||
933
933
  (node.kind === "UnaryExpr" && node.op === "*")
934
934
  )
935
935
  return;
@@ -959,6 +959,11 @@ export class FunctionEmitter {
959
959
  if (recvType) {
960
960
  let t = recvType;
961
961
  while (t.kind === "pointer") t = t.base;
962
+ if (t.kind === "SelectorExpr") {
963
+ const pkg = t.expr?.name;
964
+ if (pkg) return `${pkg}.${t.field}`;
965
+ }
966
+ if (t.kind === "simd") return "simd.F32x4";
962
967
  if (t.name) return t.name;
963
968
  if (t.kind === "named") return t.name;
964
969
  if (t.kind === "TypeName" || t.kind === "Ident") return t.name;
@@ -969,6 +974,10 @@ export class FunctionEmitter {
969
974
  return this._getReceiverTypeName(loc.goType);
970
975
  }
971
976
  }
977
+ if (node && node.kind === "SelectorExpr") {
978
+ const pkg = node.expr?.name;
979
+ if (pkg) return `${pkg}.${node.field}`;
980
+ }
972
981
  return null;
973
982
  }
974
983
 
@@ -1082,6 +1091,18 @@ export class FunctionEmitter {
1082
1091
  return defaultSize;
1083
1092
  }
1084
1093
 
1094
+ _getArrayElemType(t) {
1095
+ if (!t) return null;
1096
+ if (t.elem) return t.elem;
1097
+ if (t.underlying?.elem) return t.underlying.elem;
1098
+ if (t.kind === "ArrayType") return t.elem;
1099
+ if (t.name && this.mod.checker?.types?.has(t.name)) {
1100
+ const resolved = this.mod.checker.types.get(t.name);
1101
+ return this._getArrayElemType(resolved);
1102
+ }
1103
+ return null;
1104
+ }
1105
+
1085
1106
  emitZeroValue(goType, wType) {
1086
1107
  if (wType === "i32") {
1087
1108
  this.pushInstruction({ op: "i32.const", value: 0 });
@@ -1091,6 +1112,8 @@ export class FunctionEmitter {
1091
1112
  this.pushInstruction({ op: "f32.const", value: 0.0 });
1092
1113
  } else if (wType === "f64") {
1093
1114
  this.pushInstruction({ op: "f64.const", value: 0.0 });
1115
+ } else if (wType === "v128") {
1116
+ this.pushInstruction({ op: "v128.const", bytes: new Array(16).fill(0) });
1094
1117
  } else if (
1095
1118
  typeof wType === "object" &&
1096
1119
  wType !== null &&
@@ -1264,13 +1287,7 @@ export class FunctionEmitter {
1264
1287
  }
1265
1288
 
1266
1289
  resolveBranchDepthToOob() {
1267
- for (let i = this.controlStack.length - 1; i >= 0; i--) {
1268
- const ctrl = this.controlStack[i];
1269
- if (ctrl.role === "oob") {
1270
- return this.controlStack.length - 1 - i;
1271
- }
1272
- }
1273
- return null;
1290
+ return this.resolveBranchDepthToRole("oob");
1274
1291
  }
1275
1292
 
1276
1293
  resolveBranchDepthToRole(targetRole) {
@@ -1360,11 +1377,25 @@ export class FunctionEmitter {
1360
1377
  break;
1361
1378
  }
1362
1379
  }
1380
+
1381
+ _isPkgExpr(expr, pkgName) {
1382
+ if (expr.expr?.kind !== "Ident") return false;
1383
+ const name = expr.expr.name;
1384
+ if (pkgName !== undefined && name !== pkgName) return false;
1385
+ return !this.resolveLocal(name) && !this.mod.resolveGlobal(name);
1386
+ }
1363
1387
  }
1364
1388
 
1365
1389
  function copyMethods(target, source) {
1366
1390
  const descriptors = Object.getOwnPropertyDescriptors(source.prototype);
1367
1391
  delete descriptors.constructor;
1392
+ for (const key of Object.keys(descriptors)) {
1393
+ if (key in target.prototype) {
1394
+ throw new Error(
1395
+ `Duplicate method "${key}" found while mixing ${source.name} into ${target.name}`,
1396
+ );
1397
+ }
1398
+ }
1368
1399
  Object.defineProperties(target.prototype, descriptors);
1369
1400
  }
1370
1401
 
@@ -1372,5 +1403,11 @@ copyMethods(FunctionEmitter, MapsEmitter);
1372
1403
  copyMethods(FunctionEmitter, StmtsEmitter);
1373
1404
  copyMethods(FunctionEmitter, ExprsEmitter);
1374
1405
  copyMethods(FunctionEmitter, BuiltinsEmitter);
1375
- copyMethods(FunctionEmitter, StdlibEmitter);
1406
+ copyMethods(FunctionEmitter, StdlibCoreEmitter);
1407
+ copyMethods(FunctionEmitter, BytesEmitter);
1408
+ copyMethods(FunctionEmitter, PurePackagesEmitter);
1409
+ copyMethods(FunctionEmitter, IoEmitter);
1410
+ copyMethods(FunctionEmitter, TimeEmitter);
1411
+ copyMethods(FunctionEmitter, ExtendedPackagesEmitter);
1376
1412
  copyMethods(FunctionEmitter, SharedEmitter);
1413
+ copyMethods(FunctionEmitter, SimdEmitter);
@@ -52,20 +52,32 @@ export function encodeI64LEB(val) {
52
52
  return bytes;
53
53
  }
54
54
 
55
+ const _f32Arr = new Float32Array(1);
56
+ const _f32Bytes = new Uint8Array(_f32Arr.buffer);
55
57
  export function encodeF32(val) {
56
- const buf = new ArrayBuffer(4);
57
- new DataView(buf).setFloat32(0, Number(val), true); // little-endian
58
- return Array.from(new Uint8Array(buf));
58
+ _f32Arr[0] = Number(val);
59
+ return [_f32Bytes[0], _f32Bytes[1], _f32Bytes[2], _f32Bytes[3]];
59
60
  }
60
61
 
62
+ const _f64Arr = new Float64Array(1);
63
+ const _f64Bytes = new Uint8Array(_f64Arr.buffer);
61
64
  export function encodeF64(val) {
62
- const buf = new ArrayBuffer(8);
63
- new DataView(buf).setFloat64(0, Number(val), true); // little-endian
64
- return Array.from(new Uint8Array(buf));
65
+ _f64Arr[0] = Number(val);
66
+ return [
67
+ _f64Bytes[0],
68
+ _f64Bytes[1],
69
+ _f64Bytes[2],
70
+ _f64Bytes[3],
71
+ _f64Bytes[4],
72
+ _f64Bytes[5],
73
+ _f64Bytes[6],
74
+ _f64Bytes[7],
75
+ ];
65
76
  }
66
77
 
78
+ const _textEncoder = new TextEncoder();
67
79
  function encodeString(str) {
68
- const utf8 = new TextEncoder().encode(str);
80
+ const utf8 = _textEncoder.encode(str);
69
81
  return [...encodeU32LEB(utf8.length), ...utf8];
70
82
  }
71
83
 
@@ -381,6 +393,49 @@ const GC_OPCODES = {
381
393
  "extern.convert_any": 0x1b,
382
394
  };
383
395
 
396
+ // 0xFD prefixed SIMD instructions (Wasm SIMD / v128)
397
+ const SIMD_OPCODES = {
398
+ "v128.load": 0,
399
+ "v128.store": 11,
400
+ "v128.const": 12,
401
+ "i8x16.shuffle": 13,
402
+ "i8x16.swizzle": 14,
403
+ "i8x16.splat": 15,
404
+ "i16x8.splat": 16,
405
+ "i32x4.splat": 17,
406
+ "i64x2.splat": 18,
407
+ "f32x4.splat": 19,
408
+ "f64x2.splat": 20,
409
+ "i8x16.extract_lane_s": 21,
410
+ "i8x16.extract_lane_u": 22,
411
+ "i8x16.replace_lane": 23,
412
+ "i16x8.extract_lane_s": 24,
413
+ "i16x8.extract_lane_u": 25,
414
+ "i16x8.replace_lane": 26,
415
+ "i32x4.extract_lane": 27,
416
+ "i32x4.replace_lane": 28,
417
+ "i64x2.extract_lane": 29,
418
+ "i64x2.replace_lane": 30,
419
+ "f32x4.extract_lane": 31,
420
+ "f32x4.replace_lane": 32,
421
+ "v128.not": 77,
422
+ "v128.and": 78,
423
+ "v128.andnot": 79,
424
+ "v128.or": 80,
425
+ "v128.xor": 81,
426
+ "f32x4.abs": 224,
427
+ "f32x4.neg": 225,
428
+ "f32x4.sqrt": 227,
429
+ "f32x4.add": 228,
430
+ "f32x4.sub": 229,
431
+ "f32x4.mul": 230,
432
+ "f32x4.div": 231,
433
+ "f32x4.min": 232,
434
+ "f32x4.max": 233,
435
+ "f32x4.pmin": 234,
436
+ "f32x4.pmax": 235,
437
+ };
438
+
384
439
  // Natural alignment (log2) per load/store opcode; memarg = align, offset.
385
440
  const MEM_ALIGN = {
386
441
  "i32.load": 2,
@@ -421,6 +476,48 @@ function encodeInstruction(inst) {
421
476
  return [0xfc, ...encodeU32LEB(SAT_TRUNC_OPCODES[op])];
422
477
  }
423
478
 
479
+ // 2. Check SIMD opcodes (0xFD prefix)
480
+ if (SIMD_OPCODES[op] !== undefined) {
481
+ const subOp = SIMD_OPCODES[op];
482
+ const bytes = [0xfd, ...encodeU32LEB(subOp)];
483
+ if (op === "v128.load" || op === "v128.store") {
484
+ bytes.push(...encodeU32LEB(inst.align ?? 2));
485
+ bytes.push(...encodeU32LEB(inst.offset ?? 0));
486
+ return bytes;
487
+ }
488
+ if (op === "v128.const") {
489
+ const prefixLen = bytes.length;
490
+ if (inst.bytes) {
491
+ for (let i = 0; i < 16; i++) {
492
+ bytes.push(inst.bytes[i] ?? 0);
493
+ }
494
+ } else if (inst.values) {
495
+ const vals = inst.values.slice(0, 4);
496
+ for (const val of vals) {
497
+ bytes.push(...encodeF32(val));
498
+ }
499
+ while (bytes.length < prefixLen + 16) {
500
+ bytes.push(0);
501
+ }
502
+ } else {
503
+ for (let i = 0; i < 16; i++) bytes.push(0);
504
+ }
505
+ return bytes;
506
+ }
507
+ if (op === "i8x16.shuffle") {
508
+ const lanes = inst.lanes ?? inst.indices ?? [];
509
+ for (let i = 0; i < 16; i++) {
510
+ bytes.push(lanes[i] ?? 0);
511
+ }
512
+ return bytes;
513
+ }
514
+ if (op.includes("extract_lane") || op.includes("replace_lane")) {
515
+ bytes.push((inst.lane ?? inst.index ?? 0) & 0xff);
516
+ return bytes;
517
+ }
518
+ return bytes;
519
+ }
520
+
424
521
  // 2. Check WasmGC opcodes (0xFB prefix)
425
522
  if (GC_OPCODES[op] !== undefined) {
426
523
  const subOp = GC_OPCODES[op];
@@ -907,31 +1004,45 @@ export function encodeModule(mod) {
907
1004
  const sectionOffsets = [];
908
1005
  const codeSec = encodeCodeSection(mod.funcs, sectionOffsets);
909
1006
 
910
- const allBytes = [
911
- ...magic,
912
- ...version,
913
- ...GOFRONT_SECTION_BYTES,
914
- ...typeSec,
915
- ...importSec,
916
- ...funcSec,
917
- ...memorySec,
918
- ...tagSec,
919
- ...globalSec,
920
- ...exportSec,
921
- ...startSec,
922
- ...elemSec,
1007
+ const sections = [
1008
+ magic,
1009
+ version,
1010
+ GOFRONT_SECTION_BYTES,
1011
+ typeSec,
1012
+ importSec,
1013
+ funcSec,
1014
+ memorySec,
1015
+ tagSec,
1016
+ globalSec,
1017
+ exportSec,
1018
+ startSec,
1019
+ elemSec,
923
1020
  ];
924
- const codeStart = allBytes.length;
1021
+ let totalLen = 0;
1022
+ for (const s of sections) totalLen += s.length;
1023
+ const codeStart = totalLen;
925
1024
  mod.codeOffsets = sectionOffsets.map((o) => codeStart + o);
926
- allBytes.push(...codeSec);
1025
+ totalLen += codeSec.length;
1026
+ let smSec = null;
927
1027
  if (mod.sourceMappingURL) {
928
- allBytes.push(
929
- ...encodeSection(0, [
930
- ...encodeString("sourceMappingURL"),
931
- ...encodeString(mod.sourceMappingURL),
932
- ]),
933
- );
1028
+ smSec = encodeSection(0, [
1029
+ ...encodeString("sourceMappingURL"),
1030
+ ...encodeString(mod.sourceMappingURL),
1031
+ ]);
1032
+ totalLen += smSec.length;
1033
+ }
1034
+
1035
+ const out = new Uint8Array(totalLen);
1036
+ let offset = 0;
1037
+ for (const s of sections) {
1038
+ out.set(s, offset);
1039
+ offset += s.length;
1040
+ }
1041
+ out.set(codeSec, offset);
1042
+ offset += codeSec.length;
1043
+ if (smSec) {
1044
+ out.set(smSec, offset);
934
1045
  }
935
1046
 
936
- return new Uint8Array(allBytes);
1047
+ return out;
937
1048
  }