goscript 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/cmd/go_js_wasm_exec/main.go +201 -0
- package/cmd/go_js_wasm_exec/main_test.go +83 -0
- package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +35 -8
- package/cmd/goscript/cmd-test.go +14 -0
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript/cmd_compile_test.go +105 -6
- package/compiler/build-flags.go +9 -10
- package/compiler/compile-request.go +12 -9
- package/compiler/compliance_test.go +0 -1
- package/compiler/config.go +2 -0
- package/compiler/gotest/request.go +28 -0
- package/compiler/gotest/runner.go +353 -27
- package/compiler/gotest/runner_test.go +400 -1
- package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
- package/compiler/gotest/testdata/browserapi/go.mod +3 -0
- package/compiler/lowered-program.go +24 -17
- package/compiler/lowering.go +988 -263
- package/compiler/lowering_bench_test.go +364 -0
- package/compiler/override-facts.go +15 -0
- package/compiler/override-parity-verifier.go +450 -0
- package/compiler/override-parity.go +122 -0
- package/compiler/override-registry_test.go +559 -0
- package/compiler/package-graph.go +61 -4
- package/compiler/package-graph_test.go +30 -0
- package/compiler/protobuf-ts-binding.go +514 -0
- package/compiler/protobuf-ts-binding_test.go +172 -0
- package/compiler/semantic-model-types.go +17 -4
- package/compiler/semantic-model.go +709 -72
- package/compiler/semantic-model_test.go +219 -0
- package/compiler/service.go +20 -1
- package/compiler/skeleton_test.go +1008 -20
- package/compiler/typescript-emitter.go +147 -15
- package/dist/gs/builtin/builtin.d.ts +2 -2
- package/dist/gs/builtin/builtin.js +20 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +2 -1
- package/dist/gs/builtin/slice.js +34 -4
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +14 -6
- package/dist/gs/builtin/type.js +224 -64
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +11 -0
- package/dist/gs/builtin/varRef.js +57 -2
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +13 -6
- package/dist/gs/compress/zlib/index.js +131 -35
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.js +2 -5
- package/dist/gs/crypto/sha1/index.js.map +1 -1
- package/dist/gs/crypto/sha256/index.js +2 -5
- package/dist/gs/crypto/sha256/index.js.map +1 -1
- package/dist/gs/crypto/sha512/index.js +2 -5
- package/dist/gs/crypto/sha512/index.js.map +1 -1
- package/dist/gs/embed/index.d.ts +6 -0
- package/dist/gs/embed/index.js +210 -5
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/encoding/json/index.d.ts +114 -0
- package/dist/gs/encoding/json/index.js +544 -36
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +3 -3
- package/dist/gs/fmt/fmt.js +29 -16
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/errors.js +54 -30
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +2 -0
- package/dist/gs/go/scanner/index.js +29 -5
- package/dist/gs/go/scanner/index.js.map +1 -1
- package/dist/gs/go/token/index.js +22 -6
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/index.d.ts +6 -0
- package/dist/gs/hash/index.js +20 -0
- package/dist/gs/hash/index.js.map +1 -1
- package/dist/gs/internal/goarch/index.d.ts +43 -3
- package/dist/gs/internal/goarch/index.js +42 -10
- package/dist/gs/internal/goarch/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js +26 -14
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js +8 -4
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/sub.js +8 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.d.ts +12 -6
- package/dist/gs/io/io.js +87 -42
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +31 -5
- package/dist/gs/math/bits/index.js +29 -28
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.d.ts +16 -0
- package/dist/gs/mime/index.js +315 -6
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +12 -0
- package/dist/gs/net/http/httptest/index.js +85 -6
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +303 -6
- package/dist/gs/net/http/index.js +1615 -58
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +1 -1
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.d.ts +1 -0
- package/dist/gs/os/exec.gs.js +4 -8
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/index.d.ts +1 -1
- package/dist/gs/os/index.js +1 -1
- package/dist/gs/os/index.js.map +1 -1
- package/dist/gs/os/proc.gs.d.ts +4 -0
- package/dist/gs/os/proc.gs.js +12 -6
- package/dist/gs/os/proc.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +6 -2
- package/dist/gs/os/types_js.gs.js +170 -9
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/path.js +11 -7
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +5 -4
- package/dist/gs/reflect/index.js +4 -3
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js +15 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +26 -6
- package/dist/gs/reflect/type.js +1498 -279
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +14 -6
- package/dist/gs/reflect/types.js +35 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +1 -0
- package/dist/gs/reflect/value.js +83 -41
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +4 -140
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +8 -2
- package/dist/gs/runtime/pprof/index.js +50 -30
- package/dist/gs/runtime/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.js +5 -4
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.js +5 -19
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/complex.gs.d.ts +3 -0
- package/dist/gs/strconv/complex.gs.js +148 -0
- package/dist/gs/strconv/complex.gs.js.map +1 -0
- package/dist/gs/strconv/index.d.ts +1 -0
- package/dist/gs/strconv/index.js +1 -0
- package/dist/gs/strconv/index.js.map +1 -1
- package/dist/gs/strings/builder.js +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +11 -7
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js +15 -7
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.d.ts +5 -0
- package/dist/gs/strings/strings.js +57 -5
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js +9 -9
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js +2 -2
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +2 -1
- package/dist/gs/sync/sync.js +37 -16
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/env.js +22 -14
- package/dist/gs/syscall/env.js.map +1 -1
- package/dist/gs/syscall/js/index.js +9 -0
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/testing/testing.js +59 -15
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.d.ts +24 -1
- package/dist/gs/time/time.js +43 -3
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unique/index.js +7 -1
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +3 -3
- package/go.sum +16 -0
- package/gs/builtin/builtin.ts +25 -2
- package/gs/builtin/runtime-contract.test.ts +260 -18
- package/gs/builtin/slice.ts +51 -4
- package/gs/builtin/type.ts +310 -63
- package/gs/builtin/varRef.ts +85 -2
- package/gs/bytes/buffer.gs.ts +1 -1
- package/gs/bytes/reader.gs.ts +1 -1
- package/gs/compress/zlib/index.test.ts +159 -1
- package/gs/compress/zlib/index.ts +164 -37
- package/gs/compress/zlib/meta.json +4 -1
- package/gs/compress/zlib/parity.json +51 -0
- package/gs/crypto/sha1/index.test.ts +19 -2
- package/gs/crypto/sha1/index.ts +3 -6
- package/gs/crypto/sha256/index.test.ts +14 -2
- package/gs/crypto/sha256/index.ts +3 -6
- package/gs/crypto/sha512/index.test.ts +17 -2
- package/gs/crypto/sha512/index.ts +3 -6
- package/gs/embed/index.test.ts +87 -0
- package/gs/embed/index.ts +229 -5
- package/gs/encoding/json/index.test.ts +360 -6
- package/gs/encoding/json/index.ts +679 -38
- package/gs/encoding/json/parity.json +81 -0
- package/gs/fmt/fmt.test.ts +41 -3
- package/gs/fmt/fmt.ts +40 -17
- package/gs/fmt/meta.json +6 -1
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
- package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
- package/gs/github.com/pkg/errors/errors.ts +54 -30
- package/gs/go/scanner/index.test.ts +39 -56
- package/gs/go/scanner/index.ts +33 -5
- package/gs/go/scanner/parity.json +27 -0
- package/gs/go/token/index.ts +22 -6
- package/gs/hash/index.test.ts +20 -33
- package/gs/hash/index.ts +28 -0
- package/gs/hash/parity.json +21 -0
- package/gs/internal/goarch/index.test.ts +32 -0
- package/gs/internal/goarch/index.ts +45 -13
- package/gs/internal/goarch/parity.json +144 -0
- package/gs/io/fs/fs.ts +26 -14
- package/gs/io/fs/readdir.test.ts +38 -0
- package/gs/io/fs/readdir.ts +8 -4
- package/gs/io/fs/sub.ts +8 -1
- package/gs/io/io.test.ts +77 -6
- package/gs/io/io.ts +115 -52
- package/gs/io/meta.json +7 -1
- package/gs/io/parity.json +162 -0
- package/gs/math/bits/index.test.ts +14 -1
- package/gs/math/bits/index.ts +75 -32
- package/gs/math/bits/parity.json +156 -0
- package/gs/mime/index.test.ts +90 -0
- package/gs/mime/index.ts +369 -6
- package/gs/mime/parity.json +36 -0
- package/gs/net/http/httptest/index.test.ts +98 -2
- package/gs/net/http/httptest/index.ts +101 -6
- package/gs/net/http/httptest/parity.json +15 -0
- package/gs/net/http/index.test.ts +797 -12
- package/gs/net/http/index.ts +1874 -136
- package/gs/net/http/meta.json +16 -1
- package/gs/net/http/parity.json +193 -0
- package/gs/os/dir_unix.gs.ts +1 -1
- package/gs/os/error.gs.ts +1 -1
- package/gs/os/exec.gs.ts +4 -8
- package/gs/os/exec_posix.gs.ts +1 -1
- package/gs/os/file_unix_js.test.ts +52 -0
- package/gs/os/index.test.ts +9 -0
- package/gs/os/index.ts +1 -0
- package/gs/os/meta.json +4 -0
- package/gs/os/parity.json +9 -0
- package/gs/os/proc.gs.ts +18 -5
- package/gs/os/proc.test.ts +26 -0
- package/gs/os/readdir.test.ts +56 -0
- package/gs/os/root_js.gs.ts +1 -1
- package/gs/os/types.gs.ts +1 -1
- package/gs/os/types_js.gs.ts +170 -9
- package/gs/os/types_unix.gs.ts +1 -1
- package/gs/path/path.ts +11 -7
- package/gs/reflect/deepequal.test.ts +10 -1
- package/gs/reflect/field.test.ts +37 -15
- package/gs/reflect/function-types.test.ts +518 -22
- package/gs/reflect/index.ts +8 -6
- package/gs/reflect/map.ts +20 -0
- package/gs/reflect/meta.json +6 -4
- package/gs/reflect/parity.json +234 -0
- package/gs/reflect/sliceat.test.ts +156 -0
- package/gs/reflect/structof.test.ts +401 -0
- package/gs/reflect/type.ts +1980 -365
- package/gs/reflect/typefor.test.ts +540 -10
- package/gs/reflect/types.ts +43 -18
- package/gs/reflect/value.ts +105 -45
- package/gs/reflect/visiblefields.ts +5 -168
- package/gs/runtime/parity.json +24 -0
- package/gs/runtime/pprof/index.test.ts +29 -7
- package/gs/runtime/pprof/index.ts +56 -30
- package/gs/runtime/pprof/parity.json +27 -0
- package/gs/runtime/runtime.test.ts +3 -1
- package/gs/runtime/runtime.ts +4 -3
- package/gs/runtime/trace/index.test.ts +5 -3
- package/gs/runtime/trace/index.ts +8 -20
- package/gs/runtime/trace/parity.json +36 -0
- package/gs/strconv/atoi.gs.ts +1 -1
- package/gs/strconv/complex.gs.ts +174 -0
- package/gs/strconv/complex.test.ts +65 -0
- package/gs/strconv/index.ts +1 -0
- package/gs/strconv/parity.json +120 -0
- package/gs/strings/builder.ts +1 -1
- package/gs/strings/meta.json +5 -2
- package/gs/strings/parity.json +186 -0
- package/gs/strings/reader.test.ts +2 -2
- package/gs/strings/reader.ts +11 -7
- package/gs/strings/replace.ts +15 -7
- package/gs/strings/strings.test.ts +22 -2
- package/gs/strings/strings.ts +64 -6
- package/gs/sync/atomic/type.gs.ts +9 -9
- package/gs/sync/atomic/value.gs.ts +2 -2
- package/gs/sync/meta.json +1 -0
- package/gs/sync/sync.test.ts +41 -1
- package/gs/sync/sync.ts +41 -16
- package/gs/syscall/env.ts +29 -14
- package/gs/syscall/js/index.test.ts +18 -0
- package/gs/syscall/js/index.ts +12 -0
- package/gs/testing/testing.test.ts +99 -3
- package/gs/testing/testing.ts +95 -24
- package/gs/time/parity.json +225 -0
- package/gs/time/time.test.ts +20 -2
- package/gs/time/time.ts +49 -7
- package/gs/unique/index.ts +7 -1
- package/package.json +4 -2
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -814
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -31
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1233
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
- /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
|
@@ -1,9 +1,251 @@
|
|
|
1
1
|
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
import * as bytes from '@goscript/bytes/index.js'
|
|
3
|
+
import type * as io from '@goscript/io/index.js'
|
|
4
|
+
|
|
5
|
+
export interface Marshaler {
|
|
6
|
+
MarshalJSON(): [$.Slice<number>, $.GoError]
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
export interface Unmarshaler {
|
|
4
10
|
UnmarshalJSON(data: $.Slice<number>): $.GoError
|
|
5
11
|
}
|
|
6
12
|
|
|
13
|
+
export type RawMessage = $.Bytes
|
|
14
|
+
export type Number = string
|
|
15
|
+
export type Token = unknown
|
|
16
|
+
export type Delim = number
|
|
17
|
+
|
|
18
|
+
class jsonError extends Error {
|
|
19
|
+
public Error(): string {
|
|
20
|
+
return this.message
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type decodeOptions = {
|
|
25
|
+
disallowUnknownFields?: boolean
|
|
26
|
+
useNumber?: boolean
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type fieldMetadata = {
|
|
30
|
+
key: string
|
|
31
|
+
name: string
|
|
32
|
+
tag?: string
|
|
33
|
+
type?: unknown
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class SyntaxError extends jsonError {
|
|
37
|
+
public Offset: number
|
|
38
|
+
|
|
39
|
+
constructor(init?: Partial<{ Offset: number; Message: string }>) {
|
|
40
|
+
super(init?.Message ?? 'invalid character in JSON')
|
|
41
|
+
this.name = 'SyntaxError'
|
|
42
|
+
this.Offset = init?.Offset ?? 0
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class InvalidUTF8Error extends jsonError {
|
|
47
|
+
public S: string
|
|
48
|
+
|
|
49
|
+
constructor(init?: Partial<{ S: string }>) {
|
|
50
|
+
super(`json: invalid UTF-8 in string: ${init?.S ?? ''}`)
|
|
51
|
+
this.name = 'InvalidUTF8Error'
|
|
52
|
+
this.S = init?.S ?? ''
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export class InvalidUnmarshalError extends jsonError {
|
|
57
|
+
public Type: unknown
|
|
58
|
+
|
|
59
|
+
constructor(init?: Partial<{ Type: unknown }>) {
|
|
60
|
+
super('json: Unmarshal(non-pointer)')
|
|
61
|
+
this.name = 'InvalidUnmarshalError'
|
|
62
|
+
this.Type = init?.Type ?? null
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export class MarshalerError extends jsonError {
|
|
67
|
+
public Type: unknown
|
|
68
|
+
public Err: $.GoError
|
|
69
|
+
|
|
70
|
+
constructor(init?: Partial<{ Type: unknown; Err: $.GoError }>) {
|
|
71
|
+
super(`json: error calling MarshalJSON: ${init?.Err?.Error?.() ?? ''}`)
|
|
72
|
+
this.name = 'MarshalerError'
|
|
73
|
+
this.Type = init?.Type ?? null
|
|
74
|
+
this.Err = init?.Err ?? null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public Unwrap(): $.GoError {
|
|
78
|
+
return this.Err
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export class UnmarshalFieldError extends jsonError {
|
|
83
|
+
public Key: string
|
|
84
|
+
public Type: unknown
|
|
85
|
+
public Field: unknown
|
|
86
|
+
|
|
87
|
+
constructor(init?: Partial<{ Key: string; Type: unknown; Field: unknown }>) {
|
|
88
|
+
super(`json: cannot unmarshal object key ${init?.Key ?? ''}`)
|
|
89
|
+
this.name = 'UnmarshalFieldError'
|
|
90
|
+
this.Key = init?.Key ?? ''
|
|
91
|
+
this.Type = init?.Type ?? null
|
|
92
|
+
this.Field = init?.Field ?? null
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export class UnmarshalTypeError extends jsonError {
|
|
97
|
+
public Value: string
|
|
98
|
+
public Type: unknown
|
|
99
|
+
public Offset: number
|
|
100
|
+
public Struct: string
|
|
101
|
+
public Field: string
|
|
102
|
+
|
|
103
|
+
constructor(
|
|
104
|
+
init?: Partial<{
|
|
105
|
+
Value: string
|
|
106
|
+
Type: unknown
|
|
107
|
+
Offset: number
|
|
108
|
+
Struct: string
|
|
109
|
+
Field: string
|
|
110
|
+
}>,
|
|
111
|
+
) {
|
|
112
|
+
super(`json: cannot unmarshal ${init?.Value ?? ''}`)
|
|
113
|
+
this.name = 'UnmarshalTypeError'
|
|
114
|
+
this.Value = init?.Value ?? ''
|
|
115
|
+
this.Type = init?.Type ?? null
|
|
116
|
+
this.Offset = init?.Offset ?? 0
|
|
117
|
+
this.Struct = init?.Struct ?? ''
|
|
118
|
+
this.Field = init?.Field ?? ''
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export class UnsupportedTypeError extends jsonError {
|
|
123
|
+
public Type: unknown
|
|
124
|
+
|
|
125
|
+
constructor(init?: Partial<{ Type: unknown }>) {
|
|
126
|
+
super('json: unsupported type')
|
|
127
|
+
this.name = 'UnsupportedTypeError'
|
|
128
|
+
this.Type = init?.Type ?? null
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export class UnsupportedValueError extends jsonError {
|
|
133
|
+
public Value: unknown
|
|
134
|
+
public Str: string
|
|
135
|
+
|
|
136
|
+
constructor(init?: Partial<{ Value: unknown; Str: string }>) {
|
|
137
|
+
super(`json: unsupported value: ${init?.Str ?? ''}`)
|
|
138
|
+
this.name = 'UnsupportedValueError'
|
|
139
|
+
this.Value = init?.Value ?? null
|
|
140
|
+
this.Str = init?.Str ?? ''
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export class Decoder {
|
|
145
|
+
private disallowUnknownFields = false
|
|
146
|
+
private inputOffset = 0
|
|
147
|
+
private useNumber = false
|
|
148
|
+
|
|
149
|
+
public constructor(private readonly reader: io.Reader) {}
|
|
150
|
+
|
|
151
|
+
public Decode(v: unknown): $.GoError {
|
|
152
|
+
const [data, err] = readAllSync(this.reader)
|
|
153
|
+
if (err !== null) {
|
|
154
|
+
return err
|
|
155
|
+
}
|
|
156
|
+
this.inputOffset += $.len(data)
|
|
157
|
+
return decode(data, v, {
|
|
158
|
+
disallowUnknownFields: this.disallowUnknownFields,
|
|
159
|
+
useNumber: this.useNumber,
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public Buffered(): io.Reader {
|
|
164
|
+
return new bytes.Buffer()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public DisallowUnknownFields(): void {
|
|
168
|
+
this.disallowUnknownFields = true
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public InputOffset(): number {
|
|
172
|
+
return this.inputOffset
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public More(): boolean {
|
|
176
|
+
return false
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public Token(): [Token, $.GoError] {
|
|
180
|
+
return [null, $.newError('json: token streaming is unsupported')]
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public UseNumber(): void {
|
|
184
|
+
this.useNumber = true
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export class Encoder {
|
|
189
|
+
private escapeHTML = true
|
|
190
|
+
private indent = ''
|
|
191
|
+
private prefix = ''
|
|
192
|
+
|
|
193
|
+
public constructor(private readonly writer: io.Writer) {}
|
|
194
|
+
|
|
195
|
+
public Encode(v: unknown): $.GoError {
|
|
196
|
+
const [data, err] =
|
|
197
|
+
this.indent === '' && this.prefix === '' ?
|
|
198
|
+
marshalBytes(v, '', '', this.escapeHTML)
|
|
199
|
+
: marshalBytes(v, this.prefix, this.indent, this.escapeHTML)
|
|
200
|
+
if (err !== null) {
|
|
201
|
+
return err
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const out = $.stringToBytes($.bytesToString(data) + '\n')
|
|
205
|
+
const [n, writeErr] = this.writer.Write(out)
|
|
206
|
+
if (writeErr !== null) {
|
|
207
|
+
return writeErr
|
|
208
|
+
}
|
|
209
|
+
if (n < $.len(out)) {
|
|
210
|
+
return $.newError('short write')
|
|
211
|
+
}
|
|
212
|
+
return null
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
public SetEscapeHTML(on: boolean): void {
|
|
216
|
+
this.escapeHTML = on
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public SetIndent(prefix: string, indent: string): void {
|
|
220
|
+
this.prefix = prefix
|
|
221
|
+
this.indent = indent
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function NewDecoder(r: io.Reader): Decoder {
|
|
226
|
+
return new Decoder(r)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function NewEncoder(w: io.Writer): Encoder {
|
|
230
|
+
return new Encoder(w)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
$.registerInterfaceType('json.Marshaler', null, [
|
|
234
|
+
{
|
|
235
|
+
name: 'MarshalJSON',
|
|
236
|
+
args: [],
|
|
237
|
+
returns: [
|
|
238
|
+
{
|
|
239
|
+
type: {
|
|
240
|
+
kind: $.TypeKind.Slice,
|
|
241
|
+
elemType: { kind: $.TypeKind.Basic, name: 'uint8' },
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
{ type: 'GoError' },
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
])
|
|
248
|
+
|
|
7
249
|
$.registerInterfaceType('json.Unmarshaler', null, [
|
|
8
250
|
{
|
|
9
251
|
name: 'UnmarshalJSON',
|
|
@@ -21,58 +263,272 @@ $.registerInterfaceType('json.Unmarshaler', null, [
|
|
|
21
263
|
])
|
|
22
264
|
|
|
23
265
|
export function Marshal(v: unknown): [$.Slice<number>, $.GoError] {
|
|
266
|
+
return marshalBytes(v, '', '', true)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function marshalBytes(
|
|
270
|
+
v: unknown,
|
|
271
|
+
prefix: string,
|
|
272
|
+
indent: string,
|
|
273
|
+
escapeHTML: boolean,
|
|
274
|
+
): [$.Slice<number>, $.GoError] {
|
|
24
275
|
try {
|
|
25
|
-
|
|
276
|
+
let text = JSON.stringify(marshalValue(v), null, indent)
|
|
277
|
+
if (escapeHTML) {
|
|
278
|
+
text = escapeHTMLString(text)
|
|
279
|
+
}
|
|
280
|
+
if (prefix !== '') {
|
|
281
|
+
text = text
|
|
282
|
+
.split('\n')
|
|
283
|
+
.map((line, idx) => (idx === 0 ? line : prefix + line))
|
|
284
|
+
.join('\n')
|
|
285
|
+
}
|
|
286
|
+
return [$.stringToBytes(text), null]
|
|
26
287
|
} catch (err) {
|
|
27
288
|
return [null, goError(err)]
|
|
28
289
|
}
|
|
29
290
|
}
|
|
30
291
|
|
|
31
|
-
export function
|
|
32
|
-
|
|
292
|
+
export function Compact(
|
|
293
|
+
dst: bytes.Buffer | $.VarRef<bytes.Buffer>,
|
|
294
|
+
src: $.Slice<number>,
|
|
295
|
+
): $.GoError {
|
|
296
|
+
try {
|
|
297
|
+
const text = JSON.stringify(JSON.parse($.bytesToString(src)))
|
|
298
|
+
const [, err] = $.pointerValue<bytes.Buffer>(dst).Write(
|
|
299
|
+
$.stringToBytes(text),
|
|
300
|
+
)
|
|
301
|
+
return err
|
|
302
|
+
} catch (err) {
|
|
303
|
+
return goError(err)
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export function HTMLEscape(
|
|
308
|
+
dst: bytes.Buffer | $.VarRef<bytes.Buffer>,
|
|
309
|
+
src: $.Slice<number>,
|
|
310
|
+
): void {
|
|
311
|
+
const escaped = $.bytesToString(src).replace(/[<>&\u2028\u2029]/g, (char) => {
|
|
312
|
+
switch (char) {
|
|
313
|
+
case '<':
|
|
314
|
+
return '\\u003c'
|
|
315
|
+
case '>':
|
|
316
|
+
return '\\u003e'
|
|
317
|
+
case '&':
|
|
318
|
+
return '\\u0026'
|
|
319
|
+
case '\u2028':
|
|
320
|
+
return '\\u2028'
|
|
321
|
+
case '\u2029':
|
|
322
|
+
return '\\u2029'
|
|
323
|
+
default:
|
|
324
|
+
return char
|
|
325
|
+
}
|
|
326
|
+
})
|
|
327
|
+
$.pointerValue<bytes.Buffer>(dst).Write($.stringToBytes(escaped))
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export function Indent(
|
|
331
|
+
dst: bytes.Buffer | $.VarRef<bytes.Buffer>,
|
|
332
|
+
src: $.Slice<number>,
|
|
33
333
|
prefix: string,
|
|
34
334
|
indent: string,
|
|
35
|
-
):
|
|
335
|
+
): $.GoError {
|
|
36
336
|
try {
|
|
37
|
-
const text = JSON.stringify(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
return [
|
|
42
|
-
$.stringToBytes(
|
|
337
|
+
const text = JSON.stringify(JSON.parse($.bytesToString(src)), null, indent)
|
|
338
|
+
const prefixed =
|
|
339
|
+
prefix === '' ? text : (
|
|
43
340
|
text
|
|
44
341
|
.split('\n')
|
|
45
342
|
.map((line, idx) => (idx === 0 ? line : prefix + line))
|
|
46
|
-
.join('\n')
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
|
|
343
|
+
.join('\n')
|
|
344
|
+
)
|
|
345
|
+
const [, err] = $.pointerValue<bytes.Buffer>(dst).Write(
|
|
346
|
+
$.stringToBytes(prefixed),
|
|
347
|
+
)
|
|
348
|
+
return err
|
|
50
349
|
} catch (err) {
|
|
51
|
-
return
|
|
350
|
+
return goError(err)
|
|
52
351
|
}
|
|
53
352
|
}
|
|
54
353
|
|
|
354
|
+
export function MarshalIndent(
|
|
355
|
+
v: unknown,
|
|
356
|
+
prefix: string,
|
|
357
|
+
indent: string,
|
|
358
|
+
): [$.Slice<number>, $.GoError] {
|
|
359
|
+
return marshalBytes(v, prefix, indent, true)
|
|
360
|
+
}
|
|
361
|
+
|
|
55
362
|
export function Unmarshal(data: $.Slice<number>, v: unknown): $.GoError {
|
|
363
|
+
return decode(data, v, {})
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function decode(
|
|
367
|
+
data: $.Slice<number>,
|
|
368
|
+
v: unknown,
|
|
369
|
+
opts: decodeOptions,
|
|
370
|
+
): $.GoError {
|
|
56
371
|
try {
|
|
57
|
-
|
|
372
|
+
if (!validUnmarshalTarget(v)) {
|
|
373
|
+
return $.toGoError(new InvalidUnmarshalError())
|
|
374
|
+
}
|
|
375
|
+
const unmarshaler = unmarshalJSONTarget(v)
|
|
376
|
+
if (unmarshaler !== null) {
|
|
377
|
+
const err = unmarshaler.UnmarshalJSON(data)
|
|
378
|
+
if (err instanceof Promise) {
|
|
379
|
+
return $.newError('json: asynchronous UnmarshalJSON is unsupported')
|
|
380
|
+
}
|
|
381
|
+
return err
|
|
382
|
+
}
|
|
383
|
+
assignDecodedValue(v, parseJSON(data, opts), opts)
|
|
58
384
|
return null
|
|
59
385
|
} catch (err) {
|
|
60
386
|
return goError(err)
|
|
61
387
|
}
|
|
62
388
|
}
|
|
63
389
|
|
|
390
|
+
export function Valid(data: $.Slice<number>): boolean {
|
|
391
|
+
try {
|
|
392
|
+
JSON.parse($.bytesToString(data))
|
|
393
|
+
return true
|
|
394
|
+
} catch {
|
|
395
|
+
return false
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export function RawMessage_MarshalJSON(
|
|
400
|
+
m: RawMessage,
|
|
401
|
+
): [$.Slice<number>, $.GoError] {
|
|
402
|
+
if (m === null) {
|
|
403
|
+
return [$.stringToBytes('null'), null]
|
|
404
|
+
}
|
|
405
|
+
const out = $.makeSlice<number>($.len(m), undefined, 'byte')
|
|
406
|
+
$.copy(out, m)
|
|
407
|
+
return [out, null]
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export function RawMessage_UnmarshalJSON(
|
|
411
|
+
m: $.VarRef<RawMessage> | RawMessage | null,
|
|
412
|
+
data: $.Slice<number>,
|
|
413
|
+
): $.GoError {
|
|
414
|
+
const out = $.makeSlice<number>($.len(data), undefined, 'byte')
|
|
415
|
+
$.copy(out, data)
|
|
416
|
+
if ($.isVarRef(m)) {
|
|
417
|
+
m.value = out
|
|
418
|
+
}
|
|
419
|
+
return null
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export function Number_Float64(n: Number): [number, $.GoError] {
|
|
423
|
+
if (!isValidFloat(n)) {
|
|
424
|
+
return [0, $.newError(`strconv.ParseFloat: parsing "${n}": invalid syntax`)]
|
|
425
|
+
}
|
|
426
|
+
if (/^[+-]?nan$/i.test(n)) {
|
|
427
|
+
return [Number.NaN, null]
|
|
428
|
+
}
|
|
429
|
+
if (/^\+?inf(?:inity)?$/i.test(n)) {
|
|
430
|
+
return [Infinity, null]
|
|
431
|
+
}
|
|
432
|
+
if (/^-inf(?:inity)?$/i.test(n)) {
|
|
433
|
+
return [-Infinity, null]
|
|
434
|
+
}
|
|
435
|
+
const value = Number.parseFloat(n)
|
|
436
|
+
if (Number.isNaN(value)) {
|
|
437
|
+
return [0, $.newError(`strconv.ParseFloat: parsing "${n}": invalid syntax`)]
|
|
438
|
+
}
|
|
439
|
+
if (!Number.isFinite(value) && !/^[+-]?(?:inf(?:inity)?|nan)$/i.test(n)) {
|
|
440
|
+
return [
|
|
441
|
+
value,
|
|
442
|
+
$.newError(`strconv.ParseFloat: parsing "${n}": value out of range`),
|
|
443
|
+
]
|
|
444
|
+
}
|
|
445
|
+
return [value, null]
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export function Number_Int64(n: Number): [number, $.GoError] {
|
|
449
|
+
if (!/^[+-]?\d+$/.test(n)) {
|
|
450
|
+
return [0, $.newError(`strconv.ParseInt: parsing "${n}": invalid syntax`)]
|
|
451
|
+
}
|
|
452
|
+
const value = BigInt(n)
|
|
453
|
+
const min = -(1n << 63n)
|
|
454
|
+
const max = (1n << 63n) - 1n
|
|
455
|
+
if (value < min || value > max) {
|
|
456
|
+
const clamped = value < min ? min : max
|
|
457
|
+
return [
|
|
458
|
+
Number(clamped),
|
|
459
|
+
$.newError(`strconv.ParseInt: parsing "${n}": value out of range`),
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
return [Number(value), null]
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export function Number_String(n: Number): string {
|
|
466
|
+
return n
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function isValidFloat(value: string): boolean {
|
|
470
|
+
return /^[+-]?(?:(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?|inf(?:inity)?|nan)$/i.test(
|
|
471
|
+
value,
|
|
472
|
+
)
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function readAllSync(r: io.Reader): [$.Bytes, $.GoError] {
|
|
476
|
+
const chunks: number[] = []
|
|
477
|
+
const buf = $.makeSlice<number>(512, undefined, 'byte')
|
|
478
|
+
while (true) {
|
|
479
|
+
const read = r.Read(buf)
|
|
480
|
+
if (read instanceof Promise) {
|
|
481
|
+
return [null, $.newError('json: asynchronous reader is unsupported')]
|
|
482
|
+
}
|
|
483
|
+
const [n, err] = read
|
|
484
|
+
if (n > 0) {
|
|
485
|
+
chunks.push(...$.bytesToUint8Array($.goSlice(buf, 0, n)))
|
|
486
|
+
}
|
|
487
|
+
if (err !== null) {
|
|
488
|
+
if (err.Error() === 'EOF') {
|
|
489
|
+
return [new Uint8Array(chunks), null]
|
|
490
|
+
}
|
|
491
|
+
return [null, err]
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
64
496
|
function marshalValue(v: unknown): unknown {
|
|
497
|
+
const marshaler = marshalJSONTarget(v)
|
|
498
|
+
if (marshaler !== null) {
|
|
499
|
+
const result = marshaler.MarshalJSON()
|
|
500
|
+
if (result instanceof Promise) {
|
|
501
|
+
throw new MarshalerError({
|
|
502
|
+
Err: $.newError('json: asynchronous MarshalJSON is unsupported'),
|
|
503
|
+
})
|
|
504
|
+
}
|
|
505
|
+
const [data, err] = result
|
|
506
|
+
if (err !== null) {
|
|
507
|
+
throw new MarshalerError({ Err: err })
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
return JSON.parse($.bytesToString(data))
|
|
511
|
+
} catch (parseErr) {
|
|
512
|
+
throw new MarshalerError({ Err: goError(parseErr) })
|
|
513
|
+
}
|
|
514
|
+
}
|
|
65
515
|
if ($.isVarRef(v)) {
|
|
66
516
|
return marshalValue(v.value)
|
|
67
517
|
}
|
|
68
518
|
if (v === null || v === undefined) {
|
|
69
519
|
return null
|
|
70
520
|
}
|
|
521
|
+
if (typeof v === 'number') {
|
|
522
|
+
if (!Number.isFinite(v)) {
|
|
523
|
+
throw new UnsupportedValueError({ Value: v, Str: String(v) })
|
|
524
|
+
}
|
|
525
|
+
return v
|
|
526
|
+
}
|
|
71
527
|
if (typeof v !== 'object') {
|
|
72
528
|
return v
|
|
73
529
|
}
|
|
74
530
|
if (v instanceof Uint8Array) {
|
|
75
|
-
return
|
|
531
|
+
return base64Encode(v)
|
|
76
532
|
}
|
|
77
533
|
if (Array.isArray(v)) {
|
|
78
534
|
return v.map(marshalValue)
|
|
@@ -89,21 +545,101 @@ function marshalValue(v: unknown): unknown {
|
|
|
89
545
|
}
|
|
90
546
|
|
|
91
547
|
const out: Record<string, unknown> = {}
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
548
|
+
for (const field of structFields(v)) {
|
|
549
|
+
const ref = v._fields[field.key]
|
|
550
|
+
if (ref === undefined) {
|
|
551
|
+
continue
|
|
552
|
+
}
|
|
553
|
+
const jsonName = jsonFieldName(field.name, field.tag)
|
|
95
554
|
if (jsonName === '') {
|
|
96
555
|
continue
|
|
97
556
|
}
|
|
98
|
-
out[jsonName] =
|
|
557
|
+
out[jsonName] = marshalFieldValue(ref.value, field.type)
|
|
99
558
|
}
|
|
100
559
|
return out
|
|
101
560
|
}
|
|
102
561
|
|
|
103
|
-
function
|
|
562
|
+
function marshalFieldValue(value: unknown, fieldType: unknown): unknown {
|
|
563
|
+
if (isRawMessageType(fieldType)) {
|
|
564
|
+
const target = $.isVarRef(value) ? value.value : value
|
|
565
|
+
if (target === null || target === undefined) {
|
|
566
|
+
return null
|
|
567
|
+
}
|
|
568
|
+
try {
|
|
569
|
+
return JSON.parse($.bytesToString(target as $.Slice<number>))
|
|
570
|
+
} catch (err) {
|
|
571
|
+
throw new MarshalerError({ Err: goError(err) })
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return marshalValue(value)
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function marshalJSONTarget(value: unknown): Marshaler | null {
|
|
578
|
+
const target = $.isVarRef(value) ? value.value : value
|
|
579
|
+
if (target === null || target === undefined) {
|
|
580
|
+
return null
|
|
581
|
+
}
|
|
582
|
+
if (typeof target !== 'object' && typeof target !== 'function') {
|
|
583
|
+
return null
|
|
584
|
+
}
|
|
585
|
+
const method = Reflect.get(target, 'MarshalJSON')
|
|
586
|
+
return typeof method === 'function' ? (target as Marshaler) : null
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function unmarshalJSONTarget(value: unknown): Unmarshaler | null {
|
|
590
|
+
const target = $.isVarRef(value) ? value.value : value
|
|
591
|
+
if (target === null || target === undefined) {
|
|
592
|
+
return null
|
|
593
|
+
}
|
|
594
|
+
if (typeof target !== 'object' && typeof target !== 'function') {
|
|
595
|
+
return null
|
|
596
|
+
}
|
|
597
|
+
const method = Reflect.get(target, 'UnmarshalJSON')
|
|
598
|
+
return typeof method === 'function' ? (target as Unmarshaler) : null
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
function validUnmarshalTarget(value: unknown): boolean {
|
|
602
|
+
if (value === null || value === undefined) {
|
|
603
|
+
return false
|
|
604
|
+
}
|
|
605
|
+
if ($.isVarRef(value)) {
|
|
606
|
+
return true
|
|
607
|
+
}
|
|
608
|
+
return unmarshalJSONTarget(value) !== null || isStructValue(value)
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function parseJSON(data: $.Slice<number>, opts: decodeOptions): unknown {
|
|
612
|
+
const text = $.bytesToString(data)
|
|
613
|
+
if (opts.useNumber) {
|
|
614
|
+
return JSON.parse(text, (_key, value) =>
|
|
615
|
+
typeof value === 'number' ? String(value) : value,
|
|
616
|
+
)
|
|
617
|
+
}
|
|
618
|
+
return JSON.parse(text)
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function assignDecodedValue(
|
|
622
|
+
target: unknown,
|
|
623
|
+
decoded: unknown,
|
|
624
|
+
opts: decodeOptions,
|
|
625
|
+
): void {
|
|
104
626
|
if ($.isVarRef(target)) {
|
|
627
|
+
const unmarshaler = unmarshalJSONTarget(target.value)
|
|
628
|
+
if (unmarshaler !== null) {
|
|
629
|
+
const err = unmarshaler.UnmarshalJSON(
|
|
630
|
+
$.stringToBytes(JSON.stringify(decoded)),
|
|
631
|
+
)
|
|
632
|
+
if (err !== null) {
|
|
633
|
+
throw err
|
|
634
|
+
}
|
|
635
|
+
return
|
|
636
|
+
}
|
|
105
637
|
if (isStructValue(target.value) && isPlainObject(decoded)) {
|
|
106
|
-
assignStructFields(target.value, decoded)
|
|
638
|
+
assignStructFields(target.value, decoded, opts)
|
|
639
|
+
return
|
|
640
|
+
}
|
|
641
|
+
if (target.value instanceof Uint8Array && typeof decoded === 'string') {
|
|
642
|
+
target.value = base64Decode(decoded)
|
|
107
643
|
return
|
|
108
644
|
}
|
|
109
645
|
if (isPlainObject(decoded)) {
|
|
@@ -114,26 +650,58 @@ function assignDecodedValue(target: unknown, decoded: unknown): void {
|
|
|
114
650
|
return
|
|
115
651
|
}
|
|
116
652
|
if (isStructValue(target) && isPlainObject(decoded)) {
|
|
117
|
-
assignStructFields(target, decoded)
|
|
653
|
+
assignStructFields(target, decoded, opts)
|
|
118
654
|
}
|
|
119
655
|
}
|
|
120
656
|
|
|
121
657
|
function assignStructFields(
|
|
122
658
|
target: { _fields: Record<string, $.VarRef<unknown>> },
|
|
123
659
|
decoded: Record<string, unknown>,
|
|
660
|
+
opts: decodeOptions,
|
|
124
661
|
): void {
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
662
|
+
const fields = structFields(target)
|
|
663
|
+
const knownNames = new Set<string>()
|
|
664
|
+
for (const field of fields) {
|
|
665
|
+
const jsonName = jsonFieldName(field.name, field.tag)
|
|
666
|
+
if (jsonName !== '') {
|
|
667
|
+
knownNames.add(jsonName)
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
if (opts.disallowUnknownFields) {
|
|
671
|
+
for (const key of Object.keys(decoded)) {
|
|
672
|
+
if (!knownNames.has(key)) {
|
|
673
|
+
throw $.newError(`json: unknown field "${key}"`)
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
for (const field of fields) {
|
|
678
|
+
const ref = target._fields[field.key]
|
|
679
|
+
if (ref === undefined) {
|
|
680
|
+
continue
|
|
681
|
+
}
|
|
682
|
+
const jsonName = jsonFieldName(field.name, field.tag)
|
|
128
683
|
if (
|
|
129
684
|
jsonName !== '' &&
|
|
130
685
|
Object.prototype.hasOwnProperty.call(decoded, jsonName)
|
|
131
686
|
) {
|
|
132
|
-
ref
|
|
687
|
+
assignDecodedFieldValue(ref, decoded[jsonName], opts, field.type)
|
|
133
688
|
}
|
|
134
689
|
}
|
|
135
690
|
}
|
|
136
691
|
|
|
692
|
+
function assignDecodedFieldValue(
|
|
693
|
+
target: $.VarRef<unknown>,
|
|
694
|
+
decoded: unknown,
|
|
695
|
+
opts: decodeOptions,
|
|
696
|
+
fieldType: unknown,
|
|
697
|
+
): void {
|
|
698
|
+
if (isRawMessageType(fieldType)) {
|
|
699
|
+
target.value = $.stringToBytes(JSON.stringify(decoded))
|
|
700
|
+
return
|
|
701
|
+
}
|
|
702
|
+
assignDecodedValue(target, decoded, opts)
|
|
703
|
+
}
|
|
704
|
+
|
|
137
705
|
function objectToMap(decoded: Record<string, unknown>): Map<string, unknown> {
|
|
138
706
|
const out = new Map<string, unknown>()
|
|
139
707
|
for (const [key, value] of Object.entries(decoded)) {
|
|
@@ -167,9 +735,19 @@ function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
|
167
735
|
)
|
|
168
736
|
}
|
|
169
737
|
|
|
170
|
-
function
|
|
738
|
+
function structFields(value: {
|
|
739
|
+
_fields: Record<string, $.VarRef<unknown>>
|
|
740
|
+
}): fieldMetadata[] {
|
|
741
|
+
const fields = structFieldMetadata(value)
|
|
742
|
+
if (fields.length !== 0) {
|
|
743
|
+
return fields
|
|
744
|
+
}
|
|
745
|
+
return Object.keys(value._fields).map((key) => ({ key, name: key }))
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function structFieldMetadata(value: unknown): fieldMetadata[] {
|
|
171
749
|
if (value === null || typeof value !== 'object') {
|
|
172
|
-
return
|
|
750
|
+
return []
|
|
173
751
|
}
|
|
174
752
|
const ctor = Reflect.get(value, 'constructor')
|
|
175
753
|
if (
|
|
@@ -177,7 +755,7 @@ function structFieldMetadata(value: unknown): Record<string, { tag?: string }> {
|
|
|
177
755
|
ctor === undefined ||
|
|
178
756
|
(typeof ctor !== 'object' && typeof ctor !== 'function')
|
|
179
757
|
) {
|
|
180
|
-
return
|
|
758
|
+
return []
|
|
181
759
|
}
|
|
182
760
|
const typeInfo = Reflect.get(ctor, '__typeInfo')
|
|
183
761
|
if (
|
|
@@ -185,30 +763,93 @@ function structFieldMetadata(value: unknown): Record<string, { tag?: string }> {
|
|
|
185
763
|
typeInfo === undefined ||
|
|
186
764
|
typeof typeInfo !== 'object'
|
|
187
765
|
) {
|
|
188
|
-
return
|
|
766
|
+
return []
|
|
189
767
|
}
|
|
190
768
|
const fields = Reflect.get(typeInfo, 'fields')
|
|
191
|
-
if (
|
|
192
|
-
const out:
|
|
193
|
-
for (const
|
|
194
|
-
if (
|
|
769
|
+
if (Array.isArray(fields)) {
|
|
770
|
+
const out: fieldMetadata[] = []
|
|
771
|
+
for (const field of fields) {
|
|
772
|
+
if (!$.isStructFieldInfo(field)) {
|
|
195
773
|
continue
|
|
196
774
|
}
|
|
197
775
|
const tag = field.tag
|
|
198
|
-
out
|
|
776
|
+
out.push({
|
|
777
|
+
key: $.structFieldRuntimeKey(field),
|
|
778
|
+
name: field.name,
|
|
779
|
+
type: field.type,
|
|
780
|
+
...(typeof tag === 'string' ? { tag } : {}),
|
|
781
|
+
})
|
|
199
782
|
}
|
|
200
783
|
return out
|
|
201
784
|
}
|
|
202
|
-
return
|
|
785
|
+
return []
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
function isRawMessageType(value: unknown): boolean {
|
|
789
|
+
if (value === 'json.RawMessage' || value === 'encoding/json.RawMessage') {
|
|
790
|
+
return true
|
|
791
|
+
}
|
|
792
|
+
if (!isPlainObject(value)) {
|
|
793
|
+
return false
|
|
794
|
+
}
|
|
795
|
+
return (
|
|
796
|
+
value.typeName === 'json.RawMessage' ||
|
|
797
|
+
value.typeName === 'encoding/json.RawMessage' ||
|
|
798
|
+
value.name === 'json.RawMessage' ||
|
|
799
|
+
value.name === 'encoding/json.RawMessage'
|
|
800
|
+
)
|
|
203
801
|
}
|
|
204
802
|
|
|
205
803
|
function goError(err: unknown): $.GoError {
|
|
804
|
+
if (
|
|
805
|
+
err !== null &&
|
|
806
|
+
typeof err === 'object' &&
|
|
807
|
+
typeof (err as { Error?: unknown }).Error === 'function'
|
|
808
|
+
) {
|
|
809
|
+
return err as $.GoError
|
|
810
|
+
}
|
|
206
811
|
if (err instanceof Error) {
|
|
207
812
|
return $.toGoError(err)
|
|
208
813
|
}
|
|
209
814
|
return $.newError(String(err))
|
|
210
815
|
}
|
|
211
816
|
|
|
817
|
+
function base64Encode(data: Uint8Array): string {
|
|
818
|
+
let binary = ''
|
|
819
|
+
for (const byte of data) {
|
|
820
|
+
binary += String.fromCharCode(byte)
|
|
821
|
+
}
|
|
822
|
+
return btoa(binary)
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
function base64Decode(text: string): Uint8Array {
|
|
826
|
+
const binary = atob(text)
|
|
827
|
+
const out = new Uint8Array(binary.length)
|
|
828
|
+
for (let i = 0; i < binary.length; i++) {
|
|
829
|
+
out[i] = binary.charCodeAt(i)
|
|
830
|
+
}
|
|
831
|
+
return out
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
function escapeHTMLString(text: string): string {
|
|
835
|
+
return text.replace(/[<>&\u2028\u2029]/g, (char) => {
|
|
836
|
+
switch (char) {
|
|
837
|
+
case '<':
|
|
838
|
+
return '\\u003c'
|
|
839
|
+
case '>':
|
|
840
|
+
return '\\u003e'
|
|
841
|
+
case '&':
|
|
842
|
+
return '\\u0026'
|
|
843
|
+
case '\u2028':
|
|
844
|
+
return '\\u2028'
|
|
845
|
+
case '\u2029':
|
|
846
|
+
return '\\u2029'
|
|
847
|
+
default:
|
|
848
|
+
return char
|
|
849
|
+
}
|
|
850
|
+
})
|
|
851
|
+
}
|
|
852
|
+
|
|
212
853
|
function jsonFieldName(fieldName: string, tag: string | undefined): string {
|
|
213
854
|
if (tag === undefined || !tag.startsWith('json:"')) {
|
|
214
855
|
return fieldName
|