goscript 0.1.0 → 0.1.1
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 +267 -255
- package/cmd/goscript/cmd-test.go +193 -0
- package/cmd/goscript/cmd-test_test.go +76 -0
- package/cmd/goscript/main.go +1 -0
- package/compiler/build-flags.go +38 -0
- package/compiler/compile-request.go +2 -0
- package/compiler/compliance_test.go +0 -8
- package/compiler/gotest/owner.go +24 -0
- package/compiler/gotest/package-result.go +67 -0
- package/compiler/gotest/request.go +145 -0
- package/compiler/gotest/result.go +28 -0
- package/compiler/gotest/runner.go +588 -0
- package/compiler/gotest/runner_test.go +627 -0
- package/compiler/gotest/test.go +9 -0
- package/compiler/index.test.ts +1 -1
- package/compiler/lowered-program.go +71 -19
- package/compiler/lowering.go +5065 -569
- package/compiler/override-facts.go +307 -0
- package/compiler/override-registry.go +50 -189
- package/compiler/override-registry_test.go +47 -0
- package/compiler/package-graph.go +50 -27
- package/compiler/package-graph_test.go +37 -2
- package/compiler/package-test-function.go +9 -0
- package/compiler/package-test-graph-package.go +40 -0
- package/compiler/package-test-graph-variant.go +105 -0
- package/compiler/package-test-graph.go +117 -0
- package/compiler/package-test-graph_test.go +144 -0
- package/compiler/runtime-contract.go +189 -29
- package/compiler/runtime-contract_test.go +44 -30
- package/compiler/semantic-model-types.go +9 -6
- package/compiler/semantic-model.go +538 -38
- package/compiler/semantic-model_test.go +55 -0
- package/compiler/service.go +1 -1
- package/compiler/skeleton_test.go +679 -49
- package/compiler/tsworkspace/owner.go +334 -0
- package/compiler/tsworkspace/owner_test.go +93 -0
- package/compiler/tsworkspace/result.go +17 -0
- package/compiler/typescript-emitter.go +459 -82
- package/compiler/wasm/compile.go +1 -1
- package/compiler/wasm/compile_test.go +61 -11
- package/compiler/wasm_api.go +172 -7
- package/dist/gs/builtin/builtin.d.ts +20 -2
- package/dist/gs/builtin/builtin.js +194 -6
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +8 -0
- package/dist/gs/builtin/channel.js +12 -0
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +22 -2
- package/dist/gs/builtin/slice.js +216 -44
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +5 -2
- package/dist/gs/builtin/type.js +83 -24
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +5 -0
- package/dist/gs/builtin/varRef.js +23 -0
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +48 -44
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js +20 -18
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/context/context.d.ts +5 -4
- package/dist/gs/context/context.js +10 -10
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/internal/fips140deps/byteorder/index.d.ts +1 -0
- package/dist/gs/crypto/internal/fips140deps/byteorder/index.js +2 -0
- package/dist/gs/crypto/internal/fips140deps/byteorder/index.js.map +1 -0
- package/dist/gs/crypto/internal/fips140deps/godebug/index.d.ts +1 -0
- package/dist/gs/crypto/internal/fips140deps/godebug/index.js +2 -0
- package/dist/gs/crypto/internal/fips140deps/godebug/index.js.map +1 -0
- package/dist/gs/embed/index.d.ts +7 -0
- package/dist/gs/embed/index.js +16 -0
- package/dist/gs/embed/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +1 -0
- package/dist/gs/encoding/json/index.js +18 -0
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/errors/errors.d.ts +4 -0
- package/dist/gs/errors/errors.js +81 -0
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +4 -4
- package/dist/gs/fmt/fmt.js +42 -11
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +35 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +211 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +189 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +825 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +163 -0
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +449 -0
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -0
- package/dist/gs/github.com/klauspost/compress/internal/le/index.d.ts +9 -0
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js +71 -0
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -0
- package/dist/gs/go/internal/scannerhooks/index.d.ts +3 -0
- package/dist/gs/go/internal/scannerhooks/index.js +5 -0
- package/dist/gs/go/internal/scannerhooks/index.js.map +1 -0
- package/dist/gs/go/scanner/index.d.ts +13 -0
- package/dist/gs/go/scanner/index.js +35 -0
- package/dist/gs/go/scanner/index.js.map +1 -1
- package/dist/gs/go/token/index.d.ts +156 -0
- package/dist/gs/go/token/index.js +500 -4
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/internal/abi/index.d.ts +4 -0
- package/dist/gs/internal/abi/index.js +10 -0
- package/dist/gs/internal/abi/index.js.map +1 -1
- package/dist/gs/internal/bytealg/index.d.ts +2 -0
- package/dist/gs/internal/bytealg/index.js +14 -0
- package/dist/gs/internal/bytealg/index.js.map +1 -1
- package/dist/gs/internal/byteorder/index.d.ts +8 -2
- package/dist/gs/internal/byteorder/index.js +56 -25
- package/dist/gs/internal/byteorder/index.js.map +1 -1
- package/dist/gs/internal/godebug/index.d.ts +12 -0
- package/dist/gs/internal/godebug/index.js +30 -0
- package/dist/gs/internal/godebug/index.js.map +1 -0
- package/dist/gs/io/fs/index.d.ts +1 -0
- package/dist/gs/io/fs/index.js +1 -0
- package/dist/gs/io/fs/index.js.map +1 -1
- package/dist/gs/io/fs/readlink.d.ts +8 -0
- package/dist/gs/io/fs/readlink.js +64 -0
- package/dist/gs/io/fs/readlink.js.map +1 -0
- package/dist/gs/io/fs/walk.d.ts +3 -3
- package/dist/gs/io/fs/walk.js +7 -7
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/io/io.d.ts +40 -6
- package/dist/gs/io/io.js +151 -26
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/maps/iter.d.ts +3 -3
- package/dist/gs/maps/iter.js +3 -3
- package/dist/gs/maps/iter.js.map +1 -1
- package/dist/gs/maps/maps.d.ts +2 -2
- package/dist/gs/maps/maps.js +1 -1
- package/dist/gs/maps/maps.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +13 -4
- package/dist/gs/math/bits/index.js +66 -34
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/math/const.gs.d.ts +5 -5
- package/dist/gs/math/const.gs.js +4 -4
- package/dist/gs/math/const.gs.js.map +1 -1
- package/dist/gs/mime/index.d.ts +1 -0
- package/dist/gs/mime/index.js +50 -0
- package/dist/gs/mime/index.js.map +1 -0
- package/dist/gs/net/http/httptest/index.d.ts +11 -0
- package/dist/gs/net/http/httptest/index.js +21 -0
- package/dist/gs/net/http/httptest/index.js.map +1 -0
- package/dist/gs/net/http/index.d.ts +27 -0
- package/dist/gs/net/http/index.js +61 -0
- package/dist/gs/net/http/index.js.map +1 -0
- package/dist/gs/os/dir_unix.gs.js +2 -2
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js +165 -3
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/filepath/path.d.ts +3 -1
- package/dist/gs/path/filepath/path.js +133 -4
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/path/path.d.ts +4 -1
- package/dist/gs/path/path.js +16 -4
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +1 -1
- package/dist/gs/reflect/index.js +1 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js +3 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +7 -4
- package/dist/gs/reflect/type.js +148 -7
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/runtime/debug/index.d.ts +2 -0
- package/dist/gs/runtime/debug/index.js +8 -0
- package/dist/gs/runtime/debug/index.js.map +1 -0
- package/dist/gs/runtime/runtime.d.ts +35 -3
- package/dist/gs/runtime/runtime.js +72 -0
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +24 -5
- package/dist/gs/slices/slices.js +214 -5
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/slice.gs.d.ts +3 -3
- package/dist/gs/sort/slice.gs.js +6 -6
- package/dist/gs/sort/slice.gs.js.map +1 -1
- package/dist/gs/sort/sort.gs.d.ts +4 -4
- package/dist/gs/sort/sort.gs.js +11 -8
- package/dist/gs/sort/sort.gs.js.map +1 -1
- package/dist/gs/strings/builder.d.ts +1 -1
- package/dist/gs/strings/builder.js +3 -2
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.d.ts +9 -8
- package/dist/gs/sync/atomic/type.gs.js +0 -2
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +2 -0
- package/dist/gs/sync/sync.js +27 -0
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/constants.d.ts +36 -24
- package/dist/gs/syscall/constants.js +12 -0
- package/dist/gs/syscall/constants.js.map +1 -1
- package/dist/gs/syscall/errors.d.ts +2 -0
- package/dist/gs/syscall/errors.js +8 -0
- package/dist/gs/syscall/errors.js.map +1 -1
- package/dist/gs/syscall/fs.d.ts +43 -0
- package/dist/gs/syscall/fs.js +102 -0
- package/dist/gs/syscall/fs.js.map +1 -1
- package/dist/gs/syscall/js/index.d.ts +90 -0
- package/dist/gs/syscall/js/index.js +375 -0
- package/dist/gs/syscall/js/index.js.map +1 -0
- package/dist/gs/syscall/types.d.ts +22 -0
- package/dist/gs/syscall/types.js +45 -1
- package/dist/gs/syscall/types.js.map +1 -1
- package/dist/gs/testing/index.d.ts +1 -0
- package/dist/gs/testing/index.js +2 -0
- package/dist/gs/testing/index.js.map +1 -0
- package/dist/gs/testing/testing.d.ts +77 -0
- package/dist/gs/testing/testing.js +301 -0
- package/dist/gs/testing/testing.js.map +1 -0
- package/dist/gs/time/time.d.ts +41 -4
- package/dist/gs/time/time.js +205 -36
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.d.ts +23 -1
- package/dist/gs/unicode/unicode.js +79 -10
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/dist/gs/unicode/utf8/utf8.d.ts +4 -4
- package/dist/gs/unicode/utf8/utf8.js +24 -11
- package/dist/gs/unicode/utf8/utf8.js.map +1 -1
- package/dist/gs/unique/index.d.ts +11 -0
- package/dist/gs/unique/index.js +71 -0
- package/dist/gs/unique/index.js.map +1 -0
- package/go.sum +9 -0
- package/gs/builtin/builtin.ts +239 -8
- package/gs/builtin/channel.ts +22 -0
- package/gs/builtin/runtime-contract.test.ts +126 -0
- package/gs/builtin/slice.ts +259 -50
- package/gs/builtin/type.ts +109 -34
- package/gs/builtin/varRef.ts +38 -1
- package/gs/bytes/buffer.gs.ts +48 -44
- package/gs/bytes/meta.json +8 -3
- package/gs/bytes/reader.gs.ts +20 -19
- package/gs/context/context.test.ts +41 -0
- package/gs/context/context.ts +22 -26
- package/gs/crypto/internal/fips140deps/byteorder/index.ts +1 -0
- package/gs/crypto/internal/fips140deps/godebug/index.ts +1 -0
- package/gs/embed/index.ts +20 -0
- package/gs/embed/meta.json +5 -0
- package/gs/encoding/json/index.test.ts +15 -1
- package/gs/encoding/json/index.ts +24 -0
- package/gs/errors/errors.test.ts +82 -0
- package/gs/errors/errors.ts +104 -0
- package/gs/fmt/fmt.ts +56 -16
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +73 -1
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +297 -1
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +159 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +1005 -0
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +719 -0
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +40 -0
- package/gs/github.com/klauspost/compress/internal/le/index.test.ts +36 -0
- package/gs/github.com/klauspost/compress/internal/le/index.ts +114 -0
- package/gs/go/internal/scannerhooks/index.test.ts +14 -0
- package/gs/go/internal/scannerhooks/index.ts +9 -0
- package/gs/go/scanner/index.test.ts +22 -0
- package/gs/go/scanner/index.ts +47 -0
- package/gs/go/token/index.test.ts +47 -1
- package/gs/go/token/index.ts +570 -4
- package/gs/internal/abi/index.test.ts +18 -0
- package/gs/internal/abi/index.ts +14 -0
- package/gs/internal/bytealg/index.test.ts +18 -0
- package/gs/internal/bytealg/index.ts +16 -0
- package/gs/internal/byteorder/index.test.ts +39 -0
- package/gs/internal/byteorder/index.ts +100 -27
- package/gs/internal/godebug/index.test.ts +16 -0
- package/gs/internal/godebug/index.ts +35 -0
- package/gs/io/fs/index.ts +1 -0
- package/gs/io/fs/meta.json +5 -0
- package/gs/io/fs/readlink.test.ts +43 -0
- package/gs/io/fs/readlink.ts +77 -0
- package/gs/io/fs/walk.test.ts +61 -0
- package/gs/io/fs/walk.ts +9 -9
- package/gs/io/io.ts +174 -31
- package/gs/io/meta.json +10 -2
- package/gs/maps/iter.ts +12 -6
- package/gs/maps/maps.ts +8 -6
- package/gs/math/bits/index.ts +103 -47
- package/gs/math/const.gs.test.ts +11 -5
- package/gs/math/const.gs.ts +5 -6
- package/gs/mime/index.ts +54 -0
- package/gs/net/http/httptest/index.ts +25 -0
- package/gs/net/http/index.test.ts +20 -0
- package/gs/net/http/index.ts +81 -0
- package/gs/os/dir_unix.gs.ts +2 -3
- package/gs/os/types_js.gs.ts +2 -2
- package/gs/path/filepath/match.test.ts +31 -12
- package/gs/path/filepath/match.ts +178 -3
- package/gs/path/filepath/path.test.ts +25 -0
- package/gs/path/filepath/path.ts +159 -5
- package/gs/path/path.ts +20 -5
- package/gs/reflect/index.ts +1 -0
- package/gs/reflect/map.test.ts +19 -0
- package/gs/reflect/map.ts +4 -0
- package/gs/reflect/type.ts +197 -17
- package/gs/runtime/debug/index.test.ts +24 -0
- package/gs/runtime/debug/index.ts +8 -0
- package/gs/runtime/runtime.test.ts +19 -0
- package/gs/runtime/runtime.ts +98 -3
- package/gs/slices/slices.test.ts +94 -0
- package/gs/slices/slices.ts +245 -5
- package/gs/sort/meta.json +7 -0
- package/gs/sort/slice.gs.ts +16 -7
- package/gs/sort/sort.gs.ts +16 -13
- package/gs/strings/builder.ts +4 -3
- package/gs/sync/atomic/type.gs.ts +13 -14
- package/gs/sync/meta.json +3 -1
- package/gs/sync/sync.test.ts +13 -1
- package/gs/sync/sync.ts +27 -0
- package/gs/syscall/constants.ts +39 -24
- package/gs/syscall/errors.ts +10 -0
- package/gs/syscall/fs.ts +195 -0
- package/gs/syscall/js/index.ts +458 -0
- package/gs/syscall/js/meta.json +4 -0
- package/gs/syscall/net.test.ts +85 -0
- package/gs/syscall/types.ts +56 -0
- package/gs/testing/index.ts +1 -0
- package/gs/testing/meta.json +5 -0
- package/gs/testing/testing.test.ts +90 -0
- package/gs/testing/testing.ts +382 -0
- package/gs/time/time.test.ts +106 -0
- package/gs/time/time.ts +278 -57
- package/gs/unicode/unicode.test.ts +25 -0
- package/gs/unicode/unicode.ts +119 -9
- package/gs/unicode/utf8/utf8.test.ts +13 -0
- package/gs/unicode/utf8/utf8.ts +28 -16
- package/gs/unique/index.ts +91 -0
- package/package.json +2 -1
package/gs/builtin/builtin.ts
CHANGED
|
@@ -35,7 +35,7 @@ export function panic(...args: any[]): never {
|
|
|
35
35
|
* For maps, it deletes all entries.
|
|
36
36
|
* @param v The slice or map to clear
|
|
37
37
|
*/
|
|
38
|
-
export function clear<T>(v: T
|
|
38
|
+
export function clear<T>(v: Slice<T> | Map<unknown, unknown> | null): void {
|
|
39
39
|
if (v === null || v === undefined) {
|
|
40
40
|
return
|
|
41
41
|
}
|
|
@@ -43,12 +43,40 @@ export function clear<T>(v: T[] | Map<unknown, unknown> | null): void {
|
|
|
43
43
|
v.clear()
|
|
44
44
|
return
|
|
45
45
|
}
|
|
46
|
+
if (v instanceof Uint8Array) {
|
|
47
|
+
v.fill(0)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
if (isSliceProxy(v)) {
|
|
51
|
+
const zero = clearZeroValue(v)
|
|
52
|
+
for (let i = 0; i < v.length; i++) {
|
|
53
|
+
v[i] = zero
|
|
54
|
+
}
|
|
55
|
+
return
|
|
56
|
+
}
|
|
46
57
|
if (Array.isArray(v)) {
|
|
47
|
-
v.fill(
|
|
58
|
+
v.fill(clearZeroValue(v))
|
|
48
59
|
return
|
|
49
60
|
}
|
|
50
61
|
}
|
|
51
62
|
|
|
63
|
+
function clearZeroValue<T>(v: T[]): T {
|
|
64
|
+
for (const item of v) {
|
|
65
|
+
if (item !== null && item !== undefined) {
|
|
66
|
+
switch (typeof item) {
|
|
67
|
+
case 'number':
|
|
68
|
+
return 0 as T
|
|
69
|
+
case 'string':
|
|
70
|
+
return '' as T
|
|
71
|
+
case 'boolean':
|
|
72
|
+
return false as T
|
|
73
|
+
}
|
|
74
|
+
break
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return null as T
|
|
78
|
+
}
|
|
79
|
+
|
|
52
80
|
/**
|
|
53
81
|
* assignStruct copies all field values from source struct to target struct.
|
|
54
82
|
* Used for pointer dereference assignment: *p = value
|
|
@@ -96,13 +124,137 @@ export function pointerValue<T>(value: T | VarRef<T> | null | undefined): T {
|
|
|
96
124
|
return value
|
|
97
125
|
}
|
|
98
126
|
|
|
127
|
+
export function arrayEqual(a: unknown, b: unknown): boolean {
|
|
128
|
+
return comparableEqual(a, b)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function comparableEqual(a: unknown, b: unknown): boolean {
|
|
132
|
+
if (a === b) {
|
|
133
|
+
return true
|
|
134
|
+
}
|
|
135
|
+
if (a === null || a === undefined || b === null || b === undefined) {
|
|
136
|
+
return false
|
|
137
|
+
}
|
|
138
|
+
if (isArrayLike(a) && isArrayLike(b)) {
|
|
139
|
+
if (a.length !== b.length) {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
for (let i = 0; i < a.length; i++) {
|
|
143
|
+
if (!comparableEqual(a[i], b[i])) {
|
|
144
|
+
return false
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
if (hasGoType(a) || hasGoType(b)) {
|
|
150
|
+
if (!hasGoType(a) || !hasGoType(b) || a.__goType !== b.__goType) {
|
|
151
|
+
return false
|
|
152
|
+
}
|
|
153
|
+
if (a.__isTypedNil || b.__isTypedNil) {
|
|
154
|
+
return a.__isTypedNil === true && b.__isTypedNil === true
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (isStructValue(a) && isStructValue(b)) {
|
|
158
|
+
return fieldsEqual(a._fields, b._fields)
|
|
159
|
+
}
|
|
160
|
+
return false
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function isArrayLike(value: unknown): value is ArrayLike<unknown> {
|
|
164
|
+
return Array.isArray(value) || value instanceof Uint8Array
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function hasGoType(value: unknown): value is {
|
|
168
|
+
__goType: string
|
|
169
|
+
__isTypedNil?: boolean
|
|
170
|
+
} {
|
|
171
|
+
return (
|
|
172
|
+
typeof value === 'object' &&
|
|
173
|
+
value !== null &&
|
|
174
|
+
typeof (value as { __goType?: unknown }).__goType === 'string'
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function isStructValue(value: unknown): value is {
|
|
179
|
+
_fields: Record<string, VarRef<unknown>>
|
|
180
|
+
} {
|
|
181
|
+
return (
|
|
182
|
+
typeof value === 'object' &&
|
|
183
|
+
value !== null &&
|
|
184
|
+
typeof (value as { _fields?: unknown })._fields === 'object' &&
|
|
185
|
+
(value as { _fields?: unknown })._fields !== null
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function fieldsEqual(
|
|
190
|
+
a: Record<string, VarRef<unknown>>,
|
|
191
|
+
b: Record<string, VarRef<unknown>>,
|
|
192
|
+
): boolean {
|
|
193
|
+
const aKeys = Object.keys(a)
|
|
194
|
+
const bKeys = Object.keys(b)
|
|
195
|
+
if (aKeys.length !== bKeys.length) {
|
|
196
|
+
return false
|
|
197
|
+
}
|
|
198
|
+
for (const key of aKeys) {
|
|
199
|
+
if (!(key in b) || !comparableEqual(a[key].value, b[key].value)) {
|
|
200
|
+
return false
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return true
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export interface Complex {
|
|
207
|
+
real: number
|
|
208
|
+
imag: number
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function complex(real: number, imag: number): Complex {
|
|
212
|
+
return { real, imag }
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function real(value: number | Complex | null | undefined): number {
|
|
216
|
+
if (typeof value === 'number') {
|
|
217
|
+
return value
|
|
218
|
+
}
|
|
219
|
+
return value?.real ?? 0
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function imag(value: number | Complex | null | undefined): number {
|
|
223
|
+
if (typeof value === 'number') {
|
|
224
|
+
return 0
|
|
225
|
+
}
|
|
226
|
+
return value?.imag ?? 0
|
|
227
|
+
}
|
|
228
|
+
|
|
99
229
|
// Bytes represents all valid []byte representations in TypeScript
|
|
100
230
|
// This includes Uint8Array (the preferred representation) and $.Slice<number> (which includes null)
|
|
101
231
|
export type Bytes = Uint8Array | Slice<number>
|
|
102
232
|
|
|
103
233
|
// int converts a value to a Go int type, handling proper signed integer conversion
|
|
104
234
|
// This ensures that values like 2147483648 (2^31) are properly handled according to Go semantics
|
|
105
|
-
export function int(value: number): number {
|
|
235
|
+
export function int(value: number | bigint, bits = 0): number {
|
|
236
|
+
if (typeof value === 'bigint') {
|
|
237
|
+
if (bits > 0 && bits <= 64) {
|
|
238
|
+
return Number(BigInt.asIntN(bits, value))
|
|
239
|
+
}
|
|
240
|
+
return Number(value)
|
|
241
|
+
}
|
|
242
|
+
if (bits > 0 && bits < 64) {
|
|
243
|
+
const modulo = 2 ** bits
|
|
244
|
+
const sign = 2 ** (bits - 1)
|
|
245
|
+
let truncated = Math.trunc(value)
|
|
246
|
+
if (!Number.isFinite(truncated)) {
|
|
247
|
+
return truncated
|
|
248
|
+
}
|
|
249
|
+
truncated %= modulo
|
|
250
|
+
if (truncated < 0) {
|
|
251
|
+
truncated += modulo
|
|
252
|
+
}
|
|
253
|
+
if (truncated >= sign) {
|
|
254
|
+
truncated -= modulo
|
|
255
|
+
}
|
|
256
|
+
return truncated
|
|
257
|
+
}
|
|
106
258
|
// In Go, int is typically 64-bit on 64-bit systems, but for compatibility with JavaScript
|
|
107
259
|
// we need to handle the conversion properly. The issue is that JavaScript's number type
|
|
108
260
|
// can represent values larger than 32-bit signed integers, but when cast in certain contexts
|
|
@@ -115,6 +267,86 @@ export function int(value: number): number {
|
|
|
115
267
|
return Math.trunc(value)
|
|
116
268
|
}
|
|
117
269
|
|
|
270
|
+
// uint converts a value to an unsigned Go integer width.
|
|
271
|
+
export function uint(value: number | bigint, bits = 64): number {
|
|
272
|
+
if (typeof value === 'bigint') {
|
|
273
|
+
const normalized = BigInt.asUintN(Math.min(bits, 64), value)
|
|
274
|
+
if (bits >= 64) {
|
|
275
|
+
return normalized as unknown as number
|
|
276
|
+
}
|
|
277
|
+
return Number(normalized)
|
|
278
|
+
}
|
|
279
|
+
const modulo = bits >= 64 ? 2 ** 64 : 2 ** bits
|
|
280
|
+
let truncated = Math.trunc(value)
|
|
281
|
+
if (!Number.isFinite(truncated)) {
|
|
282
|
+
return truncated
|
|
283
|
+
}
|
|
284
|
+
truncated %= modulo
|
|
285
|
+
if (truncated < 0) {
|
|
286
|
+
truncated += modulo
|
|
287
|
+
}
|
|
288
|
+
return truncated
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export function uint64Shl(value: number | bigint, shift: number | bigint): number {
|
|
292
|
+
return uint64Result(uint64Value(value) << BigInt(Math.trunc(Number(shift))))
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function uint64Shr(value: number | bigint, shift: number | bigint): number {
|
|
296
|
+
return uint64Result(uint64Value(value) >> BigInt(Math.trunc(Number(shift))))
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function uintShr(
|
|
300
|
+
value: number | bigint,
|
|
301
|
+
shift: number | bigint,
|
|
302
|
+
bits = 32,
|
|
303
|
+
): number {
|
|
304
|
+
const width = Math.min(bits, 32)
|
|
305
|
+
const amount = Math.trunc(Number(shift))
|
|
306
|
+
if (amount < 0) {
|
|
307
|
+
throw new Error('runtime error: negative shift amount')
|
|
308
|
+
}
|
|
309
|
+
if (amount >= width) {
|
|
310
|
+
return 0
|
|
311
|
+
}
|
|
312
|
+
return uint(value, width) >>> amount
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export function uint64Mul(left: number | bigint, right: number | bigint): number {
|
|
316
|
+
return uint64Result(uint64Value(left) * uint64Value(right))
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export function uint64Add(left: number | bigint, right: number | bigint): number {
|
|
320
|
+
return uint64Result(uint64Value(left) + uint64Value(right))
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export function uint64Sub(left: number | bigint, right: number | bigint): number {
|
|
324
|
+
return uint64Result(uint64Value(left) - uint64Value(right))
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function uint64And(left: number | bigint, right: number | bigint): number {
|
|
328
|
+
return uint64Result(uint64Value(left) & uint64Value(right))
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function uint64Or(left: number | bigint, right: number | bigint): number {
|
|
332
|
+
return uint64Result(uint64Value(left) | uint64Value(right))
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function uint64Xor(left: number | bigint, right: number | bigint): number {
|
|
336
|
+
return uint64Result(uint64Value(left) ^ uint64Value(right))
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function uint64Value(value: number | bigint): bigint {
|
|
340
|
+
if (typeof value === 'bigint') {
|
|
341
|
+
return BigInt.asUintN(64, value)
|
|
342
|
+
}
|
|
343
|
+
return BigInt.asUintN(64, BigInt(Math.trunc(value)))
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function uint64Result(value: bigint): number {
|
|
347
|
+
return BigInt.asUintN(64, value) as unknown as number
|
|
348
|
+
}
|
|
349
|
+
|
|
118
350
|
/**
|
|
119
351
|
* Normalizes various byte representations into a `Uint8Array` for protobuf compatibility.
|
|
120
352
|
*
|
|
@@ -248,17 +480,16 @@ export function bytesToArray(bytes: Bytes | null): number[] {
|
|
|
248
480
|
return Array.from(bytes)
|
|
249
481
|
}
|
|
250
482
|
|
|
251
|
-
if (Array.isArray(bytes)) {
|
|
252
|
-
return bytes
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Handle SliceProxy
|
|
256
483
|
if (isSliceProxy(bytes)) {
|
|
257
484
|
const proxy = bytes as SliceProxy<number>
|
|
258
485
|
const meta = proxy.__meta__
|
|
259
486
|
return meta.backing.slice(meta.offset, meta.offset + meta.length)
|
|
260
487
|
}
|
|
261
488
|
|
|
489
|
+
if (Array.isArray(bytes)) {
|
|
490
|
+
return bytes
|
|
491
|
+
}
|
|
492
|
+
|
|
262
493
|
throw new Error(`Cannot convert bytes of type ${typeof bytes} to array`)
|
|
263
494
|
}
|
|
264
495
|
|
package/gs/builtin/channel.ts
CHANGED
|
@@ -77,6 +77,11 @@ export interface Channel<T> {
|
|
|
77
77
|
* Used for non-blocking select operations.
|
|
78
78
|
*/
|
|
79
79
|
canSendNonBlocking(): boolean
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Reports the number of buffered values currently queued in the channel.
|
|
83
|
+
*/
|
|
84
|
+
len(): number
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
/**
|
|
@@ -530,6 +535,10 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
530
535
|
this.receiversWithOk.length > 0
|
|
531
536
|
)
|
|
532
537
|
}
|
|
538
|
+
|
|
539
|
+
len(): number {
|
|
540
|
+
return this.buffer.length
|
|
541
|
+
}
|
|
533
542
|
}
|
|
534
543
|
|
|
535
544
|
/**
|
|
@@ -555,6 +564,7 @@ export interface ChannelRef<T> {
|
|
|
555
564
|
canReceiveNonBlocking(): boolean
|
|
556
565
|
selectSend(value: T, id: number): Promise<SelectResult<boolean>>
|
|
557
566
|
selectReceive(id: number): Promise<SelectResult<T>>
|
|
567
|
+
len(): number
|
|
558
568
|
}
|
|
559
569
|
|
|
560
570
|
/**
|
|
@@ -597,6 +607,10 @@ export class BidirectionalChannelRef<T> implements ChannelRef<T> {
|
|
|
597
607
|
selectReceive(id: number): Promise<SelectResult<T>> {
|
|
598
608
|
return this.channel.selectReceive(id)
|
|
599
609
|
}
|
|
610
|
+
|
|
611
|
+
len(): number {
|
|
612
|
+
return this.channel.len()
|
|
613
|
+
}
|
|
600
614
|
}
|
|
601
615
|
|
|
602
616
|
/**
|
|
@@ -641,6 +655,10 @@ export class SendOnlyChannelRef<T> implements ChannelRef<T> {
|
|
|
641
655
|
selectReceive(_id: number): Promise<SelectResult<T>> {
|
|
642
656
|
throw new Error('Cannot receive from send-only channel')
|
|
643
657
|
}
|
|
658
|
+
|
|
659
|
+
len(): number {
|
|
660
|
+
return this.channel.len()
|
|
661
|
+
}
|
|
644
662
|
}
|
|
645
663
|
|
|
646
664
|
/**
|
|
@@ -685,6 +703,10 @@ export class ReceiveOnlyChannelRef<T> implements ChannelRef<T> {
|
|
|
685
703
|
selectSend(_value: T, _id: number): Promise<SelectResult<boolean>> {
|
|
686
704
|
throw new Error('Cannot send to receive-only channel')
|
|
687
705
|
}
|
|
706
|
+
|
|
707
|
+
len(): number {
|
|
708
|
+
return this.channel.len()
|
|
709
|
+
}
|
|
688
710
|
}
|
|
689
711
|
|
|
690
712
|
/**
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
+
bytesToUint8Array,
|
|
4
5
|
byte,
|
|
6
|
+
cap,
|
|
7
|
+
cloneStructValue,
|
|
5
8
|
callGenericMethod,
|
|
6
9
|
chanRecvWithOk,
|
|
7
10
|
functionValue,
|
|
8
11
|
genericZero,
|
|
12
|
+
goSlice,
|
|
9
13
|
int,
|
|
14
|
+
indexAddress,
|
|
15
|
+
indexRef,
|
|
10
16
|
interfaceValue,
|
|
17
|
+
len,
|
|
18
|
+
makeSlice,
|
|
11
19
|
makeChannel,
|
|
12
20
|
makeMap,
|
|
13
21
|
mapGet,
|
|
@@ -18,13 +26,26 @@ import {
|
|
|
18
26
|
pointerValue,
|
|
19
27
|
print,
|
|
20
28
|
println,
|
|
29
|
+
rangeString,
|
|
21
30
|
registerInterfaceType,
|
|
22
31
|
registerStructType,
|
|
23
32
|
resetHostRuntimeForTests,
|
|
33
|
+
sliceToArray,
|
|
24
34
|
TypeKind,
|
|
25
35
|
typeAssert,
|
|
26
36
|
typedNil,
|
|
37
|
+
uint,
|
|
38
|
+
uint64Add,
|
|
39
|
+
uint64And,
|
|
40
|
+
uint64Mul,
|
|
41
|
+
uint64Or,
|
|
42
|
+
uint64Shl,
|
|
43
|
+
uint64Shr,
|
|
44
|
+
uint64Sub,
|
|
45
|
+
uint64Xor,
|
|
46
|
+
uintShr,
|
|
27
47
|
unref,
|
|
48
|
+
unsupportedPointerRef,
|
|
28
49
|
varRef,
|
|
29
50
|
} from './index.js'
|
|
30
51
|
|
|
@@ -90,14 +111,54 @@ describe('builtin runtime contract helpers', () => {
|
|
|
90
111
|
|
|
91
112
|
it('exposes numeric, varref, map, and error helpers', () => {
|
|
92
113
|
expect(int(1.9)).toBe(1)
|
|
114
|
+
expect(int(3n)).toBe(3)
|
|
115
|
+
expect(uint(-1n, 8)).toBe(255)
|
|
93
116
|
expect(byte(257)).toBe(1)
|
|
117
|
+
expect(uint(uint64Shl(1n, 63), 32)).toBe(0)
|
|
118
|
+
expect(uint(uint64Shr(uint64Shl(1n, 63), 60), 32)).toBe(8)
|
|
119
|
+
expect(uint(uint64Mul(0xffffffffffffffffn, 3), 32)).toBe(0xfffffffd)
|
|
120
|
+
expect(uint(uint64Add(0xffffffffffffffffn, 2), 32)).toBe(1)
|
|
121
|
+
expect(uint(uint64Sub(1n, 2), 32)).toBe(0xffffffff)
|
|
122
|
+
expect(uint(uint64And(0xf0n, 0x3cn), 32)).toBe(0x30)
|
|
123
|
+
expect(uint(uint64Or(0xf0n, 0x0fn), 32)).toBe(0xff)
|
|
124
|
+
expect(uint(uint64Xor(0xf0n, 0xffn), 32)).toBe(0x0f)
|
|
125
|
+
expect(uintShr(0x80000000, 31, 32)).toBe(1)
|
|
126
|
+
expect(uintShr(0x80000000, 32, 32)).toBe(0)
|
|
127
|
+
expect(uintShr(0xff, 4, 8)).toBe(15)
|
|
94
128
|
|
|
95
129
|
const value = varRef(4)
|
|
96
130
|
value.value = 8
|
|
97
131
|
expect(unref(value)).toBe(8)
|
|
98
132
|
expect(pointerValue(value)).toBe(8)
|
|
133
|
+
const pointerAssert = typeAssert<typeof value>(value, {
|
|
134
|
+
kind: TypeKind.Pointer,
|
|
135
|
+
elemType: { kind: TypeKind.Basic, name: 'int' },
|
|
136
|
+
})
|
|
137
|
+
expect(pointerAssert).toEqual({ value, ok: true })
|
|
138
|
+
const nilNamedSlice = varRef(null)
|
|
139
|
+
const nilNamedSliceIface = interfaceValue(
|
|
140
|
+
nilNamedSlice,
|
|
141
|
+
'*main.ObjectIdentifier',
|
|
142
|
+
)
|
|
143
|
+
expect(
|
|
144
|
+
typeAssert<typeof nilNamedSlice>(nilNamedSliceIface, {
|
|
145
|
+
kind: TypeKind.Pointer,
|
|
146
|
+
elemType: 'main.ObjectIdentifier',
|
|
147
|
+
}),
|
|
148
|
+
).toEqual({ value: nilNamedSlice, ok: true })
|
|
99
149
|
expect(pointerValue({ ok: true })).toEqual({ ok: true })
|
|
150
|
+
expect(cloneStructValue({ clone: () => ({ ok: true }) })).toEqual({
|
|
151
|
+
ok: true,
|
|
152
|
+
})
|
|
153
|
+
expect(
|
|
154
|
+
cloneStructValue({ __goscriptClone: () => ({ internal: true }) }),
|
|
155
|
+
).toEqual({ internal: true })
|
|
100
156
|
expect(() => pointerValue(null)).toThrow('nil pointer dereference')
|
|
157
|
+
const unsupported = unsupportedPointerRef<number>(0)
|
|
158
|
+
expect(() => unsupported.value).toThrow('unsafe pointer dereference')
|
|
159
|
+
expect(() => {
|
|
160
|
+
unsupported.value = 1
|
|
161
|
+
}).toThrow('unsafe pointer dereference')
|
|
101
162
|
|
|
102
163
|
const m = makeMap<string, number>()
|
|
103
164
|
mapSet(m, 'answer', 42)
|
|
@@ -105,6 +166,69 @@ describe('builtin runtime contract helpers', () => {
|
|
|
105
166
|
expect(mapGet(m, 'missing', 0)).toEqual([0, false])
|
|
106
167
|
|
|
107
168
|
expect(newError('bad')?.Error()).toBe('bad')
|
|
169
|
+
expect(rangeString('a¢€')).toEqual([
|
|
170
|
+
[0, 97],
|
|
171
|
+
[1, 162],
|
|
172
|
+
[3, 8364],
|
|
173
|
+
])
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('exposes addressable slice and array index references', () => {
|
|
177
|
+
const values = [1, 2, 3]
|
|
178
|
+
const second = indexRef(values, 1)
|
|
179
|
+
second.value = 8
|
|
180
|
+
expect(values).toEqual([1, 8, 3])
|
|
181
|
+
expect(pointerValue(second)).toBe(8)
|
|
182
|
+
|
|
183
|
+
const view = goSlice(values, 1, 3)
|
|
184
|
+
const firstInView = indexRef(view, 0)
|
|
185
|
+
firstInView.value = 11
|
|
186
|
+
expect(values).toEqual([1, 11, 3])
|
|
187
|
+
expect(Object.getOwnPropertyDescriptor(view, '0')?.value).toBe(11)
|
|
188
|
+
|
|
189
|
+
const bytes = new Uint8Array([4, 5])
|
|
190
|
+
const firstByte = indexRef<number>(bytes, 0)
|
|
191
|
+
firstByte.value = 9
|
|
192
|
+
expect(Array.from(bytes)).toEqual([9, 5])
|
|
193
|
+
|
|
194
|
+
const byteBacking = makeSlice<number>(8, undefined, 'byte')
|
|
195
|
+
const shortBytes = goSlice(byteBacking as Uint8Array, 0, 2)
|
|
196
|
+
expect(len(shortBytes)).toBe(2)
|
|
197
|
+
expect(cap(shortBytes)).toBe(8)
|
|
198
|
+
const fullBytes = goSlice(shortBytes, 0, 8)
|
|
199
|
+
fullBytes![7] = 12
|
|
200
|
+
expect((byteBacking as Uint8Array)[7]).toBe(12)
|
|
201
|
+
|
|
202
|
+
shortBytes![0] = 14
|
|
203
|
+
expect(bytesToUint8Array(shortBytes)).toEqual(new Uint8Array([14, 0]))
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
it('exposes stable synthetic slice index addresses', () => {
|
|
207
|
+
const values = [1, 2, 3, 4]
|
|
208
|
+
const left = goSlice(values, 1, 3)
|
|
209
|
+
const right = goSlice(values, 2, 4)
|
|
210
|
+
const other = [8, 9]
|
|
211
|
+
|
|
212
|
+
expect(indexAddress(left, 0)).toBe(indexAddress(values, 1))
|
|
213
|
+
expect(indexAddress(left, 1)).toBe(indexAddress(right, 0))
|
|
214
|
+
expect(indexAddress(left, 1)).toBeGreaterThan(indexAddress(left, 0))
|
|
215
|
+
expect(indexAddress(other, 0)).not.toBe(indexAddress(left, 0))
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
it('copies slices into fixed arrays with Go length checks', () => {
|
|
219
|
+
const source = goSlice([1, 2, 3], 1, 3)
|
|
220
|
+
const array = sliceToArray<number>(source, 2)
|
|
221
|
+
array[0] = 9
|
|
222
|
+
|
|
223
|
+
expect(array).toEqual([9, 3])
|
|
224
|
+
expect(source![0]).toBe(2)
|
|
225
|
+
expect(() => sliceToArray<number>(source, 3)).toThrow(
|
|
226
|
+
'cannot convert slice with length 2 to array with length 3',
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
expect(sliceToArray<number>(new Uint8Array([4, 5, 6]), 2, 'byte')).toEqual(
|
|
230
|
+
new Uint8Array([4, 5]),
|
|
231
|
+
)
|
|
108
232
|
})
|
|
109
233
|
|
|
110
234
|
it('exposes value and type descriptor helpers', () => {
|
|
@@ -223,7 +347,9 @@ describe('builtin runtime contract helpers', () => {
|
|
|
223
347
|
it('exposes channel helpers used by future lowering', async () => {
|
|
224
348
|
const channel = makeChannel<number>(1, 0, 'both')
|
|
225
349
|
await channel.send(7)
|
|
350
|
+
expect(len(channel)).toBe(1)
|
|
226
351
|
expect(await chanRecvWithOk(channel)).toEqual({ value: 7, ok: true })
|
|
352
|
+
expect(len(channel)).toBe(0)
|
|
227
353
|
channel.close()
|
|
228
354
|
expect(await chanRecvWithOk(channel)).toEqual({ value: 0, ok: false })
|
|
229
355
|
})
|