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/os/error.gs.ts
CHANGED
|
@@ -184,6 +184,9 @@ export function underlyingErrorIs(err: $.GoError, target: $.GoError): boolean {
|
|
|
184
184
|
if (err == target) {
|
|
185
185
|
return true
|
|
186
186
|
}
|
|
187
|
+
if (err !== null && typeof (err as any).Is === "function") {
|
|
188
|
+
return (err as any).Is(target) === true
|
|
189
|
+
}
|
|
187
190
|
// To preserve prior behavior, only examine syscall errors.
|
|
188
191
|
let { value: e, ok: ok } = $.typeAssert<any>(err, 'syscallErrorType')
|
|
189
192
|
return ok && e.Is(target)
|
|
@@ -191,15 +194,11 @@ export function underlyingErrorIs(err: $.GoError, target: $.GoError): boolean {
|
|
|
191
194
|
|
|
192
195
|
// underlyingError returns the underlying error for known os error types.
|
|
193
196
|
export function underlyingError(err: $.GoError): $.GoError {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
{ types: [{kind: $.TypeKind.Pointer, elemType: 'SyscallError'}], body: (err) => {
|
|
201
|
-
return err!.Err
|
|
202
|
-
}}])
|
|
197
|
+
if (err !== null && typeof (err as any).Unwrap === "function") {
|
|
198
|
+
const unwrapped = (err as any).Unwrap()
|
|
199
|
+
if (unwrapped !== null && typeof unwrapped?.Error === "function") {
|
|
200
|
+
return unwrapped
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
203
|
return err
|
|
204
204
|
}
|
|
205
|
-
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ErrNotExist,
|
|
5
|
+
IsExist,
|
|
6
|
+
IsNotExist,
|
|
7
|
+
IsPermission,
|
|
8
|
+
PathError,
|
|
9
|
+
} from './error.gs.js'
|
|
10
|
+
import { newHostError } from './types_js.gs.js'
|
|
11
|
+
|
|
12
|
+
function hostError(code: string): Error {
|
|
13
|
+
return Object.assign(new Error(code), { code })
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('os error classification', () => {
|
|
17
|
+
it('unwraps path errors before comparing sentinel errors', () => {
|
|
18
|
+
const err = new PathError({
|
|
19
|
+
Err: ErrNotExist,
|
|
20
|
+
Op: 'open',
|
|
21
|
+
Path: 'missing',
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
expect(IsNotExist(err)).toBe(true)
|
|
25
|
+
expect(IsExist(err)).toBe(false)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('recognizes host filesystem error codes', () => {
|
|
29
|
+
expect(IsNotExist(newHostError(hostError('ENOENT')))).toBe(true)
|
|
30
|
+
expect(IsNotExist(newHostError(hostError('ENOTDIR')))).toBe(true)
|
|
31
|
+
expect(IsExist(newHostError(hostError('EEXIST')))).toBe(true)
|
|
32
|
+
expect(IsPermission(newHostError(hostError('EACCES')))).toBe(true)
|
|
33
|
+
expect(IsPermission(newHostError(hostError('EPERM')))).toBe(true)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('does not treat unrelated host errors as filesystem sentinels', () => {
|
|
37
|
+
expect(IsNotExist(newHostError(hostError('EIO')))).toBe(false)
|
|
38
|
+
expect(IsExist(newHostError(hostError('EIO')))).toBe(false)
|
|
39
|
+
expect(IsPermission(newHostError(hostError('EIO')))).toBe(false)
|
|
40
|
+
})
|
|
41
|
+
})
|
|
@@ -231,4 +231,59 @@ describe('os stdio', () => {
|
|
|
231
231
|
expect(handle.writeSync).toHaveBeenCalledTimes(2)
|
|
232
232
|
expect(Array.from(handle.writeSync.mock.calls[1][0])).toEqual([22, 23])
|
|
233
233
|
})
|
|
234
|
+
|
|
235
|
+
it('supports ReadAt and WriteAt on process fs descriptors', () => {
|
|
236
|
+
const readSync = vi.fn(
|
|
237
|
+
(
|
|
238
|
+
_fd: number,
|
|
239
|
+
buffer: Uint8Array,
|
|
240
|
+
offset?: number,
|
|
241
|
+
length?: number,
|
|
242
|
+
position?: number | null,
|
|
243
|
+
) => {
|
|
244
|
+
expect(offset).toBe(0)
|
|
245
|
+
expect(length).toBe(3)
|
|
246
|
+
expect(position).toBe(5)
|
|
247
|
+
buffer.set([31, 32, 33], 0)
|
|
248
|
+
return 3
|
|
249
|
+
},
|
|
250
|
+
)
|
|
251
|
+
const writeSync = vi.fn(
|
|
252
|
+
(
|
|
253
|
+
_fd: number,
|
|
254
|
+
_buffer: Uint8Array,
|
|
255
|
+
offset?: number,
|
|
256
|
+
length?: number,
|
|
257
|
+
position?: number | null,
|
|
258
|
+
) => {
|
|
259
|
+
expect(offset).toBe(0)
|
|
260
|
+
expect(length).toBe(2)
|
|
261
|
+
expect(position).toBe(8)
|
|
262
|
+
return length ?? 0
|
|
263
|
+
},
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
delete (globalThis as any).Deno
|
|
267
|
+
;(globalThis as any).process = {
|
|
268
|
+
getBuiltinModule: vi.fn(() => ({
|
|
269
|
+
readSync,
|
|
270
|
+
writeSync,
|
|
271
|
+
})),
|
|
272
|
+
}
|
|
273
|
+
resetHostRuntimeForTests()
|
|
274
|
+
|
|
275
|
+
const file = createHostFile('descriptor-file', 7)
|
|
276
|
+
const buf = new Uint8Array(3)
|
|
277
|
+
|
|
278
|
+
const [readN, readErr] = file.ReadAt(buf, 5)
|
|
279
|
+
expect(readN).toBe(3)
|
|
280
|
+
expect(readErr).toBeNull()
|
|
281
|
+
expect(Array.from(buf)).toEqual([31, 32, 33])
|
|
282
|
+
|
|
283
|
+
const [writeN, writeErr] = file.WriteAt(new Uint8Array([41, 42]), 8)
|
|
284
|
+
expect(writeN).toBe(2)
|
|
285
|
+
expect(writeErr).toBeNull()
|
|
286
|
+
expect(readSync).toHaveBeenCalledTimes(1)
|
|
287
|
+
expect(writeSync).toHaveBeenCalledTimes(1)
|
|
288
|
+
})
|
|
234
289
|
})
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import { basename, join } from 'node:path'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
existsSync,
|
|
4
|
+
mkdtempSync,
|
|
5
|
+
readFileSync,
|
|
6
|
+
rmSync,
|
|
7
|
+
writeFileSync,
|
|
8
|
+
} from 'node:fs'
|
|
3
9
|
import { tmpdir } from 'node:os'
|
|
4
10
|
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
5
11
|
|
|
6
12
|
import { ErrUnimplemented } from './error.gs.js'
|
|
7
13
|
import { CreateTemp, MkdirTemp } from './tempfile.gs.js'
|
|
14
|
+
import * as errors from '../errors/errors.js'
|
|
15
|
+
import { ErrNotExist } from './error.gs.js'
|
|
16
|
+
import { Stat } from './stat_js.gs.js'
|
|
8
17
|
|
|
9
18
|
const tempRoots: string[] = []
|
|
19
|
+
const originalCrypto = globalThis.crypto
|
|
10
20
|
|
|
11
21
|
afterEach(() => {
|
|
12
22
|
vi.restoreAllMocks()
|
|
13
|
-
|
|
23
|
+
Object.defineProperty(globalThis, 'crypto', {
|
|
24
|
+
configurable: true,
|
|
25
|
+
value: originalCrypto,
|
|
26
|
+
})
|
|
14
27
|
for (const root of tempRoots.splice(0)) {
|
|
15
28
|
rmSync(root, { force: true, recursive: true })
|
|
16
29
|
}
|
|
@@ -23,13 +36,16 @@ function makeTempRoot(): string {
|
|
|
23
36
|
}
|
|
24
37
|
|
|
25
38
|
function stubRandomBytes(bytes: number[]): void {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
Object.defineProperty(globalThis, 'crypto', {
|
|
40
|
+
configurable: true,
|
|
41
|
+
value: {
|
|
42
|
+
getRandomValues: vi.fn((dst: Uint8Array) => {
|
|
43
|
+
for (let i = 0; i < dst.length; i++) {
|
|
44
|
+
dst[i] = bytes[i] ?? 0
|
|
45
|
+
}
|
|
46
|
+
return dst
|
|
47
|
+
}),
|
|
48
|
+
},
|
|
33
49
|
})
|
|
34
50
|
}
|
|
35
51
|
|
|
@@ -74,7 +90,10 @@ describe('os temp files', () => {
|
|
|
74
90
|
|
|
75
91
|
it('reports ErrUnimplemented without a secure random source', () => {
|
|
76
92
|
const root = makeTempRoot()
|
|
77
|
-
|
|
93
|
+
Object.defineProperty(globalThis, 'crypto', {
|
|
94
|
+
configurable: true,
|
|
95
|
+
value: {},
|
|
96
|
+
})
|
|
78
97
|
forbidMathRandom()
|
|
79
98
|
|
|
80
99
|
const [dir, err] = MkdirTemp(root, 'dir-*')
|
|
@@ -82,4 +101,12 @@ describe('os temp files', () => {
|
|
|
82
101
|
expect(dir).toBe('')
|
|
83
102
|
expect(err).toBe(ErrUnimplemented)
|
|
84
103
|
})
|
|
104
|
+
|
|
105
|
+
it('maps host missing-path errors to ErrNotExist', () => {
|
|
106
|
+
const root = makeTempRoot()
|
|
107
|
+
|
|
108
|
+
const [, err] = Stat(join(root, 'missing'))
|
|
109
|
+
|
|
110
|
+
expect(errors.Is(err, ErrNotExist)).toBe(true)
|
|
111
|
+
})
|
|
85
112
|
})
|
package/gs/os/types_js.gs.ts
CHANGED
|
@@ -29,7 +29,37 @@ export function newHostError(err: unknown): $.GoError {
|
|
|
29
29
|
err instanceof Error ? err.message
|
|
30
30
|
: typeof err === "string" ? err
|
|
31
31
|
: String(err)
|
|
32
|
-
|
|
32
|
+
const target = hostErrorTarget(err)
|
|
33
|
+
const hostErr: Exclude<$.GoError, null> = {
|
|
34
|
+
Error: () => message,
|
|
35
|
+
}
|
|
36
|
+
Object.defineProperty(hostErr, "Is", {
|
|
37
|
+
value: (candidate: $.GoError) => target !== null && candidate === target,
|
|
38
|
+
})
|
|
39
|
+
return hostErr
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function hostErrorTarget(err: unknown): $.GoError {
|
|
43
|
+
const codeValue = typeof err === "object" && err !== null && "code" in err
|
|
44
|
+
? Reflect.get(err, "code")
|
|
45
|
+
: ""
|
|
46
|
+
const code = codeValue === undefined ? "" : String(codeValue)
|
|
47
|
+
switch (code) {
|
|
48
|
+
case "ENOENT":
|
|
49
|
+
case "ENOTDIR":
|
|
50
|
+
return fs.ErrNotExist
|
|
51
|
+
case "EEXIST":
|
|
52
|
+
return fs.ErrExist
|
|
53
|
+
case "EACCES":
|
|
54
|
+
case "EPERM":
|
|
55
|
+
return fs.ErrPermission
|
|
56
|
+
case "EBADF":
|
|
57
|
+
return ErrClosed
|
|
58
|
+
case "EINVAL":
|
|
59
|
+
return ErrInvalid
|
|
60
|
+
default:
|
|
61
|
+
return null
|
|
62
|
+
}
|
|
33
63
|
}
|
|
34
64
|
|
|
35
65
|
export function getNodeFS(): NodeFSModule | null {
|
|
@@ -296,16 +326,44 @@ export class File {
|
|
|
296
326
|
}
|
|
297
327
|
|
|
298
328
|
public ReadAt(b: $.Bytes, off: number): [number, $.GoError] {
|
|
329
|
+
if (this.closed) {
|
|
330
|
+
return [0, ErrClosed]
|
|
331
|
+
}
|
|
332
|
+
if (off < 0) {
|
|
333
|
+
return [0, ErrInvalid]
|
|
334
|
+
}
|
|
335
|
+
if (b === null) {
|
|
336
|
+
return [0, null]
|
|
337
|
+
}
|
|
338
|
+
const buf = $.bytesToUint8Array(b)
|
|
299
339
|
const handle = this.file?.handle
|
|
300
|
-
if (
|
|
301
|
-
|
|
340
|
+
if (handle && typeof handle.seekSync === "function") {
|
|
341
|
+
try {
|
|
342
|
+
handle.seekSync(off, io.SeekStart)
|
|
343
|
+
return this.Read(b)
|
|
344
|
+
} catch (err) {
|
|
345
|
+
return [0, newHostError(err)]
|
|
346
|
+
}
|
|
302
347
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
348
|
+
if (this.fd < 0) {
|
|
349
|
+
return [0, ErrInvalid]
|
|
350
|
+
}
|
|
351
|
+
const nodeFS = getNodeFS()
|
|
352
|
+
if (nodeFS?.readSync && this.fd >= 0) {
|
|
353
|
+
try {
|
|
354
|
+
const n = nodeFS.readSync(this.fd, buf, 0, buf.length, off)
|
|
355
|
+
if (!(b instanceof Uint8Array) && n > 0) {
|
|
356
|
+
$.copy(b, buf.subarray(0, n))
|
|
357
|
+
}
|
|
358
|
+
if (n === 0) {
|
|
359
|
+
return [0, io.EOF]
|
|
360
|
+
}
|
|
361
|
+
return [n, null]
|
|
362
|
+
} catch (err) {
|
|
363
|
+
return [0, newHostError(err)]
|
|
364
|
+
}
|
|
308
365
|
}
|
|
366
|
+
return [0, ErrUnimplemented]
|
|
309
367
|
}
|
|
310
368
|
|
|
311
369
|
public ReadFrom(r: io.Reader): [number, $.GoError] {
|
|
@@ -333,16 +391,37 @@ export class File {
|
|
|
333
391
|
}
|
|
334
392
|
|
|
335
393
|
public WriteAt(b: $.Bytes, off: number): [number, $.GoError] {
|
|
394
|
+
if (this.closed) {
|
|
395
|
+
return [0, ErrClosed]
|
|
396
|
+
}
|
|
397
|
+
if (off < 0) {
|
|
398
|
+
return [0, ErrInvalid]
|
|
399
|
+
}
|
|
400
|
+
if (b === null) {
|
|
401
|
+
return [0, null]
|
|
402
|
+
}
|
|
403
|
+
const buf = $.bytesToUint8Array(b)
|
|
336
404
|
const handle = this.file?.handle
|
|
337
|
-
if (
|
|
338
|
-
|
|
405
|
+
if (handle && typeof handle.seekSync === "function") {
|
|
406
|
+
try {
|
|
407
|
+
handle.seekSync(off, io.SeekStart)
|
|
408
|
+
return this.Write(b)
|
|
409
|
+
} catch (err) {
|
|
410
|
+
return [0, newHostError(err)]
|
|
411
|
+
}
|
|
339
412
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
return this.Write(b)
|
|
343
|
-
} catch (err) {
|
|
344
|
-
return [0, newHostError(err)]
|
|
413
|
+
if (this.fd < 0) {
|
|
414
|
+
return [0, ErrInvalid]
|
|
345
415
|
}
|
|
416
|
+
const nodeFS = getNodeFS()
|
|
417
|
+
if (nodeFS?.writeSync && this.fd >= 0) {
|
|
418
|
+
try {
|
|
419
|
+
return [nodeFS.writeSync(this.fd, buf, 0, buf.length, off), null]
|
|
420
|
+
} catch (err) {
|
|
421
|
+
return [0, newHostError(err)]
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return [0, ErrUnimplemented]
|
|
346
425
|
}
|
|
347
426
|
|
|
348
427
|
public WriteTo(w: io.Writer): [number, $.GoError] {
|
|
@@ -251,7 +251,10 @@ function hasMeta(path: string): boolean {
|
|
|
251
251
|
return /[*?[\\]/.test(path)
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
function splitPattern(pattern: string): {
|
|
254
|
+
function splitPattern(pattern: string): {
|
|
255
|
+
absolute: boolean
|
|
256
|
+
segments: string[]
|
|
257
|
+
} {
|
|
255
258
|
const absolute = pattern.startsWith('/')
|
|
256
259
|
const segments = pattern.split('/').filter((segment, index) => {
|
|
257
260
|
if (index === 0 && segment === '') {
|
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
Rel,
|
|
21
21
|
EvalSymlinks,
|
|
22
22
|
Walk,
|
|
23
|
+
WalkDir,
|
|
24
|
+
SkipDir,
|
|
23
25
|
Separator,
|
|
24
26
|
ListSeparator,
|
|
25
27
|
} from './path.js'
|
|
@@ -206,14 +208,14 @@ describe('path/filepath - Path manipulation functions', () => {
|
|
|
206
208
|
})
|
|
207
209
|
|
|
208
210
|
describe('Walk', () => {
|
|
209
|
-
it('should visit host filesystem paths in lexical order', () => {
|
|
211
|
+
it('should visit host filesystem paths in lexical order', async () => {
|
|
210
212
|
const root = mkdtempSync(join(tmpdir(), 'goscript-filepath-walk-'))
|
|
211
213
|
try {
|
|
212
214
|
mkdirSync(join(root, 'a', 'b'), { recursive: true })
|
|
213
215
|
writeFileSync(join(root, 'a', 'b', 'file.txt'), 'ok')
|
|
214
216
|
|
|
215
217
|
const visited: string[] = []
|
|
216
|
-
const err = Walk(root, (path) => {
|
|
218
|
+
const err = await Walk(root, (path) => {
|
|
217
219
|
visited.push(path.slice(root.length).replace(/^\/?/, '') || '.')
|
|
218
220
|
return null
|
|
219
221
|
})
|
|
@@ -226,6 +228,59 @@ describe('path/filepath - Path manipulation functions', () => {
|
|
|
226
228
|
})
|
|
227
229
|
})
|
|
228
230
|
|
|
231
|
+
describe('WalkDir', () => {
|
|
232
|
+
it('should visit host filesystem dir entries in lexical order', async () => {
|
|
233
|
+
const root = mkdtempSync(join(tmpdir(), 'goscript-filepath-walkdir-'))
|
|
234
|
+
try {
|
|
235
|
+
mkdirSync(join(root, 'b'), { recursive: true })
|
|
236
|
+
mkdirSync(join(root, 'a'), { recursive: true })
|
|
237
|
+
writeFileSync(join(root, 'a', 'skipped.txt'), 'skip')
|
|
238
|
+
writeFileSync(join(root, 'b', 'file.txt'), 'ok')
|
|
239
|
+
|
|
240
|
+
const visited: string[] = []
|
|
241
|
+
const err = await WalkDir(root, (path, d, walkErr) => {
|
|
242
|
+
expect(walkErr).toBeNull()
|
|
243
|
+
visited.push(
|
|
244
|
+
`${path.slice(root.length).replace(/^\/?/, '') || '.'}:${d.Name()}:${d.IsDir()}`,
|
|
245
|
+
)
|
|
246
|
+
if (d.Name() === 'a') {
|
|
247
|
+
return SkipDir
|
|
248
|
+
}
|
|
249
|
+
return null
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
expect(err).toBeNull()
|
|
253
|
+
expect(visited).toEqual([
|
|
254
|
+
`.:${root.split('/').pop()}:true`,
|
|
255
|
+
'a:a:true',
|
|
256
|
+
'b:b:true',
|
|
257
|
+
'b/file.txt:file.txt:false',
|
|
258
|
+
])
|
|
259
|
+
} finally {
|
|
260
|
+
rmSync(root, { force: true, recursive: true })
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
it('should await async host filesystem dir callbacks', async () => {
|
|
265
|
+
const root = mkdtempSync(join(tmpdir(), 'goscript-filepath-walkdir-'))
|
|
266
|
+
try {
|
|
267
|
+
writeFileSync(join(root, 'file.txt'), 'ok')
|
|
268
|
+
|
|
269
|
+
const visited: string[] = []
|
|
270
|
+
const err = await WalkDir(root, async (path) => {
|
|
271
|
+
await Promise.resolve()
|
|
272
|
+
visited.push(path.slice(root.length).replace(/^\/?/, '') || '.')
|
|
273
|
+
return null
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
expect(err).toBeNull()
|
|
277
|
+
expect(visited).toEqual(['.', 'file.txt'])
|
|
278
|
+
} finally {
|
|
279
|
+
rmSync(root, { force: true, recursive: true })
|
|
280
|
+
}
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
|
|
229
284
|
describe('Constants', () => {
|
|
230
285
|
it('should have correct separator constants', () => {
|
|
231
286
|
expect(Separator).toBe(47)
|
package/gs/path/filepath/path.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// in a way compatible with the target operating system-defined file paths.
|
|
3
3
|
import * as $ from '@goscript/builtin/index.js'
|
|
4
4
|
import { getHostRuntime } from '@goscript/builtin/hostio.js'
|
|
5
|
+
import type { DirEntry } from '@goscript/io/fs/fs.js'
|
|
6
|
+
import { FileInfoToDirEntry } from '@goscript/io/fs/readdir.js'
|
|
5
7
|
|
|
6
8
|
type JoinElement = string | $.Slice<string>
|
|
7
9
|
|
|
@@ -320,15 +322,27 @@ export function Glob(_pattern: string): [string[], $.GoError] {
|
|
|
320
322
|
// prefix; that is, if Walk is called with "dir" and finds a file "a"
|
|
321
323
|
// in that directory, the walk function will be called with argument
|
|
322
324
|
// "dir/a". The info argument is the fs.FileInfo for the named path.
|
|
323
|
-
export type WalkFunc = (
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
325
|
+
export type WalkFunc = (
|
|
326
|
+
path: string,
|
|
327
|
+
info: any,
|
|
328
|
+
err: $.GoError,
|
|
329
|
+
) => $.GoError | Promise<$.GoError>
|
|
330
|
+
|
|
331
|
+
export async function Walk(root: string, walkFn: WalkFunc): Promise<$.GoError> {
|
|
332
|
+
return await walkHost(root, walkFn)
|
|
327
333
|
}
|
|
328
334
|
|
|
329
|
-
export
|
|
330
|
-
|
|
331
|
-
|
|
335
|
+
export type WalkDirFunc = (
|
|
336
|
+
path: string,
|
|
337
|
+
d: DirEntry,
|
|
338
|
+
err: $.GoError,
|
|
339
|
+
) => $.GoError | Promise<$.GoError>
|
|
340
|
+
|
|
341
|
+
export async function WalkDir(
|
|
342
|
+
root: string,
|
|
343
|
+
walkFn: WalkDirFunc,
|
|
344
|
+
): Promise<$.GoError> {
|
|
345
|
+
return await walkDirHost(root, walkFn)
|
|
332
346
|
}
|
|
333
347
|
|
|
334
348
|
// Localize is a stub - in Go it's used for Windows path localization
|
|
@@ -374,6 +388,10 @@ function fileInfo(path: string, stat: HostStat): any {
|
|
|
374
388
|
}
|
|
375
389
|
}
|
|
376
390
|
|
|
391
|
+
function dirEntry(path: string, stat: HostStat): DirEntry {
|
|
392
|
+
return FileInfoToDirEntry(fileInfo(path, stat))
|
|
393
|
+
}
|
|
394
|
+
|
|
377
395
|
function statPath(path: string): [HostStat | null, $.GoError] {
|
|
378
396
|
const runtime = getHostRuntime()
|
|
379
397
|
if (runtime.deno?.statSync) {
|
|
@@ -433,13 +451,13 @@ function readDir(path: string): [HostEntry[] | null, $.GoError] {
|
|
|
433
451
|
return [null, $.newError('filesystem not supported')]
|
|
434
452
|
}
|
|
435
453
|
|
|
436
|
-
function walkHost(path: string, walkFn: WalkFunc):
|
|
454
|
+
async function walkHost(path: string, walkFn: WalkFunc): Promise<$.GoError> {
|
|
437
455
|
const [stat, statErr] = statPath(path)
|
|
438
456
|
if (statErr !== null) {
|
|
439
|
-
return walkFn(path, null, statErr)
|
|
457
|
+
return await walkFn(path, null, statErr)
|
|
440
458
|
}
|
|
441
459
|
|
|
442
|
-
const visitErr = walkFn(path, fileInfo(path, stat!), null)
|
|
460
|
+
const visitErr = await walkFn(path, fileInfo(path, stat!), null)
|
|
443
461
|
if (visitErr === SkipAll) {
|
|
444
462
|
return null
|
|
445
463
|
}
|
|
@@ -455,10 +473,71 @@ function walkHost(path: string, walkFn: WalkFunc): $.GoError {
|
|
|
455
473
|
|
|
456
474
|
const [entries, readErr] = readDir(path)
|
|
457
475
|
if (readErr !== null) {
|
|
458
|
-
return walkFn(path, fileInfo(path, stat!), readErr)
|
|
476
|
+
return await walkFn(path, fileInfo(path, stat!), readErr)
|
|
477
|
+
}
|
|
478
|
+
for (const entry of entries!) {
|
|
479
|
+
const err = await walkHost(Join(path, entry.name), walkFn)
|
|
480
|
+
if (err === SkipDir) {
|
|
481
|
+
if (entry.isDir) {
|
|
482
|
+
continue
|
|
483
|
+
}
|
|
484
|
+
return err
|
|
485
|
+
}
|
|
486
|
+
if (err === SkipAll) {
|
|
487
|
+
return null
|
|
488
|
+
}
|
|
489
|
+
if (err !== null) {
|
|
490
|
+
return err
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return null
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function normalizeWalkDirErr(d: DirEntry, err: $.GoError): $.GoError {
|
|
497
|
+
if (err === SkipAll) {
|
|
498
|
+
return null
|
|
499
|
+
}
|
|
500
|
+
if (err === SkipDir && d?.IsDir?.()) {
|
|
501
|
+
return null
|
|
502
|
+
}
|
|
503
|
+
return err
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function normalizeRootWalkDirErr(err: $.GoError): $.GoError {
|
|
507
|
+
if (err === SkipAll || err === SkipDir) {
|
|
508
|
+
return null
|
|
509
|
+
}
|
|
510
|
+
return err
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
async function walkDirHost(
|
|
514
|
+
path: string,
|
|
515
|
+
walkFn: WalkDirFunc,
|
|
516
|
+
): Promise<$.GoError> {
|
|
517
|
+
const [stat, statErr] = statPath(path)
|
|
518
|
+
if (statErr !== null) {
|
|
519
|
+
return normalizeRootWalkDirErr(await walkFn(path, null, statErr))
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const d = dirEntry(path, stat!)
|
|
523
|
+
const visitErr = await walkFn(path, d, null)
|
|
524
|
+
if (visitErr === SkipAll) {
|
|
525
|
+
return null
|
|
526
|
+
}
|
|
527
|
+
if (visitErr === SkipDir && statIsDir(stat!)) {
|
|
528
|
+
return null
|
|
529
|
+
}
|
|
530
|
+
if (visitErr !== null || !statIsDir(stat!)) {
|
|
531
|
+
return visitErr
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const [entries, readErr] = readDir(path)
|
|
535
|
+
if (readErr !== null) {
|
|
536
|
+
return normalizeWalkDirErr(d, await walkFn(path, d, readErr))
|
|
459
537
|
}
|
|
538
|
+
|
|
460
539
|
for (const entry of entries!) {
|
|
461
|
-
const err =
|
|
540
|
+
const err = await walkDirHost(Join(path, entry.name), walkFn)
|
|
462
541
|
if (err === SkipDir) {
|
|
463
542
|
if (entry.isDir) {
|
|
464
543
|
continue
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
TypeKind,
|
|
5
|
+
arrayToSlice,
|
|
6
|
+
asArray,
|
|
7
|
+
registerStructType,
|
|
8
|
+
} from '../builtin/index.js'
|
|
9
|
+
import { NewAt, TypeOf, ValueOf } from './index.js'
|
|
10
|
+
|
|
11
|
+
class Person {
|
|
12
|
+
public Name = 'Ada'
|
|
13
|
+
public Count = 3
|
|
14
|
+
|
|
15
|
+
public String(): string {
|
|
16
|
+
return this.Name
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
;(Person as any).__typeInfo = { name: 'main.Person' }
|
|
20
|
+
|
|
21
|
+
describe('reflect struct field access', () => {
|
|
22
|
+
it('finds struct fields by name and index', () => {
|
|
23
|
+
registerStructType(
|
|
24
|
+
'main.Person',
|
|
25
|
+
new Person(),
|
|
26
|
+
[{ name: 'String', args: [], returns: [] }],
|
|
27
|
+
Person,
|
|
28
|
+
{
|
|
29
|
+
Name: 'string',
|
|
30
|
+
Count: { kind: TypeKind.Basic, name: 'int' },
|
|
31
|
+
},
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
const person = new Person()
|
|
35
|
+
const typ = TypeOf(person)
|
|
36
|
+
const [field, ok] = typ.FieldByName('Name')
|
|
37
|
+
|
|
38
|
+
expect(ok).toBe(true)
|
|
39
|
+
expect(field.Name).toBe('Name')
|
|
40
|
+
expect(field.Index).toEqual([0])
|
|
41
|
+
expect(typ.FieldByNameFunc((name) => name === 'Count')[0].Name).toBe(
|
|
42
|
+
'Count',
|
|
43
|
+
)
|
|
44
|
+
expect(typ.AssignableTo(typ)).toBe(true)
|
|
45
|
+
expect(typ.MethodByName('String')[1]).toBe(true)
|
|
46
|
+
expect(ValueOf(person).FieldByName('Name').String()).toBe('Ada')
|
|
47
|
+
expect(
|
|
48
|
+
ValueOf(person)
|
|
49
|
+
.FieldByIndex(arrayToSlice([1]))
|
|
50
|
+
.Int(),
|
|
51
|
+
).toBe(3)
|
|
52
|
+
expect(ValueOf(person).FieldByName('Missing').IsValid()).toBe(false)
|
|
53
|
+
|
|
54
|
+
const stringMethod = ValueOf(person).MethodByName('String')
|
|
55
|
+
expect(stringMethod.IsValid()).toBe(true)
|
|
56
|
+
expect(asArray(stringMethod.Call(arrayToSlice([])))[0].String()).toBe('Ada')
|
|
57
|
+
|
|
58
|
+
const nameField = ValueOf(person).FieldByName('Name')
|
|
59
|
+
const namePtr = NewAt(nameField.Type(), nameField.UnsafeAddr() as any)
|
|
60
|
+
namePtr.Elem().SetString('Grace')
|
|
61
|
+
expect(person.Name).toBe('Grace')
|
|
62
|
+
})
|
|
63
|
+
})
|