gofront 1.8.0 → 1.9.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.
- package/README.md +3 -3
- package/package.json +5 -4
- package/src/backend/js/expressions.js +849 -371
- package/src/backend/js/index.js +241 -147
- package/src/backend/js/natives.js +383 -0
- package/src/backend/js/runtime.js +512 -2547
- package/src/backend/js/statements.js +506 -103
- package/src/backend/js/stdlib/index.js +45 -93
- package/src/backend/js/templ.js +32 -45
- package/src/backend/js/type-info.js +177 -13
- package/src/backend/shared/fixed-float.js +20 -0
- package/src/backend/shared/fmt-types.js +63 -171
- package/src/backend/shared/host-unicode.js +36 -0
- package/src/backend/wasm/boundary.js +490 -965
- package/src/backend/wasm/emit-builtins.js +643 -256
- package/src/backend/wasm/emit-exprs.js +124 -57
- package/src/backend/wasm/emit-maps.js +17 -367
- package/src/backend/wasm/emit-stmts.js +325 -75
- package/src/backend/wasm/emit.js +104 -13
- package/src/backend/wasm/globals.js +47 -8
- package/src/backend/wasm/glue.js +2 -4
- package/src/backend/wasm/index.js +36 -530
- package/src/backend/wasm/method-expr.js +12 -1
- package/src/backend/wasm/module-emitter.js +92 -717
- package/src/backend/wasm/monomorph.js +103 -6
- package/src/backend/wasm/natives.js +596 -0
- package/src/backend/wasm/prescan.js +5 -153
- package/src/backend/wasm/prune-funcs.js +89 -0
- package/src/backend/wasm/stdlib/index.js +2 -32
- package/src/backend/wasm/types.js +68 -20
- package/src/backend/wasm/variadic.js +3 -3
- package/src/cli/cli-core.js +5 -1
- package/src/cli/test-runner.js +115 -342
- package/src/compiler.js +108 -130
- package/src/lexer/lexer.js +105 -11
- package/src/lexer/templ-lexer.js +61 -18
- package/src/lexer/tokens.js +1 -0
- package/src/link/stdlib.js +354 -132
- package/src/link/type-names.js +148 -0
- package/src/link/wasm.js +30 -6
- package/src/lower/bounds.js +153 -0
- package/src/lower/captures.js +92 -33
- package/src/lower/embedding.js +32 -3
- package/src/lower/errors-as.js +196 -0
- package/src/lower/fmt-formatters.js +905 -0
- package/src/lower/functions.js +2 -0
- package/src/lower/gen-types.js +274 -0
- package/src/lower/index.js +7 -1
- package/src/lower/json-codecs.js +228 -247
- package/src/lower/ownership.js +25 -7
- package/src/lower/reachability.js +69 -51
- package/src/lower/walk.js +12 -0
- package/src/parser/declarations.js +28 -5
- package/src/parser/expressions.js +86 -16
- package/src/parser/statements.js +1 -0
- package/src/parser/templ.js +44 -5
- package/src/parser/types.js +1 -0
- package/src/resolver.js +1 -2
- package/src/typechecker/assignability.js +124 -11
- package/src/typechecker/const-fold.js +70 -27
- package/src/typechecker/constants.js +32 -6
- package/src/typechecker/expressions.js +326 -98
- package/src/typechecker/index.js +208 -33
- package/src/typechecker/init-order.js +136 -40
- package/src/typechecker/operand-text.js +40 -0
- package/src/typechecker/resolve.js +192 -36
- package/src/typechecker/statements.js +122 -11
- package/src/typechecker/stdlib/excluded.js +9 -5
- package/src/typechecker/stdlib/index.js +25 -9
- package/src/typechecker/termination.js +10 -1
- package/src/typechecker/types.js +203 -573
- package/stdlib/bytes/buffer.go +479 -0
- package/stdlib/bytes/bytes.go +1010 -0
- package/stdlib/bytes/reader.go +161 -0
- package/stdlib/context/context.go +115 -0
- package/stdlib/crypto/rand/rand.go +34 -0
- package/stdlib/crypto/sha256/sha256.go +249 -0
- package/stdlib/encoding/base64/base64.go +331 -0
- package/stdlib/encoding/binary/binary.go +332 -0
- package/stdlib/encoding/hex/hex.go +140 -0
- package/stdlib/encoding/json/json.go +62 -0
- package/stdlib/errors/errors.go +174 -0
- package/stdlib/fmt/errors.go +110 -0
- package/stdlib/fmt/format.go +732 -0
- package/stdlib/fmt/print.go +1232 -0
- package/stdlib/gom/gom.go +293 -0
- package/stdlib/html/html.go +251 -0
- package/stdlib/internal/fmtrt/fmtrt.go +163 -0
- package/stdlib/internal/jsonrt/dec.go +171 -38
- package/stdlib/internal/jsonrt/enc.go +186 -36
- package/stdlib/internal/jsonrt/scanner.go +17 -8
- package/stdlib/io/io.go +157 -1
- package/stdlib/maps/maps.go +131 -0
- package/stdlib/math/bits/bits.go +507 -0
- package/stdlib/math/extra.go +16 -14
- package/stdlib/math/math.go +439 -0
- package/stdlib/math/rand/rand.go +297 -0
- package/stdlib/os/os.go +93 -0
- package/stdlib/path/filepath/filepath.go +47 -0
- package/stdlib/path/path.go +394 -0
- package/stdlib/regexp/regexp.go +231 -0
- package/stdlib/slices/slices.go +526 -0
- package/stdlib/slices/sort.go +209 -0
- package/stdlib/slices/zsort_cmp.go +480 -0
- package/stdlib/slices/zsort_ordered.go +482 -0
- package/stdlib/sort/sort.go +391 -452
- package/stdlib/sort/zsort_func.go +480 -0
- package/stdlib/sort/zsort_iface.go +480 -0
- package/stdlib/strconv/float.go +1699 -0
- package/stdlib/strconv/isprint.go +752 -0
- package/stdlib/strconv/quote.go +235 -50
- package/stdlib/strconv/strconv.go +616 -0
- package/stdlib/strings/builder.go +95 -0
- package/stdlib/strings/reader.go +163 -0
- package/stdlib/strings/replacer.go +102 -0
- package/stdlib/strings/strings.go +807 -0
- package/stdlib/sync/sync.go +268 -0
- package/stdlib/testing/async_js.go +61 -0
- package/stdlib/testing/benchmark.go +297 -0
- package/stdlib/testing/testing.go +523 -0
- package/stdlib/time/duration.go +233 -0
- package/stdlib/time/format.go +745 -0
- package/stdlib/time/parse.go +790 -0
- package/stdlib/time/sleep_js.go +63 -0
- package/stdlib/time/time.go +834 -0
- package/stdlib/unicode/unicode.go +141 -3
- package/stdlib/unicode/utf8/utf8.go +464 -0
- package/src/backend/js/fmt-runtime.js +0 -573
- package/src/backend/js/stdlib/base64.js +0 -12
- package/src/backend/js/stdlib/binary.js +0 -102
- package/src/backend/js/stdlib/bits.js +0 -119
- package/src/backend/js/stdlib/builder.js +0 -98
- package/src/backend/js/stdlib/bytes.js +0 -368
- package/src/backend/js/stdlib/errors.js +0 -45
- package/src/backend/js/stdlib/fmt.js +0 -517
- package/src/backend/js/stdlib/gom.js +0 -155
- package/src/backend/js/stdlib/hex.js +0 -17
- package/src/backend/js/stdlib/html.js +0 -20
- package/src/backend/js/stdlib/io.js +0 -137
- package/src/backend/js/stdlib/json.js +0 -1167
- package/src/backend/js/stdlib/maps.js +0 -37
- package/src/backend/js/stdlib/math.js +0 -85
- package/src/backend/js/stdlib/os.js +0 -13
- package/src/backend/js/stdlib/path.js +0 -48
- package/src/backend/js/stdlib/rand.js +0 -32
- package/src/backend/js/stdlib/regexp.js +0 -54
- package/src/backend/js/stdlib/sha256.js +0 -12
- package/src/backend/js/stdlib/shared.js +0 -17
- package/src/backend/js/stdlib/simd.js +0 -34
- package/src/backend/js/stdlib/slices.js +0 -107
- package/src/backend/js/stdlib/sort.js +0 -30
- package/src/backend/js/stdlib/strconv.js +0 -79
- package/src/backend/js/stdlib/strings.js +0 -301
- package/src/backend/js/stdlib/sync.js +0 -13
- package/src/backend/js/stdlib/testing.js +0 -41
- package/src/backend/js/stdlib/time.js +0 -152
- package/src/backend/js/stdlib/unicode.js +0 -25
- package/src/backend/js/stdlib/utf8.js +0 -26
- package/src/backend/wasm/stdlib/bytes.js +0 -6716
- package/src/backend/wasm/stdlib/core.js +0 -10278
- package/src/backend/wasm/stdlib/io.js +0 -3578
- package/src/backend/wasm/stdlib/packages.js +0 -2402
- package/src/backend/wasm/stdlib/pure.js +0 -720
- package/src/backend/wasm/stdlib/time.js +0 -2229
- package/src/typechecker/stdlib/core.js +0 -1079
- package/src/typechecker/stdlib/extended.js +0 -1210
- package/stdlib/bytes/iter.go +0 -192
- package/stdlib/bytes/search.go +0 -240
- package/stdlib/bytes/split.go +0 -218
- package/stdlib/errors/overlay.go +0 -12
- package/stdlib/maps/iter.go +0 -65
- package/stdlib/slices/extra.go +0 -73
- package/stdlib/slices/iter.go +0 -113
- package/stdlib/strings/extra.go +0 -35
- package/stdlib/strings/iter.go +0 -122
- package/stdlib/sync/extra.go +0 -105
- package/stdlib/unicode/utf8/bytes.go +0 -239
package/src/backend/wasm/emit.js
CHANGED
|
@@ -55,6 +55,18 @@ function sameSignature(c, params, paramTypes, want, got) {
|
|
|
55
55
|
return want === undefined || got === undefined || sameTypes(got, want);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// True when a struct type embeds a pointer, directly or through an embedded
|
|
59
|
+
// struct: promoted method calls read through it.
|
|
60
|
+
function _embedsPointer(t, seen = new Set()) {
|
|
61
|
+
const base = t?.kind === "pointer" ? t.base : t;
|
|
62
|
+
const st = base?.underlying ?? base;
|
|
63
|
+
if (!st || seen.has(st)) return false;
|
|
64
|
+
seen.add(st);
|
|
65
|
+
return (st._embeds ?? []).some(
|
|
66
|
+
(e) => e.kind === "pointer" || _embedsPointer(e, seen),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
58
70
|
export class FunctionEmitter {
|
|
59
71
|
constructor(moduleEmitter, funcDecl, funcIndex) {
|
|
60
72
|
this.mod = moduleEmitter;
|
|
@@ -781,7 +793,22 @@ export class FunctionEmitter {
|
|
|
781
793
|
// A pointer dereference or a call through a func value: sites whose nil
|
|
782
794
|
// operand raises Go's panic through the `nil` block.
|
|
783
795
|
_isNilTrapSite(node) {
|
|
784
|
-
if (node.kind === "CallExpr")
|
|
796
|
+
if (node.kind === "CallExpr")
|
|
797
|
+
return (
|
|
798
|
+
this._isFuncValueCall(node) ||
|
|
799
|
+
(node.func?.kind === "SelectorExpr" &&
|
|
800
|
+
_embedsPointer(node.func.expr?._type))
|
|
801
|
+
);
|
|
802
|
+
// Binding a method value on an interface checks it for nil.
|
|
803
|
+
if (node.kind === "NilCheckStmt") return true;
|
|
804
|
+
// A pointer to an array: indexing, slicing and ranging with a value
|
|
805
|
+
// read the array.
|
|
806
|
+
if (
|
|
807
|
+
node.kind === "IndexExpr" ||
|
|
808
|
+
node.kind === "SliceExpr" ||
|
|
809
|
+
node.kind === "RangeExpr"
|
|
810
|
+
)
|
|
811
|
+
return node.expr?._type?.kind === "pointer";
|
|
785
812
|
const star =
|
|
786
813
|
(node.kind === "UnaryExpr" && node.op === "*") ||
|
|
787
814
|
node.kind === "StarExpr";
|
|
@@ -893,11 +920,12 @@ export class FunctionEmitter {
|
|
|
893
920
|
return null;
|
|
894
921
|
}
|
|
895
922
|
|
|
896
|
-
_buildEnvFields(capturedNames) {
|
|
923
|
+
_buildEnvFields(capturedNames, funcLit) {
|
|
897
924
|
const envFields = [];
|
|
925
|
+
const types = this.captureAnalysis?.captureTypes?.get(funcLit);
|
|
898
926
|
for (const name of capturedNames) {
|
|
899
927
|
const isBoxed = this.mutatedCaptures.has(name);
|
|
900
|
-
const goType = this._findCapturedVarGoType(name);
|
|
928
|
+
const goType = types?.get(name) ?? this._findCapturedVarGoType(name);
|
|
901
929
|
const boxInfo = isBoxed ? this.mod.getBoxType(goType) : null;
|
|
902
930
|
envFields.push({
|
|
903
931
|
name,
|
|
@@ -913,7 +941,10 @@ export class FunctionEmitter {
|
|
|
913
941
|
}
|
|
914
942
|
|
|
915
943
|
_unpackClosureEnv() {
|
|
916
|
-
const envFields = this._buildEnvFields(
|
|
944
|
+
const envFields = this._buildEnvFields(
|
|
945
|
+
this.capturedNames,
|
|
946
|
+
this.funcDecl._funcLit,
|
|
947
|
+
);
|
|
917
948
|
const envInfo = this.mod.getEnvType(envFields);
|
|
918
949
|
this.envInfo = envInfo;
|
|
919
950
|
this.envFields = envFields;
|
|
@@ -1126,7 +1157,7 @@ export class FunctionEmitter {
|
|
|
1126
1157
|
const instName = (ft?.kind === "PointerType" ? ft.base : ft)?.name;
|
|
1127
1158
|
const embedInfo =
|
|
1128
1159
|
(instName && this.mod.structTypes.get(instName)) ??
|
|
1129
|
-
this.mod.structTypes.get(embed.name);
|
|
1160
|
+
this.mod.structTypes.get(embed.typeName ?? embed.name);
|
|
1130
1161
|
if (embedInfo) {
|
|
1131
1162
|
const sub = this._resolveFieldPath(embedInfo, fieldName);
|
|
1132
1163
|
if (sub) {
|
|
@@ -1381,6 +1412,7 @@ export class FunctionEmitter {
|
|
|
1381
1412
|
|
|
1382
1413
|
// 2. Iterate candidates
|
|
1383
1414
|
for (const cand of candidates) {
|
|
1415
|
+
this._emitNilPtrCandidate(cand, fn, recvLocal);
|
|
1384
1416
|
this.pushInstruction({ op: "block", blockType: "void" });
|
|
1385
1417
|
this.pushInstruction({ op: "local.get", index: recvLocal });
|
|
1386
1418
|
this.pushInstruction({ op: "ref.test", typeIndex: cand.testTypeIndex });
|
|
@@ -1445,6 +1477,36 @@ export class FunctionEmitter {
|
|
|
1445
1477
|
emitMiss("interface conversion: nil or unmatched type for method call");
|
|
1446
1478
|
}
|
|
1447
1479
|
|
|
1480
|
+
// A typed nil `*S` inside the interface is a marker object (see
|
|
1481
|
+
// getNilBoxType): a pointer-receiver method runs with a nil receiver, as in
|
|
1482
|
+
// Go; a value-receiver or promoted method must read through the nil pointer.
|
|
1483
|
+
_emitNilPtrCandidate(cand, fn, recvLocal) {
|
|
1484
|
+
if (cand.isBoxedValue || !cand.structInfo) return;
|
|
1485
|
+
if (cand.testTypeIndex !== cand.structInfo.typeIndex) return;
|
|
1486
|
+
const nilBox = this.mod.getNilBoxType({
|
|
1487
|
+
kind: "pointer",
|
|
1488
|
+
base: { kind: "named", name: cand.recvTypeName },
|
|
1489
|
+
});
|
|
1490
|
+
this.pushInstruction({ op: "block", blockType: "void" });
|
|
1491
|
+
this.pushInstruction({ op: "local.get", index: recvLocal });
|
|
1492
|
+
this.pushInstruction({ op: "ref.test", typeIndex: nilBox.typeIndex });
|
|
1493
|
+
this.pushInstruction("i32.eqz");
|
|
1494
|
+
this.pushInstruction({ op: "br_if", depth: 0 });
|
|
1495
|
+
if (cand.needsValueDeref || cand.embedPath) {
|
|
1496
|
+
this.emitPanic(
|
|
1497
|
+
"runtime error: invalid memory address or nil pointer dereference",
|
|
1498
|
+
);
|
|
1499
|
+
} else {
|
|
1500
|
+
this.pushInstruction({ op: "ref.null", heapType: cand.testTypeIndex });
|
|
1501
|
+
for (let p = 1; p < fn.params.length; p++) {
|
|
1502
|
+
this.pushInstruction({ op: "local.get", index: p });
|
|
1503
|
+
}
|
|
1504
|
+
this.pushInstruction({ op: "call", funcIndex: cand.funcIndex });
|
|
1505
|
+
this.pushInstruction("return");
|
|
1506
|
+
}
|
|
1507
|
+
this.pushInstruction("end");
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1448
1510
|
// A value-receiver method reached through a pointer box reads the pointee
|
|
1449
1511
|
// first, so a nil pointer inside the interface is a catchable panic.
|
|
1450
1512
|
_emitNilPtrBoxPanic(cand, recvLocal) {
|
|
@@ -1570,11 +1632,9 @@ export class FunctionEmitter {
|
|
|
1570
1632
|
size,
|
|
1571
1633
|
});
|
|
1572
1634
|
} else {
|
|
1573
|
-
this.
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
typeIndex: arrInfo.typeIndex,
|
|
1577
|
-
});
|
|
1635
|
+
this._emitNewArray(elemType, arrInfo, () =>
|
|
1636
|
+
this.pushInstruction({ op: "i32.const", value: size }),
|
|
1637
|
+
);
|
|
1578
1638
|
}
|
|
1579
1639
|
return;
|
|
1580
1640
|
}
|
|
@@ -1616,8 +1676,24 @@ export class FunctionEmitter {
|
|
|
1616
1676
|
}
|
|
1617
1677
|
}
|
|
1618
1678
|
|
|
1619
|
-
|
|
1620
|
-
|
|
1679
|
+
// Pushes a new array of `arrInfo` with the length `emitLen` pushes. Elements
|
|
1680
|
+
// start at their zero value: strings are the empty string, not a null
|
|
1681
|
+
// reference, so the array reads, compares and prints like Go's.
|
|
1682
|
+
_emitNewArray(elemType, arrInfo, emitLen) {
|
|
1683
|
+
if (
|
|
1684
|
+
arrInfo.elemWType === "externref" &&
|
|
1685
|
+
isStringType(elemType, this.mod.checker)
|
|
1686
|
+
) {
|
|
1687
|
+
this.emitZeroValue(elemType, "externref");
|
|
1688
|
+
emitLen();
|
|
1689
|
+
this.pushInstruction({ op: "array.new", typeIndex: arrInfo.typeIndex });
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
emitLen();
|
|
1693
|
+
this.pushInstruction({
|
|
1694
|
+
op: "array.new_default",
|
|
1695
|
+
typeIndex: arrInfo.typeIndex,
|
|
1696
|
+
});
|
|
1621
1697
|
}
|
|
1622
1698
|
|
|
1623
1699
|
// Temps are keyed by a canonical string so ref-typed temps (fresh object
|
|
@@ -1796,10 +1872,25 @@ export class FunctionEmitter {
|
|
|
1796
1872
|
this.emitExprStmt(stmt);
|
|
1797
1873
|
break;
|
|
1798
1874
|
|
|
1875
|
+
// Evaluates `stmt.expr` and panics (recoverably) when it is nil.
|
|
1876
|
+
case "NilCheckStmt":
|
|
1877
|
+
this.emitExpr(stmt.expr, "anyref");
|
|
1878
|
+
this._emitNilBranch();
|
|
1879
|
+
this.pushInstruction("drop");
|
|
1880
|
+
break;
|
|
1881
|
+
|
|
1799
1882
|
case "LabeledStmt":
|
|
1800
1883
|
if (stmt.body) {
|
|
1801
|
-
|
|
1884
|
+
// Stacked labels (`a: b: for`) all target the loop: outer
|
|
1885
|
+
// labels alias the innermost one.
|
|
1886
|
+
if (stmt.body.kind !== "LabeledStmt") {
|
|
1802
1887
|
stmt.body.label = stmt.label;
|
|
1888
|
+
this._labelAliases?.delete(stmt.label);
|
|
1889
|
+
} else {
|
|
1890
|
+
let inner = stmt.body;
|
|
1891
|
+
while (inner.body?.kind === "LabeledStmt") inner = inner.body;
|
|
1892
|
+
this._labelAliases ??= new Map();
|
|
1893
|
+
this._labelAliases.set(stmt.label, inner.label);
|
|
1803
1894
|
}
|
|
1804
1895
|
this.emitStmt(stmt.body);
|
|
1805
1896
|
}
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
import { foldConstExpr } from "../../typechecker/const-fold.js";
|
|
6
6
|
import { orderPackageInits } from "../../typechecker/init-order.js";
|
|
7
7
|
import { _someNode } from "./prescan.js";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
isStringType,
|
|
10
|
+
isStructType,
|
|
11
|
+
toWasmType,
|
|
12
|
+
variadicAsSlice,
|
|
13
|
+
} from "./types.js";
|
|
9
14
|
|
|
10
15
|
// Package-level `const` declarations (iota is already substituted by the
|
|
11
16
|
// parser). Literals and expressions the folder can reduce become BasicLits in
|
|
@@ -169,6 +174,36 @@ function _zeroArrayConst(goType, mod, depth = 0) {
|
|
|
169
174
|
return out;
|
|
170
175
|
}
|
|
171
176
|
|
|
177
|
+
// True when the zero value of `t` holds a string (a string, or a struct or
|
|
178
|
+
// array containing one). A constant expression cannot build the empty string,
|
|
179
|
+
// so such globals get their zero value from the start function.
|
|
180
|
+
function _zeroHasString(t, mod, depth = 0) {
|
|
181
|
+
if (!t || depth > 4 || _isPointerGoType(t, mod)) return false;
|
|
182
|
+
if (isStringType(t, mod.checker)) return true;
|
|
183
|
+
const shape = _arrayShape(t, mod.checker);
|
|
184
|
+
if (shape) return _zeroHasString(shape.elem, mod, depth + 1);
|
|
185
|
+
const w = toWasmType(t, mod.checker, mod);
|
|
186
|
+
if (typeof w === "object" && typeof w?.typeIndex === "number") {
|
|
187
|
+
const info = Array.from(mod.structTypes.values()).find(
|
|
188
|
+
(x) => x.typeIndex === w.typeIndex,
|
|
189
|
+
);
|
|
190
|
+
if (info)
|
|
191
|
+
return info.fields.some((f) => _zeroHasString(f.goType, mod, depth + 1));
|
|
192
|
+
}
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Types of the names in `var a, b = f()` / `var v, ok = m[k]`: one value fills
|
|
197
|
+
// every name.
|
|
198
|
+
function _spreadValueTypes(spec, value) {
|
|
199
|
+
if (spec._commaOk)
|
|
200
|
+
return [
|
|
201
|
+
value._mapValueType ?? value._type,
|
|
202
|
+
{ kind: "basic", name: "bool" },
|
|
203
|
+
];
|
|
204
|
+
return value?._type?.types ?? [];
|
|
205
|
+
}
|
|
206
|
+
|
|
172
207
|
export function _collectPackageGlobals(progs, mod, checker) {
|
|
173
208
|
const pending = []; // non-constant initializers, run by the start function
|
|
174
209
|
const pendingConsts = []; // unfoldable consts; they run before any var
|
|
@@ -183,11 +218,12 @@ export function _collectPackageGlobals(progs, mod, checker) {
|
|
|
183
218
|
const name = names[i];
|
|
184
219
|
// Foldable consts live in `constCache`, not in a global.
|
|
185
220
|
if (isConst && !mod.isNonLiteralConst(name)) continue;
|
|
221
|
+
const spreadTypes =
|
|
222
|
+
values.length === 1 && names.length > 1
|
|
223
|
+
? _spreadValueTypes(spec, values[0])
|
|
224
|
+
: null;
|
|
186
225
|
const rawType =
|
|
187
|
-
spec.type ??
|
|
188
|
-
(values.length === 1 && names.length > 1
|
|
189
|
-
? values[0]?._type?.types?.[i]
|
|
190
|
-
: values[i]?._type);
|
|
226
|
+
spec.type ?? (spreadTypes ? spreadTypes[i] : values[i]?._type);
|
|
191
227
|
const wType = toWasmType(rawType, checker, mod);
|
|
192
228
|
const gIdx = mod.globals.length;
|
|
193
229
|
let needsRuntimeZero = false;
|
|
@@ -252,6 +288,9 @@ export function _collectPackageGlobals(progs, mod, checker) {
|
|
|
252
288
|
}
|
|
253
289
|
}
|
|
254
290
|
|
|
291
|
+
if (values.length === 0 && _zeroHasString(rawType, mod))
|
|
292
|
+
needsRuntimeZero = true;
|
|
293
|
+
|
|
255
294
|
let litNode = values?.[i];
|
|
256
295
|
let sign = 1;
|
|
257
296
|
if (
|
|
@@ -302,7 +341,7 @@ export function _collectPackageGlobals(progs, mod, checker) {
|
|
|
302
341
|
if (needsRuntimeZero) pending.push({ name, zeroType: rawType });
|
|
303
342
|
if (!isConst && i === 0 && values.length === 1 && names.length > 1) {
|
|
304
343
|
// `var q, r = pair()`: one call fills every name.
|
|
305
|
-
pending.push({ name, names, expr: values[0] });
|
|
344
|
+
pending.push({ name, names, expr: values[0], types: spreadTypes });
|
|
306
345
|
}
|
|
307
346
|
if (values[i] && !isConstInit && names.length === values.length) {
|
|
308
347
|
(isConst ? pendingConsts : pending).push({
|
|
@@ -355,7 +394,7 @@ export function _orderConstInits(entries) {
|
|
|
355
394
|
// initializer in declaration order and invoking package `init()` functions;
|
|
356
395
|
// registered as the module start function.
|
|
357
396
|
export function _makeGlobalInitFunc(pending, initNames = []) {
|
|
358
|
-
const stmts = pending.map(({ name, names, expr, zeroType }) =>
|
|
397
|
+
const stmts = pending.map(({ name, names, expr, types, zeroType }) =>
|
|
359
398
|
zeroType
|
|
360
399
|
? { kind: "GlobalZeroInit", name, goType: zeroType }
|
|
361
400
|
: {
|
|
@@ -364,7 +403,7 @@ export function _makeGlobalInitFunc(pending, initNames = []) {
|
|
|
364
403
|
? names.map((n, i) => ({
|
|
365
404
|
kind: "Ident",
|
|
366
405
|
name: n,
|
|
367
|
-
_type: expr._type?.types?.[i],
|
|
406
|
+
_type: types?.[i] ?? expr._type?.types?.[i],
|
|
368
407
|
}))
|
|
369
408
|
: [{ kind: "Ident", name, _type: expr._type }],
|
|
370
409
|
op: "=",
|
package/src/backend/wasm/glue.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
// src/backend/wasm/glue.js
|
|
2
2
|
// Runtime imports and JS glue for executing GoFront WASM modules.
|
|
3
3
|
|
|
4
|
-
import { WASM_IMPORTS_JS
|
|
4
|
+
import { WASM_IMPORTS_JS } from "./boundary.js";
|
|
5
5
|
|
|
6
6
|
// The import table is authored once as source text (it is spliced into the
|
|
7
7
|
// production bundle by the facade); evaluate that same text here so tests
|
|
8
8
|
// exercise exactly what ships. The text is a compile-time constant.
|
|
9
|
-
const makeImports = new Function(
|
|
10
|
-
`${WASM_IMPORTS_JS}\n${WASM_STDLIB_JS}\nreturn __gfw_imports;`,
|
|
11
|
-
)();
|
|
9
|
+
const makeImports = new Function(`${WASM_IMPORTS_JS}\nreturn __gfw_imports;`)();
|
|
12
10
|
|
|
13
11
|
function createWasmImports({
|
|
14
12
|
stringTable = [],
|