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
package/dist/gs/reflect/type.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StructField, StructTag, ValueError, } from './types.js';
|
|
2
2
|
export { StructField };
|
|
3
3
|
import { MapIter } from './map.js';
|
|
4
|
-
import { getTypeByName as builtinGetTypeByName,
|
|
4
|
+
import { getTypeByName as builtinGetTypeByName, isStructTypeInfo, isInterfaceTypeInfo, structFieldRuntimeKey, } from '../builtin/type.js';
|
|
5
5
|
import { Zero } from './value.js';
|
|
6
6
|
import { DeepEqual } from './deepequal.js';
|
|
7
7
|
import * as $ from '../builtin/index.js';
|
|
@@ -153,8 +153,10 @@ export const Struct = 25;
|
|
|
153
153
|
export const UnsafePointer = 26;
|
|
154
154
|
const pointerAddressStride = 0x100000000;
|
|
155
155
|
const pointerAddresses = new WeakMap();
|
|
156
|
+
const fieldPointerAddresses = new WeakMap();
|
|
156
157
|
let nextPointerAddress = 1;
|
|
157
158
|
const canonicalTypes = new globalThis.Map();
|
|
159
|
+
const constructingRegisteredTypes = new globalThis.Map();
|
|
158
160
|
function pointerAddress(value) {
|
|
159
161
|
let address = pointerAddresses.get(value);
|
|
160
162
|
if (address === undefined) {
|
|
@@ -164,15 +166,121 @@ function pointerAddress(value) {
|
|
|
164
166
|
}
|
|
165
167
|
return address;
|
|
166
168
|
}
|
|
169
|
+
function fieldPointerAddress(target, key) {
|
|
170
|
+
let addresses = fieldPointerAddresses.get(target);
|
|
171
|
+
if (addresses === undefined) {
|
|
172
|
+
addresses = new globalThis.Map();
|
|
173
|
+
fieldPointerAddresses.set(target, addresses);
|
|
174
|
+
}
|
|
175
|
+
let address = addresses.get(key);
|
|
176
|
+
if (address === undefined) {
|
|
177
|
+
address = nextPointerAddress * pointerAddressStride;
|
|
178
|
+
nextPointerAddress++;
|
|
179
|
+
addresses.set(key, address);
|
|
180
|
+
}
|
|
181
|
+
return address;
|
|
182
|
+
}
|
|
167
183
|
function internType(t) {
|
|
168
|
-
const key =
|
|
184
|
+
const key = typeIdentityKey(t);
|
|
169
185
|
const existing = canonicalTypes.get(key);
|
|
170
186
|
if (existing) {
|
|
187
|
+
mergeTypeMetadata(existing, t);
|
|
171
188
|
return existing;
|
|
172
189
|
}
|
|
173
190
|
canonicalTypes.set(key, t);
|
|
174
191
|
return t;
|
|
175
192
|
}
|
|
193
|
+
function mergeTypeMetadata(target, source) {
|
|
194
|
+
if (target instanceof BasicType && source instanceof BasicType) {
|
|
195
|
+
target.mergeMethodSignatures(source.methodSignatures());
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (target instanceof PointerType && source instanceof PointerType) {
|
|
199
|
+
target.mergeMethodSignatures(source.methodSignatures());
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (target instanceof FunctionType && source instanceof FunctionType) {
|
|
203
|
+
target.mergeSignature(source);
|
|
204
|
+
target.mergeMethodSignatures(source.methodSignatures());
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function typeIdentityKey(t, seen = new Set()) {
|
|
208
|
+
if (seen.has(t)) {
|
|
209
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
|
|
210
|
+
}
|
|
211
|
+
seen.add(t);
|
|
212
|
+
if (t instanceof StructType) {
|
|
213
|
+
return t.identityKey(seen);
|
|
214
|
+
}
|
|
215
|
+
switch (t.Kind()) {
|
|
216
|
+
case Array:
|
|
217
|
+
return `${t.Kind()}:${t.Len()}:${typeIdentityKey(t.Elem(), seen)}`;
|
|
218
|
+
case Chan:
|
|
219
|
+
case Ptr:
|
|
220
|
+
case Slice:
|
|
221
|
+
return `${t.Kind()}:${t.String()}:${typeIdentityKey(t.Elem(), seen)}`;
|
|
222
|
+
case Map:
|
|
223
|
+
return `${t.Kind()}:${typeIdentityKey(t.Key(), seen)}:${typeIdentityKey(t.Elem(), seen)}`;
|
|
224
|
+
case Func: {
|
|
225
|
+
if (t.Name() !== '') {
|
|
226
|
+
return `${t.Kind()}:named:${t.PkgPath()}:${t.Name()}`;
|
|
227
|
+
}
|
|
228
|
+
const params = globalThis.Array.from({ length: t.NumIn() }, (_unused, idx) => typeIdentityKey(t.In(idx), seen));
|
|
229
|
+
const results = globalThis.Array.from({ length: t.NumOut() }, (_unused, idx) => typeIdentityKey(t.Out(idx), seen));
|
|
230
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}:${t.IsVariadic()}:${params.join(',')}:${results.join(',')}`;
|
|
231
|
+
}
|
|
232
|
+
default:
|
|
233
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function typeUnderlyingIdentityKey(t, seen = new Set()) {
|
|
237
|
+
if (seen.has(t)) {
|
|
238
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
|
|
239
|
+
}
|
|
240
|
+
seen.add(t);
|
|
241
|
+
if (t instanceof BasicType) {
|
|
242
|
+
return `basic:${t.underlyingName()}`;
|
|
243
|
+
}
|
|
244
|
+
if (t instanceof StructType) {
|
|
245
|
+
return t.underlyingIdentityKey(seen);
|
|
246
|
+
}
|
|
247
|
+
switch (t.Kind()) {
|
|
248
|
+
case Array:
|
|
249
|
+
return `array:${t.Len()}:${typeIdentityKey(t.Elem(), seen)}`;
|
|
250
|
+
case Chan:
|
|
251
|
+
return `chan:${t.String()}:${typeIdentityKey(t.Elem(), seen)}`;
|
|
252
|
+
case Ptr:
|
|
253
|
+
return `ptr:${typeIdentityKey(t.Elem(), seen)}`;
|
|
254
|
+
case Slice:
|
|
255
|
+
return `slice:${typeIdentityKey(t.Elem(), seen)}`;
|
|
256
|
+
case Map:
|
|
257
|
+
return `map:${typeIdentityKey(t.Key(), seen)}:${typeIdentityKey(t.Elem(), seen)}`;
|
|
258
|
+
case Func: {
|
|
259
|
+
const params = globalThis.Array.from({ length: t.NumIn() }, (_unused, idx) => typeIdentityKey(t.In(idx), seen));
|
|
260
|
+
const results = globalThis.Array.from({ length: t.NumOut() }, (_unused, idx) => typeIdentityKey(t.Out(idx), seen));
|
|
261
|
+
return `func:${t.IsVariadic()}:${params.join(',')}:${results.join(',')}`;
|
|
262
|
+
}
|
|
263
|
+
case Interface:
|
|
264
|
+
return `interface:${typeMethods(t).map(methodSignatureIdentityKey).join('|')}`;
|
|
265
|
+
default:
|
|
266
|
+
return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function typeIsNamed(t) {
|
|
270
|
+
if (t.Kind() === Interface) {
|
|
271
|
+
return t.String() !== 'interface{}' && !t.String().startsWith('interface {');
|
|
272
|
+
}
|
|
273
|
+
if (t.Kind() === Struct || t.Kind() === Func) {
|
|
274
|
+
return t.Name() !== '';
|
|
275
|
+
}
|
|
276
|
+
if (t instanceof BasicType) {
|
|
277
|
+
return t.Kind() !== Invalid && t.Name() !== '';
|
|
278
|
+
}
|
|
279
|
+
return t.Name() !== '';
|
|
280
|
+
}
|
|
281
|
+
function nonFunctionTypePanic(method, t) {
|
|
282
|
+
throw new Error(`reflect: ${method} of non-func type ${t.String()}`);
|
|
283
|
+
}
|
|
176
284
|
// InvalidTypeInstance is a singleton type for invalid/zero reflect.Value
|
|
177
285
|
class InvalidTypeClass {
|
|
178
286
|
Kind() {
|
|
@@ -202,6 +310,21 @@ class InvalidTypeClass {
|
|
|
202
310
|
NumField() {
|
|
203
311
|
return 0;
|
|
204
312
|
}
|
|
313
|
+
NumIn() {
|
|
314
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
315
|
+
}
|
|
316
|
+
In(_i) {
|
|
317
|
+
return nonFunctionTypePanic('In', this);
|
|
318
|
+
}
|
|
319
|
+
NumOut() {
|
|
320
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
321
|
+
}
|
|
322
|
+
Out(_i) {
|
|
323
|
+
return nonFunctionTypePanic('Out', this);
|
|
324
|
+
}
|
|
325
|
+
IsVariadic() {
|
|
326
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
327
|
+
}
|
|
205
328
|
Field(_i) {
|
|
206
329
|
throw new Error('reflect: Field of invalid type');
|
|
207
330
|
}
|
|
@@ -276,24 +399,27 @@ export class Value {
|
|
|
276
399
|
}
|
|
277
400
|
// Methods required by godoc.txt and used throughout the codebase
|
|
278
401
|
Int() {
|
|
279
|
-
|
|
280
|
-
|
|
402
|
+
const value = this.numericValue();
|
|
403
|
+
if (value !== null && Number.isInteger(value)) {
|
|
404
|
+
return value;
|
|
281
405
|
}
|
|
282
406
|
throw new Error('reflect: call of reflect.Value.Int on ' +
|
|
283
407
|
Kind_String(this._type.Kind()) +
|
|
284
408
|
' Value');
|
|
285
409
|
}
|
|
286
410
|
Uint() {
|
|
287
|
-
|
|
288
|
-
|
|
411
|
+
const value = this.numericValue();
|
|
412
|
+
if (value !== null && value >= 0) {
|
|
413
|
+
return value;
|
|
289
414
|
}
|
|
290
415
|
throw new Error('reflect: call of reflect.Value.Uint on ' +
|
|
291
416
|
Kind_String(this._type.Kind()) +
|
|
292
417
|
' Value');
|
|
293
418
|
}
|
|
294
419
|
Float() {
|
|
295
|
-
|
|
296
|
-
|
|
420
|
+
const value = this.numericValue();
|
|
421
|
+
if (value !== null) {
|
|
422
|
+
return value;
|
|
297
423
|
}
|
|
298
424
|
throw new Error('reflect: call of reflect.Value.Float on ' +
|
|
299
425
|
Kind_String(this._type.Kind()) +
|
|
@@ -307,6 +433,20 @@ export class Value {
|
|
|
307
433
|
Kind_String(this._type.Kind()) +
|
|
308
434
|
' Value');
|
|
309
435
|
}
|
|
436
|
+
numericValue() {
|
|
437
|
+
if (typeof this._value === 'number') {
|
|
438
|
+
return this._value;
|
|
439
|
+
}
|
|
440
|
+
if (this._value !== null &&
|
|
441
|
+
typeof this._value === 'object' &&
|
|
442
|
+
typeof this._value.valueOf === 'function') {
|
|
443
|
+
const value = this._value.valueOf();
|
|
444
|
+
if (typeof value === 'number') {
|
|
445
|
+
return value;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
310
450
|
String() {
|
|
311
451
|
if (typeof this._value === 'string') {
|
|
312
452
|
return this._value;
|
|
@@ -318,6 +458,9 @@ export class Value {
|
|
|
318
458
|
return this._type.String();
|
|
319
459
|
}
|
|
320
460
|
Len() {
|
|
461
|
+
if (this.Kind() === Slice || this.Kind() === Array) {
|
|
462
|
+
return $.len(this._value);
|
|
463
|
+
}
|
|
321
464
|
// Check for slice objects created by $.arrayToSlice
|
|
322
465
|
if (this._value &&
|
|
323
466
|
typeof this._value === 'object' &&
|
|
@@ -366,8 +509,9 @@ export class Value {
|
|
|
366
509
|
return this._value === null || this._value === undefined;
|
|
367
510
|
}
|
|
368
511
|
Index(i) {
|
|
369
|
-
if (
|
|
370
|
-
|
|
512
|
+
if (this.Kind() === Slice || this.Kind() === Array) {
|
|
513
|
+
const ref = $.indexRef(this._value, i);
|
|
514
|
+
return new Value(ref.value, this._type.Elem(), ref);
|
|
371
515
|
}
|
|
372
516
|
throw new Error('reflect: call of reflect.Value.Index on ' +
|
|
373
517
|
Kind_String(this._type.Kind()) +
|
|
@@ -409,6 +553,15 @@ export class Value {
|
|
|
409
553
|
const elemType = this._type.Elem();
|
|
410
554
|
return new Value(varRef.value, elemType, varRef);
|
|
411
555
|
}
|
|
556
|
+
if (this._type.Kind() === Ptr &&
|
|
557
|
+
this._value &&
|
|
558
|
+
typeof this._value === 'object' &&
|
|
559
|
+
'__goValue' in this._value &&
|
|
560
|
+
$.isVarRef(this._value.__goValue)) {
|
|
561
|
+
const varRef = this._value
|
|
562
|
+
.__goValue;
|
|
563
|
+
return new Value(varRef.value, this._type.Elem(), varRef);
|
|
564
|
+
}
|
|
412
565
|
// For interfaces, return the underlying value
|
|
413
566
|
return new Value(this._value, this._type, this._parentVarRef);
|
|
414
567
|
}
|
|
@@ -420,16 +573,17 @@ export class Value {
|
|
|
420
573
|
throw new ValueError({ Kind: this.Kind(), Method: 'Field' });
|
|
421
574
|
}
|
|
422
575
|
const field = this.Type().Field(i);
|
|
576
|
+
const fieldKey = structFieldStorageKey(this.Type(), i);
|
|
423
577
|
if (!field) {
|
|
424
578
|
throw new Error('reflect: struct field index out of range');
|
|
425
579
|
}
|
|
426
580
|
const parentObj = this._value;
|
|
427
|
-
let fieldVal = parentObj[
|
|
581
|
+
let fieldVal = parentObj[fieldKey];
|
|
428
582
|
if (fieldVal === undefined) {
|
|
429
583
|
fieldVal = null;
|
|
430
584
|
}
|
|
431
585
|
// Pass parent struct and field name so Set() can update the struct
|
|
432
|
-
return new Value(fieldVal, field.Type, undefined, parentObj,
|
|
586
|
+
return new Value(fieldVal, field.Type, undefined, parentObj, fieldKey);
|
|
433
587
|
}
|
|
434
588
|
FieldByIndex(index) {
|
|
435
589
|
let current = this;
|
|
@@ -462,6 +616,9 @@ export class Value {
|
|
|
462
616
|
if (this._value === null || this._value === undefined) {
|
|
463
617
|
return 0;
|
|
464
618
|
}
|
|
619
|
+
if ($.isOwnedPointerHandle(this._value)) {
|
|
620
|
+
return $.ownedPointerAddress(this._value);
|
|
621
|
+
}
|
|
465
622
|
if ($.isVarRef(this._value)) {
|
|
466
623
|
const address = this._value.__goAddress?.();
|
|
467
624
|
if (address !== undefined) {
|
|
@@ -491,7 +648,18 @@ export class Value {
|
|
|
491
648
|
throw new ValueError({ Kind: this.Kind(), Method: 'UnsafeAddr' });
|
|
492
649
|
}
|
|
493
650
|
if (this._parentStruct && this._fieldName) {
|
|
494
|
-
|
|
651
|
+
const target = this._parentStruct;
|
|
652
|
+
const key = this._fieldName;
|
|
653
|
+
const ref = $.fieldRef(target, key);
|
|
654
|
+
return {
|
|
655
|
+
__goOwnedPointer: true,
|
|
656
|
+
__goAddress: () => fieldPointerAddress(target, key),
|
|
657
|
+
__goRef: () => ref,
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
if (this._parentVarRef?.__goPointer) {
|
|
661
|
+
return this._parentVarRef
|
|
662
|
+
.__goPointer;
|
|
495
663
|
}
|
|
496
664
|
return this.Pointer();
|
|
497
665
|
}
|
|
@@ -521,6 +689,9 @@ export class Value {
|
|
|
521
689
|
if (this._parentStruct && this._fieldName) {
|
|
522
690
|
return new Value($.fieldRef(this._parentStruct, this._fieldName), ptrType);
|
|
523
691
|
}
|
|
692
|
+
if (this._parentVarRef) {
|
|
693
|
+
return new Value(this._parentVarRef, ptrType);
|
|
694
|
+
}
|
|
524
695
|
return new Value($.varRef(this._value), ptrType);
|
|
525
696
|
}
|
|
526
697
|
CanSet() {
|
|
@@ -532,23 +703,9 @@ export class Value {
|
|
|
532
703
|
if (!this.CanSet()) {
|
|
533
704
|
throw new Error('reflect: assign to invalid value');
|
|
534
705
|
}
|
|
535
|
-
// Interface types can accept any value
|
|
536
|
-
if (this.Kind() === Interface) {
|
|
537
|
-
this._value = x.value;
|
|
538
|
-
// Also update the parent VarRef if we were dereferenced from one
|
|
539
|
-
if (this._parentVarRef) {
|
|
540
|
-
this._parentVarRef.value = x.value;
|
|
541
|
-
}
|
|
542
|
-
// Also update the parent struct field if this is a struct field
|
|
543
|
-
if (this._parentStruct && this._fieldName) {
|
|
544
|
-
this._parentStruct[this._fieldName] = x.value;
|
|
545
|
-
}
|
|
546
|
-
return;
|
|
547
|
-
}
|
|
548
|
-
// For other types, check if types are compatible (simplified check)
|
|
549
706
|
const thisType = this.Type();
|
|
550
707
|
const xType = x.Type();
|
|
551
|
-
if (
|
|
708
|
+
if (!xType.AssignableTo(thisType)) {
|
|
552
709
|
throw new Error('reflect: assign to wrong type');
|
|
553
710
|
}
|
|
554
711
|
this._value = x.value;
|
|
@@ -579,21 +736,23 @@ export class Value {
|
|
|
579
736
|
if (typeof method !== 'function') {
|
|
580
737
|
return new Value();
|
|
581
738
|
}
|
|
582
|
-
|
|
739
|
+
const [signature] = methodSignatureByName(this.Type(), name);
|
|
740
|
+
const methodType = signature ?
|
|
741
|
+
methodTypeFromSignature(signature, this.Type(), false)
|
|
742
|
+
: new FunctionType('func');
|
|
743
|
+
return new Value(method.bind(receiver), methodType);
|
|
583
744
|
}
|
|
584
|
-
Call(inArgs) {
|
|
745
|
+
async Call(inArgs) {
|
|
585
746
|
if (this.Kind() !== Func || typeof this._value !== 'function') {
|
|
586
747
|
throw new ValueError({ Kind: this.Kind(), Method: 'Call' });
|
|
587
748
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
if (result === undefined) {
|
|
594
|
-
return $.makeSlice(0);
|
|
749
|
+
return await callReflectFunction(this._value, this._type, inArgs, 'Call');
|
|
750
|
+
}
|
|
751
|
+
async CallSlice(inArgs) {
|
|
752
|
+
if (this.Kind() !== Func || typeof this._value !== 'function') {
|
|
753
|
+
throw new ValueError({ Kind: this.Kind(), Method: 'CallSlice' });
|
|
595
754
|
}
|
|
596
|
-
return
|
|
755
|
+
return await callReflectFunction(this._value, this._type, inArgs, 'CallSlice');
|
|
597
756
|
}
|
|
598
757
|
IsZero() {
|
|
599
758
|
const zeroVal = Zero(this.Type()).value;
|
|
@@ -860,10 +1019,7 @@ export class Value {
|
|
|
860
1019
|
Cap() {
|
|
861
1020
|
const k = this.Kind();
|
|
862
1021
|
if (k === Slice || k === Array) {
|
|
863
|
-
|
|
864
|
-
return this._value.length;
|
|
865
|
-
}
|
|
866
|
-
return 0;
|
|
1022
|
+
return $.cap(this._value);
|
|
867
1023
|
}
|
|
868
1024
|
if (k === Chan) {
|
|
869
1025
|
return 0; // Simplified
|
|
@@ -936,11 +1092,13 @@ export class BasicType {
|
|
|
936
1092
|
_name;
|
|
937
1093
|
_size;
|
|
938
1094
|
_typeName;
|
|
939
|
-
|
|
1095
|
+
_methods;
|
|
1096
|
+
constructor(_kind, _name, _size = 8, _typeName = '', _methods = []) {
|
|
940
1097
|
this._kind = _kind;
|
|
941
1098
|
this._name = _name;
|
|
942
1099
|
this._size = _size;
|
|
943
1100
|
this._typeName = _typeName;
|
|
1101
|
+
this._methods = _methods;
|
|
944
1102
|
}
|
|
945
1103
|
String() {
|
|
946
1104
|
return this._typeName || this._name;
|
|
@@ -948,6 +1106,9 @@ export class BasicType {
|
|
|
948
1106
|
Kind() {
|
|
949
1107
|
return this._kind;
|
|
950
1108
|
}
|
|
1109
|
+
underlyingName() {
|
|
1110
|
+
return Kind_String(this._kind);
|
|
1111
|
+
}
|
|
951
1112
|
Comparable() {
|
|
952
1113
|
return this._kind !== Func && this._kind !== Map && this._kind !== Slice;
|
|
953
1114
|
}
|
|
@@ -960,6 +1121,21 @@ export class BasicType {
|
|
|
960
1121
|
NumField() {
|
|
961
1122
|
return 0;
|
|
962
1123
|
}
|
|
1124
|
+
NumIn() {
|
|
1125
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
1126
|
+
}
|
|
1127
|
+
In(_i) {
|
|
1128
|
+
return nonFunctionTypePanic('In', this);
|
|
1129
|
+
}
|
|
1130
|
+
NumOut() {
|
|
1131
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
1132
|
+
}
|
|
1133
|
+
Out(_i) {
|
|
1134
|
+
return nonFunctionTypePanic('Out', this);
|
|
1135
|
+
}
|
|
1136
|
+
IsVariadic() {
|
|
1137
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
1138
|
+
}
|
|
963
1139
|
PkgPath() {
|
|
964
1140
|
if (this._typeName) {
|
|
965
1141
|
const dotIndex = this._typeName.lastIndexOf('.');
|
|
@@ -999,7 +1175,7 @@ export class BasicType {
|
|
|
999
1175
|
if (u.Kind() !== Interface) {
|
|
1000
1176
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1001
1177
|
}
|
|
1002
|
-
return
|
|
1178
|
+
return typeImplementsInterface(this, u);
|
|
1003
1179
|
}
|
|
1004
1180
|
AssignableTo(u) {
|
|
1005
1181
|
return typeAssignableTo(this, u);
|
|
@@ -1058,10 +1234,16 @@ export class BasicType {
|
|
|
1058
1234
|
' Type');
|
|
1059
1235
|
}
|
|
1060
1236
|
NumMethod() {
|
|
1061
|
-
return
|
|
1237
|
+
return typeMethods(this).length;
|
|
1062
1238
|
}
|
|
1063
|
-
MethodByName(
|
|
1064
|
-
return
|
|
1239
|
+
MethodByName(name) {
|
|
1240
|
+
return typeMethodByName(this, name);
|
|
1241
|
+
}
|
|
1242
|
+
methodSignatures() {
|
|
1243
|
+
return this._methods;
|
|
1244
|
+
}
|
|
1245
|
+
mergeMethodSignatures(methods) {
|
|
1246
|
+
this._methods = mergeMethodSignatureList(this._methods, methods);
|
|
1065
1247
|
}
|
|
1066
1248
|
Len() {
|
|
1067
1249
|
throw new Error('reflect: call of reflect.Type.Len on ' +
|
|
@@ -1124,6 +1306,21 @@ class SliceType {
|
|
|
1124
1306
|
NumField() {
|
|
1125
1307
|
return 0;
|
|
1126
1308
|
}
|
|
1309
|
+
NumIn() {
|
|
1310
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
1311
|
+
}
|
|
1312
|
+
In(_i) {
|
|
1313
|
+
return nonFunctionTypePanic('In', this);
|
|
1314
|
+
}
|
|
1315
|
+
NumOut() {
|
|
1316
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
1317
|
+
}
|
|
1318
|
+
Out(_i) {
|
|
1319
|
+
return nonFunctionTypePanic('Out', this);
|
|
1320
|
+
}
|
|
1321
|
+
IsVariadic() {
|
|
1322
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
1323
|
+
}
|
|
1127
1324
|
PkgPath() {
|
|
1128
1325
|
return '';
|
|
1129
1326
|
}
|
|
@@ -1150,7 +1347,7 @@ class SliceType {
|
|
|
1150
1347
|
if (u.Kind() !== Interface) {
|
|
1151
1348
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1152
1349
|
}
|
|
1153
|
-
return
|
|
1350
|
+
return typeImplementsInterface(this, u);
|
|
1154
1351
|
}
|
|
1155
1352
|
AssignableTo(u) {
|
|
1156
1353
|
return typeAssignableTo(this, u);
|
|
@@ -1203,6 +1400,21 @@ class ArrayType {
|
|
|
1203
1400
|
NumField() {
|
|
1204
1401
|
return 0;
|
|
1205
1402
|
}
|
|
1403
|
+
NumIn() {
|
|
1404
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
1405
|
+
}
|
|
1406
|
+
In(_i) {
|
|
1407
|
+
return nonFunctionTypePanic('In', this);
|
|
1408
|
+
}
|
|
1409
|
+
NumOut() {
|
|
1410
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
1411
|
+
}
|
|
1412
|
+
Out(_i) {
|
|
1413
|
+
return nonFunctionTypePanic('Out', this);
|
|
1414
|
+
}
|
|
1415
|
+
IsVariadic() {
|
|
1416
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
1417
|
+
}
|
|
1206
1418
|
Len() {
|
|
1207
1419
|
return this._len;
|
|
1208
1420
|
}
|
|
@@ -1232,7 +1444,7 @@ class ArrayType {
|
|
|
1232
1444
|
if (u.Kind() !== Interface) {
|
|
1233
1445
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1234
1446
|
}
|
|
1235
|
-
return
|
|
1447
|
+
return typeImplementsInterface(this, u);
|
|
1236
1448
|
}
|
|
1237
1449
|
AssignableTo(u) {
|
|
1238
1450
|
return typeAssignableTo(this, u);
|
|
@@ -1262,8 +1474,10 @@ class ArrayType {
|
|
|
1262
1474
|
// Pointer type implementation
|
|
1263
1475
|
class PointerType {
|
|
1264
1476
|
_elemType;
|
|
1265
|
-
|
|
1477
|
+
_methods;
|
|
1478
|
+
constructor(_elemType, _methods = []) {
|
|
1266
1479
|
this._elemType = _elemType;
|
|
1480
|
+
this._methods = _methods;
|
|
1267
1481
|
}
|
|
1268
1482
|
String() {
|
|
1269
1483
|
return '*' + this._elemType.String();
|
|
@@ -1283,6 +1497,21 @@ class PointerType {
|
|
|
1283
1497
|
NumField() {
|
|
1284
1498
|
return 0;
|
|
1285
1499
|
}
|
|
1500
|
+
NumIn() {
|
|
1501
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
1502
|
+
}
|
|
1503
|
+
In(_i) {
|
|
1504
|
+
return nonFunctionTypePanic('In', this);
|
|
1505
|
+
}
|
|
1506
|
+
NumOut() {
|
|
1507
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
1508
|
+
}
|
|
1509
|
+
Out(_i) {
|
|
1510
|
+
return nonFunctionTypePanic('Out', this);
|
|
1511
|
+
}
|
|
1512
|
+
IsVariadic() {
|
|
1513
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
1514
|
+
}
|
|
1286
1515
|
PkgPath() {
|
|
1287
1516
|
return '';
|
|
1288
1517
|
}
|
|
@@ -1309,9 +1538,7 @@ class PointerType {
|
|
|
1309
1538
|
if (u.Kind() !== Interface) {
|
|
1310
1539
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1311
1540
|
}
|
|
1312
|
-
|
|
1313
|
-
const elemTypeName = this._elemType.String();
|
|
1314
|
-
return typeImplementsInterface(elemTypeName, u);
|
|
1541
|
+
return typeImplementsInterface(this, u);
|
|
1315
1542
|
}
|
|
1316
1543
|
AssignableTo(u) {
|
|
1317
1544
|
return typeAssignableTo(this, u);
|
|
@@ -1329,10 +1556,16 @@ class PointerType {
|
|
|
1329
1556
|
throw new Error('reflect: call of reflect.Type.OverflowFloat on pointer Type');
|
|
1330
1557
|
}
|
|
1331
1558
|
NumMethod() {
|
|
1332
|
-
return
|
|
1559
|
+
return typeMethods(this).length;
|
|
1333
1560
|
}
|
|
1334
1561
|
MethodByName(name) {
|
|
1335
|
-
return typeMethodByName(this
|
|
1562
|
+
return typeMethodByName(this, name);
|
|
1563
|
+
}
|
|
1564
|
+
methodSignatures() {
|
|
1565
|
+
return this._methods;
|
|
1566
|
+
}
|
|
1567
|
+
mergeMethodSignatures(methods) {
|
|
1568
|
+
this._methods = mergeMethodSignatureList(this._methods, methods);
|
|
1336
1569
|
}
|
|
1337
1570
|
Len() {
|
|
1338
1571
|
throw new Error('reflect: call of reflect.Type.Len on pointer Type');
|
|
@@ -1341,13 +1574,42 @@ class PointerType {
|
|
|
1341
1574
|
throw new Error('reflect: call of reflect.Type.Bits on pointer Type');
|
|
1342
1575
|
}
|
|
1343
1576
|
}
|
|
1344
|
-
// Function type implementation
|
|
1345
1577
|
class FunctionType {
|
|
1578
|
+
_name;
|
|
1346
1579
|
_signature;
|
|
1347
|
-
|
|
1348
|
-
|
|
1580
|
+
_params;
|
|
1581
|
+
_results;
|
|
1582
|
+
_variadic;
|
|
1583
|
+
_hasSignature;
|
|
1584
|
+
_methods;
|
|
1585
|
+
constructor(signatureOrDescriptor) {
|
|
1586
|
+
if (typeof signatureOrDescriptor === 'string') {
|
|
1587
|
+
this._name = '';
|
|
1588
|
+
this._signature = signatureOrDescriptor;
|
|
1589
|
+
this._params = [];
|
|
1590
|
+
this._results = [];
|
|
1591
|
+
this._variadic = false;
|
|
1592
|
+
this._hasSignature = false;
|
|
1593
|
+
this._methods = [];
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
this._name = signatureOrDescriptor.name ?? '';
|
|
1597
|
+
this._params = signatureOrDescriptor.params ?? [];
|
|
1598
|
+
this._results = signatureOrDescriptor.results ?? [];
|
|
1599
|
+
this._variadic = signatureOrDescriptor.variadic ?? false;
|
|
1600
|
+
this._hasSignature =
|
|
1601
|
+
signatureOrDescriptor.signature !== undefined ||
|
|
1602
|
+
signatureOrDescriptor.params !== undefined ||
|
|
1603
|
+
signatureOrDescriptor.results !== undefined;
|
|
1604
|
+
this._methods = signatureOrDescriptor.methods ?? [];
|
|
1605
|
+
this._signature =
|
|
1606
|
+
signatureOrDescriptor.signature ??
|
|
1607
|
+
formatFunctionSignature(this._params, this._results, this._variadic);
|
|
1349
1608
|
}
|
|
1350
1609
|
String() {
|
|
1610
|
+
if (this._name !== '') {
|
|
1611
|
+
return this._name;
|
|
1612
|
+
}
|
|
1351
1613
|
return this._signature;
|
|
1352
1614
|
}
|
|
1353
1615
|
Kind() {
|
|
@@ -1365,11 +1627,44 @@ class FunctionType {
|
|
|
1365
1627
|
NumField() {
|
|
1366
1628
|
return 0;
|
|
1367
1629
|
}
|
|
1630
|
+
NumIn() {
|
|
1631
|
+
return this._params.length;
|
|
1632
|
+
}
|
|
1633
|
+
In(i) {
|
|
1634
|
+
if (i < 0 || i >= this._params.length) {
|
|
1635
|
+
throw new Error(`reflect: In index out of range [${i}] with length ${this._params.length}`);
|
|
1636
|
+
}
|
|
1637
|
+
return this._params[i];
|
|
1638
|
+
}
|
|
1639
|
+
NumOut() {
|
|
1640
|
+
return this._results.length;
|
|
1641
|
+
}
|
|
1642
|
+
Out(i) {
|
|
1643
|
+
if (i < 0 || i >= this._results.length) {
|
|
1644
|
+
throw new Error(`reflect: Out index out of range [${i}] with length ${this._results.length}`);
|
|
1645
|
+
}
|
|
1646
|
+
return this._results[i];
|
|
1647
|
+
}
|
|
1648
|
+
IsVariadic() {
|
|
1649
|
+
return this._variadic;
|
|
1650
|
+
}
|
|
1368
1651
|
PkgPath() {
|
|
1652
|
+
if (this._name !== '') {
|
|
1653
|
+
const dotIndex = this._name.lastIndexOf('.');
|
|
1654
|
+
if (dotIndex > 0) {
|
|
1655
|
+
return this._name.substring(0, dotIndex);
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1369
1658
|
return '';
|
|
1370
1659
|
}
|
|
1371
1660
|
Name() {
|
|
1372
|
-
|
|
1661
|
+
if (this._name !== '') {
|
|
1662
|
+
const dotIndex = this._name.lastIndexOf('.');
|
|
1663
|
+
if (dotIndex >= 0) {
|
|
1664
|
+
return this._name.substring(dotIndex + 1);
|
|
1665
|
+
}
|
|
1666
|
+
return this._name;
|
|
1667
|
+
}
|
|
1373
1668
|
return '';
|
|
1374
1669
|
}
|
|
1375
1670
|
Field(_i) {
|
|
@@ -1391,7 +1686,7 @@ class FunctionType {
|
|
|
1391
1686
|
if (u.Kind() !== Interface) {
|
|
1392
1687
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1393
1688
|
}
|
|
1394
|
-
return
|
|
1689
|
+
return typeImplementsInterface(this, u);
|
|
1395
1690
|
}
|
|
1396
1691
|
AssignableTo(u) {
|
|
1397
1692
|
return typeAssignableTo(this, u);
|
|
@@ -1409,10 +1704,26 @@ class FunctionType {
|
|
|
1409
1704
|
throw new Error('reflect: call of reflect.Type.OverflowFloat on func Type');
|
|
1410
1705
|
}
|
|
1411
1706
|
NumMethod() {
|
|
1412
|
-
return
|
|
1707
|
+
return typeMethods(this).length;
|
|
1413
1708
|
}
|
|
1414
|
-
MethodByName(
|
|
1415
|
-
return
|
|
1709
|
+
MethodByName(name) {
|
|
1710
|
+
return typeMethodByName(this, name);
|
|
1711
|
+
}
|
|
1712
|
+
methodSignatures() {
|
|
1713
|
+
return this._methods;
|
|
1714
|
+
}
|
|
1715
|
+
mergeMethodSignatures(methods) {
|
|
1716
|
+
this._methods = mergeMethodSignatureList(this._methods, methods);
|
|
1717
|
+
}
|
|
1718
|
+
mergeSignature(source) {
|
|
1719
|
+
if (!source._hasSignature || this._hasSignature) {
|
|
1720
|
+
return;
|
|
1721
|
+
}
|
|
1722
|
+
this._params = source._params;
|
|
1723
|
+
this._results = source._results;
|
|
1724
|
+
this._variadic = source._variadic;
|
|
1725
|
+
this._signature = source._signature;
|
|
1726
|
+
this._hasSignature = true;
|
|
1416
1727
|
}
|
|
1417
1728
|
Len() {
|
|
1418
1729
|
throw new Error('reflect: call of reflect.Type.Len on func Type');
|
|
@@ -1421,6 +1732,174 @@ class FunctionType {
|
|
|
1421
1732
|
throw new Error('reflect: call of reflect.Type.Bits on func Type');
|
|
1422
1733
|
}
|
|
1423
1734
|
}
|
|
1735
|
+
function formatFunctionSignature(params, results, variadic) {
|
|
1736
|
+
const paramStrings = params.map((param, index) => {
|
|
1737
|
+
const typeName = param.String();
|
|
1738
|
+
if (!variadic || index !== params.length - 1) {
|
|
1739
|
+
return typeName;
|
|
1740
|
+
}
|
|
1741
|
+
if (typeName.startsWith('[]')) {
|
|
1742
|
+
return '...' + typeName.slice(2);
|
|
1743
|
+
}
|
|
1744
|
+
return '...' + typeName;
|
|
1745
|
+
});
|
|
1746
|
+
let signature = `func(${paramStrings.join(', ')})`;
|
|
1747
|
+
if (results.length === 1) {
|
|
1748
|
+
signature += ` ${results[0].String()}`;
|
|
1749
|
+
}
|
|
1750
|
+
else if (results.length > 1) {
|
|
1751
|
+
signature += ` (${results.map((result) => result.String()).join(', ')})`;
|
|
1752
|
+
}
|
|
1753
|
+
return signature;
|
|
1754
|
+
}
|
|
1755
|
+
async function callReflectFunction(fn, fnType, inArgs, op) {
|
|
1756
|
+
const args = $.asArray(inArgs);
|
|
1757
|
+
const rawArgs = reflectCallRawArgs(fnType, args, op);
|
|
1758
|
+
const result = await fn(...rawArgs);
|
|
1759
|
+
return normalizeReflectCallResults(fnType, result);
|
|
1760
|
+
}
|
|
1761
|
+
function reflectCallRawArgs(fnType, args, op) {
|
|
1762
|
+
if (op === 'CallSlice') {
|
|
1763
|
+
return reflectCallSliceRawArgs(fnType, args);
|
|
1764
|
+
}
|
|
1765
|
+
if (!fnType.IsVariadic()) {
|
|
1766
|
+
validateReflectCallInputCount(fnType, args.length);
|
|
1767
|
+
return args.map((arg, index) => reflectCallValueInterface(op, arg, fnType.In(index), index));
|
|
1768
|
+
}
|
|
1769
|
+
const fixedCount = fnType.NumIn() - 1;
|
|
1770
|
+
if (args.length < fixedCount) {
|
|
1771
|
+
throw new Error('reflect: Call with too few input arguments');
|
|
1772
|
+
}
|
|
1773
|
+
const rawArgs = [];
|
|
1774
|
+
for (let i = 0; i < fixedCount; i++) {
|
|
1775
|
+
rawArgs.push(reflectCallValueInterface(op, args[i], fnType.In(i), i));
|
|
1776
|
+
}
|
|
1777
|
+
const variadicElemType = fnType.In(fixedCount).Elem();
|
|
1778
|
+
const variadicValues = args.slice(fixedCount);
|
|
1779
|
+
for (let i = 0; i < variadicValues.length; i++) {
|
|
1780
|
+
const value = variadicValues[i];
|
|
1781
|
+
if (!value.IsValid()) {
|
|
1782
|
+
throw new Error(`reflect: ${op} using zero Value argument`);
|
|
1783
|
+
}
|
|
1784
|
+
if (!value.Type().AssignableTo(variadicElemType)) {
|
|
1785
|
+
throw new Error(`reflect: cannot use ${value.Type().String()} as type ${variadicElemType.String()} in ${op}`);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
rawArgs.push($.arrayToSlice(variadicValues.map((value) => value.Interface())));
|
|
1789
|
+
return rawArgs;
|
|
1790
|
+
}
|
|
1791
|
+
function reflectCallSliceRawArgs(fnType, args) {
|
|
1792
|
+
if (!fnType.IsVariadic()) {
|
|
1793
|
+
throw new Error('reflect: CallSlice of non-variadic function');
|
|
1794
|
+
}
|
|
1795
|
+
const expected = fnType.NumIn();
|
|
1796
|
+
if (args.length < expected) {
|
|
1797
|
+
throw new Error('reflect: CallSlice with too few input arguments');
|
|
1798
|
+
}
|
|
1799
|
+
if (args.length > expected) {
|
|
1800
|
+
throw new Error('reflect: CallSlice with too many input arguments');
|
|
1801
|
+
}
|
|
1802
|
+
return args.map((arg, index) => reflectCallValueInterface('CallSlice', arg, fnType.In(index), index));
|
|
1803
|
+
}
|
|
1804
|
+
function reflectCallValueInterface(op, value, target, _index) {
|
|
1805
|
+
if (!value.IsValid()) {
|
|
1806
|
+
throw new Error(`reflect: ${op} using zero Value argument`);
|
|
1807
|
+
}
|
|
1808
|
+
if (!value.Type().AssignableTo(target)) {
|
|
1809
|
+
throw new Error(`reflect: ${op} using ${value.Type().String()} as type ${target.String()}`);
|
|
1810
|
+
}
|
|
1811
|
+
return value.Interface();
|
|
1812
|
+
}
|
|
1813
|
+
function validateReflectCallInputCount(fnType, actual) {
|
|
1814
|
+
const expected = fnType.NumIn();
|
|
1815
|
+
if (actual !== expected) {
|
|
1816
|
+
throw new Error(`reflect: Call with ${actual} input arguments for function with ${expected} inputs`);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
function normalizeReflectCallResults(fnType, result) {
|
|
1820
|
+
const expected = fnType.NumOut();
|
|
1821
|
+
if (expected === 0) {
|
|
1822
|
+
if (result !== undefined) {
|
|
1823
|
+
throw new Error('reflect: Call returned 1 results for function with 0 outputs');
|
|
1824
|
+
}
|
|
1825
|
+
return $.makeSlice(0);
|
|
1826
|
+
}
|
|
1827
|
+
if (expected === 1) {
|
|
1828
|
+
return $.arrayToSlice([new Value(result, fnType.Out(0))]);
|
|
1829
|
+
}
|
|
1830
|
+
if (!globalThis.Array.isArray(result)) {
|
|
1831
|
+
throw new Error(`reflect: Call returned 1 results for function with ${expected} outputs`);
|
|
1832
|
+
}
|
|
1833
|
+
if (result.length !== expected) {
|
|
1834
|
+
throw new Error(`reflect: Call returned ${result.length} results for function with ${expected} outputs`);
|
|
1835
|
+
}
|
|
1836
|
+
return $.arrayToSlice(result.map((value, index) => new Value(value, fnType.Out(index))));
|
|
1837
|
+
}
|
|
1838
|
+
export function MakeFunc(typ, fn) {
|
|
1839
|
+
if (!typ || typ.Kind() !== Func) {
|
|
1840
|
+
throw new Error('reflect: call of MakeFunc with non-Func type');
|
|
1841
|
+
}
|
|
1842
|
+
if (typeof fn !== 'function') {
|
|
1843
|
+
throw new Error('reflect.MakeFunc: nil implementation');
|
|
1844
|
+
}
|
|
1845
|
+
const typeInfo = functionTypeInfoFromType(typ);
|
|
1846
|
+
const wrapper = $.functionValue(async (...rawArgs) => {
|
|
1847
|
+
const args = makeFuncArgs(typ, rawArgs);
|
|
1848
|
+
const resultValues = $.asArray(await fn($.arrayToSlice(args)));
|
|
1849
|
+
validateMakeFuncResults(typ, resultValues);
|
|
1850
|
+
if (typ.NumOut() === 0) {
|
|
1851
|
+
return undefined;
|
|
1852
|
+
}
|
|
1853
|
+
if (typ.NumOut() === 1) {
|
|
1854
|
+
return makeFuncReturnInterface(resultValues[0], typ.Out(0));
|
|
1855
|
+
}
|
|
1856
|
+
return resultValues.map((value, index) => makeFuncReturnInterface(value, typ.Out(index)));
|
|
1857
|
+
}, typeInfo);
|
|
1858
|
+
return new Value(wrapper, typ);
|
|
1859
|
+
}
|
|
1860
|
+
function makeFuncArgs(typ, rawArgs) {
|
|
1861
|
+
validateReflectCallInputCount(typ, rawArgs.length);
|
|
1862
|
+
return rawArgs.map((arg, index) => {
|
|
1863
|
+
const value = ValueOf(arg);
|
|
1864
|
+
const target = typ.In(index);
|
|
1865
|
+
if (!value.Type().AssignableTo(target)) {
|
|
1866
|
+
throw new Error(`reflect.MakeFunc: cannot use ${value.Type().String()} as type ${target.String()} in argument ${index}`);
|
|
1867
|
+
}
|
|
1868
|
+
return value;
|
|
1869
|
+
});
|
|
1870
|
+
}
|
|
1871
|
+
function validateMakeFuncResults(typ, resultValues) {
|
|
1872
|
+
const expected = typ.NumOut();
|
|
1873
|
+
if (resultValues.length !== expected) {
|
|
1874
|
+
throw new Error(`reflect.MakeFunc: returned ${resultValues.length} results for function with ${expected} outputs`);
|
|
1875
|
+
}
|
|
1876
|
+
for (let i = 0; i < resultValues.length; i++) {
|
|
1877
|
+
const result = resultValues[i];
|
|
1878
|
+
if (!result.IsValid()) {
|
|
1879
|
+
throw new Error(`reflect.MakeFunc: returned zero Value for result ${i}`);
|
|
1880
|
+
}
|
|
1881
|
+
const target = typ.Out(i);
|
|
1882
|
+
if (!result.Type().AssignableTo(target)) {
|
|
1883
|
+
throw new Error(`reflect.MakeFunc: cannot use ${result.Type().String()} as type ${target.String()} in result ${i}`);
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
function makeFuncReturnInterface(value, target) {
|
|
1888
|
+
const raw = value.Interface();
|
|
1889
|
+
if (target.Kind() === Interface) {
|
|
1890
|
+
return raw;
|
|
1891
|
+
}
|
|
1892
|
+
return unwrapGoInterfaceBox(raw);
|
|
1893
|
+
}
|
|
1894
|
+
function unwrapGoInterfaceBox(value) {
|
|
1895
|
+
if (value !== null &&
|
|
1896
|
+
value !== undefined &&
|
|
1897
|
+
typeof value === 'object' &&
|
|
1898
|
+
'__goValue' in value) {
|
|
1899
|
+
return value.__goValue;
|
|
1900
|
+
}
|
|
1901
|
+
return value;
|
|
1902
|
+
}
|
|
1424
1903
|
// Map type implementation
|
|
1425
1904
|
class MapType {
|
|
1426
1905
|
_keyType;
|
|
@@ -1447,6 +1926,21 @@ class MapType {
|
|
|
1447
1926
|
NumField() {
|
|
1448
1927
|
return 0;
|
|
1449
1928
|
}
|
|
1929
|
+
NumIn() {
|
|
1930
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
1931
|
+
}
|
|
1932
|
+
In(_i) {
|
|
1933
|
+
return nonFunctionTypePanic('In', this);
|
|
1934
|
+
}
|
|
1935
|
+
NumOut() {
|
|
1936
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
1937
|
+
}
|
|
1938
|
+
Out(_i) {
|
|
1939
|
+
return nonFunctionTypePanic('Out', this);
|
|
1940
|
+
}
|
|
1941
|
+
IsVariadic() {
|
|
1942
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
1943
|
+
}
|
|
1450
1944
|
Key() {
|
|
1451
1945
|
return this._keyType;
|
|
1452
1946
|
}
|
|
@@ -1473,7 +1967,7 @@ class MapType {
|
|
|
1473
1967
|
if (u.Kind() !== Interface) {
|
|
1474
1968
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1475
1969
|
}
|
|
1476
|
-
return
|
|
1970
|
+
return typeImplementsInterface(this, u);
|
|
1477
1971
|
}
|
|
1478
1972
|
AssignableTo(u) {
|
|
1479
1973
|
return typeAssignableTo(this, u);
|
|
@@ -1504,47 +1998,122 @@ class MapType {
|
|
|
1504
1998
|
}
|
|
1505
1999
|
}
|
|
1506
2000
|
// Struct type implementation
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
*
|
|
1511
|
-
* @param typeName The name of the type to check (e.g., "main.MyType")
|
|
1512
|
-
* @param interfaceType The interface type that must be implemented
|
|
1513
|
-
* @returns True if the type implements the interface, false otherwise
|
|
1514
|
-
*/
|
|
1515
|
-
function typeImplementsInterface(typeName, interfaceType) {
|
|
1516
|
-
// Get the interface name and look it up in the type registry
|
|
1517
|
-
const interfaceName = interfaceType instanceof InterfaceType ?
|
|
1518
|
-
interfaceType.registeredName() || interfaceType.String()
|
|
1519
|
-
: interfaceType.String();
|
|
1520
|
-
const interfaceTypeInfo = builtinGetTypeByName(interfaceName);
|
|
1521
|
-
if (!interfaceTypeInfo || !isInterfaceTypeInfo(interfaceTypeInfo)) {
|
|
1522
|
-
return false;
|
|
2001
|
+
function typeImplementsInterface(t, interfaceType) {
|
|
2002
|
+
if (interfaceType.Kind() !== Interface) {
|
|
2003
|
+
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1523
2004
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
2005
|
+
const requiredMethods = typeMethods(interfaceType);
|
|
2006
|
+
if (requiredMethods.length === 0) {
|
|
2007
|
+
return true;
|
|
2008
|
+
}
|
|
2009
|
+
const methods = typeMethods(t);
|
|
2010
|
+
return requiredMethods.every((requiredMethod) => {
|
|
2011
|
+
const method = methods.find((candidate) => candidate.name === requiredMethod.name);
|
|
2012
|
+
return (method !== undefined && methodSignatureIdentical(method, requiredMethod));
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
function methodSignatureIdentical(actual, required) {
|
|
2016
|
+
return (methodArgListIdentical(actual.args, required.args) &&
|
|
2017
|
+
methodArgListIdentical(actual.returns, required.returns));
|
|
2018
|
+
}
|
|
2019
|
+
function methodArgListIdentical(actual, required) {
|
|
2020
|
+
if (actual.length !== required.length) {
|
|
1527
2021
|
return false;
|
|
1528
2022
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
2023
|
+
return actual.every((arg, index) => methodArgIdentityKey(arg) === methodArgIdentityKey(required[index]));
|
|
2024
|
+
}
|
|
2025
|
+
function methodArgIdentityKey(arg) {
|
|
2026
|
+
return typeInfoIdentityKey(arg.type, new Set());
|
|
2027
|
+
}
|
|
2028
|
+
function methodSignatureIdentityKey(method) {
|
|
2029
|
+
const args = method.args.map(methodArgIdentityKey).join(',');
|
|
2030
|
+
const returns = method.returns.map(methodArgIdentityKey).join(',');
|
|
2031
|
+
return `${method.name}(${args})(${returns})`;
|
|
2032
|
+
}
|
|
2033
|
+
function mergeMethodSignatureList(existing, incoming) {
|
|
2034
|
+
if (incoming.length === 0) {
|
|
2035
|
+
return existing;
|
|
2036
|
+
}
|
|
2037
|
+
const merged = [...existing];
|
|
2038
|
+
for (const method of incoming) {
|
|
2039
|
+
const existingIndex = merged.findIndex((candidate) => candidate.name === method.name);
|
|
2040
|
+
if (existingIndex === -1) {
|
|
2041
|
+
merged.push(method);
|
|
2042
|
+
continue;
|
|
1537
2043
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
2044
|
+
if (methodSignatureIdentityKey(merged[existingIndex]) !==
|
|
2045
|
+
methodSignatureIdentityKey(method)) {
|
|
2046
|
+
merged[existingIndex] = method;
|
|
1541
2047
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
2048
|
+
}
|
|
2049
|
+
return merged.sort((left, right) => left.name.localeCompare(right.name));
|
|
2050
|
+
}
|
|
2051
|
+
function typeInfoIdentityKey(info, seen) {
|
|
2052
|
+
if (typeof info === 'string') {
|
|
2053
|
+
const registered = builtinGetTypeByName(info);
|
|
2054
|
+
if (!registered) {
|
|
2055
|
+
return `named:${info}`;
|
|
2056
|
+
}
|
|
2057
|
+
const registeredName = registered.name ?? info;
|
|
2058
|
+
if (registeredName !== '') {
|
|
2059
|
+
return `named:${registeredName}`;
|
|
1544
2060
|
}
|
|
1545
|
-
|
|
2061
|
+
if (seen.has(info)) {
|
|
2062
|
+
return `named:${info}`;
|
|
2063
|
+
}
|
|
2064
|
+
seen.add(info);
|
|
2065
|
+
const key = typeInfoIdentityKey(registered, seen);
|
|
2066
|
+
seen.delete(info);
|
|
2067
|
+
return key;
|
|
2068
|
+
}
|
|
2069
|
+
switch (info.kind) {
|
|
2070
|
+
case $.TypeKind.Basic:
|
|
2071
|
+
if (info.typeName) {
|
|
2072
|
+
return `named:${info.typeName}`;
|
|
2073
|
+
}
|
|
2074
|
+
return `basic:${info.name ?? 'unknown'}`;
|
|
2075
|
+
case $.TypeKind.Interface:
|
|
2076
|
+
if (info.name) {
|
|
2077
|
+
return `named:${info.name}`;
|
|
2078
|
+
}
|
|
2079
|
+
return `interface:${(info.methods ?? [])
|
|
2080
|
+
.map(methodSignatureIdentityKey)
|
|
2081
|
+
.join('|')}`;
|
|
2082
|
+
case $.TypeKind.Struct:
|
|
2083
|
+
if (info.name) {
|
|
2084
|
+
return `named:${info.name}`;
|
|
2085
|
+
}
|
|
2086
|
+
return `struct:${(info.fields ?? [])
|
|
2087
|
+
.map((field) => [
|
|
2088
|
+
field.name,
|
|
2089
|
+
field.pkgPath ?? '',
|
|
2090
|
+
field.tag ?? '',
|
|
2091
|
+
field.anonymous === true ? 'anonymous' : 'named',
|
|
2092
|
+
typeInfoIdentityKey(field.type, seen),
|
|
2093
|
+
].join('\u0000'))
|
|
2094
|
+
.join('\u0001')}`;
|
|
2095
|
+
case $.TypeKind.Pointer:
|
|
2096
|
+
return `ptr:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
2097
|
+
case $.TypeKind.Slice:
|
|
2098
|
+
return `slice:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
2099
|
+
case $.TypeKind.Array:
|
|
2100
|
+
return `array:${info.length}:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
2101
|
+
case $.TypeKind.Map:
|
|
2102
|
+
return `map:${typeInfoIdentityKey(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
2103
|
+
case $.TypeKind.Function:
|
|
2104
|
+
if (info.name) {
|
|
2105
|
+
return `named:${info.name}`;
|
|
2106
|
+
}
|
|
2107
|
+
return `func:${info.isVariadic === true}:${(info.params ?? [])
|
|
2108
|
+
.map((param) => typeInfoIdentityKey(param, seen))
|
|
2109
|
+
.join(',')}:${(info.results ?? [])
|
|
2110
|
+
.map((result) => typeInfoIdentityKey(result, seen))
|
|
2111
|
+
.join(',')}`;
|
|
2112
|
+
case $.TypeKind.Channel:
|
|
2113
|
+
return `chan:${info.direction ?? 'both'}:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
2114
|
+
default:
|
|
2115
|
+
return 'unknown';
|
|
1546
2116
|
}
|
|
1547
|
-
return true;
|
|
1548
2117
|
}
|
|
1549
2118
|
function typeFieldByName(t, name) {
|
|
1550
2119
|
return typeFieldByNameFunc(t, (fieldName) => fieldName === name);
|
|
@@ -1553,14 +2122,62 @@ function typeFieldByNameFunc(t, match) {
|
|
|
1553
2122
|
if (t.Kind() !== Struct) {
|
|
1554
2123
|
throw new Error('reflect: FieldByName of non-struct type');
|
|
1555
2124
|
}
|
|
1556
|
-
for (
|
|
1557
|
-
const field = t.Field(i);
|
|
2125
|
+
for (const field of visibleStructFields(t)) {
|
|
1558
2126
|
if (match(field.Name)) {
|
|
1559
2127
|
return [field, true];
|
|
1560
2128
|
}
|
|
1561
2129
|
}
|
|
1562
2130
|
return [new StructField(), false];
|
|
1563
2131
|
}
|
|
2132
|
+
export function visibleStructFields(t) {
|
|
2133
|
+
const fields = [];
|
|
2134
|
+
const byName = new globalThis.Map();
|
|
2135
|
+
const visiting = new Set();
|
|
2136
|
+
const index = [];
|
|
2137
|
+
const walk = (typ) => {
|
|
2138
|
+
if (visiting.has(typ)) {
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2141
|
+
visiting.add(typ);
|
|
2142
|
+
for (let i = 0; i < typ.NumField(); i++) {
|
|
2143
|
+
const field = typ.Field(i).clone();
|
|
2144
|
+
index.push(i);
|
|
2145
|
+
let add = true;
|
|
2146
|
+
const oldIndex = byName.get(field.Name);
|
|
2147
|
+
if (oldIndex !== undefined) {
|
|
2148
|
+
const old = fields[oldIndex];
|
|
2149
|
+
if (index.length === old.Index.length) {
|
|
2150
|
+
old.Name = '';
|
|
2151
|
+
add = false;
|
|
2152
|
+
}
|
|
2153
|
+
else if (index.length < old.Index.length) {
|
|
2154
|
+
old.Name = '';
|
|
2155
|
+
}
|
|
2156
|
+
else {
|
|
2157
|
+
add = false;
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
if (add) {
|
|
2161
|
+
field.Index = [...index];
|
|
2162
|
+
byName.set(field.Name, fields.length);
|
|
2163
|
+
fields.push(field);
|
|
2164
|
+
}
|
|
2165
|
+
if (field.Anonymous) {
|
|
2166
|
+
let fieldType = field.Type;
|
|
2167
|
+
if (fieldType.Kind() === Ptr) {
|
|
2168
|
+
fieldType = fieldType.Elem();
|
|
2169
|
+
}
|
|
2170
|
+
if (fieldType.Kind() === Struct) {
|
|
2171
|
+
walk(fieldType);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
index.pop();
|
|
2175
|
+
}
|
|
2176
|
+
visiting.delete(typ);
|
|
2177
|
+
};
|
|
2178
|
+
walk(t);
|
|
2179
|
+
return fields.filter((field) => field.Name !== '');
|
|
2180
|
+
}
|
|
1564
2181
|
function zeroMethod() {
|
|
1565
2182
|
return {
|
|
1566
2183
|
Name: '',
|
|
@@ -1569,16 +2186,50 @@ function zeroMethod() {
|
|
|
1569
2186
|
Index: 0,
|
|
1570
2187
|
};
|
|
1571
2188
|
}
|
|
1572
|
-
function methodFromSignature(signature, index) {
|
|
2189
|
+
function methodFromSignature(signature, index, receiver) {
|
|
1573
2190
|
return {
|
|
1574
2191
|
Name: signature.name,
|
|
1575
|
-
Type:
|
|
2192
|
+
Type: methodTypeFromSignature(signature, receiver, receiver.Kind() !== Interface),
|
|
1576
2193
|
Func: () => undefined,
|
|
1577
2194
|
Index: index,
|
|
1578
2195
|
};
|
|
1579
2196
|
}
|
|
2197
|
+
function methodTypeFromSignature(signature, receiver, includeReceiver) {
|
|
2198
|
+
const params = signature.args.map(methodArgType);
|
|
2199
|
+
if (includeReceiver) {
|
|
2200
|
+
params.unshift(receiver);
|
|
2201
|
+
}
|
|
2202
|
+
return new FunctionType({
|
|
2203
|
+
params,
|
|
2204
|
+
results: signature.returns.map(methodArgType),
|
|
2205
|
+
});
|
|
2206
|
+
}
|
|
2207
|
+
function methodArgType(arg) {
|
|
2208
|
+
return typeFromTypeInfoWithSeen(arg.type, new Set());
|
|
2209
|
+
}
|
|
1580
2210
|
function typeMethods(t) {
|
|
1581
|
-
|
|
2211
|
+
let typeInfo = builtinGetTypeByName(t.String());
|
|
2212
|
+
if (!typeInfo && t.Kind() === Ptr) {
|
|
2213
|
+
typeInfo = builtinGetTypeByName(t.Elem().String());
|
|
2214
|
+
}
|
|
2215
|
+
if (!typeInfo && t instanceof InterfaceType) {
|
|
2216
|
+
const registeredName = t.registeredName();
|
|
2217
|
+
if (registeredName) {
|
|
2218
|
+
typeInfo = builtinGetTypeByName(registeredName);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
if (!typeInfo && t instanceof InterfaceType) {
|
|
2222
|
+
return t.methodSignatures();
|
|
2223
|
+
}
|
|
2224
|
+
if (!typeInfo && t instanceof PointerType) {
|
|
2225
|
+
return mergeMethodSignatureList(typeMethods(t.Elem()), t.methodSignatures());
|
|
2226
|
+
}
|
|
2227
|
+
if (!typeInfo && t instanceof BasicType) {
|
|
2228
|
+
return t.methodSignatures();
|
|
2229
|
+
}
|
|
2230
|
+
if (!typeInfo && t instanceof FunctionType) {
|
|
2231
|
+
return t.methodSignatures();
|
|
2232
|
+
}
|
|
1582
2233
|
if (!typeInfo) {
|
|
1583
2234
|
return [];
|
|
1584
2235
|
}
|
|
@@ -1587,29 +2238,98 @@ function typeMethods(t) {
|
|
|
1587
2238
|
}
|
|
1588
2239
|
return [];
|
|
1589
2240
|
}
|
|
1590
|
-
function
|
|
2241
|
+
function methodSignatureByName(t, name) {
|
|
1591
2242
|
const methods = typeMethods(t);
|
|
1592
2243
|
const index = methods.findIndex((method) => method.name === name);
|
|
1593
2244
|
if (index === -1) {
|
|
2245
|
+
return [undefined, -1];
|
|
2246
|
+
}
|
|
2247
|
+
return [methods[index], index];
|
|
2248
|
+
}
|
|
2249
|
+
function typeMethodByName(t, name) {
|
|
2250
|
+
const [signature, index] = methodSignatureByName(t, name);
|
|
2251
|
+
if (!signature) {
|
|
1594
2252
|
return [zeroMethod(), false];
|
|
1595
2253
|
}
|
|
1596
|
-
return [methodFromSignature(
|
|
2254
|
+
return [methodFromSignature(signature, index, t), true];
|
|
1597
2255
|
}
|
|
1598
2256
|
function typeAssignableTo(t, u) {
|
|
1599
2257
|
if (u === null) {
|
|
1600
2258
|
return false;
|
|
1601
2259
|
}
|
|
1602
|
-
|
|
2260
|
+
if (typeIdentityKey(t) === typeIdentityKey(u)) {
|
|
2261
|
+
return true;
|
|
2262
|
+
}
|
|
2263
|
+
if ((!typeIsNamed(t) || !typeIsNamed(u)) &&
|
|
2264
|
+
typeUnderlyingIdentityKey(t) === typeUnderlyingIdentityKey(u)) {
|
|
2265
|
+
return true;
|
|
2266
|
+
}
|
|
2267
|
+
if (u.Kind() !== Interface) {
|
|
2268
|
+
return false;
|
|
2269
|
+
}
|
|
2270
|
+
return t.Implements(u);
|
|
2271
|
+
}
|
|
2272
|
+
export function structFieldStorageKey(t, i) {
|
|
2273
|
+
if (t instanceof StructType) {
|
|
2274
|
+
return t.fieldKey(i);
|
|
2275
|
+
}
|
|
2276
|
+
return t.Field(i).Name;
|
|
2277
|
+
}
|
|
2278
|
+
function typeAlignment(typ) {
|
|
2279
|
+
switch (typ.Kind()) {
|
|
2280
|
+
case Bool:
|
|
2281
|
+
case Int8:
|
|
2282
|
+
case Uint8:
|
|
2283
|
+
return 1;
|
|
2284
|
+
case Int16:
|
|
2285
|
+
case Uint16:
|
|
2286
|
+
return 2;
|
|
2287
|
+
case Int32:
|
|
2288
|
+
case Uint32:
|
|
2289
|
+
case Float32:
|
|
2290
|
+
case Complex64:
|
|
2291
|
+
return 4;
|
|
2292
|
+
case Array:
|
|
2293
|
+
return typeAlignment(typ.Elem());
|
|
2294
|
+
case Struct: {
|
|
2295
|
+
let align = 1;
|
|
2296
|
+
for (let i = 0; i < typ.NumField(); i++) {
|
|
2297
|
+
align = Math.max(align, typeAlignment(typ.Field(i).Type));
|
|
2298
|
+
}
|
|
2299
|
+
return align;
|
|
2300
|
+
}
|
|
2301
|
+
default:
|
|
2302
|
+
return 8;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
function alignOffset(offset, alignment) {
|
|
2306
|
+
if (alignment <= 1) {
|
|
2307
|
+
return offset;
|
|
2308
|
+
}
|
|
2309
|
+
return Math.ceil(offset / alignment) * alignment;
|
|
2310
|
+
}
|
|
2311
|
+
function structDescriptorSize(fields) {
|
|
2312
|
+
let size = 0;
|
|
2313
|
+
let alignment = 1;
|
|
2314
|
+
for (const field of fields) {
|
|
2315
|
+
alignment = Math.max(alignment, typeAlignment(field.type));
|
|
2316
|
+
size = Math.max(size, field.offset + field.type.Size());
|
|
2317
|
+
}
|
|
2318
|
+
return alignOffset(size, alignment);
|
|
1603
2319
|
}
|
|
1604
2320
|
class StructType {
|
|
1605
2321
|
_name;
|
|
1606
2322
|
_fields;
|
|
1607
|
-
|
|
2323
|
+
_pkgPath;
|
|
2324
|
+
_string;
|
|
2325
|
+
constructor(_name, _fields = [], _pkgPath = '', _string = _name) {
|
|
1608
2326
|
this._name = _name;
|
|
1609
2327
|
this._fields = _fields;
|
|
2328
|
+
this._pkgPath = _pkgPath;
|
|
2329
|
+
this._string = _string;
|
|
1610
2330
|
}
|
|
1611
2331
|
String() {
|
|
1612
|
-
return this.
|
|
2332
|
+
return this._string;
|
|
1613
2333
|
}
|
|
1614
2334
|
Kind() {
|
|
1615
2335
|
return Struct;
|
|
@@ -1618,8 +2338,7 @@ class StructType {
|
|
|
1618
2338
|
return this._fields.every((field) => field.type.Comparable());
|
|
1619
2339
|
}
|
|
1620
2340
|
Size() {
|
|
1621
|
-
|
|
1622
|
-
return this._fields.reduce((sum, field) => sum + field.type.Size(), 0);
|
|
2341
|
+
return structDescriptorSize(this._fields);
|
|
1623
2342
|
}
|
|
1624
2343
|
Elem() {
|
|
1625
2344
|
throw new Error('reflect: Elem of invalid type');
|
|
@@ -1627,7 +2346,28 @@ class StructType {
|
|
|
1627
2346
|
NumField() {
|
|
1628
2347
|
return this._fields.length;
|
|
1629
2348
|
}
|
|
2349
|
+
NumIn() {
|
|
2350
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
2351
|
+
}
|
|
2352
|
+
In(_i) {
|
|
2353
|
+
return nonFunctionTypePanic('In', this);
|
|
2354
|
+
}
|
|
2355
|
+
NumOut() {
|
|
2356
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
2357
|
+
}
|
|
2358
|
+
Out(_i) {
|
|
2359
|
+
return nonFunctionTypePanic('Out', this);
|
|
2360
|
+
}
|
|
2361
|
+
IsVariadic() {
|
|
2362
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
2363
|
+
}
|
|
1630
2364
|
PkgPath() {
|
|
2365
|
+
if (this._pkgPath !== '') {
|
|
2366
|
+
return this._pkgPath;
|
|
2367
|
+
}
|
|
2368
|
+
if (this._name === '') {
|
|
2369
|
+
return '';
|
|
2370
|
+
}
|
|
1631
2371
|
// Extract package path from full type name (e.g., "main.Person" -> "main")
|
|
1632
2372
|
const dotIndex = this._name.lastIndexOf('.');
|
|
1633
2373
|
if (dotIndex > 0) {
|
|
@@ -1636,6 +2376,9 @@ class StructType {
|
|
|
1636
2376
|
return '';
|
|
1637
2377
|
}
|
|
1638
2378
|
Name() {
|
|
2379
|
+
if (this._name === '') {
|
|
2380
|
+
return '';
|
|
2381
|
+
}
|
|
1639
2382
|
// Extract type name from full type name (e.g., "main.Person" -> "Person")
|
|
1640
2383
|
const dotIndex = this._name.lastIndexOf('.');
|
|
1641
2384
|
if (dotIndex >= 0) {
|
|
@@ -1650,12 +2393,56 @@ class StructType {
|
|
|
1650
2393
|
const f = this._fields[i];
|
|
1651
2394
|
return new StructField({
|
|
1652
2395
|
Name: f.name,
|
|
1653
|
-
PkgPath:
|
|
2396
|
+
PkgPath: f.pkgPath,
|
|
1654
2397
|
Type: f.type,
|
|
1655
2398
|
Tag: f.tag ? new StructTag(f.tag) : undefined,
|
|
1656
|
-
|
|
2399
|
+
Offset: f.offset,
|
|
2400
|
+
Index: [...f.index],
|
|
2401
|
+
Anonymous: f.anonymous,
|
|
1657
2402
|
});
|
|
1658
2403
|
}
|
|
2404
|
+
fieldKey(i) {
|
|
2405
|
+
if (i < 0 || i >= this.NumField()) {
|
|
2406
|
+
throw new Error(`reflect: Field index out of range [${i}] with length ${this.NumField()}`);
|
|
2407
|
+
}
|
|
2408
|
+
return this._fields[i].key;
|
|
2409
|
+
}
|
|
2410
|
+
descriptors() {
|
|
2411
|
+
return this._fields.map((field) => ({
|
|
2412
|
+
...field,
|
|
2413
|
+
index: [...field.index],
|
|
2414
|
+
}));
|
|
2415
|
+
}
|
|
2416
|
+
replaceDescriptors(fields) {
|
|
2417
|
+
this._fields = fields;
|
|
2418
|
+
}
|
|
2419
|
+
identityKey(seen) {
|
|
2420
|
+
if (this._name !== '') {
|
|
2421
|
+
return `struct:${this._name}`;
|
|
2422
|
+
}
|
|
2423
|
+
const fields = this._fields
|
|
2424
|
+
.map((field) => [
|
|
2425
|
+
field.name,
|
|
2426
|
+
field.pkgPath,
|
|
2427
|
+
field.tag ?? '',
|
|
2428
|
+
field.anonymous ? 'anonymous' : 'named',
|
|
2429
|
+
typeIdentityKey(field.type, seen),
|
|
2430
|
+
].join('\u0000'))
|
|
2431
|
+
.join('\u0001');
|
|
2432
|
+
return `struct:${this._pkgPath}:${this._name}:${fields}`;
|
|
2433
|
+
}
|
|
2434
|
+
underlyingIdentityKey(seen) {
|
|
2435
|
+
const fields = this._fields
|
|
2436
|
+
.map((field) => [
|
|
2437
|
+
field.name,
|
|
2438
|
+
field.pkgPath,
|
|
2439
|
+
field.tag ?? '',
|
|
2440
|
+
field.anonymous ? 'anonymous' : 'named',
|
|
2441
|
+
typeIdentityKey(field.type, seen),
|
|
2442
|
+
].join('\u0000'))
|
|
2443
|
+
.join('\u0001');
|
|
2444
|
+
return `struct:${fields}`;
|
|
2445
|
+
}
|
|
1659
2446
|
FieldByName(name) {
|
|
1660
2447
|
return typeFieldByName(this, name);
|
|
1661
2448
|
}
|
|
@@ -1672,7 +2459,7 @@ class StructType {
|
|
|
1672
2459
|
if (u.Kind() !== Interface) {
|
|
1673
2460
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1674
2461
|
}
|
|
1675
|
-
return typeImplementsInterface(this
|
|
2462
|
+
return typeImplementsInterface(this, u);
|
|
1676
2463
|
}
|
|
1677
2464
|
AssignableTo(u) {
|
|
1678
2465
|
return typeAssignableTo(this, u);
|
|
@@ -1701,32 +2488,9 @@ class StructType {
|
|
|
1701
2488
|
Bits() {
|
|
1702
2489
|
throw new Error('reflect: call of reflect.Type.Bits on struct Type');
|
|
1703
2490
|
}
|
|
1704
|
-
static createTypeFromFieldInfo(ti) {
|
|
2491
|
+
static createTypeFromFieldInfo(ti, seen = new Set()) {
|
|
1705
2492
|
if (typeof ti === 'string') {
|
|
1706
|
-
|
|
1707
|
-
case 'string':
|
|
1708
|
-
return new BasicType(String, ti, 16);
|
|
1709
|
-
case 'int':
|
|
1710
|
-
case 'int32':
|
|
1711
|
-
case 'int64':
|
|
1712
|
-
case 'number':
|
|
1713
|
-
return new BasicType(Int, ti === 'number' ? 'int' : ti, 8);
|
|
1714
|
-
case 'bool':
|
|
1715
|
-
case 'boolean':
|
|
1716
|
-
return new BasicType(Bool, 'bool', 1);
|
|
1717
|
-
case 'float64':
|
|
1718
|
-
return new BasicType(Float64, ti, 8);
|
|
1719
|
-
case 'complex64':
|
|
1720
|
-
return new BasicType(Complex64, ti, 8);
|
|
1721
|
-
case 'complex128':
|
|
1722
|
-
return new BasicType(Complex128, ti, 16);
|
|
1723
|
-
case 'uint':
|
|
1724
|
-
case 'uint32':
|
|
1725
|
-
case 'uint64':
|
|
1726
|
-
return new BasicType(Uint, ti, 8);
|
|
1727
|
-
default:
|
|
1728
|
-
return new BasicType(Invalid, ti, 8);
|
|
1729
|
-
}
|
|
2493
|
+
return basicTypeFromName(ti === 'number' ? 'int' : ti);
|
|
1730
2494
|
}
|
|
1731
2495
|
else if (ti && ti.kind) {
|
|
1732
2496
|
// Handle TypeInfo objects from the builtin type system
|
|
@@ -1734,41 +2498,24 @@ class StructType {
|
|
|
1734
2498
|
const typeName = ti.typeName || '';
|
|
1735
2499
|
switch (ti.kind) {
|
|
1736
2500
|
case 'basic':
|
|
1737
|
-
|
|
1738
|
-
switch (name) {
|
|
1739
|
-
case 'string':
|
|
1740
|
-
return new BasicType(String, 'string', 16, typeName);
|
|
1741
|
-
case 'number':
|
|
1742
|
-
case 'int':
|
|
1743
|
-
case 'int32':
|
|
1744
|
-
case 'int64':
|
|
1745
|
-
return new BasicType(Int, name === 'number' ? 'int' : name, 8, typeName);
|
|
1746
|
-
case 'boolean':
|
|
1747
|
-
case 'bool':
|
|
1748
|
-
return new BasicType(Bool, 'bool', 1, typeName);
|
|
1749
|
-
case 'float64':
|
|
1750
|
-
return new BasicType(Float64, 'float64', 8, typeName);
|
|
1751
|
-
case 'complex64':
|
|
1752
|
-
return new BasicType(Complex64, 'complex64', 8, typeName);
|
|
1753
|
-
case 'complex128':
|
|
1754
|
-
return new BasicType(Complex128, 'complex128', 16, typeName);
|
|
1755
|
-
default:
|
|
1756
|
-
return new BasicType(Invalid, name, 8, typeName);
|
|
1757
|
-
}
|
|
2501
|
+
return basicTypeFromName(name === 'number' ? 'int' : name, typeName);
|
|
1758
2502
|
case 'slice':
|
|
1759
2503
|
if (ti.elemType) {
|
|
1760
|
-
return new SliceType(StructType.createTypeFromFieldInfo(ti.elemType));
|
|
2504
|
+
return new SliceType(StructType.createTypeFromFieldInfo(ti.elemType, seen));
|
|
1761
2505
|
}
|
|
1762
2506
|
return new SliceType(new BasicType(Invalid, 'unknown', 8));
|
|
1763
2507
|
case 'pointer':
|
|
1764
2508
|
if (ti.elemType) {
|
|
1765
|
-
return new PointerType(StructType.createTypeFromFieldInfo(ti.elemType));
|
|
2509
|
+
return new PointerType(StructType.createTypeFromFieldInfo(ti.elemType, seen));
|
|
1766
2510
|
}
|
|
1767
2511
|
return new PointerType(new BasicType(Invalid, 'unknown', 8));
|
|
1768
2512
|
case 'interface':
|
|
1769
|
-
return
|
|
1770
|
-
case 'struct':
|
|
1771
|
-
|
|
2513
|
+
return interfaceTypeFromInfo(ti, seen);
|
|
2514
|
+
case 'struct': {
|
|
2515
|
+
const structName = ti.name ?? '';
|
|
2516
|
+
const fields = structFieldsFromTypeInfo(ti, seen);
|
|
2517
|
+
return new StructType(structName, fields, '', structName === '' ? structTypeString(fields) : structName);
|
|
2518
|
+
}
|
|
1772
2519
|
default:
|
|
1773
2520
|
return new BasicType(Invalid, name, 8);
|
|
1774
2521
|
}
|
|
@@ -1776,18 +2523,60 @@ class StructType {
|
|
|
1776
2523
|
return new BasicType(Invalid, 'unknown', 8);
|
|
1777
2524
|
}
|
|
1778
2525
|
}
|
|
1779
|
-
function
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
return
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
2526
|
+
function basicTypeFromName(name, typeName = '') {
|
|
2527
|
+
switch (name) {
|
|
2528
|
+
case 'string':
|
|
2529
|
+
return new BasicType(String, 'string', 16, typeName);
|
|
2530
|
+
case 'bool':
|
|
2531
|
+
case 'boolean':
|
|
2532
|
+
return new BasicType(Bool, 'bool', 1, typeName);
|
|
2533
|
+
case 'int':
|
|
2534
|
+
return new BasicType(Int, 'int', 8, typeName);
|
|
2535
|
+
case 'int8':
|
|
2536
|
+
return new BasicType(Int8, 'int8', 1, typeName);
|
|
2537
|
+
case 'int16':
|
|
2538
|
+
return new BasicType(Int16, 'int16', 2, typeName);
|
|
2539
|
+
case 'int32':
|
|
2540
|
+
return new BasicType(Int32, 'int32', 4, typeName);
|
|
2541
|
+
case 'int64':
|
|
2542
|
+
return new BasicType(Int64, 'int64', 8, typeName);
|
|
2543
|
+
case 'uint':
|
|
2544
|
+
return new BasicType(Uint, 'uint', 8, typeName);
|
|
2545
|
+
case 'uint8':
|
|
2546
|
+
case 'byte':
|
|
2547
|
+
return new BasicType(Uint8, name, 1, typeName);
|
|
2548
|
+
case 'uint16':
|
|
2549
|
+
return new BasicType(Uint16, 'uint16', 2, typeName);
|
|
2550
|
+
case 'uint32':
|
|
2551
|
+
return new BasicType(Uint32, 'uint32', 4, typeName);
|
|
2552
|
+
case 'uint64':
|
|
2553
|
+
return new BasicType(Uint64, 'uint64', 8, typeName);
|
|
2554
|
+
case 'uintptr':
|
|
2555
|
+
return new BasicType(Uintptr, 'uintptr', 8, typeName);
|
|
2556
|
+
case 'float32':
|
|
2557
|
+
return new BasicType(Float32, 'float32', 4, typeName);
|
|
2558
|
+
case 'float64':
|
|
2559
|
+
return new BasicType(Float64, 'float64', 8, typeName);
|
|
2560
|
+
case 'complex64':
|
|
2561
|
+
return new BasicType(Complex64, 'complex64', 8, typeName);
|
|
2562
|
+
case 'complex128':
|
|
2563
|
+
return new BasicType(Complex128, 'complex128', 16, typeName);
|
|
2564
|
+
default:
|
|
2565
|
+
return new BasicType(Invalid, name, 8, typeName);
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
function structFieldsFromTypeInfo(ti, seen = new Set()) {
|
|
2569
|
+
return (ti.fields || []).map((fieldInfo, index) => {
|
|
1788
2570
|
return {
|
|
1789
|
-
name,
|
|
1790
|
-
|
|
2571
|
+
name: fieldInfo.name,
|
|
2572
|
+
key: structFieldRuntimeKey(fieldInfo),
|
|
2573
|
+
type: typeFromTypeInfoWithSeen(fieldInfo.type, seen),
|
|
2574
|
+
tag: fieldInfo.tag,
|
|
2575
|
+
pkgPath: fieldInfo.pkgPath ?? '',
|
|
2576
|
+
anonymous: fieldInfo.anonymous ?? false,
|
|
2577
|
+
index: fieldInfo.index ? [...fieldInfo.index] : [index],
|
|
2578
|
+
offset: fieldInfo.offset ?? index * 8,
|
|
2579
|
+
exported: fieldInfo.exported ?? (fieldInfo.pkgPath ?? '') === '',
|
|
1791
2580
|
};
|
|
1792
2581
|
});
|
|
1793
2582
|
}
|
|
@@ -1827,6 +2616,21 @@ class ChannelType {
|
|
|
1827
2616
|
NumField() {
|
|
1828
2617
|
return 0;
|
|
1829
2618
|
}
|
|
2619
|
+
NumIn() {
|
|
2620
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
2621
|
+
}
|
|
2622
|
+
In(_i) {
|
|
2623
|
+
return nonFunctionTypePanic('In', this);
|
|
2624
|
+
}
|
|
2625
|
+
NumOut() {
|
|
2626
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
2627
|
+
}
|
|
2628
|
+
Out(_i) {
|
|
2629
|
+
return nonFunctionTypePanic('Out', this);
|
|
2630
|
+
}
|
|
2631
|
+
IsVariadic() {
|
|
2632
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
2633
|
+
}
|
|
1830
2634
|
PkgPath() {
|
|
1831
2635
|
return '';
|
|
1832
2636
|
}
|
|
@@ -1853,7 +2657,7 @@ class ChannelType {
|
|
|
1853
2657
|
if (u.Kind() !== Interface) {
|
|
1854
2658
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1855
2659
|
}
|
|
1856
|
-
return
|
|
2660
|
+
return typeImplementsInterface(this, u);
|
|
1857
2661
|
}
|
|
1858
2662
|
AssignableTo(u) {
|
|
1859
2663
|
return typeAssignableTo(this, u);
|
|
@@ -1890,9 +2694,11 @@ class ChannelType {
|
|
|
1890
2694
|
class InterfaceType {
|
|
1891
2695
|
_name;
|
|
1892
2696
|
_registeredName;
|
|
1893
|
-
|
|
2697
|
+
_methods;
|
|
2698
|
+
constructor(_name = 'interface{}', _registeredName, _methods = []) {
|
|
1894
2699
|
this._name = _name;
|
|
1895
2700
|
this._registeredName = _registeredName;
|
|
2701
|
+
this._methods = _methods;
|
|
1896
2702
|
}
|
|
1897
2703
|
String() {
|
|
1898
2704
|
return this._name;
|
|
@@ -1912,6 +2718,21 @@ class InterfaceType {
|
|
|
1912
2718
|
NumField() {
|
|
1913
2719
|
return 0;
|
|
1914
2720
|
}
|
|
2721
|
+
NumIn() {
|
|
2722
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
2723
|
+
}
|
|
2724
|
+
In(_i) {
|
|
2725
|
+
return nonFunctionTypePanic('In', this);
|
|
2726
|
+
}
|
|
2727
|
+
NumOut() {
|
|
2728
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
2729
|
+
}
|
|
2730
|
+
Out(_i) {
|
|
2731
|
+
return nonFunctionTypePanic('Out', this);
|
|
2732
|
+
}
|
|
2733
|
+
IsVariadic() {
|
|
2734
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
2735
|
+
}
|
|
1915
2736
|
PkgPath() {
|
|
1916
2737
|
if (this._name === 'interface{}' || this._name.startsWith('interface {')) {
|
|
1917
2738
|
return '';
|
|
@@ -1944,8 +2765,14 @@ class InterfaceType {
|
|
|
1944
2765
|
Key() {
|
|
1945
2766
|
throw new Error('reflect: Key of non-map type');
|
|
1946
2767
|
}
|
|
1947
|
-
Implements(
|
|
1948
|
-
|
|
2768
|
+
Implements(u) {
|
|
2769
|
+
if (!u) {
|
|
2770
|
+
return false;
|
|
2771
|
+
}
|
|
2772
|
+
if (u.Kind() !== Interface) {
|
|
2773
|
+
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
2774
|
+
}
|
|
2775
|
+
return typeImplementsInterface(this, u);
|
|
1949
2776
|
}
|
|
1950
2777
|
AssignableTo(u) {
|
|
1951
2778
|
return typeAssignableTo(this, u);
|
|
@@ -1977,6 +2804,9 @@ class InterfaceType {
|
|
|
1977
2804
|
registeredName() {
|
|
1978
2805
|
return this._registeredName;
|
|
1979
2806
|
}
|
|
2807
|
+
methodSignatures() {
|
|
2808
|
+
return this._methods;
|
|
2809
|
+
}
|
|
1980
2810
|
}
|
|
1981
2811
|
function getTypeOf(value) {
|
|
1982
2812
|
// Check for typed nil before checking for plain null
|
|
@@ -2018,22 +2848,19 @@ function getTypeOf(value) {
|
|
|
2018
2848
|
if ((typeInfo.kind === 'function' || typeInfo.kind === 'Function') &&
|
|
2019
2849
|
typeInfo.params &&
|
|
2020
2850
|
typeInfo.results) {
|
|
2851
|
+
if (funcWithMeta.__goTypeName && !typeInfo.name) {
|
|
2852
|
+
return functionTypeFromInfo({
|
|
2853
|
+
...typeInfo,
|
|
2854
|
+
name: funcWithMeta.__goTypeName,
|
|
2855
|
+
});
|
|
2856
|
+
}
|
|
2021
2857
|
return functionTypeFromInfo(typeInfo);
|
|
2022
2858
|
}
|
|
2023
2859
|
}
|
|
2024
2860
|
// Then check for __goTypeName which indicates a typed function
|
|
2025
2861
|
if (funcWithMeta.__goTypeName) {
|
|
2026
|
-
// This is a typed Go function - try to reconstruct the signature
|
|
2027
2862
|
const typeName = funcWithMeta.__goTypeName;
|
|
2028
|
-
|
|
2029
|
-
if (typeName === 'Greeter') {
|
|
2030
|
-
return new FunctionType('func(string) string');
|
|
2031
|
-
}
|
|
2032
|
-
else if (typeName === 'Adder') {
|
|
2033
|
-
return new FunctionType('func(int, int) int');
|
|
2034
|
-
}
|
|
2035
|
-
// Generic fallback for typed functions
|
|
2036
|
-
return new FunctionType(`func`); // Could be enhanced with parameter parsing
|
|
2863
|
+
return new FunctionType({ name: typeName });
|
|
2037
2864
|
}
|
|
2038
2865
|
// For untyped functions, try to parse the signature
|
|
2039
2866
|
const funcStr = value.toString();
|
|
@@ -2069,6 +2896,10 @@ function getTypeOf(value) {
|
|
|
2069
2896
|
const elemType = getTypeOf(value.value);
|
|
2070
2897
|
return new PointerType(elemType);
|
|
2071
2898
|
}
|
|
2899
|
+
if ('__goTypeInfo' in value &&
|
|
2900
|
+
value.__goTypeInfo) {
|
|
2901
|
+
return typeFromTypeInfo(value.__goTypeInfo);
|
|
2902
|
+
}
|
|
2072
2903
|
if ('real' in value &&
|
|
2073
2904
|
'imag' in value &&
|
|
2074
2905
|
typeof value.real === 'number' &&
|
|
@@ -2136,34 +2967,31 @@ function getTypeOf(value) {
|
|
|
2136
2967
|
}
|
|
2137
2968
|
}
|
|
2138
2969
|
// Check if it has a constructor with __typeInfo for proper struct names
|
|
2970
|
+
if (value &&
|
|
2971
|
+
typeof value === 'object' &&
|
|
2972
|
+
value.constructor &&
|
|
2973
|
+
'__reflectType' in value.constructor) {
|
|
2974
|
+
const reflectType = value.constructor
|
|
2975
|
+
.__reflectType;
|
|
2976
|
+
if (reflectType) {
|
|
2977
|
+
return reflectType;
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2139
2980
|
if (value &&
|
|
2140
2981
|
typeof value === 'object' &&
|
|
2141
2982
|
value.constructor &&
|
|
2142
2983
|
'__typeInfo' in value.constructor) {
|
|
2143
2984
|
const typeInfo = value.constructor.__typeInfo;
|
|
2144
|
-
if (typeInfo && typeInfo
|
|
2145
|
-
const
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
const regTypeInfo = builtinGetTypeByName(typeName);
|
|
2149
|
-
let fields = [];
|
|
2150
|
-
if (regTypeInfo && isStructTypeInfo(regTypeInfo)) {
|
|
2151
|
-
fields = Object.entries(regTypeInfo.fields || {}).map(([name, fieldInfo]) => {
|
|
2152
|
-
// Check if fieldInfo is a StructFieldInfo with type and tag
|
|
2153
|
-
if (isStructFieldInfo(fieldInfo)) {
|
|
2154
|
-
return {
|
|
2155
|
-
name: fieldInfo.name ?? name,
|
|
2156
|
-
type: StructType.createTypeFromFieldInfo(fieldInfo.type),
|
|
2157
|
-
tag: fieldInfo.tag,
|
|
2158
|
-
};
|
|
2159
|
-
}
|
|
2160
|
-
// Otherwise it's just the type info directly (backwards compatible)
|
|
2161
|
-
return {
|
|
2162
|
-
name,
|
|
2163
|
-
type: StructType.createTypeFromFieldInfo(fieldInfo),
|
|
2164
|
-
};
|
|
2165
|
-
});
|
|
2985
|
+
if (typeInfo && isStructTypeInfo(typeInfo)) {
|
|
2986
|
+
const name = typeInfo.name ?? '';
|
|
2987
|
+
if (name === '') {
|
|
2988
|
+
return new StructType('', structFieldsFromTypeInfo(typeInfo));
|
|
2166
2989
|
}
|
|
2990
|
+
const typeName = name.includes('.') ? name : `main.${name}`;
|
|
2991
|
+
const regTypeInfo = builtinGetTypeByName(typeName);
|
|
2992
|
+
const fields = regTypeInfo && isStructTypeInfo(regTypeInfo) ?
|
|
2993
|
+
structFieldsFromTypeInfo(regTypeInfo)
|
|
2994
|
+
: structFieldsFromTypeInfo(typeInfo);
|
|
2167
2995
|
return new StructType(typeName, fields);
|
|
2168
2996
|
}
|
|
2169
2997
|
}
|
|
@@ -2213,86 +3041,497 @@ export function MapOf(key, elem) {
|
|
|
2213
3041
|
export function ChanOf(dir, t) {
|
|
2214
3042
|
return internType(new ChannelType(t, dir));
|
|
2215
3043
|
}
|
|
3044
|
+
export function StructOf(fields) {
|
|
3045
|
+
const inputFields = $.asArray(fields);
|
|
3046
|
+
const descriptors = [];
|
|
3047
|
+
const names = new Set();
|
|
3048
|
+
let pkgPath = '';
|
|
3049
|
+
let offset = 0;
|
|
3050
|
+
for (const [idx, field] of inputFields.entries()) {
|
|
3051
|
+
validateStructOfField(field, idx);
|
|
3052
|
+
if (field.PkgPath !== '') {
|
|
3053
|
+
if (pkgPath === '') {
|
|
3054
|
+
pkgPath = field.PkgPath;
|
|
3055
|
+
}
|
|
3056
|
+
else if (pkgPath !== field.PkgPath) {
|
|
3057
|
+
throw new Error(`reflect.Struct: fields with different PkgPath ${pkgPath} and ${field.PkgPath}`);
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
if (names.has(field.Name) && field.Name !== '_') {
|
|
3061
|
+
throw new Error(`reflect.StructOf: duplicate field ${field.Name}`);
|
|
3062
|
+
}
|
|
3063
|
+
names.add(field.Name);
|
|
3064
|
+
const fieldOffset = alignOffset(offset, typeAlignment(field.Type));
|
|
3065
|
+
const tag = field.Tag?.toString();
|
|
3066
|
+
const descriptor = {
|
|
3067
|
+
name: field.Name,
|
|
3068
|
+
key: field.Name === '_' ? `_${idx}` : field.Name,
|
|
3069
|
+
type: field.Type,
|
|
3070
|
+
...(tag ? { tag } : {}),
|
|
3071
|
+
pkgPath: field.PkgPath,
|
|
3072
|
+
anonymous: field.Anonymous,
|
|
3073
|
+
index: [idx],
|
|
3074
|
+
offset: fieldOffset,
|
|
3075
|
+
exported: field.IsExported(),
|
|
3076
|
+
};
|
|
3077
|
+
descriptors.push(descriptor);
|
|
3078
|
+
offset = fieldOffset + field.Type.Size();
|
|
3079
|
+
}
|
|
3080
|
+
return internType(new StructType('', descriptors, '', structTypeString(descriptors)));
|
|
3081
|
+
}
|
|
3082
|
+
function validateStructOfField(field, idx) {
|
|
3083
|
+
if (field.Name === '') {
|
|
3084
|
+
throw new Error(`reflect.StructOf: field ${idx} has no name`);
|
|
3085
|
+
}
|
|
3086
|
+
if (!isValidStructFieldName(field.Name)) {
|
|
3087
|
+
throw new Error(`reflect.StructOf: field ${idx} has invalid name`);
|
|
3088
|
+
}
|
|
3089
|
+
if (!field.Type) {
|
|
3090
|
+
throw new Error(`reflect.StructOf: field ${idx} has no type`);
|
|
3091
|
+
}
|
|
3092
|
+
if (field.Anonymous && field.PkgPath !== '') {
|
|
3093
|
+
throw new Error(`reflect.StructOf: field "${field.Name}" is anonymous but has PkgPath set`);
|
|
3094
|
+
}
|
|
3095
|
+
if (field.IsExported() && isUnexportedStructFieldName(field.Name)) {
|
|
3096
|
+
throw new Error(`reflect.StructOf: field "${field.Name}" is unexported but missing PkgPath`);
|
|
3097
|
+
}
|
|
3098
|
+
validateAnonymousStructOfField(field);
|
|
3099
|
+
}
|
|
3100
|
+
function isValidStructFieldName(name) {
|
|
3101
|
+
return /^[\p{L}_][\p{L}\p{N}_]*$/u.test(name);
|
|
3102
|
+
}
|
|
3103
|
+
function isUnexportedStructFieldName(name) {
|
|
3104
|
+
const first = name.charCodeAt(0);
|
|
3105
|
+
return name[0] === '_' || (first >= 97 && first <= 122);
|
|
3106
|
+
}
|
|
3107
|
+
function validateAnonymousStructOfField(field) {
|
|
3108
|
+
if (!field.Anonymous) {
|
|
3109
|
+
return;
|
|
3110
|
+
}
|
|
3111
|
+
const typ = field.Type;
|
|
3112
|
+
if (typ.Kind() === Ptr) {
|
|
3113
|
+
const elem = typ.Elem();
|
|
3114
|
+
if (elem.Kind() === Ptr || elem.Kind() === Interface) {
|
|
3115
|
+
throw new Error(`reflect.StructOf: illegal embedded field type ${typ.String()}`);
|
|
3116
|
+
}
|
|
3117
|
+
if (embeddedMethodCount(typ) > 0) {
|
|
3118
|
+
throw new Error('reflect: embedded type with methods not implemented');
|
|
3119
|
+
}
|
|
3120
|
+
return;
|
|
3121
|
+
}
|
|
3122
|
+
if (embeddedMethodCount(typ) > 0) {
|
|
3123
|
+
throw new Error('reflect: embedded type with methods not implemented');
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
function embeddedMethodCount(typ) {
|
|
3127
|
+
if (typ.Kind() === Ptr) {
|
|
3128
|
+
return Math.max(typ.NumMethod(), typ.Elem().NumMethod());
|
|
3129
|
+
}
|
|
3130
|
+
return typ.NumMethod();
|
|
3131
|
+
}
|
|
3132
|
+
function structTypeString(fields) {
|
|
3133
|
+
if (fields.length === 0) {
|
|
3134
|
+
return 'struct {}';
|
|
3135
|
+
}
|
|
3136
|
+
return `struct { ${fields.map(structFieldString).join('; ')} }`;
|
|
3137
|
+
}
|
|
3138
|
+
function structFieldString(field) {
|
|
3139
|
+
const tag = field.tag ? ` ${JSON.stringify(field.tag)}` : '';
|
|
3140
|
+
const prefix = field.anonymous ? '' : `${field.name} `;
|
|
3141
|
+
return `${prefix}${field.type.String()}${tag}`;
|
|
3142
|
+
}
|
|
3143
|
+
export function FuncOf(inTypes, outTypes, variadic) {
|
|
3144
|
+
const params = $.asArray(inTypes).map(funcOfType);
|
|
3145
|
+
const results = $.asArray(outTypes).map(funcOfType);
|
|
3146
|
+
if (variadic &&
|
|
3147
|
+
(params.length === 0 || params[params.length - 1].Kind() !== Slice)) {
|
|
3148
|
+
throw new Error('reflect.FuncOf: last arg of variadic func must be slice');
|
|
3149
|
+
}
|
|
3150
|
+
if (params.length + results.length > 128) {
|
|
3151
|
+
throw new Error('reflect.FuncOf: too many arguments');
|
|
3152
|
+
}
|
|
3153
|
+
return internType(new FunctionType({ params, results, variadic }));
|
|
3154
|
+
}
|
|
3155
|
+
function funcOfType(typ) {
|
|
3156
|
+
if (!typ) {
|
|
3157
|
+
throw new Error('reflect.FuncOf: nil Type');
|
|
3158
|
+
}
|
|
3159
|
+
return typ;
|
|
3160
|
+
}
|
|
2216
3161
|
export function TypeFor(typeArgs) {
|
|
2217
3162
|
const descriptor = typeArgs?.T;
|
|
3163
|
+
const methodSignatures = genericMethodSignatures(descriptor);
|
|
2218
3164
|
if (descriptor?.type) {
|
|
2219
|
-
return internType(typeFromTypeInfo(descriptor.type));
|
|
3165
|
+
return internType(typeWithMethodSignatures(typeFromTypeInfo(descriptor.type), methodSignatures));
|
|
2220
3166
|
}
|
|
2221
|
-
if (
|
|
2222
|
-
|
|
2223
|
-
if (methods.length !== 0) {
|
|
2224
|
-
return internType(new InterfaceType(`interface { ${methods.map((method) => method + '()').join('; ')} }`));
|
|
2225
|
-
}
|
|
3167
|
+
if (methodSignatures.length !== 0) {
|
|
3168
|
+
return internType(new InterfaceType(interfaceTypeString(methodSignatures), undefined, methodSignatures));
|
|
2226
3169
|
}
|
|
2227
3170
|
if (descriptor?.zero) {
|
|
2228
3171
|
return internType(getTypeOf(descriptor.zero()));
|
|
2229
3172
|
}
|
|
2230
3173
|
return internType(new InterfaceType('interface{}'));
|
|
2231
3174
|
}
|
|
3175
|
+
function genericMethodSignatures(descriptor) {
|
|
3176
|
+
if (!descriptor) {
|
|
3177
|
+
return [];
|
|
3178
|
+
}
|
|
3179
|
+
if (descriptor.methodSignatures && descriptor.methodSignatures.length !== 0) {
|
|
3180
|
+
return descriptor.methodSignatures;
|
|
3181
|
+
}
|
|
3182
|
+
if (!descriptor.methods) {
|
|
3183
|
+
return [];
|
|
3184
|
+
}
|
|
3185
|
+
return Object.keys(descriptor.methods).map((method) => ({
|
|
3186
|
+
name: method,
|
|
3187
|
+
args: [],
|
|
3188
|
+
returns: [],
|
|
3189
|
+
}));
|
|
3190
|
+
}
|
|
3191
|
+
function typeWithMethodSignatures(typ, methods) {
|
|
3192
|
+
if (methods.length === 0) {
|
|
3193
|
+
return typ;
|
|
3194
|
+
}
|
|
3195
|
+
if (typ instanceof BasicType) {
|
|
3196
|
+
typ.mergeMethodSignatures(methods);
|
|
3197
|
+
return typ;
|
|
3198
|
+
}
|
|
3199
|
+
if (typ instanceof PointerType) {
|
|
3200
|
+
typ.mergeMethodSignatures(methods);
|
|
3201
|
+
return typ;
|
|
3202
|
+
}
|
|
3203
|
+
if (typ instanceof FunctionType) {
|
|
3204
|
+
typ.mergeMethodSignatures(methods);
|
|
3205
|
+
return typ;
|
|
3206
|
+
}
|
|
3207
|
+
return typ;
|
|
3208
|
+
}
|
|
2232
3209
|
function typeFromTypeInfo(info) {
|
|
3210
|
+
return typeFromTypeInfoWithSeen(info, new Set());
|
|
3211
|
+
}
|
|
3212
|
+
function typeFromTypeInfoWithSeen(info, seen) {
|
|
2233
3213
|
if (typeof info === 'string') {
|
|
2234
3214
|
const registered = builtinGetTypeByName(info);
|
|
2235
3215
|
if (registered) {
|
|
2236
|
-
|
|
3216
|
+
const typ = typeFromTypeInfoWithSeen(registered, seen);
|
|
3217
|
+
return internType(typ);
|
|
3218
|
+
}
|
|
3219
|
+
return internType(StructType.createTypeFromFieldInfo(info, seen));
|
|
3220
|
+
}
|
|
3221
|
+
const recursiveName = recursiveTypeInfoName(info);
|
|
3222
|
+
if (recursiveName !== '') {
|
|
3223
|
+
const constructing = constructingRegisteredTypes.get(recursiveName);
|
|
3224
|
+
if (constructing) {
|
|
3225
|
+
return constructing;
|
|
2237
3226
|
}
|
|
2238
|
-
|
|
3227
|
+
if (seen.has(recursiveName)) {
|
|
3228
|
+
return internType(shallowTypeFromRegisteredInfo(recursiveName, info));
|
|
3229
|
+
}
|
|
3230
|
+
if (info.kind === $.TypeKind.Struct) {
|
|
3231
|
+
const typ = new StructType(recursiveName, []);
|
|
3232
|
+
constructingRegisteredTypes.set(recursiveName, typ);
|
|
3233
|
+
seen.add(recursiveName);
|
|
3234
|
+
try {
|
|
3235
|
+
typ.replaceDescriptors(structFieldsFromTypeInfo(info, seen));
|
|
3236
|
+
return internType(typ);
|
|
3237
|
+
}
|
|
3238
|
+
finally {
|
|
3239
|
+
seen.delete(recursiveName);
|
|
3240
|
+
constructingRegisteredTypes.delete(recursiveName);
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
seen.add(recursiveName);
|
|
3244
|
+
const typ = typeFromStructuredTypeInfoWithSeen(info, seen);
|
|
3245
|
+
seen.delete(recursiveName);
|
|
3246
|
+
return internType(typ);
|
|
3247
|
+
}
|
|
3248
|
+
return internType(typeFromStructuredTypeInfoWithSeen(info, seen));
|
|
3249
|
+
}
|
|
3250
|
+
function recursiveTypeInfoName(info) {
|
|
3251
|
+
if (info.kind === $.TypeKind.Basic) {
|
|
3252
|
+
return info.typeName ?? '';
|
|
2239
3253
|
}
|
|
3254
|
+
return info.name ?? '';
|
|
3255
|
+
}
|
|
3256
|
+
function typeFromStructuredTypeInfoWithSeen(info, seen) {
|
|
2240
3257
|
switch (info.kind) {
|
|
2241
3258
|
case $.TypeKind.Array:
|
|
2242
|
-
return
|
|
3259
|
+
return new ArrayType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), info.length);
|
|
2243
3260
|
case $.TypeKind.Basic:
|
|
2244
|
-
return
|
|
3261
|
+
return StructType.createTypeFromFieldInfo(info, seen);
|
|
2245
3262
|
case $.TypeKind.Channel:
|
|
2246
|
-
return
|
|
3263
|
+
return new ChannelType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), chanDirFromTypeInfo(info.direction));
|
|
2247
3264
|
case $.TypeKind.Function:
|
|
2248
|
-
return
|
|
3265
|
+
return functionTypeFromInfo(info, seen);
|
|
2249
3266
|
case $.TypeKind.Interface:
|
|
2250
|
-
return
|
|
3267
|
+
return interfaceTypeFromInfo(info, seen);
|
|
2251
3268
|
case $.TypeKind.Map:
|
|
2252
|
-
return
|
|
3269
|
+
return new MapType(typeFromTypeInfoWithSeen(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
|
|
2253
3270
|
case $.TypeKind.Slice:
|
|
2254
|
-
return
|
|
3271
|
+
return new SliceType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
|
|
2255
3272
|
case $.TypeKind.Struct:
|
|
2256
|
-
return
|
|
3273
|
+
return StructType.createTypeFromFieldInfo(info, seen);
|
|
2257
3274
|
case $.TypeKind.Pointer:
|
|
2258
|
-
return
|
|
3275
|
+
return new PointerType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
|
|
2259
3276
|
default:
|
|
2260
|
-
return
|
|
3277
|
+
return StructType.createTypeFromFieldInfo(info, seen);
|
|
2261
3278
|
}
|
|
2262
3279
|
}
|
|
2263
|
-
function
|
|
2264
|
-
|
|
2265
|
-
|
|
3280
|
+
function shallowTypeFromRegisteredInfo(name, info) {
|
|
3281
|
+
switch (info.kind) {
|
|
3282
|
+
case $.TypeKind.Interface:
|
|
3283
|
+
return new InterfaceType(name, name, info.methods ?? []);
|
|
3284
|
+
case $.TypeKind.Struct:
|
|
3285
|
+
return new StructType(name, []);
|
|
3286
|
+
case $.TypeKind.Function:
|
|
3287
|
+
return new FunctionType({ name });
|
|
3288
|
+
case $.TypeKind.Basic:
|
|
3289
|
+
return StructType.createTypeFromFieldInfo({
|
|
3290
|
+
kind: $.TypeKind.Basic,
|
|
3291
|
+
name: info.name ?? 'unknown',
|
|
3292
|
+
typeName: info.typeName ?? name,
|
|
3293
|
+
});
|
|
3294
|
+
default:
|
|
3295
|
+
return StructType.createTypeFromFieldInfo(name);
|
|
2266
3296
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
return '...' + typeName;
|
|
3297
|
+
}
|
|
3298
|
+
function functionTypeFromInfo(info, seen = new Set()) {
|
|
3299
|
+
const params = (info.params ?? []).map((param) => typeFromTypeInfoWithSeen(param, seen));
|
|
3300
|
+
const results = (info.results ?? []).map((result) => typeFromTypeInfoWithSeen(result, seen));
|
|
3301
|
+
return new FunctionType({
|
|
3302
|
+
name: info.name,
|
|
3303
|
+
params,
|
|
3304
|
+
results,
|
|
3305
|
+
variadic: info.isVariadic ?? false,
|
|
2277
3306
|
});
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
3307
|
+
}
|
|
3308
|
+
function functionTypeInfoFromType(typ) {
|
|
3309
|
+
const params = [];
|
|
3310
|
+
for (let i = 0; i < typ.NumIn(); i++) {
|
|
3311
|
+
params.push(typeInfoFromReflectType(typ.In(i)));
|
|
3312
|
+
}
|
|
3313
|
+
const results = [];
|
|
3314
|
+
for (let i = 0; i < typ.NumOut(); i++) {
|
|
3315
|
+
results.push(typeInfoFromReflectType(typ.Out(i)));
|
|
3316
|
+
}
|
|
3317
|
+
const info = {
|
|
3318
|
+
kind: $.TypeKind.Function,
|
|
3319
|
+
params,
|
|
3320
|
+
results,
|
|
3321
|
+
};
|
|
3322
|
+
if (typ.Name() !== '') {
|
|
3323
|
+
info.name = typ.String();
|
|
3324
|
+
}
|
|
3325
|
+
if (typ.IsVariadic()) {
|
|
3326
|
+
info.isVariadic = true;
|
|
3327
|
+
}
|
|
3328
|
+
return info;
|
|
3329
|
+
}
|
|
3330
|
+
export function typeInfoFromReflectType(typ) {
|
|
3331
|
+
if (typ.PkgPath() !== '' && typ.Name() !== '') {
|
|
3332
|
+
return typ.String();
|
|
3333
|
+
}
|
|
3334
|
+
switch (typ.Kind()) {
|
|
3335
|
+
case Bool:
|
|
3336
|
+
case Int:
|
|
3337
|
+
case Int8:
|
|
3338
|
+
case Int16:
|
|
3339
|
+
case Int32:
|
|
3340
|
+
case Int64:
|
|
3341
|
+
case Uint:
|
|
3342
|
+
case Uint8:
|
|
3343
|
+
case Uint16:
|
|
3344
|
+
case Uint32:
|
|
3345
|
+
case Uint64:
|
|
3346
|
+
case Uintptr:
|
|
3347
|
+
case Float32:
|
|
3348
|
+
case Float64:
|
|
3349
|
+
case Complex64:
|
|
3350
|
+
case Complex128:
|
|
3351
|
+
case String:
|
|
3352
|
+
case UnsafePointer:
|
|
3353
|
+
return { kind: $.TypeKind.Basic, name: typ.String() };
|
|
3354
|
+
case Interface:
|
|
3355
|
+
return {
|
|
3356
|
+
kind: $.TypeKind.Interface,
|
|
3357
|
+
methods: typeMethods(typ).map((method) => ({
|
|
3358
|
+
name: method.name,
|
|
3359
|
+
args: method.args,
|
|
3360
|
+
returns: method.returns,
|
|
3361
|
+
})),
|
|
3362
|
+
};
|
|
3363
|
+
case Slice:
|
|
3364
|
+
return {
|
|
3365
|
+
kind: $.TypeKind.Slice,
|
|
3366
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3367
|
+
};
|
|
3368
|
+
case Array:
|
|
3369
|
+
return {
|
|
3370
|
+
kind: $.TypeKind.Array,
|
|
3371
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3372
|
+
length: typ.Len(),
|
|
3373
|
+
};
|
|
3374
|
+
case Ptr:
|
|
3375
|
+
return {
|
|
3376
|
+
kind: $.TypeKind.Pointer,
|
|
3377
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3378
|
+
};
|
|
3379
|
+
case Map:
|
|
3380
|
+
return {
|
|
3381
|
+
kind: $.TypeKind.Map,
|
|
3382
|
+
keyType: typeInfoFromReflectType(typ.Key()),
|
|
3383
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3384
|
+
};
|
|
3385
|
+
case Chan:
|
|
3386
|
+
return {
|
|
3387
|
+
kind: $.TypeKind.Channel,
|
|
3388
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3389
|
+
direction: channelDirectionFromString(typ.String()),
|
|
3390
|
+
};
|
|
3391
|
+
case Func:
|
|
3392
|
+
return functionTypeInfoFromType(typ);
|
|
3393
|
+
case Struct: {
|
|
3394
|
+
const fields = typ instanceof StructType ?
|
|
3395
|
+
typ.descriptors()
|
|
3396
|
+
: globalThis.Array.from({ length: typ.NumField() }, (_unused, idx) => {
|
|
3397
|
+
const field = typ.Field(idx);
|
|
3398
|
+
return {
|
|
3399
|
+
name: field.Name,
|
|
3400
|
+
key: structFieldStorageKey(typ, idx),
|
|
3401
|
+
type: field.Type,
|
|
3402
|
+
tag: field.Tag?.toString(),
|
|
3403
|
+
pkgPath: field.PkgPath,
|
|
3404
|
+
anonymous: field.Anonymous,
|
|
3405
|
+
index: [...field.Index],
|
|
3406
|
+
offset: field.Offset,
|
|
3407
|
+
exported: field.IsExported(),
|
|
3408
|
+
};
|
|
3409
|
+
});
|
|
3410
|
+
return {
|
|
3411
|
+
kind: $.TypeKind.Struct,
|
|
3412
|
+
name: typ.Name() === '' ? '' : typ.String(),
|
|
3413
|
+
methods: [],
|
|
3414
|
+
fields: fields.map((field) => ({
|
|
3415
|
+
name: field.name,
|
|
3416
|
+
key: field.key,
|
|
3417
|
+
type: typeInfoFromReflectType(field.type),
|
|
3418
|
+
...(field.tag ? { tag: field.tag } : {}),
|
|
3419
|
+
...(field.pkgPath ? { pkgPath: field.pkgPath } : {}),
|
|
3420
|
+
...(field.anonymous ? { anonymous: true } : {}),
|
|
3421
|
+
index: [...field.index],
|
|
3422
|
+
offset: field.offset,
|
|
3423
|
+
exported: field.exported,
|
|
3424
|
+
})),
|
|
3425
|
+
};
|
|
3426
|
+
}
|
|
3427
|
+
default:
|
|
3428
|
+
return typ.String();
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
function channelDirectionFromString(typeName) {
|
|
3432
|
+
if (typeName.startsWith('<-chan ')) {
|
|
3433
|
+
return 'receive';
|
|
3434
|
+
}
|
|
3435
|
+
if (typeName.startsWith('chan<- ')) {
|
|
3436
|
+
return 'send';
|
|
3437
|
+
}
|
|
3438
|
+
return 'both';
|
|
3439
|
+
}
|
|
3440
|
+
function interfaceTypeFromInfo(info, seen = new Set()) {
|
|
3441
|
+
const methods = info.methods ?? [];
|
|
3442
|
+
if (methods.length === 0) {
|
|
3443
|
+
return new InterfaceType('interface{}', info.name, methods);
|
|
3444
|
+
}
|
|
3445
|
+
return new InterfaceType(interfaceTypeString(methods, seen), info.name, methods);
|
|
3446
|
+
}
|
|
3447
|
+
function interfaceTypeString(methods, seen = new Set()) {
|
|
3448
|
+
return `interface { ${methods
|
|
3449
|
+
.map((method) => interfaceMethodString(method, seen))
|
|
3450
|
+
.join('; ')} }`;
|
|
3451
|
+
}
|
|
3452
|
+
function interfaceMethodString(method, seen) {
|
|
3453
|
+
const args = method.args.map((arg) => methodArgString(arg, seen)).join(', ');
|
|
3454
|
+
const returns = method.returns.map((arg) => methodArgString(arg, seen));
|
|
3455
|
+
if (returns.length === 0) {
|
|
3456
|
+
return `${method.name}(${args})`;
|
|
2282
3457
|
}
|
|
2283
|
-
if (
|
|
2284
|
-
|
|
3458
|
+
if (returns.length === 1) {
|
|
3459
|
+
return `${method.name}(${args}) ${returns[0]}`;
|
|
2285
3460
|
}
|
|
2286
|
-
return
|
|
3461
|
+
return `${method.name}(${args}) (${returns.join(', ')})`;
|
|
3462
|
+
}
|
|
3463
|
+
function structTypeInfoString(info, seen) {
|
|
3464
|
+
if (info.name) {
|
|
3465
|
+
return info.name;
|
|
3466
|
+
}
|
|
3467
|
+
const fields = info.fields ?? [];
|
|
3468
|
+
if (fields.length === 0) {
|
|
3469
|
+
return 'struct {}';
|
|
3470
|
+
}
|
|
3471
|
+
return `struct { ${fields
|
|
3472
|
+
.map((field) => structFieldInfoString(field, seen))
|
|
3473
|
+
.join('; ')} }`;
|
|
3474
|
+
}
|
|
3475
|
+
function structFieldInfoString(field, seen) {
|
|
3476
|
+
const tag = field.tag ? ` ${JSON.stringify(field.tag)}` : '';
|
|
3477
|
+
const prefix = field.anonymous ? '' : `${field.name} `;
|
|
3478
|
+
return `${prefix}${typeInfoString(field.type, seen)}${tag}`;
|
|
2287
3479
|
}
|
|
2288
|
-
function
|
|
2289
|
-
return
|
|
3480
|
+
function methodArgString(arg, seen) {
|
|
3481
|
+
return typeInfoString(arg.type, seen);
|
|
2290
3482
|
}
|
|
2291
|
-
function
|
|
2292
|
-
if (info
|
|
2293
|
-
return
|
|
3483
|
+
function typeInfoString(info, seen) {
|
|
3484
|
+
if (typeof info === 'string') {
|
|
3485
|
+
return info;
|
|
3486
|
+
}
|
|
3487
|
+
switch (info.kind) {
|
|
3488
|
+
case $.TypeKind.Basic:
|
|
3489
|
+
return info.typeName ?? info.name ?? 'unknown';
|
|
3490
|
+
case $.TypeKind.Interface: {
|
|
3491
|
+
const name = info.name ?? '';
|
|
3492
|
+
if (name !== '' && seen.has(name)) {
|
|
3493
|
+
return name;
|
|
3494
|
+
}
|
|
3495
|
+
if (info.methods.length === 0) {
|
|
3496
|
+
return 'interface{}';
|
|
3497
|
+
}
|
|
3498
|
+
if (name !== '') {
|
|
3499
|
+
seen.add(name);
|
|
3500
|
+
}
|
|
3501
|
+
const text = interfaceTypeString(info.methods, seen);
|
|
3502
|
+
if (name !== '') {
|
|
3503
|
+
seen.delete(name);
|
|
3504
|
+
}
|
|
3505
|
+
return text;
|
|
3506
|
+
}
|
|
3507
|
+
case $.TypeKind.Struct:
|
|
3508
|
+
return structTypeInfoString(info, seen);
|
|
3509
|
+
case $.TypeKind.Pointer:
|
|
3510
|
+
return `*${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3511
|
+
case $.TypeKind.Slice:
|
|
3512
|
+
return `[]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3513
|
+
case $.TypeKind.Array:
|
|
3514
|
+
return `[${info.length}]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3515
|
+
case $.TypeKind.Map:
|
|
3516
|
+
return `map[${typeInfoString(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3517
|
+
case $.TypeKind.Function: {
|
|
3518
|
+
const params = (info.params ?? [])
|
|
3519
|
+
.map((param) => typeInfoString(param, seen))
|
|
3520
|
+
.join(', ');
|
|
3521
|
+
const results = (info.results ?? []).map((result) => typeInfoString(result, seen));
|
|
3522
|
+
if (results.length === 0) {
|
|
3523
|
+
return `func(${params})`;
|
|
3524
|
+
}
|
|
3525
|
+
if (results.length === 1) {
|
|
3526
|
+
return `func(${params}) ${results[0]}`;
|
|
3527
|
+
}
|
|
3528
|
+
return `func(${params}) (${results.join(', ')})`;
|
|
3529
|
+
}
|
|
3530
|
+
case $.TypeKind.Channel:
|
|
3531
|
+
return `chan ${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3532
|
+
default:
|
|
3533
|
+
return 'unknown';
|
|
2294
3534
|
}
|
|
2295
|
-
return new InterfaceType(`interface { ${info.methods.map((method) => method.name + '()').join('; ')} }`, info.name);
|
|
2296
3535
|
}
|
|
2297
3536
|
function chanDirFromTypeInfo(direction) {
|
|
2298
3537
|
switch (direction) {
|
|
@@ -2310,35 +3549,15 @@ function chanDirFromTypeInfo(direction) {
|
|
|
2310
3549
|
*/
|
|
2311
3550
|
export function getInterfaceTypeByName(name) {
|
|
2312
3551
|
const typeInfo = builtinGetTypeByName(name);
|
|
2313
|
-
if (typeInfo && typeInfo
|
|
2314
|
-
return new InterfaceType(name, name);
|
|
3552
|
+
if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
|
|
3553
|
+
return new InterfaceType(name, name, typeInfo.methods ?? []);
|
|
2315
3554
|
}
|
|
2316
3555
|
return new InterfaceType('interface{}');
|
|
2317
3556
|
}
|
|
2318
3557
|
export function getInterfaceLiteralTypeByName(name) {
|
|
2319
3558
|
const typeInfo = builtinGetTypeByName(name);
|
|
2320
|
-
if (typeInfo && typeInfo
|
|
2321
|
-
|
|
2322
|
-
if (methods.length === 0) {
|
|
2323
|
-
return new InterfaceType('interface{}', name);
|
|
2324
|
-
}
|
|
2325
|
-
const methodSigs = methods
|
|
2326
|
-
.map((m) => {
|
|
2327
|
-
const args = m.args
|
|
2328
|
-
?.map((a) => (typeof a === 'string' ? a : 'any'))
|
|
2329
|
-
.join(', ') || '';
|
|
2330
|
-
const returns = m.returns?.map((r) => typeof r === 'string' ? r : 'any');
|
|
2331
|
-
let returnSig = '';
|
|
2332
|
-
if (returns && returns.length === 1) {
|
|
2333
|
-
returnSig = ` ${returns[0]}`;
|
|
2334
|
-
}
|
|
2335
|
-
else if (returns && returns.length > 1) {
|
|
2336
|
-
returnSig = ` (${returns.join(', ')})`;
|
|
2337
|
-
}
|
|
2338
|
-
return `${m.name}(${args})${returnSig}`;
|
|
2339
|
-
})
|
|
2340
|
-
.join('; ');
|
|
2341
|
-
return new InterfaceType(`interface { ${methodSigs} }`, name);
|
|
3559
|
+
if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
|
|
3560
|
+
return interfaceTypeFromInfo(typeInfo);
|
|
2342
3561
|
}
|
|
2343
3562
|
return new InterfaceType('interface{}');
|
|
2344
3563
|
}
|