goscript 0.1.1 → 0.1.3
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/cmd/goscript/cmd-test.go +104 -11
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript/cmd_compile.go +9 -0
- package/compiler/compile-request.go +31 -0
- package/compiler/compiler.go +1 -1
- package/compiler/compliance_test.go +0 -2
- package/compiler/config.go +2 -0
- package/compiler/gotest/package-result.go +2 -0
- package/compiler/gotest/request.go +85 -20
- package/compiler/gotest/runner.go +733 -96
- package/compiler/gotest/runner_test.go +647 -3
- package/compiler/lowered-program.go +10 -2
- package/compiler/lowering.go +2676 -349
- package/compiler/override-facts.go +77 -27
- package/compiler/override-registry.go +5 -4
- package/compiler/override-registry_test.go +178 -0
- package/compiler/package-graph_test.go +62 -7
- package/compiler/package-test-graph-variant.go +40 -16
- package/compiler/package-test-graph.go +0 -5
- package/compiler/package-test-graph_test.go +61 -3
- package/compiler/runtime-contract.go +40 -0
- package/compiler/semantic-model-types.go +16 -0
- package/compiler/semantic-model.go +336 -91
- package/compiler/semantic-model_test.go +50 -1
- package/compiler/service.go +9 -3
- package/compiler/skeleton_test.go +2371 -296
- package/compiler/tsworkspace/owner-process-unix_test.go +72 -0
- package/compiler/tsworkspace/owner.go +8 -0
- package/compiler/tsworkspace/tool-process-other.go +14 -0
- package/compiler/tsworkspace/tool-process-unix.go +19 -0
- package/compiler/typescript-emitter.go +149 -10
- package/dist/gs/builtin/builtin.d.ts +20 -1
- package/dist/gs/builtin/builtin.js +246 -26
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +24 -10
- package/dist/gs/builtin/channel.js +143 -34
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/defer.d.ts +1 -0
- package/dist/gs/builtin/defer.js +12 -2
- package/dist/gs/builtin/defer.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +9 -0
- package/dist/gs/builtin/hostio.js +25 -0
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/map.js +40 -6
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/print.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +43 -9
- package/dist/gs/builtin/slice.js +437 -234
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +2 -0
- package/dist/gs/builtin/type.js +55 -10
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +2 -0
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +28 -28
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.d.ts +7 -5
- package/dist/gs/bytes/bytes.gs.js +10 -4
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/iter.gs.js +13 -13
- package/dist/gs/bytes/iter.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +26 -0
- package/dist/gs/compress/zlib/index.js +168 -0
- package/dist/gs/compress/zlib/index.js.map +1 -0
- package/dist/gs/context/context.d.ts +1 -1
- package/dist/gs/context/context.js +8 -3
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/ecdh/index.d.ts +52 -0
- package/dist/gs/crypto/ecdh/index.js +226 -0
- package/dist/gs/crypto/ecdh/index.js.map +1 -0
- package/dist/gs/crypto/ed25519/index.d.ts +34 -0
- package/dist/gs/crypto/ed25519/index.js +160 -0
- package/dist/gs/crypto/ed25519/index.js.map +1 -0
- package/dist/gs/crypto/internal/constanttime/index.d.ts +4 -0
- package/dist/gs/crypto/internal/constanttime/index.js +18 -0
- package/dist/gs/crypto/internal/constanttime/index.js.map +1 -0
- package/dist/gs/crypto/rand/index.d.ts +2 -0
- package/dist/gs/crypto/rand/index.js +85 -0
- package/dist/gs/crypto/rand/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.d.ts +5 -0
- package/dist/gs/crypto/sha1/index.js +106 -0
- package/dist/gs/crypto/sha1/index.js.map +1 -0
- package/dist/gs/crypto/sha256/index.d.ts +8 -0
- package/dist/gs/crypto/sha256/index.js +118 -0
- package/dist/gs/crypto/sha256/index.js.map +1 -0
- package/dist/gs/crypto/sha512/index.d.ts +14 -0
- package/dist/gs/crypto/sha512/index.js +129 -0
- package/dist/gs/crypto/sha512/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +3 -0
- package/dist/gs/encoding/json/index.js +15 -0
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/errors/errors.js +29 -6
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +1 -1
- package/dist/gs/fmt/fmt.js +64 -3
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +7 -7
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +52 -18
- 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.js +56 -20
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +57 -3
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +366 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +20 -0
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js +134 -0
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +1 -0
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.d.ts +3 -0
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js +50 -0
- package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js.map +1 -0
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js +3 -2
- package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -1
- package/dist/gs/github.com/mr-tron/base58/base58/index.d.ts +27 -0
- package/dist/gs/github.com/mr-tron/base58/base58/index.js +172 -0
- package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.d.ts +21 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js +22 -0
- package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js.map +1 -0
- package/dist/gs/go/token/index.js +11 -4
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/fnv/index.d.ts +57 -0
- package/dist/gs/hash/fnv/index.js +299 -0
- package/dist/gs/hash/fnv/index.js.map +1 -0
- package/dist/gs/hash/index.d.ts +17 -0
- package/dist/gs/hash/index.js +94 -0
- package/dist/gs/hash/index.js.map +1 -0
- package/dist/gs/io/fs/readlink.js +2 -6
- package/dist/gs/io/fs/readlink.js.map +1 -1
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/io/io.d.ts +8 -5
- package/dist/gs/io/io.js +20 -2
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/iter/iter.d.ts +3 -2
- package/dist/gs/iter/iter.js.map +1 -1
- package/dist/gs/maps/iter.d.ts +5 -5
- package/dist/gs/maps/iter.js +48 -21
- package/dist/gs/maps/iter.js.map +1 -1
- package/dist/gs/maps/maps.d.ts +6 -6
- package/dist/gs/math/bits/index.js +14 -24
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.js +3 -1
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +20 -1
- package/dist/gs/net/http/httptest/index.js +85 -3
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +118 -6
- package/dist/gs/net/http/index.js +389 -14
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/net/http/pprof/index.d.ts +8 -0
- package/dist/gs/net/http/pprof/index.js +59 -0
- package/dist/gs/net/http/pprof/index.js.map +1 -0
- package/dist/gs/os/error.gs.js +9 -7
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.js +95 -15
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/filepath/path.d.ts +5 -3
- package/dist/gs/path/filepath/path.js +65 -10
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +3 -2
- package/dist/gs/reflect/index.js +2 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/iter.js +2 -2
- package/dist/gs/reflect/iter.js.map +1 -1
- package/dist/gs/reflect/map.js +26 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +24 -5
- package/dist/gs/reflect/type.js +390 -38
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +1 -0
- package/dist/gs/reflect/types.js +3 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +4 -1
- package/dist/gs/reflect/value.js +39 -1
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/debug/index.d.ts +39 -0
- package/dist/gs/runtime/debug/index.js +58 -0
- package/dist/gs/runtime/debug/index.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +20 -0
- package/dist/gs/runtime/pprof/index.js +85 -0
- package/dist/gs/runtime/pprof/index.js.map +1 -0
- package/dist/gs/runtime/trace/index.d.ts +19 -0
- package/dist/gs/runtime/trace/index.js +64 -0
- package/dist/gs/runtime/trace/index.js.map +1 -0
- package/dist/gs/slices/slices.d.ts +24 -9
- package/dist/gs/slices/slices.js +229 -24
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/slice.gs.d.ts +5 -3
- package/dist/gs/sort/slice.gs.js +55 -17
- package/dist/gs/sort/slice.gs.js.map +1 -1
- package/dist/gs/strings/builder.js +26 -17
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/iter.js +140 -75
- package/dist/gs/strings/iter.js.map +1 -1
- package/dist/gs/strings/replace.js +2 -2
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.js +52 -6
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +6 -3
- package/dist/gs/sync/sync.js +39 -11
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/errors.d.ts +116 -112
- package/dist/gs/syscall/errors.js +38 -1
- package/dist/gs/syscall/errors.js.map +1 -1
- package/dist/gs/syscall/fs.d.ts +2 -8
- package/dist/gs/syscall/fs.js.map +1 -1
- package/dist/gs/syscall/js/index.js +20 -12
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/syscall/types.d.ts +4 -1
- package/dist/gs/syscall/types.js.map +1 -1
- package/dist/gs/testing/testing.d.ts +4 -3
- package/dist/gs/testing/testing.js +21 -4
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.js +22 -0
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/dist/gs/unique/index.js +7 -2
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +8 -8
- package/go.sum +14 -23
- package/gs/builtin/builtin.ts +364 -37
- package/gs/builtin/channel.ts +208 -38
- package/gs/builtin/defer.ts +13 -2
- package/gs/builtin/hostio.test.ts +1 -0
- package/gs/builtin/hostio.ts +38 -0
- package/gs/builtin/map.ts +46 -6
- package/gs/builtin/print.ts +12 -3
- package/gs/builtin/runtime-contract.test.ts +290 -10
- package/gs/builtin/slice.test.ts +70 -0
- package/gs/builtin/slice.ts +566 -255
- package/gs/builtin/type.ts +63 -10
- package/gs/builtin/varRef.ts +2 -0
- package/gs/bytes/buffer.gs.ts +28 -28
- package/gs/bytes/bytes.gs.ts +19 -10
- package/gs/bytes/bytes.test.ts +17 -0
- package/gs/bytes/iter.gs.ts +13 -14
- package/gs/compress/zlib/index.test.ts +28 -0
- package/gs/compress/zlib/index.ts +200 -0
- package/gs/compress/zlib/meta.json +3 -0
- package/gs/context/context.test.ts +36 -2
- package/gs/context/context.ts +9 -4
- package/gs/crypto/ecdh/index.test.ts +43 -0
- package/gs/crypto/ecdh/index.ts +274 -0
- package/gs/crypto/ed25519/index.test.ts +41 -0
- package/gs/crypto/ed25519/index.ts +238 -0
- package/gs/crypto/ed25519/meta.json +13 -0
- package/gs/crypto/internal/constanttime/index.test.ts +25 -0
- package/gs/crypto/internal/constanttime/index.ts +22 -0
- package/gs/crypto/rand/index.test.ts +89 -1
- package/gs/crypto/rand/index.ts +103 -1
- package/gs/crypto/rand/meta.json +4 -1
- package/gs/crypto/sha1/index.test.ts +28 -0
- package/gs/crypto/sha1/index.ts +130 -0
- package/gs/crypto/sha1/meta.json +8 -0
- package/gs/crypto/sha256/index.test.ts +78 -0
- package/gs/crypto/sha256/index.ts +150 -0
- package/gs/crypto/sha256/meta.json +9 -0
- package/gs/crypto/sha512/index.test.ts +31 -0
- package/gs/crypto/sha512/index.ts +161 -0
- package/gs/crypto/sha512/meta.json +11 -0
- package/gs/encoding/json/index.test.ts +25 -3
- package/gs/encoding/json/index.ts +21 -3
- package/gs/errors/errors.test.ts +4 -1
- package/gs/errors/errors.ts +32 -8
- package/gs/fmt/fmt.test.ts +23 -1
- package/gs/fmt/fmt.ts +76 -10
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +62 -7
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +78 -36
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +32 -11
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +122 -43
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +31 -0
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +518 -4
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +6 -0
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +30 -0
- package/gs/github.com/aperturerobotics/util/conc/index.ts +172 -0
- package/gs/github.com/aperturerobotics/util/conc/meta.json +9 -0
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +1 -4
- package/gs/github.com/hack-pad/safejs/internal/catch/index.test.ts +35 -0
- package/gs/github.com/hack-pad/safejs/internal/catch/index.ts +65 -0
- package/gs/github.com/hack-pad/safejs/internal/catch/meta.json +9 -0
- package/gs/github.com/klauspost/compress/internal/le/index.test.ts +2 -1
- package/gs/github.com/klauspost/compress/internal/le/index.ts +6 -5
- package/gs/github.com/mr-tron/base58/base58/index.test.ts +70 -0
- package/gs/github.com/mr-tron/base58/base58/index.ts +231 -0
- package/gs/github.com/mr-tron/base58/base58/meta.json +3 -0
- package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +46 -0
- package/gs/github.com/zeebo/blake3/internal/consts/index.ts +26 -0
- package/gs/go/token/index.ts +17 -4
- package/gs/hash/fnv/index.test.ts +67 -0
- package/gs/hash/fnv/index.ts +351 -0
- package/gs/hash/fnv/meta.json +3 -0
- package/gs/hash/index.test.ts +37 -0
- package/gs/hash/index.ts +118 -0
- package/gs/hash/meta.json +5 -0
- package/gs/internal/byteorder/index.test.ts +6 -6
- package/gs/io/fs/readlink.ts +40 -48
- package/gs/io/fs/walk.ts +10 -2
- package/gs/io/io.test.ts +64 -0
- package/gs/io/io.ts +34 -13
- package/gs/iter/iter.ts +8 -2
- package/gs/maps/iter.ts +69 -26
- package/gs/maps/maps.test.ts +23 -0
- package/gs/maps/maps.ts +6 -6
- package/gs/math/bits/index.test.ts +20 -0
- package/gs/math/bits/index.ts +15 -28
- package/gs/mime/index.ts +8 -2
- package/gs/net/http/httptest/index.test.ts +85 -0
- package/gs/net/http/httptest/index.ts +113 -3
- package/gs/net/http/index.test.ts +159 -1
- package/gs/net/http/index.ts +515 -15
- package/gs/net/http/meta.json +6 -0
- package/gs/net/http/pprof/index.test.ts +47 -0
- package/gs/net/http/pprof/index.ts +65 -0
- package/gs/os/error.gs.ts +9 -10
- package/gs/os/error.test.ts +41 -0
- package/gs/os/file_unix_js.test.ts +55 -0
- package/gs/os/tempfile.gs.test.ts +37 -10
- package/gs/os/types_js.gs.ts +94 -15
- package/gs/os/zero_copy_posix.gs.ts +1 -2
- package/gs/path/filepath/match.ts +4 -1
- package/gs/path/filepath/meta.json +6 -0
- package/gs/path/filepath/path.test.ts +57 -2
- package/gs/path/filepath/path.ts +91 -12
- package/gs/reflect/field.test.ts +63 -0
- package/gs/reflect/index.ts +4 -1
- package/gs/reflect/iter.ts +2 -2
- package/gs/reflect/map.test.ts +24 -2
- package/gs/reflect/map.ts +35 -0
- package/gs/reflect/type.ts +543 -60
- package/gs/reflect/typefor.test.ts +100 -0
- package/gs/reflect/types.ts +3 -1
- package/gs/reflect/value.ts +50 -1
- package/gs/reflect/visiblefields.ts +1 -1
- package/gs/runtime/debug/index.test.ts +22 -1
- package/gs/runtime/debug/index.ts +88 -0
- package/gs/runtime/pprof/index.test.ts +36 -0
- package/gs/runtime/pprof/index.ts +104 -0
- package/gs/runtime/pprof/meta.json +6 -0
- package/gs/runtime/trace/index.test.ts +45 -0
- package/gs/runtime/trace/index.ts +97 -0
- package/gs/runtime/trace/meta.json +7 -0
- package/gs/slices/meta.json +2 -1
- package/gs/slices/slices.test.ts +86 -0
- package/gs/slices/slices.ts +284 -37
- package/gs/sort/slice.gs.ts +73 -23
- package/gs/sort/slice.test.ts +40 -0
- package/gs/strings/builder.test.ts +8 -0
- package/gs/strings/builder.ts +29 -17
- package/gs/strings/iter.test.ts +5 -7
- package/gs/strings/iter.ts +146 -71
- package/gs/strings/replace.test.ts +1 -4
- package/gs/strings/replace.ts +6 -6
- package/gs/strings/strings.test.ts +4 -0
- package/gs/strings/strings.ts +54 -6
- package/gs/sync/meta.json +1 -0
- package/gs/sync/sync.test.ts +57 -1
- package/gs/sync/sync.ts +45 -13
- package/gs/syscall/errors.ts +158 -115
- package/gs/syscall/fs.ts +8 -8
- package/gs/syscall/js/index.ts +49 -22
- package/gs/syscall/net.test.ts +26 -0
- package/gs/syscall/types.ts +7 -2
- package/gs/testing/testing.test.ts +56 -0
- package/gs/testing/testing.ts +27 -10
- package/gs/time/meta.json +2 -2
- package/gs/time/time.test.ts +4 -0
- package/gs/time/time.ts +33 -2
- package/gs/unicode/unicode.test.ts +14 -3
- package/gs/unicode/unicode.ts +1 -5
- package/gs/unique/index.ts +9 -2
- package/package.json +3 -3
package/gs/builtin/channel.ts
CHANGED
|
@@ -15,6 +15,38 @@ export interface SelectResult<T> {
|
|
|
15
15
|
id: number
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
function scheduleClosedChannelWake(wake: () => void): void {
|
|
19
|
+
// Closed-channel wakeups represent goroutine scheduling, not an immediate
|
|
20
|
+
// Promise continuation. Keep them on a task boundary so goroutine work queued
|
|
21
|
+
// around the close can observe state published before the blocked receiver
|
|
22
|
+
// resumes.
|
|
23
|
+
setTimeout(wake, 0)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function completeUnbufferedReceive<T>(
|
|
27
|
+
resolveReceive: (value: T) => void,
|
|
28
|
+
value: T,
|
|
29
|
+
): Promise<void> {
|
|
30
|
+
return new Promise<void>((resolve) => {
|
|
31
|
+
queueMicrotask(() => {
|
|
32
|
+
resolveReceive(value)
|
|
33
|
+
queueMicrotask(resolve)
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function completeUnbufferedReceiveWithOk<T>(
|
|
39
|
+
resolveReceive: (result: ChannelReceiveResult<T>) => void,
|
|
40
|
+
result: ChannelReceiveResult<T>,
|
|
41
|
+
): Promise<void> {
|
|
42
|
+
return new Promise<void>((resolve) => {
|
|
43
|
+
queueMicrotask(() => {
|
|
44
|
+
resolveReceive(result)
|
|
45
|
+
queueMicrotask(resolve)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
18
50
|
/**
|
|
19
51
|
* Represents a Go channel in TypeScript.
|
|
20
52
|
* Supports asynchronous sending and receiving of values.
|
|
@@ -56,7 +88,7 @@ export interface Channel<T> {
|
|
|
56
88
|
* @param id An identifier for this case in the select statement
|
|
57
89
|
* @returns Promise that resolves when this case is selected
|
|
58
90
|
*/
|
|
59
|
-
selectReceive(id: number): Promise<SelectResult<T>>
|
|
91
|
+
selectReceive(id: number, signal?: AbortSignal): Promise<SelectResult<T>>
|
|
60
92
|
|
|
61
93
|
/**
|
|
62
94
|
* Used in select statements to create a send operation promise.
|
|
@@ -64,7 +96,11 @@ export interface Channel<T> {
|
|
|
64
96
|
* @param id An identifier for this case in the select statement
|
|
65
97
|
* @returns Promise that resolves when this case is selected
|
|
66
98
|
*/
|
|
67
|
-
selectSend(
|
|
99
|
+
selectSend(
|
|
100
|
+
value: T,
|
|
101
|
+
id: number,
|
|
102
|
+
signal?: AbortSignal,
|
|
103
|
+
): Promise<SelectResult<boolean>>
|
|
68
104
|
|
|
69
105
|
/**
|
|
70
106
|
* Checks if the channel has data ready to be received without blocking.
|
|
@@ -82,6 +118,11 @@ export interface Channel<T> {
|
|
|
82
118
|
* Reports the number of buffered values currently queued in the channel.
|
|
83
119
|
*/
|
|
84
120
|
len(): number
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Reports the channel buffer capacity.
|
|
124
|
+
*/
|
|
125
|
+
cap(): number
|
|
85
126
|
}
|
|
86
127
|
|
|
87
128
|
/**
|
|
@@ -96,6 +137,27 @@ export interface SelectCase<T> {
|
|
|
96
137
|
onSelected?: (result: SelectResult<T>) => Promise<any>
|
|
97
138
|
}
|
|
98
139
|
|
|
140
|
+
const selectVoidReturnMarker = '__goscriptSelectVoidReturn'
|
|
141
|
+
|
|
142
|
+
export interface SelectVoidReturn {
|
|
143
|
+
readonly [selectVoidReturnMarker]: true
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function selectVoidReturn(): SelectVoidReturn {
|
|
147
|
+
return { [selectVoidReturnMarker]: true }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function selectHandlerResult<V>(handlerResult: any): [boolean, V] {
|
|
151
|
+
if (
|
|
152
|
+
handlerResult &&
|
|
153
|
+
typeof handlerResult === 'object' &&
|
|
154
|
+
handlerResult[selectVoidReturnMarker] === true
|
|
155
|
+
) {
|
|
156
|
+
return [true, undefined as V]
|
|
157
|
+
}
|
|
158
|
+
return [handlerResult !== undefined, handlerResult as V]
|
|
159
|
+
}
|
|
160
|
+
|
|
99
161
|
/**
|
|
100
162
|
* Helper for 'select' statements. Takes an array of select cases
|
|
101
163
|
* and resolves when one of them completes, following Go's select rules.
|
|
@@ -151,13 +213,13 @@ export async function selectStatement<T, V = void>(
|
|
|
151
213
|
const handlerResult = await selectedCase.onSelected(
|
|
152
214
|
result as SelectResult<T>,
|
|
153
215
|
)
|
|
154
|
-
return
|
|
216
|
+
return selectHandlerResult<V>(handlerResult)
|
|
155
217
|
}
|
|
156
218
|
} else {
|
|
157
219
|
const result = await selectedCase.channel.selectReceive(selectedCase.id)
|
|
158
220
|
if (selectedCase.onSelected) {
|
|
159
221
|
const handlerResult = await selectedCase.onSelected(result)
|
|
160
|
-
return
|
|
222
|
+
return selectHandlerResult<V>(handlerResult)
|
|
161
223
|
}
|
|
162
224
|
}
|
|
163
225
|
} else {
|
|
@@ -178,22 +240,27 @@ export async function selectStatement<T, V = void>(
|
|
|
178
240
|
ok: false,
|
|
179
241
|
id: -1,
|
|
180
242
|
} as SelectResult<T>)
|
|
181
|
-
return
|
|
243
|
+
return selectHandlerResult<V>(handlerResult)
|
|
182
244
|
}
|
|
183
245
|
return [false, undefined as V] // Return after executing the default case
|
|
184
246
|
}
|
|
185
247
|
|
|
186
248
|
// 3. If no operations are ready and no default case, block until one is ready
|
|
187
249
|
// Use Promise.race on the blocking promises
|
|
250
|
+
const abort = new AbortController()
|
|
188
251
|
const blockingPromises = cases
|
|
189
252
|
.filter((c) => c.id !== -1) // Exclude default case
|
|
190
253
|
.filter((c) => c.channel !== null) // Exclude nil channels (they would block forever)
|
|
191
254
|
.map((caseObj) => {
|
|
192
255
|
// At this point caseObj.channel is guaranteed to be non-null
|
|
193
256
|
if (caseObj.isSend) {
|
|
194
|
-
return caseObj.channel!.selectSend(
|
|
257
|
+
return caseObj.channel!.selectSend(
|
|
258
|
+
caseObj.value,
|
|
259
|
+
caseObj.id,
|
|
260
|
+
abort.signal,
|
|
261
|
+
)
|
|
195
262
|
} else {
|
|
196
|
-
return caseObj.channel!.selectReceive(caseObj.id)
|
|
263
|
+
return caseObj.channel!.selectReceive(caseObj.id, abort.signal)
|
|
197
264
|
}
|
|
198
265
|
})
|
|
199
266
|
|
|
@@ -204,11 +271,12 @@ export async function selectStatement<T, V = void>(
|
|
|
204
271
|
}
|
|
205
272
|
|
|
206
273
|
const result = await Promise.race(blockingPromises)
|
|
274
|
+
abort.abort()
|
|
207
275
|
// Execute onSelected handler for the selected case
|
|
208
276
|
const selectedCase = cases.find((c) => c.id === result.id)
|
|
209
277
|
if (selectedCase && selectedCase.onSelected) {
|
|
210
278
|
const handlerResult = await selectedCase.onSelected(result)
|
|
211
|
-
return
|
|
279
|
+
return selectHandlerResult<V>(handlerResult)
|
|
212
280
|
}
|
|
213
281
|
|
|
214
282
|
// No explicit return needed here, as the function will implicitly return after the await
|
|
@@ -344,13 +412,14 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
344
412
|
// Attempt to hand off to a waiting receiver (rendezvous)
|
|
345
413
|
if (this.receivers.length > 0) {
|
|
346
414
|
const receiverTask = this.receivers.shift()!
|
|
347
|
-
|
|
348
|
-
return
|
|
415
|
+
return completeUnbufferedReceive(receiverTask.resolveReceive, value)
|
|
349
416
|
}
|
|
350
417
|
if (this.receiversWithOk.length > 0) {
|
|
351
418
|
const receiverTask = this.receiversWithOk.shift()!
|
|
352
|
-
|
|
353
|
-
|
|
419
|
+
return completeUnbufferedReceiveWithOk(receiverTask.resolveReceive, {
|
|
420
|
+
value,
|
|
421
|
+
ok: true,
|
|
422
|
+
})
|
|
354
423
|
}
|
|
355
424
|
|
|
356
425
|
// If no waiting receivers, try to buffer if space is available
|
|
@@ -430,7 +499,10 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
430
499
|
})
|
|
431
500
|
}
|
|
432
501
|
|
|
433
|
-
async selectReceive(
|
|
502
|
+
async selectReceive(
|
|
503
|
+
id: number,
|
|
504
|
+
signal?: AbortSignal,
|
|
505
|
+
): Promise<SelectResult<T>> {
|
|
434
506
|
if (this.buffer.length > 0) {
|
|
435
507
|
const value = this.buffer.shift()!
|
|
436
508
|
if (this.senders.length > 0) {
|
|
@@ -452,15 +524,43 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
452
524
|
}
|
|
453
525
|
|
|
454
526
|
return new Promise<SelectResult<T>>((resolve) => {
|
|
455
|
-
|
|
527
|
+
const state = { done: false }
|
|
528
|
+
const receiversWithOk = this.receiversWithOk
|
|
529
|
+
const task = {
|
|
456
530
|
resolveReceive: (result: ChannelReceiveResult<T>) => {
|
|
457
|
-
|
|
531
|
+
if (!state.done) {
|
|
532
|
+
state.done = true
|
|
533
|
+
cleanup()
|
|
534
|
+
resolve({ ...result, id })
|
|
535
|
+
}
|
|
458
536
|
},
|
|
459
|
-
}
|
|
537
|
+
}
|
|
538
|
+
function cleanup() {
|
|
539
|
+
signal?.removeEventListener('abort', onAbort)
|
|
540
|
+
const idx = receiversWithOk.indexOf(task)
|
|
541
|
+
if (idx >= 0) {
|
|
542
|
+
receiversWithOk.splice(idx, 1)
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
function onAbort() {
|
|
546
|
+
if (!state.done) {
|
|
547
|
+
state.done = true
|
|
548
|
+
cleanup()
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (signal?.aborted) {
|
|
552
|
+
return
|
|
553
|
+
}
|
|
554
|
+
signal?.addEventListener('abort', onAbort, { once: true })
|
|
555
|
+
this.receiversWithOk.push(task)
|
|
460
556
|
})
|
|
461
557
|
}
|
|
462
558
|
|
|
463
|
-
async selectSend(
|
|
559
|
+
async selectSend(
|
|
560
|
+
value: T,
|
|
561
|
+
id: number,
|
|
562
|
+
signal?: AbortSignal,
|
|
563
|
+
): Promise<SelectResult<boolean>> {
|
|
464
564
|
if (this.closed) {
|
|
465
565
|
// A select case sending on a closed channel panics in Go.
|
|
466
566
|
// This will cause Promise.race in selectStatement to reject.
|
|
@@ -469,12 +569,15 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
469
569
|
|
|
470
570
|
if (this.receivers.length > 0) {
|
|
471
571
|
const receiverTask = this.receivers.shift()!
|
|
472
|
-
|
|
572
|
+
await completeUnbufferedReceive(receiverTask.resolveReceive, value)
|
|
473
573
|
return { value: true, ok: true, id }
|
|
474
574
|
}
|
|
475
575
|
if (this.receiversWithOk.length > 0) {
|
|
476
576
|
const receiverTask = this.receiversWithOk.shift()!
|
|
477
|
-
|
|
577
|
+
await completeUnbufferedReceiveWithOk(receiverTask.resolveReceive, {
|
|
578
|
+
value,
|
|
579
|
+
ok: true,
|
|
580
|
+
})
|
|
478
581
|
return { value: true, ok: true, id }
|
|
479
582
|
}
|
|
480
583
|
|
|
@@ -484,11 +587,43 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
484
587
|
}
|
|
485
588
|
|
|
486
589
|
return new Promise<SelectResult<boolean>>((resolve, reject) => {
|
|
487
|
-
|
|
590
|
+
const state = { done: false }
|
|
591
|
+
const senders = this.senders
|
|
592
|
+
const task = {
|
|
488
593
|
value,
|
|
489
|
-
resolveSend: () =>
|
|
490
|
-
|
|
491
|
-
|
|
594
|
+
resolveSend: () => {
|
|
595
|
+
if (!state.done) {
|
|
596
|
+
state.done = true
|
|
597
|
+
cleanup()
|
|
598
|
+
resolve({ value: true, ok: true, id })
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
rejectSend: (e: Error) => {
|
|
602
|
+
if (!state.done) {
|
|
603
|
+
state.done = true
|
|
604
|
+
cleanup()
|
|
605
|
+
reject(e)
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
}
|
|
609
|
+
function cleanup() {
|
|
610
|
+
signal?.removeEventListener('abort', onAbort)
|
|
611
|
+
const idx = senders.indexOf(task)
|
|
612
|
+
if (idx >= 0) {
|
|
613
|
+
senders.splice(idx, 1)
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
function onAbort() {
|
|
617
|
+
if (!state.done) {
|
|
618
|
+
state.done = true
|
|
619
|
+
cleanup()
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (signal?.aborted) {
|
|
623
|
+
return
|
|
624
|
+
}
|
|
625
|
+
signal?.addEventListener('abort', onAbort, { once: true })
|
|
626
|
+
this.senders.push(task)
|
|
492
627
|
})
|
|
493
628
|
}
|
|
494
629
|
|
|
@@ -501,7 +636,7 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
501
636
|
const sendersToNotify = [...this.senders] // Shallow copy for iteration
|
|
502
637
|
this.senders = []
|
|
503
638
|
for (const senderTask of sendersToNotify) {
|
|
504
|
-
|
|
639
|
+
scheduleClosedChannelWake(() =>
|
|
505
640
|
senderTask.rejectSend(new Error('send on closed channel')),
|
|
506
641
|
)
|
|
507
642
|
}
|
|
@@ -509,13 +644,15 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
509
644
|
const receiversToNotify = [...this.receivers]
|
|
510
645
|
this.receivers = []
|
|
511
646
|
for (const receiverTask of receiversToNotify) {
|
|
512
|
-
|
|
647
|
+
scheduleClosedChannelWake(() =>
|
|
648
|
+
receiverTask.resolveReceive(this.zeroValue),
|
|
649
|
+
)
|
|
513
650
|
}
|
|
514
651
|
|
|
515
652
|
const receiversWithOkToNotify = [...this.receiversWithOk]
|
|
516
653
|
this.receiversWithOk = []
|
|
517
654
|
for (const receiverTask of receiversWithOkToNotify) {
|
|
518
|
-
|
|
655
|
+
scheduleClosedChannelWake(() =>
|
|
519
656
|
receiverTask.resolveReceive({ value: this.zeroValue, ok: false }),
|
|
520
657
|
)
|
|
521
658
|
}
|
|
@@ -539,6 +676,10 @@ class BufferedChannel<T> implements Channel<T> {
|
|
|
539
676
|
len(): number {
|
|
540
677
|
return this.buffer.length
|
|
541
678
|
}
|
|
679
|
+
|
|
680
|
+
cap(): number {
|
|
681
|
+
return this.capacity
|
|
682
|
+
}
|
|
542
683
|
}
|
|
543
684
|
|
|
544
685
|
/**
|
|
@@ -562,9 +703,14 @@ export interface ChannelRef<T> {
|
|
|
562
703
|
close(): void
|
|
563
704
|
canSendNonBlocking(): boolean
|
|
564
705
|
canReceiveNonBlocking(): boolean
|
|
565
|
-
selectSend(
|
|
566
|
-
|
|
706
|
+
selectSend(
|
|
707
|
+
value: T,
|
|
708
|
+
id: number,
|
|
709
|
+
signal?: AbortSignal,
|
|
710
|
+
): Promise<SelectResult<boolean>>
|
|
711
|
+
selectReceive(id: number, signal?: AbortSignal): Promise<SelectResult<T>>
|
|
567
712
|
len(): number
|
|
713
|
+
cap(): number
|
|
568
714
|
}
|
|
569
715
|
|
|
570
716
|
/**
|
|
@@ -600,17 +746,25 @@ export class BidirectionalChannelRef<T> implements ChannelRef<T> {
|
|
|
600
746
|
return this.channel.canReceiveNonBlocking()
|
|
601
747
|
}
|
|
602
748
|
|
|
603
|
-
selectSend(
|
|
604
|
-
|
|
749
|
+
selectSend(
|
|
750
|
+
value: T,
|
|
751
|
+
id: number,
|
|
752
|
+
signal?: AbortSignal,
|
|
753
|
+
): Promise<SelectResult<boolean>> {
|
|
754
|
+
return this.channel.selectSend(value, id, signal)
|
|
605
755
|
}
|
|
606
756
|
|
|
607
|
-
selectReceive(id: number): Promise<SelectResult<T>> {
|
|
608
|
-
return this.channel.selectReceive(id)
|
|
757
|
+
selectReceive(id: number, signal?: AbortSignal): Promise<SelectResult<T>> {
|
|
758
|
+
return this.channel.selectReceive(id, signal)
|
|
609
759
|
}
|
|
610
760
|
|
|
611
761
|
len(): number {
|
|
612
762
|
return this.channel.len()
|
|
613
763
|
}
|
|
764
|
+
|
|
765
|
+
cap(): number {
|
|
766
|
+
return this.channel.cap()
|
|
767
|
+
}
|
|
614
768
|
}
|
|
615
769
|
|
|
616
770
|
/**
|
|
@@ -635,8 +789,12 @@ export class SendOnlyChannelRef<T> implements ChannelRef<T> {
|
|
|
635
789
|
return this.channel.canSendNonBlocking()
|
|
636
790
|
}
|
|
637
791
|
|
|
638
|
-
selectSend(
|
|
639
|
-
|
|
792
|
+
selectSend(
|
|
793
|
+
value: T,
|
|
794
|
+
id: number,
|
|
795
|
+
signal?: AbortSignal,
|
|
796
|
+
): Promise<SelectResult<boolean>> {
|
|
797
|
+
return this.channel.selectSend(value, id, signal)
|
|
640
798
|
}
|
|
641
799
|
|
|
642
800
|
// Disallow receive operations
|
|
@@ -652,13 +810,17 @@ export class SendOnlyChannelRef<T> implements ChannelRef<T> {
|
|
|
652
810
|
return false
|
|
653
811
|
}
|
|
654
812
|
|
|
655
|
-
selectReceive(_id: number): Promise<SelectResult<T>> {
|
|
813
|
+
selectReceive(_id: number, _signal?: AbortSignal): Promise<SelectResult<T>> {
|
|
656
814
|
throw new Error('Cannot receive from send-only channel')
|
|
657
815
|
}
|
|
658
816
|
|
|
659
817
|
len(): number {
|
|
660
818
|
return this.channel.len()
|
|
661
819
|
}
|
|
820
|
+
|
|
821
|
+
cap(): number {
|
|
822
|
+
return this.channel.cap()
|
|
823
|
+
}
|
|
662
824
|
}
|
|
663
825
|
|
|
664
826
|
/**
|
|
@@ -682,8 +844,8 @@ export class ReceiveOnlyChannelRef<T> implements ChannelRef<T> {
|
|
|
682
844
|
return this.channel.canReceiveNonBlocking()
|
|
683
845
|
}
|
|
684
846
|
|
|
685
|
-
selectReceive(id: number): Promise<SelectResult<T>> {
|
|
686
|
-
return this.channel.selectReceive(id)
|
|
847
|
+
selectReceive(id: number, signal?: AbortSignal): Promise<SelectResult<T>> {
|
|
848
|
+
return this.channel.selectReceive(id, signal)
|
|
687
849
|
}
|
|
688
850
|
|
|
689
851
|
// Disallow send operations
|
|
@@ -700,13 +862,21 @@ export class ReceiveOnlyChannelRef<T> implements ChannelRef<T> {
|
|
|
700
862
|
return false
|
|
701
863
|
}
|
|
702
864
|
|
|
703
|
-
selectSend(
|
|
865
|
+
selectSend(
|
|
866
|
+
_value: T,
|
|
867
|
+
_id: number,
|
|
868
|
+
_signal?: AbortSignal,
|
|
869
|
+
): Promise<SelectResult<boolean>> {
|
|
704
870
|
throw new Error('Cannot send to receive-only channel')
|
|
705
871
|
}
|
|
706
872
|
|
|
707
873
|
len(): number {
|
|
708
874
|
return this.channel.len()
|
|
709
875
|
}
|
|
876
|
+
|
|
877
|
+
cap(): number {
|
|
878
|
+
return this.channel.cap()
|
|
879
|
+
}
|
|
710
880
|
}
|
|
711
881
|
|
|
712
882
|
/**
|
package/gs/builtin/defer.ts
CHANGED
|
@@ -51,8 +51,19 @@ export class AsyncDisposableStack implements AsyncDisposable {
|
|
|
51
51
|
*/
|
|
52
52
|
async [Symbol.asyncDispose](): Promise<void> {
|
|
53
53
|
// Execute in LIFO order, awaiting each potentially async function
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
while (this.stack.length) {
|
|
55
|
+
const fn = this.stack.pop()!
|
|
56
|
+
await fn()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
[Symbol.dispose](): void {
|
|
61
|
+
while (this.stack.length) {
|
|
62
|
+
const fn = this.stack.pop()!
|
|
63
|
+
const result = fn()
|
|
64
|
+
if (result && typeof (result as Promise<void>).then === "function") {
|
|
65
|
+
throw new Error("async deferred function disposed synchronously")
|
|
66
|
+
}
|
|
56
67
|
}
|
|
57
68
|
}
|
|
58
69
|
}
|
package/gs/builtin/hostio.ts
CHANGED
|
@@ -54,6 +54,16 @@ export type NodeFSModule = {
|
|
|
54
54
|
): void
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
export type NodeCryptoHash = {
|
|
58
|
+
copy?(): NodeCryptoHash
|
|
59
|
+
update(data: Uint8Array): NodeCryptoHash
|
|
60
|
+
digest(): Uint8Array
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type NodeCryptoModule = {
|
|
64
|
+
createHash(algorithm: string): NodeCryptoHash
|
|
65
|
+
}
|
|
66
|
+
|
|
57
67
|
export type DenoStream = {
|
|
58
68
|
readSync?(buffer: Uint8Array): number | null
|
|
59
69
|
writeSync?(buffer: Uint8Array): number
|
|
@@ -74,6 +84,7 @@ type HostTextWrite = (data: string) => void
|
|
|
74
84
|
|
|
75
85
|
export type HostRuntime = {
|
|
76
86
|
deno: any | null
|
|
87
|
+
nodeCrypto: NodeCryptoModule | null
|
|
77
88
|
nodeFS: NodeFSModule | null
|
|
78
89
|
platform: string
|
|
79
90
|
processObj: any | null
|
|
@@ -166,6 +177,31 @@ function detectNodeFS(processObj: any | null): NodeFSModule | null {
|
|
|
166
177
|
return null
|
|
167
178
|
}
|
|
168
179
|
|
|
180
|
+
function detectNodeCrypto(processObj: any | null): NodeCryptoModule | null {
|
|
181
|
+
if (processObj && typeof processObj.getBuiltinModule === 'function') {
|
|
182
|
+
const module = processObj.getBuiltinModule('crypto')
|
|
183
|
+
if (module && typeof module.createHash === 'function') {
|
|
184
|
+
return module as NodeCryptoModule
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const requireFn = getDynamicRequire()
|
|
189
|
+
if (requireFn) {
|
|
190
|
+
for (const specifier of ['node:crypto', 'crypto']) {
|
|
191
|
+
try {
|
|
192
|
+
const module = requireFn(specifier) as NodeCryptoModule | null
|
|
193
|
+
if (module && typeof module.createHash === 'function') {
|
|
194
|
+
return module
|
|
195
|
+
}
|
|
196
|
+
} catch {
|
|
197
|
+
// Try the next fallback.
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return null
|
|
203
|
+
}
|
|
204
|
+
|
|
169
205
|
function hasURLScheme(path: string): boolean {
|
|
170
206
|
return /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(path)
|
|
171
207
|
}
|
|
@@ -247,6 +283,7 @@ function detectHostRuntime(): HostRuntime {
|
|
|
247
283
|
const deno = globalObj.Deno ?? null
|
|
248
284
|
const processObj = globalObj.process ?? null
|
|
249
285
|
const nodeFS = detectNodeFS(processObj)
|
|
286
|
+
const nodeCrypto = detectNodeCrypto(processObj)
|
|
250
287
|
|
|
251
288
|
const getStdioHandle = (fd: number): DenoFileLike | null => {
|
|
252
289
|
if (!deno) {
|
|
@@ -344,6 +381,7 @@ function detectHostRuntime(): HostRuntime {
|
|
|
344
381
|
deno,
|
|
345
382
|
getEnv,
|
|
346
383
|
getStdioHandle,
|
|
384
|
+
nodeCrypto,
|
|
347
385
|
nodeFS,
|
|
348
386
|
platform,
|
|
349
387
|
processObj,
|
package/gs/builtin/map.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { comparableEqual } from './builtin.js'
|
|
2
|
+
import { GoBinaryString, stringEqual } from './slice.js'
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Creates a new map (TypeScript Map).
|
|
3
6
|
* @returns A new TypeScript Map.
|
|
@@ -18,9 +21,9 @@ export function mapGet<K, V, D>(
|
|
|
18
21
|
key: K,
|
|
19
22
|
defaultValue: D,
|
|
20
23
|
): [V, true] | [D, false] {
|
|
21
|
-
const
|
|
22
|
-
if (
|
|
23
|
-
return [
|
|
24
|
+
const entry = findMapEntry(map, key)
|
|
25
|
+
if (entry.found) {
|
|
26
|
+
return [entry.value, true]
|
|
24
27
|
} else {
|
|
25
28
|
return [defaultValue, false]
|
|
26
29
|
}
|
|
@@ -36,7 +39,8 @@ export const mapSet = <K, V>(map: Map<K, V> | null, key: K, value: V): void => {
|
|
|
36
39
|
if (!map) {
|
|
37
40
|
throw new Error('assign to nil map')
|
|
38
41
|
}
|
|
39
|
-
map
|
|
42
|
+
const entry = findMapEntry(map, key)
|
|
43
|
+
map.set(entry.found ? entry.key : key, value)
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
/**
|
|
@@ -45,7 +49,10 @@ export const mapSet = <K, V>(map: Map<K, V> | null, key: K, value: V): void => {
|
|
|
45
49
|
* @param key The key to delete.
|
|
46
50
|
*/
|
|
47
51
|
export const deleteMapEntry = <K, V>(map: Map<K, V> | null, key: K): void => {
|
|
48
|
-
map
|
|
52
|
+
const entry = findMapEntry(map, key)
|
|
53
|
+
if (entry.found) {
|
|
54
|
+
map!.delete(entry.key)
|
|
55
|
+
}
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
/**
|
|
@@ -55,5 +62,38 @@ export const deleteMapEntry = <K, V>(map: Map<K, V> | null, key: K): void => {
|
|
|
55
62
|
* @returns True if the key exists, false otherwise.
|
|
56
63
|
*/
|
|
57
64
|
export const mapHas = <K, V>(map: Map<K, V> | null, key: K): boolean => {
|
|
58
|
-
return map
|
|
65
|
+
return findMapEntry(map, key).found
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function findMapEntry<K, V>(
|
|
69
|
+
map: Map<K, V> | null,
|
|
70
|
+
key: K,
|
|
71
|
+
): { found: false } | { found: true; key: K; value: V } {
|
|
72
|
+
if (!map) {
|
|
73
|
+
return { found: false }
|
|
74
|
+
}
|
|
75
|
+
if (map.has(key)) {
|
|
76
|
+
return { found: true, key, value: map.get(key)! }
|
|
77
|
+
}
|
|
78
|
+
if (isGoStringKey(key)) {
|
|
79
|
+
for (const [candidate, value] of map.entries()) {
|
|
80
|
+
if (isGoStringKey(candidate) && stringEqual(candidate as string, key as string)) {
|
|
81
|
+
return { found: true, key: candidate, value }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { found: false }
|
|
85
|
+
}
|
|
86
|
+
if (key === null || (typeof key !== 'object' && typeof key !== 'function')) {
|
|
87
|
+
return { found: false }
|
|
88
|
+
}
|
|
89
|
+
for (const [candidate, value] of map.entries()) {
|
|
90
|
+
if (candidate !== key && comparableEqual(candidate, key)) {
|
|
91
|
+
return { found: true, key: candidate, value }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { found: false }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isGoStringKey(value: unknown): value is string | GoBinaryString {
|
|
98
|
+
return typeof value === 'string' || value instanceof GoBinaryString
|
|
59
99
|
}
|
package/gs/builtin/print.ts
CHANGED
|
@@ -68,7 +68,10 @@ function formatValue(
|
|
|
68
68
|
try {
|
|
69
69
|
if (value instanceof Map) {
|
|
70
70
|
return formatArray(
|
|
71
|
-
Array.from(value.entries()).map(
|
|
71
|
+
Array.from(value.entries()).map(
|
|
72
|
+
([k, v]) =>
|
|
73
|
+
`${formatValue(k, depth + 1, true, seen)} => ${formatValue(v, depth + 1, true, seen)}`,
|
|
74
|
+
),
|
|
72
75
|
depth,
|
|
73
76
|
seen,
|
|
74
77
|
)
|
|
@@ -113,7 +116,11 @@ function formatUint8Array(value: Uint8Array): string {
|
|
|
113
116
|
return `Uint8Array(${value.length}) [ ${Array.from(value).join(', ')} ]`
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
function formatArray(
|
|
119
|
+
function formatArray(
|
|
120
|
+
value: readonly any[],
|
|
121
|
+
depth: number,
|
|
122
|
+
seen: WeakSet<object>,
|
|
123
|
+
): string {
|
|
117
124
|
if (value.length === 0) {
|
|
118
125
|
return '[]'
|
|
119
126
|
}
|
|
@@ -150,5 +157,7 @@ function getObjectEntries(value: Record<string, any>): [string, any][] {
|
|
|
150
157
|
})
|
|
151
158
|
}
|
|
152
159
|
|
|
153
|
-
return Object.entries(value).filter(
|
|
160
|
+
return Object.entries(value).filter(
|
|
161
|
+
([, entry]) => typeof entry !== 'function',
|
|
162
|
+
)
|
|
154
163
|
}
|