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,8 +1,34 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
|
|
3
3
|
import * as $ from '@goscript/builtin/index.js'
|
|
4
|
+
import * as bytes from '@goscript/bytes/index.js'
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Compact,
|
|
8
|
+
HTMLEscape,
|
|
9
|
+
Indent,
|
|
10
|
+
InvalidUTF8Error,
|
|
11
|
+
InvalidUnmarshalError,
|
|
12
|
+
MarshalerError,
|
|
13
|
+
Marshal,
|
|
14
|
+
MarshalIndent,
|
|
15
|
+
NewDecoder,
|
|
16
|
+
NewEncoder,
|
|
17
|
+
Number_Float64,
|
|
18
|
+
Number_Int64,
|
|
19
|
+
Number_String,
|
|
20
|
+
RawMessage_MarshalJSON,
|
|
21
|
+
RawMessage_UnmarshalJSON,
|
|
22
|
+
SyntaxError as JSONSyntaxError,
|
|
23
|
+
UnmarshalFieldError,
|
|
24
|
+
Unmarshal,
|
|
25
|
+
UnmarshalTypeError,
|
|
26
|
+
UnsupportedTypeError,
|
|
27
|
+
UnsupportedValueError,
|
|
28
|
+
Valid,
|
|
29
|
+
type Marshaler,
|
|
30
|
+
type Unmarshaler,
|
|
31
|
+
} from './index.js'
|
|
6
32
|
|
|
7
33
|
class Person {
|
|
8
34
|
public _fields = {
|
|
@@ -16,37 +42,92 @@ class Person {
|
|
|
16
42
|
new Person(),
|
|
17
43
|
[],
|
|
18
44
|
Person,
|
|
19
|
-
|
|
20
|
-
|
|
45
|
+
[
|
|
46
|
+
{
|
|
47
|
+
name: 'Name',
|
|
48
|
+
key: 'Name',
|
|
21
49
|
type: { kind: $.TypeKind.Basic, name: 'string' },
|
|
22
50
|
tag: 'json:"name"',
|
|
23
51
|
},
|
|
24
|
-
|
|
25
|
-
|
|
52
|
+
{
|
|
53
|
+
name: 'Age',
|
|
54
|
+
key: 'Age',
|
|
55
|
+
type: { kind: $.TypeKind.Basic, name: 'int' },
|
|
56
|
+
tag: 'json:"age"',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'Active',
|
|
60
|
+
key: 'Active',
|
|
26
61
|
type: { kind: $.TypeKind.Basic, name: 'bool' },
|
|
27
62
|
tag: 'json:"active"',
|
|
28
63
|
},
|
|
29
|
-
|
|
64
|
+
],
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
class FieldAlias {
|
|
69
|
+
public _fields = {
|
|
70
|
+
Name: $.varRef(''),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static __typeInfo = $.registerStructType(
|
|
74
|
+
'test.FieldAlias',
|
|
75
|
+
new FieldAlias(),
|
|
76
|
+
[],
|
|
77
|
+
FieldAlias,
|
|
78
|
+
[
|
|
79
|
+
{
|
|
80
|
+
name: 'FullName',
|
|
81
|
+
key: 'Name',
|
|
82
|
+
type: { kind: $.TypeKind.Basic, name: 'string' },
|
|
83
|
+
},
|
|
84
|
+
],
|
|
30
85
|
)
|
|
31
86
|
}
|
|
32
87
|
|
|
33
88
|
describe('encoding/json override', () => {
|
|
34
89
|
it('registers the Unmarshaler interface shape', () => {
|
|
90
|
+
class CustomMarshaler implements Marshaler {
|
|
91
|
+
MarshalJSON(): [$.Slice<number>, $.GoError] {
|
|
92
|
+
return [$.stringToBytes('{"ok":true}'), null]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
35
96
|
class CustomUnmarshaler implements Unmarshaler {
|
|
36
97
|
UnmarshalJSON(_data: $.Slice<number>): $.GoError {
|
|
37
98
|
return null
|
|
38
99
|
}
|
|
39
100
|
}
|
|
40
101
|
|
|
102
|
+
const [, marshalOK] = $.typeAssertTuple<Marshaler>(
|
|
103
|
+
new CustomMarshaler(),
|
|
104
|
+
'json.Marshaler',
|
|
105
|
+
)
|
|
41
106
|
const [value, ok] = $.typeAssertTuple<Unmarshaler>(
|
|
42
107
|
new CustomUnmarshaler(),
|
|
43
108
|
'json.Unmarshaler',
|
|
44
109
|
)
|
|
45
110
|
|
|
111
|
+
expect(marshalOK).toBe(true)
|
|
46
112
|
expect(ok).toBe(true)
|
|
47
113
|
expect(value.UnmarshalJSON($.stringToBytes('{}'))).toBeNull()
|
|
48
114
|
})
|
|
49
115
|
|
|
116
|
+
it('exposes JSON error structs as Go errors', () => {
|
|
117
|
+
for (const err of [
|
|
118
|
+
new JSONSyntaxError(),
|
|
119
|
+
new InvalidUTF8Error({ S: 'bad' }),
|
|
120
|
+
new InvalidUnmarshalError(),
|
|
121
|
+
new MarshalerError({ Err: $.newError('bad marshal') }),
|
|
122
|
+
new UnmarshalFieldError({ Key: 'field' }),
|
|
123
|
+
new UnmarshalTypeError({ Value: 'string' }),
|
|
124
|
+
new UnsupportedTypeError(),
|
|
125
|
+
new UnsupportedValueError({ Str: 'NaN' }),
|
|
126
|
+
]) {
|
|
127
|
+
expect(err.Error()).toBe(err.message)
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
|
|
50
131
|
it('marshals struct fields through json tags', () => {
|
|
51
132
|
const person = new Person()
|
|
52
133
|
person._fields.Name.value = 'Alice'
|
|
@@ -61,6 +142,187 @@ describe('encoding/json override', () => {
|
|
|
61
142
|
)
|
|
62
143
|
})
|
|
63
144
|
|
|
145
|
+
it('uses descriptor names separately from storage keys', () => {
|
|
146
|
+
const alias = new FieldAlias()
|
|
147
|
+
alias._fields.Name.value = 'Ada'
|
|
148
|
+
|
|
149
|
+
const [data, err] = Marshal(alias)
|
|
150
|
+
expect(err).toBeNull()
|
|
151
|
+
expect($.bytesToString(data)).toBe('{"FullName":"Ada"}')
|
|
152
|
+
|
|
153
|
+
const target = $.varRef(new FieldAlias())
|
|
154
|
+
expect(
|
|
155
|
+
Unmarshal($.stringToBytes('{"FullName":"Grace"}'), target),
|
|
156
|
+
).toBeNull()
|
|
157
|
+
expect(target.value._fields.Name.value).toBe('Grace')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('rejects unsupported values and invalid unmarshal targets', () => {
|
|
161
|
+
const [nanData, nanErr] = Marshal(Number.NaN)
|
|
162
|
+
expect(nanData).toBeNull()
|
|
163
|
+
expect(nanErr).toBeInstanceOf(UnsupportedValueError)
|
|
164
|
+
|
|
165
|
+
const [htmlData, htmlErr] = Marshal(new Map([['text', '<tag>&']]))
|
|
166
|
+
expect(htmlErr).toBeNull()
|
|
167
|
+
expect($.bytesToString(htmlData)).toBe(
|
|
168
|
+
'{"text":"\\u003ctag\\u003e\\u0026"}',
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
expect(Unmarshal($.stringToBytes('{}'), null)).toBeInstanceOf(
|
|
172
|
+
InvalidUnmarshalError,
|
|
173
|
+
)
|
|
174
|
+
expect(Unmarshal($.stringToBytes('{}'), 1)).toBeInstanceOf(
|
|
175
|
+
InvalidUnmarshalError,
|
|
176
|
+
)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
it('uses custom marshal and unmarshal hooks', () => {
|
|
180
|
+
class CustomJSON implements Marshaler, Unmarshaler {
|
|
181
|
+
public Text = ''
|
|
182
|
+
|
|
183
|
+
MarshalJSON(): [$.Slice<number>, $.GoError] {
|
|
184
|
+
return [$.stringToBytes('{"hook":true}'), null]
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
UnmarshalJSON(data: $.Slice<number>): $.GoError {
|
|
188
|
+
this.Text = $.bytesToString(data)
|
|
189
|
+
return null
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
class RawEnvelope {
|
|
194
|
+
public _fields = {
|
|
195
|
+
Raw: $.varRef($.stringToBytes('{"embedded":true}')),
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
static __typeInfo = $.registerStructType(
|
|
199
|
+
'test.RawEnvelope',
|
|
200
|
+
new RawEnvelope(),
|
|
201
|
+
[],
|
|
202
|
+
RawEnvelope,
|
|
203
|
+
[
|
|
204
|
+
{
|
|
205
|
+
name: 'Raw',
|
|
206
|
+
key: 'Raw',
|
|
207
|
+
type: 'json.RawMessage',
|
|
208
|
+
tag: 'json:"raw"',
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
class Envelope {
|
|
215
|
+
public _fields = {
|
|
216
|
+
Person: $.varRef(new Person()),
|
|
217
|
+
Data: $.varRef(new Uint8Array(0)),
|
|
218
|
+
Raw: $.varRef(new Uint8Array(0)),
|
|
219
|
+
Hook: $.varRef(new CustomJSON()),
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static __typeInfo = $.registerStructType(
|
|
223
|
+
'test.Envelope',
|
|
224
|
+
new Envelope(),
|
|
225
|
+
[],
|
|
226
|
+
Envelope,
|
|
227
|
+
[
|
|
228
|
+
{
|
|
229
|
+
name: 'Person',
|
|
230
|
+
key: 'Person',
|
|
231
|
+
type: { kind: $.TypeKind.Struct, name: 'test.Person' },
|
|
232
|
+
tag: 'json:"person"',
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: 'Data',
|
|
236
|
+
key: 'Data',
|
|
237
|
+
type: {
|
|
238
|
+
kind: $.TypeKind.Slice,
|
|
239
|
+
elemType: { kind: $.TypeKind.Basic, name: 'uint8' },
|
|
240
|
+
},
|
|
241
|
+
tag: 'json:"data"',
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: 'Raw',
|
|
245
|
+
key: 'Raw',
|
|
246
|
+
type: {
|
|
247
|
+
kind: $.TypeKind.Slice,
|
|
248
|
+
elemType: { kind: $.TypeKind.Basic, name: 'uint8' },
|
|
249
|
+
typeName: 'json.RawMessage',
|
|
250
|
+
},
|
|
251
|
+
tag: 'json:"raw"',
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
name: 'Hook',
|
|
255
|
+
key: 'Hook',
|
|
256
|
+
type: { kind: $.TypeKind.Struct, name: 'test.CustomJSON' },
|
|
257
|
+
tag: 'json:"hook"',
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const [data, err] = Marshal(new CustomJSON())
|
|
264
|
+
expect(err).toBeNull()
|
|
265
|
+
expect($.bytesToString(data)).toBe('{"hook":true}')
|
|
266
|
+
|
|
267
|
+
const [indented, indentErr] = MarshalIndent(new CustomJSON(), '', ' ')
|
|
268
|
+
expect(indentErr).toBeNull()
|
|
269
|
+
expect($.bytesToString(indented)).toBe('{\n "hook": true\n}')
|
|
270
|
+
|
|
271
|
+
const target = $.varRef(new CustomJSON())
|
|
272
|
+
expect(Unmarshal($.stringToBytes('{"input":1}'), target)).toBeNull()
|
|
273
|
+
expect(target.value.Text).toBe('{"input":1}')
|
|
274
|
+
|
|
275
|
+
const raw = $.namedValueInterfaceValue<unknown>(
|
|
276
|
+
$.stringToBytes('{"raw":true}'),
|
|
277
|
+
'json.RawMessage',
|
|
278
|
+
{ MarshalJSON: RawMessage_MarshalJSON },
|
|
279
|
+
)
|
|
280
|
+
const [rawData, rawErr] = Marshal(raw)
|
|
281
|
+
expect(rawErr).toBeNull()
|
|
282
|
+
expect($.bytesToString(rawData)).toBe('{"raw":true}')
|
|
283
|
+
|
|
284
|
+
const [byteData, byteErr] = Marshal($.stringToBytes('x'))
|
|
285
|
+
expect(byteErr).toBeNull()
|
|
286
|
+
expect($.bytesToString(byteData)).toBe('"eA=="')
|
|
287
|
+
|
|
288
|
+
const [rawEnvelopeData, rawEnvelopeErr] = Marshal(new RawEnvelope())
|
|
289
|
+
expect(rawEnvelopeErr).toBeNull()
|
|
290
|
+
expect($.bytesToString(rawEnvelopeData)).toBe('{"raw":{"embedded":true}}')
|
|
291
|
+
|
|
292
|
+
const rawEnvelopeTarget = $.varRef(new RawEnvelope())
|
|
293
|
+
expect(
|
|
294
|
+
Unmarshal($.stringToBytes('{"raw":{"next":1}}'), rawEnvelopeTarget),
|
|
295
|
+
).toBeNull()
|
|
296
|
+
expect($.bytesToString(rawEnvelopeTarget.value._fields.Raw.value)).toBe(
|
|
297
|
+
'{"next":1}',
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
const byteTarget = $.varRef(new Uint8Array(0))
|
|
301
|
+
expect(Unmarshal($.stringToBytes('"eA=="'), byteTarget)).toBeNull()
|
|
302
|
+
expect($.bytesToString(byteTarget.value)).toBe('x')
|
|
303
|
+
|
|
304
|
+
const envelope = $.varRef(new Envelope())
|
|
305
|
+
expect(
|
|
306
|
+
Unmarshal(
|
|
307
|
+
$.stringToBytes(
|
|
308
|
+
'{"person":{"name":"Eve","age":31},"data":"eA==","raw":{"keep":true},"hook":{"nested":true}}',
|
|
309
|
+
),
|
|
310
|
+
envelope,
|
|
311
|
+
),
|
|
312
|
+
).toBeNull()
|
|
313
|
+
expect(envelope.value._fields.Person.value._fields.Name.value).toBe('Eve')
|
|
314
|
+
expect(envelope.value._fields.Person.value._fields.Age.value).toBe(31)
|
|
315
|
+
expect($.bytesToString(envelope.value._fields.Data.value)).toBe('x')
|
|
316
|
+
expect($.bytesToString(envelope.value._fields.Raw.value)).toBe(
|
|
317
|
+
'{"keep":true}',
|
|
318
|
+
)
|
|
319
|
+
expect(envelope.value._fields.Hook.value.Text).toBe('{"nested":true}')
|
|
320
|
+
|
|
321
|
+
const [envelopeData, envelopeErr] = Marshal(envelope.value)
|
|
322
|
+
expect(envelopeErr).toBeNull()
|
|
323
|
+
expect($.bytesToString(envelopeData)).toContain('"raw":{"keep":true}')
|
|
324
|
+
})
|
|
325
|
+
|
|
64
326
|
it('marshals indented JSON with a line prefix', () => {
|
|
65
327
|
const person = new Person()
|
|
66
328
|
person._fields.Name.value = 'Alice'
|
|
@@ -98,4 +360,96 @@ describe('encoding/json override', () => {
|
|
|
98
360
|
expect(mapRef.value?.get('age')).toBe(22)
|
|
99
361
|
expect(mapRef.value?.get('active')).toBe(true)
|
|
100
362
|
})
|
|
363
|
+
|
|
364
|
+
it('encodes JSON to an io.Writer with newline, indentation, and HTML escaping', () => {
|
|
365
|
+
const chunks: string[] = []
|
|
366
|
+
const writer = {
|
|
367
|
+
Write(p: $.Bytes): [number, $.GoError] {
|
|
368
|
+
chunks.push($.bytesToString(p))
|
|
369
|
+
return [$.len(p), null]
|
|
370
|
+
},
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const encoder = NewEncoder(writer)
|
|
374
|
+
expect(encoder.Encode(new Map([['text', '<tag>&']]))).toBeNull()
|
|
375
|
+
encoder.SetEscapeHTML(false)
|
|
376
|
+
encoder.SetIndent('', ' ')
|
|
377
|
+
expect(encoder.Encode(new Map([['text', '<tag>&']]))).toBeNull()
|
|
378
|
+
|
|
379
|
+
expect(chunks).toEqual([
|
|
380
|
+
'{"text":"\\u003ctag\\u003e\\u0026"}\n',
|
|
381
|
+
'{\n "text": "<tag>&"\n}\n',
|
|
382
|
+
])
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it('validates, compacts, indents, and escapes JSON bytes', () => {
|
|
386
|
+
expect(Valid($.stringToBytes('{"ok":true}'))).toBe(true)
|
|
387
|
+
expect(Valid($.stringToBytes('{'))).toBe(false)
|
|
388
|
+
|
|
389
|
+
const compact = new bytes.Buffer()
|
|
390
|
+
expect(Compact(compact, $.stringToBytes('{ "ok" : true }'))).toBeNull()
|
|
391
|
+
expect(compact.String()).toBe('{"ok":true}')
|
|
392
|
+
|
|
393
|
+
const indented = new bytes.Buffer()
|
|
394
|
+
expect(
|
|
395
|
+
Indent(indented, $.stringToBytes('{"ok":true}'), '> ', ' '),
|
|
396
|
+
).toBeNull()
|
|
397
|
+
expect(indented.String()).toBe('{\n> "ok": true\n> }')
|
|
398
|
+
|
|
399
|
+
const escaped = new bytes.Buffer()
|
|
400
|
+
HTMLEscape(escaped, $.stringToBytes('"<tag>&"'))
|
|
401
|
+
expect(escaped.String()).toBe('"\\u003ctag\\u003e\\u0026"')
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
it('decodes from readers and exposes raw message and number helpers', () => {
|
|
405
|
+
const reader = bytes.NewBufferString('{"name":"Dana","age":28}')!
|
|
406
|
+
const decoder = NewDecoder(reader)
|
|
407
|
+
const target = $.varRef(new Person())
|
|
408
|
+
|
|
409
|
+
expect(decoder.Decode(target)).toBeNull()
|
|
410
|
+
expect(target.value._fields.Name.value).toBe('Dana')
|
|
411
|
+
expect(target.value._fields.Age.value).toBe(28)
|
|
412
|
+
expect(decoder.InputOffset()).toBeGreaterThan(0)
|
|
413
|
+
|
|
414
|
+
const raw = $.stringToBytes('{"raw":true}')
|
|
415
|
+
const [marshaled, marshalErr] = RawMessage_MarshalJSON(raw)
|
|
416
|
+
expect(marshalErr).toBeNull()
|
|
417
|
+
expect($.bytesToString(marshaled)).toBe('{"raw":true}')
|
|
418
|
+
|
|
419
|
+
const rawRef = $.varRef<$.Bytes>(null)
|
|
420
|
+
expect(
|
|
421
|
+
RawMessage_UnmarshalJSON(rawRef, $.stringToBytes('[1,2]')),
|
|
422
|
+
).toBeNull()
|
|
423
|
+
expect($.bytesToString(rawRef.value)).toBe('[1,2]')
|
|
424
|
+
|
|
425
|
+
expect(Number_String('42')).toBe('42')
|
|
426
|
+
expect(Number_Int64('42')).toEqual([42, null])
|
|
427
|
+
expect(Number_Float64('3.5')).toEqual([3.5, null])
|
|
428
|
+
expect(Number.isNaN(Number_Float64('NaN')[0])).toBe(true)
|
|
429
|
+
expect(Number_Float64('-Inf')).toEqual([-Infinity, null])
|
|
430
|
+
expect(Number_Float64('1x')[1]?.Error()).toContain('invalid syntax')
|
|
431
|
+
expect(Number_Float64('1e999')[1]?.Error()).toContain('value out of range')
|
|
432
|
+
expect(Number_Int64('9223372036854775808')[1]?.Error()).toContain(
|
|
433
|
+
'value out of range',
|
|
434
|
+
)
|
|
435
|
+
})
|
|
436
|
+
|
|
437
|
+
it('applies decoder UseNumber and DisallowUnknownFields options', () => {
|
|
438
|
+
const numberReader = bytes.NewBufferString('{"n":12}')!
|
|
439
|
+
const numberDecoder = NewDecoder(numberReader)
|
|
440
|
+
numberDecoder.UseNumber()
|
|
441
|
+
const numberTarget = $.varRef<Map<string, unknown> | null>(null)
|
|
442
|
+
|
|
443
|
+
expect(numberDecoder.Decode(numberTarget)).toBeNull()
|
|
444
|
+
expect(numberTarget.value?.get('n')).toBe('12')
|
|
445
|
+
|
|
446
|
+
const strictReader = bytes.NewBufferString('{"name":"Ada","extra":true}')!
|
|
447
|
+
const strictDecoder = NewDecoder(strictReader)
|
|
448
|
+
strictDecoder.DisallowUnknownFields()
|
|
449
|
+
const strictTarget = $.varRef(new Person())
|
|
450
|
+
|
|
451
|
+
expect(strictDecoder.Decode(strictTarget)?.Error()).toBe(
|
|
452
|
+
'json: unknown field "extra"',
|
|
453
|
+
)
|
|
454
|
+
})
|
|
101
455
|
})
|