goscript 0.1.1 → 0.1.2
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 +9 -2
- package/compiler/lowering.go +2001 -345
- package/compiler/override-facts.go +77 -27
- package/compiler/override-registry.go +5 -4
- package/compiler/override-registry_test.go +135 -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 +1921 -298
- 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 +122 -9
- 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 +107 -25
- 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 +47 -7
- 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/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/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.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.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 +83 -3
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +110 -6
- package/dist/gs/net/http/index.js +262 -16
- 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/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 +161 -29
- 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 +257 -10
- package/gs/builtin/slice.test.ts +70 -0
- package/gs/builtin/slice.ts +566 -255
- package/gs/builtin/type.ts +53 -9
- package/gs/builtin/varRef.ts +2 -0
- package/gs/bytes/buffer.gs.ts +28 -28
- 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 +31 -1
- 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/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 +3 -1
- package/gs/fmt/fmt.ts +1 -5
- 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.ts +4 -1
- 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 +53 -0
- package/gs/net/http/httptest/index.ts +98 -3
- package/gs/net/http/index.test.ts +129 -1
- package/gs/net/http/index.ts +370 -19
- 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/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/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
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import {
|
|
3
|
+
makeMap,
|
|
4
|
+
mapGet,
|
|
5
|
+
mapSet,
|
|
3
6
|
TypeKind,
|
|
4
7
|
registerInterfaceType,
|
|
5
8
|
registerStructType,
|
|
6
9
|
} from '../builtin/index.js'
|
|
10
|
+
import { StructField } from './types.js'
|
|
7
11
|
import { Int, Struct, TypeFor } from './type.js'
|
|
8
12
|
|
|
9
13
|
describe('TypeFor', () => {
|
|
14
|
+
it('exposes StructField PkgPath and exported semantics', () => {
|
|
15
|
+
const exported = new StructField({ Name: 'Field' })
|
|
16
|
+
const unexported = new StructField({
|
|
17
|
+
Name: 'field',
|
|
18
|
+
PkgPath: 'example.test/pkg',
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
expect(exported.PkgPath).toBe('')
|
|
22
|
+
expect(exported.IsExported()).toBe(true)
|
|
23
|
+
expect(unexported.IsExported()).toBe(false)
|
|
24
|
+
expect(unexported.clone().PkgPath).toBe('example.test/pkg')
|
|
25
|
+
})
|
|
26
|
+
|
|
10
27
|
it('uses generic runtime type descriptors', () => {
|
|
11
28
|
const intType = TypeFor({
|
|
12
29
|
T: {
|
|
@@ -17,6 +34,18 @@ describe('TypeFor', () => {
|
|
|
17
34
|
|
|
18
35
|
expect(intType.String()).toBe('int')
|
|
19
36
|
expect(intType.Kind()).toBe(Int)
|
|
37
|
+
expect(intType.PkgPath()).toBe('')
|
|
38
|
+
|
|
39
|
+
const namedIntType = TypeFor({
|
|
40
|
+
T: {
|
|
41
|
+
type: { kind: TypeKind.Basic, name: 'int', typeName: 'gob.typeId' },
|
|
42
|
+
zero: () => 0,
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
expect(namedIntType.String()).toBe('gob.typeId')
|
|
46
|
+
expect(namedIntType.Name()).toBe('typeId')
|
|
47
|
+
expect(namedIntType.PkgPath()).toBe('gob')
|
|
48
|
+
expect(namedIntType.Kind()).toBe(Int)
|
|
20
49
|
})
|
|
21
50
|
|
|
22
51
|
it('formats literal interface methods from type metadata', () => {
|
|
@@ -50,6 +79,7 @@ describe('TypeFor', () => {
|
|
|
50
79
|
|
|
51
80
|
it('resolves registered type names from descriptors', () => {
|
|
52
81
|
class RegisteredStruct {}
|
|
82
|
+
class RegisteredWithFields {}
|
|
53
83
|
registerStructType(
|
|
54
84
|
'main.RegisteredStruct',
|
|
55
85
|
new RegisteredStruct(),
|
|
@@ -57,6 +87,24 @@ describe('TypeFor', () => {
|
|
|
57
87
|
RegisteredStruct,
|
|
58
88
|
{},
|
|
59
89
|
)
|
|
90
|
+
registerStructType(
|
|
91
|
+
'main.RegisteredWithFields',
|
|
92
|
+
new RegisteredWithFields(),
|
|
93
|
+
[],
|
|
94
|
+
RegisteredWithFields,
|
|
95
|
+
{
|
|
96
|
+
Name: { kind: TypeKind.Basic, name: 'string' },
|
|
97
|
+
Count: {
|
|
98
|
+
name: 'Total',
|
|
99
|
+
type: { kind: TypeKind.Basic, name: 'int' },
|
|
100
|
+
tag: 'json:"total"',
|
|
101
|
+
},
|
|
102
|
+
Items: {
|
|
103
|
+
kind: TypeKind.Slice,
|
|
104
|
+
elemType: 'main.RegisteredStruct',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
)
|
|
60
108
|
registerInterfaceType('main.RegisteredInterface', null, [
|
|
61
109
|
{ name: 'SomeMethod', args: [], returns: [] },
|
|
62
110
|
])
|
|
@@ -71,5 +119,57 @@ describe('TypeFor', () => {
|
|
|
71
119
|
expect(structType.String()).toBe('main.RegisteredStruct')
|
|
72
120
|
expect(structType.Kind()).toBe(Struct)
|
|
73
121
|
expect(ifaceType.String()).toBe('interface { SomeMethod() }')
|
|
122
|
+
|
|
123
|
+
const fieldsType = TypeFor({
|
|
124
|
+
T: {
|
|
125
|
+
type: 'main.RegisteredWithFields',
|
|
126
|
+
zero: () => new RegisteredWithFields(),
|
|
127
|
+
},
|
|
128
|
+
})
|
|
129
|
+
expect(fieldsType.NumField()).toBe(3)
|
|
130
|
+
expect(fieldsType.Field(0).Name).toBe('Name')
|
|
131
|
+
expect(fieldsType.Field(0).Type.String()).toBe('string')
|
|
132
|
+
expect(fieldsType.Field(1).Name).toBe('Total')
|
|
133
|
+
expect(fieldsType.Field(1).Tag.Get('json')).toBe('total')
|
|
134
|
+
expect(fieldsType.Field(2).Type.String()).toBe('[]main.RegisteredStruct')
|
|
135
|
+
expect(fieldsType.Field(2).Type.Elem().String()).toBe('main.RegisteredStruct')
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('interns runtime type descriptors for reflect.Type map keys', () => {
|
|
139
|
+
const first = TypeFor({
|
|
140
|
+
T: { type: 'gob.wireType', zero: () => ({}) },
|
|
141
|
+
})
|
|
142
|
+
const second = TypeFor({
|
|
143
|
+
T: { type: 'gob.wireType', zero: () => ({}) },
|
|
144
|
+
})
|
|
145
|
+
const arrayType = TypeFor({
|
|
146
|
+
T: {
|
|
147
|
+
type: {
|
|
148
|
+
kind: TypeKind.Array,
|
|
149
|
+
elemType: { kind: TypeKind.Basic, name: 'uint8' },
|
|
150
|
+
length: 16,
|
|
151
|
+
},
|
|
152
|
+
zero: () => new Uint8Array(16),
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
expect(second).toBe(first)
|
|
157
|
+
expect(arrayType).toBe(
|
|
158
|
+
TypeFor({
|
|
159
|
+
T: {
|
|
160
|
+
type: {
|
|
161
|
+
kind: TypeKind.Array,
|
|
162
|
+
elemType: { kind: TypeKind.Basic, name: 'uint8' },
|
|
163
|
+
length: 16,
|
|
164
|
+
},
|
|
165
|
+
zero: () => new Uint8Array(16),
|
|
166
|
+
},
|
|
167
|
+
}),
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
const m = makeMap<typeof first, string>()
|
|
171
|
+
mapSet(m, first, 'wire')
|
|
172
|
+
|
|
173
|
+
expect(mapGet(m, second, '')).toEqual(['wire', true])
|
|
74
174
|
})
|
|
75
175
|
})
|
package/gs/reflect/types.ts
CHANGED
|
@@ -40,6 +40,7 @@ import { Type, Kind, Value, Kind_String, ChanDir } from './type.js'
|
|
|
40
40
|
// Struct field representation
|
|
41
41
|
export class StructField {
|
|
42
42
|
public Name: string = ''
|
|
43
|
+
public PkgPath: string = ''
|
|
43
44
|
public Type!: Type
|
|
44
45
|
public Tag: StructTag = new StructTag('')
|
|
45
46
|
public Offset: uintptr = 0
|
|
@@ -55,6 +56,7 @@ export class StructField {
|
|
|
55
56
|
public clone(): StructField {
|
|
56
57
|
return new StructField({
|
|
57
58
|
Name: this.Name,
|
|
59
|
+
PkgPath: this.PkgPath,
|
|
58
60
|
Type: this.Type,
|
|
59
61
|
Tag: this.Tag,
|
|
60
62
|
Offset: this.Offset,
|
|
@@ -64,7 +66,7 @@ export class StructField {
|
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
public IsExported(): boolean {
|
|
67
|
-
return this.
|
|
69
|
+
return this.PkgPath === ''
|
|
68
70
|
}
|
|
69
71
|
}
|
|
70
72
|
|
package/gs/reflect/value.ts
CHANGED
|
@@ -26,7 +26,13 @@ import {
|
|
|
26
26
|
BasicType,
|
|
27
27
|
Invalid,
|
|
28
28
|
} from './type.js'
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
Pointer,
|
|
31
|
+
ReflectValue,
|
|
32
|
+
SelectCase,
|
|
33
|
+
SelectRecv,
|
|
34
|
+
SelectDefault,
|
|
35
|
+
} from './types.js'
|
|
30
36
|
|
|
31
37
|
interface ChannelObject {
|
|
32
38
|
_sendQueue?: unknown[]
|
|
@@ -142,6 +148,33 @@ export function New(typ: Type | null): Value {
|
|
|
142
148
|
return new Value(null, ptrType) // null represents the pointer value
|
|
143
149
|
}
|
|
144
150
|
|
|
151
|
+
// NewAt returns a Value representing a pointer to the value at p.
|
|
152
|
+
export function NewAt(typ: Type | null, p: Pointer | unknown): Value {
|
|
153
|
+
if (typ === null) {
|
|
154
|
+
return new Value()
|
|
155
|
+
}
|
|
156
|
+
const ptrType = PointerTo(typ)
|
|
157
|
+
if (
|
|
158
|
+
p &&
|
|
159
|
+
typeof p === 'object' &&
|
|
160
|
+
'value' in p &&
|
|
161
|
+
(p as { value?: unknown }).value instanceof Value
|
|
162
|
+
) {
|
|
163
|
+
const target = (p as { value: Value }).value
|
|
164
|
+
const ref: $.VarRef<ReflectValue> = {
|
|
165
|
+
get value(): ReflectValue {
|
|
166
|
+
return target.Interface() as ReflectValue
|
|
167
|
+
},
|
|
168
|
+
set value(value: ReflectValue) {
|
|
169
|
+
target.Set(new Value(value, typ))
|
|
170
|
+
},
|
|
171
|
+
__isVarRef: true,
|
|
172
|
+
}
|
|
173
|
+
return new Value(ref, ptrType)
|
|
174
|
+
}
|
|
175
|
+
return new Value($.unsupportedPointerRef<ReflectValue>(p), ptrType)
|
|
176
|
+
}
|
|
177
|
+
|
|
145
178
|
// MakeSlice returns a Value representing a new slice with the specified type, length, and capacity.
|
|
146
179
|
export function MakeSlice(typ: Type | null, len: number, _cap: number): Value {
|
|
147
180
|
if (typ === null || typ.Kind() !== Slice) {
|
|
@@ -171,6 +204,10 @@ export function MakeMap(typ: Type | null): Value {
|
|
|
171
204
|
return new Value(map, typ)
|
|
172
205
|
}
|
|
173
206
|
|
|
207
|
+
export function MakeMapWithSize(typ: Type | null, _n: number): Value {
|
|
208
|
+
return MakeMap(typ)
|
|
209
|
+
}
|
|
210
|
+
|
|
174
211
|
// Append appends the values x to a slice and returns the resulting slice.
|
|
175
212
|
export function Append(s: Value, x: Value): Value {
|
|
176
213
|
if (s.Kind() !== Slice) {
|
|
@@ -188,6 +225,18 @@ export function Append(s: Value, x: Value): Value {
|
|
|
188
225
|
return new Value(newArray, s.Type())
|
|
189
226
|
}
|
|
190
227
|
|
|
228
|
+
export function AppendSlice(s: Value, t: Value): Value {
|
|
229
|
+
if (s.Kind() !== Slice || t.Kind() !== Slice) {
|
|
230
|
+
throw new Error('reflect.AppendSlice of non-slice')
|
|
231
|
+
}
|
|
232
|
+
const left = getArrayFromValue(s)
|
|
233
|
+
const right = getArrayFromValue(t)
|
|
234
|
+
if (!left || !right) {
|
|
235
|
+
throw new Error('cannot get array from slice value')
|
|
236
|
+
}
|
|
237
|
+
return new Value([...left, ...right], s.Type())
|
|
238
|
+
}
|
|
239
|
+
|
|
191
240
|
// MakeChan returns a Value representing a new channel with the specified type.
|
|
192
241
|
export function MakeChan(typ: Type, buffer: number): Value {
|
|
193
242
|
if (typ.Kind() !== Chan) {
|
|
@@ -131,7 +131,7 @@ class visibleFieldsWalker {
|
|
|
131
131
|
const field = t!.Field(i)
|
|
132
132
|
if (field) {
|
|
133
133
|
const f = field.clone()
|
|
134
|
-
f.Index = $.append(null, w.index) as number[]
|
|
134
|
+
f.Index = $.append(null, ...(w.index ?? [])) as number[]
|
|
135
135
|
if (f.Anonymous) {
|
|
136
136
|
if (f.Type && f.Type.Kind() === Ptr) {
|
|
137
137
|
const elemType = f.Type.Elem!()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest'
|
|
2
2
|
|
|
3
|
-
import { PrintStack, Stack } from './index.js'
|
|
3
|
+
import { BuildInfo, BuildSetting, Module, PrintStack, ReadBuildInfo, Stack } from './index.js'
|
|
4
4
|
|
|
5
5
|
describe('runtime/debug override', () => {
|
|
6
6
|
it('returns a stack trace as bytes', () => {
|
|
@@ -21,4 +21,25 @@ describe('runtime/debug override', () => {
|
|
|
21
21
|
consoleError.mockRestore()
|
|
22
22
|
}
|
|
23
23
|
})
|
|
24
|
+
|
|
25
|
+
it('exposes build info structs and reports no embedded module table', () => {
|
|
26
|
+
const module = new Module({
|
|
27
|
+
Path: 'example.test/module',
|
|
28
|
+
Version: 'v1.2.3',
|
|
29
|
+
Sum: 'h1:sum',
|
|
30
|
+
Replace: new Module({ Path: '../module' }),
|
|
31
|
+
})
|
|
32
|
+
const info = new BuildInfo({
|
|
33
|
+
GoVersion: 'go1.26.3',
|
|
34
|
+
Path: 'example.test/main',
|
|
35
|
+
Main: module,
|
|
36
|
+
Deps: [module],
|
|
37
|
+
Settings: [new BuildSetting({ Key: 'GOOS', Value: 'js' })],
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
expect(info.Main.Path).toBe('example.test/module')
|
|
41
|
+
expect(info.Deps?.[0]).toBe(module)
|
|
42
|
+
expect(info.Settings?.[0]?.Value).toBe('js')
|
|
43
|
+
expect(ReadBuildInfo()).toEqual([null, false])
|
|
44
|
+
})
|
|
24
45
|
})
|
|
@@ -1,3 +1,87 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
|
|
3
|
+
export class BuildSetting {
|
|
4
|
+
public Key: string
|
|
5
|
+
public Value: string
|
|
6
|
+
|
|
7
|
+
constructor(init?: Partial<{ Key: string; Value: string }>) {
|
|
8
|
+
this.Key = init?.Key ?? ''
|
|
9
|
+
this.Value = init?.Value ?? ''
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public clone(): BuildSetting {
|
|
13
|
+
return $.markAsStructValue(new BuildSetting({ Key: this.Key, Value: this.Value }))
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class Module {
|
|
18
|
+
public Path: string
|
|
19
|
+
public Version: string
|
|
20
|
+
public Sum: string
|
|
21
|
+
public Replace: Module | $.VarRef<Module> | null
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
init?: Partial<{
|
|
25
|
+
Path: string
|
|
26
|
+
Version: string
|
|
27
|
+
Sum: string
|
|
28
|
+
Replace: Module | $.VarRef<Module> | null
|
|
29
|
+
}>,
|
|
30
|
+
) {
|
|
31
|
+
this.Path = init?.Path ?? ''
|
|
32
|
+
this.Version = init?.Version ?? ''
|
|
33
|
+
this.Sum = init?.Sum ?? ''
|
|
34
|
+
this.Replace = init?.Replace ?? null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public clone(): Module {
|
|
38
|
+
return $.markAsStructValue(
|
|
39
|
+
new Module({
|
|
40
|
+
Path: this.Path,
|
|
41
|
+
Version: this.Version,
|
|
42
|
+
Sum: this.Sum,
|
|
43
|
+
Replace: this.Replace,
|
|
44
|
+
}),
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class BuildInfo {
|
|
50
|
+
public GoVersion: string
|
|
51
|
+
public Path: string
|
|
52
|
+
public Main: Module
|
|
53
|
+
public Deps: $.Slice<Module | $.VarRef<Module> | null>
|
|
54
|
+
public Settings: $.Slice<BuildSetting>
|
|
55
|
+
|
|
56
|
+
constructor(
|
|
57
|
+
init?: Partial<{
|
|
58
|
+
GoVersion: string
|
|
59
|
+
Path: string
|
|
60
|
+
Main: Module
|
|
61
|
+
Deps: $.Slice<Module | $.VarRef<Module> | null>
|
|
62
|
+
Settings: $.Slice<BuildSetting>
|
|
63
|
+
}>,
|
|
64
|
+
) {
|
|
65
|
+
this.GoVersion = init?.GoVersion ?? ''
|
|
66
|
+
this.Path = init?.Path ?? ''
|
|
67
|
+
this.Main = init?.Main ?? new Module()
|
|
68
|
+
this.Deps = init?.Deps ?? null
|
|
69
|
+
this.Settings = init?.Settings ?? null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public clone(): BuildInfo {
|
|
73
|
+
return $.markAsStructValue(
|
|
74
|
+
new BuildInfo({
|
|
75
|
+
GoVersion: this.GoVersion,
|
|
76
|
+
Path: this.Path,
|
|
77
|
+
Main: this.Main.clone(),
|
|
78
|
+
Deps: this.Deps,
|
|
79
|
+
Settings: this.Settings,
|
|
80
|
+
}),
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
1
85
|
export function Stack(): Uint8Array {
|
|
2
86
|
const stack = new Error().stack ?? 'stack trace unavailable'
|
|
3
87
|
return new TextEncoder().encode(stack)
|
|
@@ -6,3 +90,7 @@ export function Stack(): Uint8Array {
|
|
|
6
90
|
export function PrintStack(): void {
|
|
7
91
|
console.error(new TextDecoder().decode(Stack()))
|
|
8
92
|
}
|
|
93
|
+
|
|
94
|
+
export function ReadBuildInfo(): [BuildInfo | null, boolean] {
|
|
95
|
+
return [null, false]
|
|
96
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { Lookup, StartCPUProfile, StopCPUProfile } from './index.js'
|
|
4
|
+
|
|
5
|
+
describe('runtime/pprof override', () => {
|
|
6
|
+
it('writes deterministic CPU profile bytes', () => {
|
|
7
|
+
const chunks: Uint8Array[] = []
|
|
8
|
+
const writer = {
|
|
9
|
+
Write(p: Uint8Array): [number, null] {
|
|
10
|
+
chunks.push(new Uint8Array(p))
|
|
11
|
+
return [p.length, null]
|
|
12
|
+
},
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
expect(StartCPUProfile(writer)).toBeNull()
|
|
16
|
+
StopCPUProfile()
|
|
17
|
+
|
|
18
|
+
expect(chunks.reduce((total, chunk) => total + chunk.length, 0)).toBeGreaterThan(0)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('writes deterministic memory profile bytes', () => {
|
|
22
|
+
const chunks: Uint8Array[] = []
|
|
23
|
+
const writer = {
|
|
24
|
+
Write(p: Uint8Array): [number, null] {
|
|
25
|
+
chunks.push(new Uint8Array(p))
|
|
26
|
+
return [p.length, null]
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const profile = Lookup('allocs')
|
|
31
|
+
|
|
32
|
+
expect(profile).not.toBeNull()
|
|
33
|
+
expect(profile!.WriteTo(writer, 0)).toBeNull()
|
|
34
|
+
expect(chunks.reduce((total, chunk) => total + chunk.length, 0)).toBeGreaterThan(0)
|
|
35
|
+
})
|
|
36
|
+
})
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import * as errors from '@goscript/errors/index.js'
|
|
3
|
+
import * as io from '@goscript/io/index.js'
|
|
4
|
+
|
|
5
|
+
type WriterArg = io.Writer | $.VarRef<io.Writer> | null | undefined
|
|
6
|
+
|
|
7
|
+
let activeCPUWriter: io.Writer | null = null
|
|
8
|
+
|
|
9
|
+
export class Profile {
|
|
10
|
+
public name: string
|
|
11
|
+
|
|
12
|
+
constructor(name = '') {
|
|
13
|
+
this.name = name
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public Name(): string {
|
|
17
|
+
return this.name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public Count(): number {
|
|
21
|
+
return this.name === '' ? 0 : 1
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public WriteTo(w: WriterArg, debug: number): $.GoError {
|
|
25
|
+
return writeProfile(w, `goscript pprof ${this.name} debug=${debug}\n`)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function Lookup(name: string): Profile | null {
|
|
30
|
+
switch (name) {
|
|
31
|
+
case 'heap':
|
|
32
|
+
case 'allocs':
|
|
33
|
+
case 'goroutine':
|
|
34
|
+
case 'threadcreate':
|
|
35
|
+
case 'block':
|
|
36
|
+
case 'mutex':
|
|
37
|
+
return new Profile(name)
|
|
38
|
+
default:
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function Profiles(): $.Slice<Profile | null> {
|
|
44
|
+
return $.arrayToSlice([
|
|
45
|
+
new Profile('allocs'),
|
|
46
|
+
new Profile('block'),
|
|
47
|
+
new Profile('goroutine'),
|
|
48
|
+
new Profile('heap'),
|
|
49
|
+
new Profile('mutex'),
|
|
50
|
+
new Profile('threadcreate'),
|
|
51
|
+
])
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function StartCPUProfile(w: WriterArg): $.GoError {
|
|
55
|
+
const writer = writerFromArg(w)
|
|
56
|
+
if (writer == null) {
|
|
57
|
+
return errors.New('runtime/pprof: nil profile writer')
|
|
58
|
+
}
|
|
59
|
+
if (activeCPUWriter != null) {
|
|
60
|
+
return errors.New('runtime/pprof: CPU profiling already active')
|
|
61
|
+
}
|
|
62
|
+
activeCPUWriter = writer
|
|
63
|
+
return writeProfile(writer, 'goscript cpu profile start\n')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function StopCPUProfile(): void {
|
|
67
|
+
if (activeCPUWriter != null) {
|
|
68
|
+
writeProfile(activeCPUWriter, 'goscript cpu profile stop\n')
|
|
69
|
+
activeCPUWriter = null
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function SetGoroutineLabels(_ctx: unknown): void {}
|
|
74
|
+
|
|
75
|
+
export function Do(_ctx: unknown, _labels: unknown, fn: (() => void) | null): void {
|
|
76
|
+
fn?.()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function ForLabels(_ctx: unknown, _f: unknown): void {}
|
|
80
|
+
|
|
81
|
+
export function WithLabels(ctx: unknown, _labels: unknown): unknown {
|
|
82
|
+
return ctx
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function Labels(...args: string[]): Map<string, string> {
|
|
86
|
+
const labels = new Map<string, string>()
|
|
87
|
+
for (let i = 0; i + 1 < args.length; i += 2) {
|
|
88
|
+
labels.set(args[i], args[i + 1])
|
|
89
|
+
}
|
|
90
|
+
return labels
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function writerFromArg(w: WriterArg): io.Writer | null {
|
|
94
|
+
return $.pointerValueOrNil(w)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function writeProfile(w: WriterArg, text: string): $.GoError {
|
|
98
|
+
const writer = writerFromArg(w)
|
|
99
|
+
if (writer == null) {
|
|
100
|
+
return errors.New('runtime/pprof: nil profile writer')
|
|
101
|
+
}
|
|
102
|
+
const [, err] = writer.Write($.stringToBytes(text))
|
|
103
|
+
return err
|
|
104
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import * as context from '@goscript/context/index.js'
|
|
4
|
+
|
|
5
|
+
import { IsEnabled, Log, NewTask, Start, StartRegion, Stop, WithRegion } from './index.js'
|
|
6
|
+
|
|
7
|
+
describe('runtime/trace override', () => {
|
|
8
|
+
it('creates no-op tasks from nil context', () => {
|
|
9
|
+
const [ctx, task] = NewTask(null, 'task')
|
|
10
|
+
|
|
11
|
+
expect(ctx).not.toBeNull()
|
|
12
|
+
expect(task).not.toBeNull()
|
|
13
|
+
task.End()
|
|
14
|
+
Log(ctx, 'category', 'message')
|
|
15
|
+
expect(IsEnabled()).toBe(false)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('runs no-op regions', () => {
|
|
19
|
+
const [ctx] = NewTask(context.Background(), 'task')
|
|
20
|
+
const called = { value: false }
|
|
21
|
+
|
|
22
|
+
WithRegion(ctx, 'region', () => {
|
|
23
|
+
called.value = true
|
|
24
|
+
})
|
|
25
|
+
StartRegion(ctx, 'region').End()
|
|
26
|
+
|
|
27
|
+
expect(called.value).toBe(true)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('writes deterministic trace bytes', () => {
|
|
31
|
+
const chunks: Uint8Array[] = []
|
|
32
|
+
const writer = {
|
|
33
|
+
Write(p: Uint8Array): [number, null] {
|
|
34
|
+
chunks.push(new Uint8Array(p))
|
|
35
|
+
return [p.length, null]
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
expect(Start(writer)).toBeNull()
|
|
40
|
+
Log(context.Background(), 'category', 'message')
|
|
41
|
+
Stop()
|
|
42
|
+
|
|
43
|
+
expect(chunks.reduce((total, chunk) => total + chunk.length, 0)).toBeGreaterThan(0)
|
|
44
|
+
})
|
|
45
|
+
})
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import * as context from '@goscript/context/index.js'
|
|
3
|
+
import * as errors from '@goscript/errors/index.js'
|
|
4
|
+
import * as io from '@goscript/io/index.js'
|
|
5
|
+
|
|
6
|
+
class traceContextKey {}
|
|
7
|
+
|
|
8
|
+
const traceState = {
|
|
9
|
+
activeWriter: null as io.Writer | null,
|
|
10
|
+
nextTaskID: 0,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class Task {
|
|
14
|
+
public id: number
|
|
15
|
+
|
|
16
|
+
constructor(id = 0) {
|
|
17
|
+
this.id = id
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public End(): void {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class Region {
|
|
24
|
+
public End(): void {}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function NewTask(
|
|
28
|
+
pctx: context.Context | null,
|
|
29
|
+
_taskType: string,
|
|
30
|
+
): [context.Context | null, Task] {
|
|
31
|
+
const parent = pctx ?? context.Background()
|
|
32
|
+
const task = new Task(++traceState.nextTaskID)
|
|
33
|
+
return [
|
|
34
|
+
context.WithValue(
|
|
35
|
+
parent,
|
|
36
|
+
$.interfaceValue(new traceContextKey(), 'trace.traceContextKey'),
|
|
37
|
+
$.interfaceValue(task, '*trace.Task'),
|
|
38
|
+
),
|
|
39
|
+
task,
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function Log(_ctx: context.Context | null, category: string, message: string): void {
|
|
44
|
+
writeTrace(`log ${category} ${message}\n`)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function Logf(
|
|
48
|
+
_ctx: context.Context | null,
|
|
49
|
+
_category: string,
|
|
50
|
+
_format: string,
|
|
51
|
+
..._args: unknown[]
|
|
52
|
+
): void {}
|
|
53
|
+
|
|
54
|
+
export function WithRegion(
|
|
55
|
+
_ctx: context.Context | null,
|
|
56
|
+
_regionType: string,
|
|
57
|
+
fn: (() => void) | null,
|
|
58
|
+
): void {
|
|
59
|
+
fn?.()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function StartRegion(
|
|
63
|
+
_ctx: context.Context | null,
|
|
64
|
+
_regionType: string,
|
|
65
|
+
): Region {
|
|
66
|
+
return new Region()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function IsEnabled(): boolean {
|
|
70
|
+
return false
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function Start(w: io.Writer | $.VarRef<io.Writer> | null): $.GoError {
|
|
74
|
+
const writer = $.pointerValueOrNil(w)
|
|
75
|
+
if (writer == null) {
|
|
76
|
+
return errors.New('runtime/trace: nil trace writer')
|
|
77
|
+
}
|
|
78
|
+
if (traceState.activeWriter != null) {
|
|
79
|
+
return errors.New('runtime/trace: trace already active')
|
|
80
|
+
}
|
|
81
|
+
traceState.activeWriter = writer
|
|
82
|
+
return writeTrace('goscript trace start\n')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function Stop(): void {
|
|
86
|
+
writeTrace('goscript trace stop\n')
|
|
87
|
+
traceState.activeWriter = null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function writeTrace(text: string): $.GoError {
|
|
91
|
+
const writer = traceState.activeWriter
|
|
92
|
+
if (writer == null) {
|
|
93
|
+
return null
|
|
94
|
+
}
|
|
95
|
+
const [, err] = writer.Write($.stringToBytes(text))
|
|
96
|
+
return err
|
|
97
|
+
}
|