goscript 0.1.4 → 0.2.1
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} +7 -0
- package/cmd/goscript/cmd-test.go +14 -0
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript-wasm/main.go +38 -6
- package/compiler/compile-request.go +12 -9
- package/compiler/compliance_test.go +0 -1
- package/compiler/config.go +2 -0
- package/compiler/diagnostic.go +104 -12
- package/compiler/diagnostic_test.go +106 -0
- package/compiler/gotest/request.go +28 -0
- package/compiler/gotest/runner.go +354 -44
- package/compiler/gotest/runner_test.go +293 -1
- package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
- package/compiler/gotest/testdata/browserapi/go.mod +3 -0
- package/compiler/index.test.ts +23 -0
- package/compiler/lowered-program.go +33 -24
- package/compiler/lowering.go +746 -194
- package/compiler/lowering_bench_test.go +42 -27
- package/compiler/lowering_internal_test.go +18 -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/protobuf-ts-binding.go +567 -0
- package/compiler/protobuf-ts-binding_test.go +402 -0
- package/compiler/runtime-contract.go +4 -0
- package/compiler/runtime-contract_test.go +2 -0
- package/compiler/semantic-model-types.go +9 -4
- package/compiler/semantic-model.go +282 -70
- package/compiler/semantic-model_test.go +82 -1
- package/compiler/service.go +21 -1
- package/compiler/skeleton_test.go +118 -10
- package/compiler/typescript-emitter.go +128 -13
- package/compiler/wasm/compile_test.go +37 -4
- package/compiler/{wasm_api.go → wasm-api.go} +57 -7
- package/dist/gs/builtin/hostio.js +5 -0
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +13 -2
- package/dist/gs/builtin/slice.js +187 -6
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +13 -5
- package/dist/gs/builtin/type.js +153 -60
- 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 +10 -3
- package/dist/gs/compress/zlib/index.js +50 -16
- package/dist/gs/compress/zlib/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/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +101 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +589 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +1 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +17 -11
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
- 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/byteorder/index.js +2 -2
- package/dist/gs/internal/byteorder/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 +4 -2
- 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 +2 -0
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +5 -0
- package/dist/gs/math/bits/index.js +16 -4
- 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 +300 -5
- package/dist/gs/net/http/index.js +1598 -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.js +1 -1
- 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 +25 -6
- package/dist/gs/reflect/type.js +1475 -228
- 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.js +9 -5
- 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/doc_64.gs.js +7 -6
- package/dist/gs/sync/atomic/doc_64.gs.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/syscall/env.js +22 -14
- package/dist/gs/syscall/env.js.map +1 -1
- package/dist/gs/testing/testing.js +55 -13
- 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/hostio.test.ts +16 -0
- package/gs/builtin/hostio.ts +7 -0
- package/gs/builtin/runtime-contract.test.ts +246 -21
- package/gs/builtin/slice.ts +269 -24
- package/gs/builtin/type.ts +226 -59
- 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 +62 -1
- package/gs/compress/zlib/index.ts +53 -16
- package/gs/compress/zlib/parity.json +51 -0
- 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/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +373 -3
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +893 -1
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +18 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +17 -11
- 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/byteorder/index.test.ts +2 -2
- package/gs/internal/byteorder/index.ts +2 -2
- 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.ts +4 -4
- package/gs/io/fs/sub.ts +8 -1
- package/gs/io/io.ts +1 -0
- package/gs/io/parity.json +162 -0
- package/gs/math/bits/index.test.ts +14 -1
- package/gs/math/bits/index.ts +23 -4
- 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 +781 -12
- package/gs/net/http/index.ts +1860 -139
- 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/index.test.ts +9 -0
- package/gs/os/index.ts +1 -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/root_js.gs.ts +1 -1
- package/gs/os/types.gs.ts +1 -1
- package/gs/os/types_js.gs.ts +1 -1
- package/gs/os/types_unix.gs.ts +1 -1
- package/gs/path/path.ts +11 -7
- 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 +1961 -317
- package/gs/reflect/typefor.test.ts +530 -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/parity.json +186 -0
- package/gs/strings/reader.ts +9 -5
- 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/doc_64.gs.ts +6 -7
- package/gs/sync/atomic/doc_64.test.ts +43 -0
- package/gs/sync/atomic/type.gs.ts +9 -9
- package/gs/sync/atomic/value.gs.ts +2 -2
- package/gs/syscall/env.ts +29 -14
- package/gs/testing/testing.test.ts +67 -0
- package/gs/testing/testing.ts +87 -19
- 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 -926
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
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
|
}
|
|
@@ -335,6 +458,9 @@ export class Value {
|
|
|
335
458
|
return this._type.String();
|
|
336
459
|
}
|
|
337
460
|
Len() {
|
|
461
|
+
if (this.Kind() === Slice || this.Kind() === Array) {
|
|
462
|
+
return $.len(this._value);
|
|
463
|
+
}
|
|
338
464
|
// Check for slice objects created by $.arrayToSlice
|
|
339
465
|
if (this._value &&
|
|
340
466
|
typeof this._value === 'object' &&
|
|
@@ -383,8 +509,9 @@ export class Value {
|
|
|
383
509
|
return this._value === null || this._value === undefined;
|
|
384
510
|
}
|
|
385
511
|
Index(i) {
|
|
386
|
-
if (
|
|
387
|
-
|
|
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);
|
|
388
515
|
}
|
|
389
516
|
throw new Error('reflect: call of reflect.Value.Index on ' +
|
|
390
517
|
Kind_String(this._type.Kind()) +
|
|
@@ -446,16 +573,17 @@ export class Value {
|
|
|
446
573
|
throw new ValueError({ Kind: this.Kind(), Method: 'Field' });
|
|
447
574
|
}
|
|
448
575
|
const field = this.Type().Field(i);
|
|
576
|
+
const fieldKey = structFieldStorageKey(this.Type(), i);
|
|
449
577
|
if (!field) {
|
|
450
578
|
throw new Error('reflect: struct field index out of range');
|
|
451
579
|
}
|
|
452
580
|
const parentObj = this._value;
|
|
453
|
-
let fieldVal = parentObj[
|
|
581
|
+
let fieldVal = parentObj[fieldKey];
|
|
454
582
|
if (fieldVal === undefined) {
|
|
455
583
|
fieldVal = null;
|
|
456
584
|
}
|
|
457
585
|
// Pass parent struct and field name so Set() can update the struct
|
|
458
|
-
return new Value(fieldVal, field.Type, undefined, parentObj,
|
|
586
|
+
return new Value(fieldVal, field.Type, undefined, parentObj, fieldKey);
|
|
459
587
|
}
|
|
460
588
|
FieldByIndex(index) {
|
|
461
589
|
let current = this;
|
|
@@ -488,6 +616,9 @@ export class Value {
|
|
|
488
616
|
if (this._value === null || this._value === undefined) {
|
|
489
617
|
return 0;
|
|
490
618
|
}
|
|
619
|
+
if ($.isOwnedPointerHandle(this._value)) {
|
|
620
|
+
return $.ownedPointerAddress(this._value);
|
|
621
|
+
}
|
|
491
622
|
if ($.isVarRef(this._value)) {
|
|
492
623
|
const address = this._value.__goAddress?.();
|
|
493
624
|
if (address !== undefined) {
|
|
@@ -517,7 +648,18 @@ export class Value {
|
|
|
517
648
|
throw new ValueError({ Kind: this.Kind(), Method: 'UnsafeAddr' });
|
|
518
649
|
}
|
|
519
650
|
if (this._parentStruct && this._fieldName) {
|
|
520
|
-
|
|
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;
|
|
521
663
|
}
|
|
522
664
|
return this.Pointer();
|
|
523
665
|
}
|
|
@@ -547,6 +689,9 @@ export class Value {
|
|
|
547
689
|
if (this._parentStruct && this._fieldName) {
|
|
548
690
|
return new Value($.fieldRef(this._parentStruct, this._fieldName), ptrType);
|
|
549
691
|
}
|
|
692
|
+
if (this._parentVarRef) {
|
|
693
|
+
return new Value(this._parentVarRef, ptrType);
|
|
694
|
+
}
|
|
550
695
|
return new Value($.varRef(this._value), ptrType);
|
|
551
696
|
}
|
|
552
697
|
CanSet() {
|
|
@@ -558,23 +703,9 @@ export class Value {
|
|
|
558
703
|
if (!this.CanSet()) {
|
|
559
704
|
throw new Error('reflect: assign to invalid value');
|
|
560
705
|
}
|
|
561
|
-
// Interface types can accept any value
|
|
562
|
-
if (this.Kind() === Interface) {
|
|
563
|
-
this._value = x.value;
|
|
564
|
-
// Also update the parent VarRef if we were dereferenced from one
|
|
565
|
-
if (this._parentVarRef) {
|
|
566
|
-
this._parentVarRef.value = x.value;
|
|
567
|
-
}
|
|
568
|
-
// Also update the parent struct field if this is a struct field
|
|
569
|
-
if (this._parentStruct && this._fieldName) {
|
|
570
|
-
this._parentStruct[this._fieldName] = x.value;
|
|
571
|
-
}
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
// For other types, check if types are compatible (simplified check)
|
|
575
706
|
const thisType = this.Type();
|
|
576
707
|
const xType = x.Type();
|
|
577
|
-
if (
|
|
708
|
+
if (!xType.AssignableTo(thisType)) {
|
|
578
709
|
throw new Error('reflect: assign to wrong type');
|
|
579
710
|
}
|
|
580
711
|
this._value = x.value;
|
|
@@ -605,21 +736,23 @@ export class Value {
|
|
|
605
736
|
if (typeof method !== 'function') {
|
|
606
737
|
return new Value();
|
|
607
738
|
}
|
|
608
|
-
|
|
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);
|
|
609
744
|
}
|
|
610
|
-
Call(inArgs) {
|
|
745
|
+
async Call(inArgs) {
|
|
611
746
|
if (this.Kind() !== Func || typeof this._value !== 'function') {
|
|
612
747
|
throw new ValueError({ Kind: this.Kind(), Method: 'Call' });
|
|
613
748
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (result === undefined) {
|
|
620
|
-
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' });
|
|
621
754
|
}
|
|
622
|
-
return
|
|
755
|
+
return await callReflectFunction(this._value, this._type, inArgs, 'CallSlice');
|
|
623
756
|
}
|
|
624
757
|
IsZero() {
|
|
625
758
|
const zeroVal = Zero(this.Type()).value;
|
|
@@ -886,10 +1019,7 @@ export class Value {
|
|
|
886
1019
|
Cap() {
|
|
887
1020
|
const k = this.Kind();
|
|
888
1021
|
if (k === Slice || k === Array) {
|
|
889
|
-
|
|
890
|
-
return this._value.length;
|
|
891
|
-
}
|
|
892
|
-
return 0;
|
|
1022
|
+
return $.cap(this._value);
|
|
893
1023
|
}
|
|
894
1024
|
if (k === Chan) {
|
|
895
1025
|
return 0; // Simplified
|
|
@@ -962,11 +1092,13 @@ export class BasicType {
|
|
|
962
1092
|
_name;
|
|
963
1093
|
_size;
|
|
964
1094
|
_typeName;
|
|
965
|
-
|
|
1095
|
+
_methods;
|
|
1096
|
+
constructor(_kind, _name, _size = 8, _typeName = '', _methods = []) {
|
|
966
1097
|
this._kind = _kind;
|
|
967
1098
|
this._name = _name;
|
|
968
1099
|
this._size = _size;
|
|
969
1100
|
this._typeName = _typeName;
|
|
1101
|
+
this._methods = _methods;
|
|
970
1102
|
}
|
|
971
1103
|
String() {
|
|
972
1104
|
return this._typeName || this._name;
|
|
@@ -974,6 +1106,9 @@ export class BasicType {
|
|
|
974
1106
|
Kind() {
|
|
975
1107
|
return this._kind;
|
|
976
1108
|
}
|
|
1109
|
+
underlyingName() {
|
|
1110
|
+
return Kind_String(this._kind);
|
|
1111
|
+
}
|
|
977
1112
|
Comparable() {
|
|
978
1113
|
return this._kind !== Func && this._kind !== Map && this._kind !== Slice;
|
|
979
1114
|
}
|
|
@@ -986,6 +1121,21 @@ export class BasicType {
|
|
|
986
1121
|
NumField() {
|
|
987
1122
|
return 0;
|
|
988
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
|
+
}
|
|
989
1139
|
PkgPath() {
|
|
990
1140
|
if (this._typeName) {
|
|
991
1141
|
const dotIndex = this._typeName.lastIndexOf('.');
|
|
@@ -1025,7 +1175,7 @@ export class BasicType {
|
|
|
1025
1175
|
if (u.Kind() !== Interface) {
|
|
1026
1176
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1027
1177
|
}
|
|
1028
|
-
return
|
|
1178
|
+
return typeImplementsInterface(this, u);
|
|
1029
1179
|
}
|
|
1030
1180
|
AssignableTo(u) {
|
|
1031
1181
|
return typeAssignableTo(this, u);
|
|
@@ -1084,10 +1234,16 @@ export class BasicType {
|
|
|
1084
1234
|
' Type');
|
|
1085
1235
|
}
|
|
1086
1236
|
NumMethod() {
|
|
1087
|
-
return
|
|
1237
|
+
return typeMethods(this).length;
|
|
1088
1238
|
}
|
|
1089
|
-
MethodByName(
|
|
1090
|
-
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);
|
|
1091
1247
|
}
|
|
1092
1248
|
Len() {
|
|
1093
1249
|
throw new Error('reflect: call of reflect.Type.Len on ' +
|
|
@@ -1150,6 +1306,21 @@ class SliceType {
|
|
|
1150
1306
|
NumField() {
|
|
1151
1307
|
return 0;
|
|
1152
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
|
+
}
|
|
1153
1324
|
PkgPath() {
|
|
1154
1325
|
return '';
|
|
1155
1326
|
}
|
|
@@ -1176,7 +1347,7 @@ class SliceType {
|
|
|
1176
1347
|
if (u.Kind() !== Interface) {
|
|
1177
1348
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1178
1349
|
}
|
|
1179
|
-
return
|
|
1350
|
+
return typeImplementsInterface(this, u);
|
|
1180
1351
|
}
|
|
1181
1352
|
AssignableTo(u) {
|
|
1182
1353
|
return typeAssignableTo(this, u);
|
|
@@ -1229,6 +1400,21 @@ class ArrayType {
|
|
|
1229
1400
|
NumField() {
|
|
1230
1401
|
return 0;
|
|
1231
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
|
+
}
|
|
1232
1418
|
Len() {
|
|
1233
1419
|
return this._len;
|
|
1234
1420
|
}
|
|
@@ -1258,7 +1444,7 @@ class ArrayType {
|
|
|
1258
1444
|
if (u.Kind() !== Interface) {
|
|
1259
1445
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1260
1446
|
}
|
|
1261
|
-
return
|
|
1447
|
+
return typeImplementsInterface(this, u);
|
|
1262
1448
|
}
|
|
1263
1449
|
AssignableTo(u) {
|
|
1264
1450
|
return typeAssignableTo(this, u);
|
|
@@ -1288,8 +1474,10 @@ class ArrayType {
|
|
|
1288
1474
|
// Pointer type implementation
|
|
1289
1475
|
class PointerType {
|
|
1290
1476
|
_elemType;
|
|
1291
|
-
|
|
1477
|
+
_methods;
|
|
1478
|
+
constructor(_elemType, _methods = []) {
|
|
1292
1479
|
this._elemType = _elemType;
|
|
1480
|
+
this._methods = _methods;
|
|
1293
1481
|
}
|
|
1294
1482
|
String() {
|
|
1295
1483
|
return '*' + this._elemType.String();
|
|
@@ -1309,6 +1497,21 @@ class PointerType {
|
|
|
1309
1497
|
NumField() {
|
|
1310
1498
|
return 0;
|
|
1311
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
|
+
}
|
|
1312
1515
|
PkgPath() {
|
|
1313
1516
|
return '';
|
|
1314
1517
|
}
|
|
@@ -1335,9 +1538,7 @@ class PointerType {
|
|
|
1335
1538
|
if (u.Kind() !== Interface) {
|
|
1336
1539
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1337
1540
|
}
|
|
1338
|
-
|
|
1339
|
-
const elemTypeName = this._elemType.String();
|
|
1340
|
-
return typeImplementsInterface(elemTypeName, u);
|
|
1541
|
+
return typeImplementsInterface(this, u);
|
|
1341
1542
|
}
|
|
1342
1543
|
AssignableTo(u) {
|
|
1343
1544
|
return typeAssignableTo(this, u);
|
|
@@ -1355,10 +1556,16 @@ class PointerType {
|
|
|
1355
1556
|
throw new Error('reflect: call of reflect.Type.OverflowFloat on pointer Type');
|
|
1356
1557
|
}
|
|
1357
1558
|
NumMethod() {
|
|
1358
|
-
return
|
|
1559
|
+
return typeMethods(this).length;
|
|
1359
1560
|
}
|
|
1360
1561
|
MethodByName(name) {
|
|
1361
|
-
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);
|
|
1362
1569
|
}
|
|
1363
1570
|
Len() {
|
|
1364
1571
|
throw new Error('reflect: call of reflect.Type.Len on pointer Type');
|
|
@@ -1367,13 +1574,42 @@ class PointerType {
|
|
|
1367
1574
|
throw new Error('reflect: call of reflect.Type.Bits on pointer Type');
|
|
1368
1575
|
}
|
|
1369
1576
|
}
|
|
1370
|
-
// Function type implementation
|
|
1371
1577
|
class FunctionType {
|
|
1578
|
+
_name;
|
|
1372
1579
|
_signature;
|
|
1373
|
-
|
|
1374
|
-
|
|
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);
|
|
1375
1608
|
}
|
|
1376
1609
|
String() {
|
|
1610
|
+
if (this._name !== '') {
|
|
1611
|
+
return this._name;
|
|
1612
|
+
}
|
|
1377
1613
|
return this._signature;
|
|
1378
1614
|
}
|
|
1379
1615
|
Kind() {
|
|
@@ -1391,11 +1627,44 @@ class FunctionType {
|
|
|
1391
1627
|
NumField() {
|
|
1392
1628
|
return 0;
|
|
1393
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
|
+
}
|
|
1394
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
|
+
}
|
|
1395
1658
|
return '';
|
|
1396
1659
|
}
|
|
1397
1660
|
Name() {
|
|
1398
|
-
|
|
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
|
+
}
|
|
1399
1668
|
return '';
|
|
1400
1669
|
}
|
|
1401
1670
|
Field(_i) {
|
|
@@ -1417,7 +1686,7 @@ class FunctionType {
|
|
|
1417
1686
|
if (u.Kind() !== Interface) {
|
|
1418
1687
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1419
1688
|
}
|
|
1420
|
-
return
|
|
1689
|
+
return typeImplementsInterface(this, u);
|
|
1421
1690
|
}
|
|
1422
1691
|
AssignableTo(u) {
|
|
1423
1692
|
return typeAssignableTo(this, u);
|
|
@@ -1435,10 +1704,26 @@ class FunctionType {
|
|
|
1435
1704
|
throw new Error('reflect: call of reflect.Type.OverflowFloat on func Type');
|
|
1436
1705
|
}
|
|
1437
1706
|
NumMethod() {
|
|
1438
|
-
return
|
|
1707
|
+
return typeMethods(this).length;
|
|
1439
1708
|
}
|
|
1440
|
-
MethodByName(
|
|
1441
|
-
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;
|
|
1442
1727
|
}
|
|
1443
1728
|
Len() {
|
|
1444
1729
|
throw new Error('reflect: call of reflect.Type.Len on func Type');
|
|
@@ -1447,6 +1732,174 @@ class FunctionType {
|
|
|
1447
1732
|
throw new Error('reflect: call of reflect.Type.Bits on func Type');
|
|
1448
1733
|
}
|
|
1449
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
|
+
}
|
|
1450
1903
|
// Map type implementation
|
|
1451
1904
|
class MapType {
|
|
1452
1905
|
_keyType;
|
|
@@ -1473,6 +1926,21 @@ class MapType {
|
|
|
1473
1926
|
NumField() {
|
|
1474
1927
|
return 0;
|
|
1475
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
|
+
}
|
|
1476
1944
|
Key() {
|
|
1477
1945
|
return this._keyType;
|
|
1478
1946
|
}
|
|
@@ -1499,7 +1967,7 @@ class MapType {
|
|
|
1499
1967
|
if (u.Kind() !== Interface) {
|
|
1500
1968
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1501
1969
|
}
|
|
1502
|
-
return
|
|
1970
|
+
return typeImplementsInterface(this, u);
|
|
1503
1971
|
}
|
|
1504
1972
|
AssignableTo(u) {
|
|
1505
1973
|
return typeAssignableTo(this, u);
|
|
@@ -1530,47 +1998,122 @@ class MapType {
|
|
|
1530
1998
|
}
|
|
1531
1999
|
}
|
|
1532
2000
|
// Struct type implementation
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
*/
|
|
1541
|
-
function typeImplementsInterface(typeName, interfaceType) {
|
|
1542
|
-
// Get the interface name and look it up in the type registry
|
|
1543
|
-
const interfaceName = interfaceType instanceof InterfaceType ?
|
|
1544
|
-
interfaceType.registeredName() || interfaceType.String()
|
|
1545
|
-
: interfaceType.String();
|
|
1546
|
-
const interfaceTypeInfo = builtinGetTypeByName(interfaceName);
|
|
1547
|
-
if (!interfaceTypeInfo || !isInterfaceTypeInfo(interfaceTypeInfo)) {
|
|
1548
|
-
return false;
|
|
2001
|
+
function typeImplementsInterface(t, interfaceType) {
|
|
2002
|
+
if (interfaceType.Kind() !== Interface) {
|
|
2003
|
+
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
2004
|
+
}
|
|
2005
|
+
const requiredMethods = typeMethods(interfaceType);
|
|
2006
|
+
if (requiredMethods.length === 0) {
|
|
2007
|
+
return true;
|
|
1549
2008
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
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) {
|
|
1553
2021
|
return false;
|
|
1554
2022
|
}
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
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;
|
|
1563
2043
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
2044
|
+
if (methodSignatureIdentityKey(merged[existingIndex]) !==
|
|
2045
|
+
methodSignatureIdentityKey(method)) {
|
|
2046
|
+
merged[existingIndex] = method;
|
|
1567
2047
|
}
|
|
1568
|
-
|
|
1569
|
-
|
|
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}`;
|
|
2060
|
+
}
|
|
2061
|
+
if (seen.has(info)) {
|
|
2062
|
+
return `named:${info}`;
|
|
1570
2063
|
}
|
|
1571
|
-
|
|
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';
|
|
1572
2116
|
}
|
|
1573
|
-
return true;
|
|
1574
2117
|
}
|
|
1575
2118
|
function typeFieldByName(t, name) {
|
|
1576
2119
|
return typeFieldByNameFunc(t, (fieldName) => fieldName === name);
|
|
@@ -1579,14 +2122,62 @@ function typeFieldByNameFunc(t, match) {
|
|
|
1579
2122
|
if (t.Kind() !== Struct) {
|
|
1580
2123
|
throw new Error('reflect: FieldByName of non-struct type');
|
|
1581
2124
|
}
|
|
1582
|
-
for (
|
|
1583
|
-
const field = t.Field(i);
|
|
2125
|
+
for (const field of visibleStructFields(t)) {
|
|
1584
2126
|
if (match(field.Name)) {
|
|
1585
2127
|
return [field, true];
|
|
1586
2128
|
}
|
|
1587
2129
|
}
|
|
1588
2130
|
return [new StructField(), false];
|
|
1589
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
|
+
}
|
|
1590
2181
|
function zeroMethod() {
|
|
1591
2182
|
return {
|
|
1592
2183
|
Name: '',
|
|
@@ -1595,16 +2186,50 @@ function zeroMethod() {
|
|
|
1595
2186
|
Index: 0,
|
|
1596
2187
|
};
|
|
1597
2188
|
}
|
|
1598
|
-
function methodFromSignature(signature, index) {
|
|
2189
|
+
function methodFromSignature(signature, index, receiver) {
|
|
1599
2190
|
return {
|
|
1600
2191
|
Name: signature.name,
|
|
1601
|
-
Type:
|
|
2192
|
+
Type: methodTypeFromSignature(signature, receiver, receiver.Kind() !== Interface),
|
|
1602
2193
|
Func: () => undefined,
|
|
1603
2194
|
Index: index,
|
|
1604
2195
|
};
|
|
1605
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
|
+
}
|
|
1606
2210
|
function typeMethods(t) {
|
|
1607
|
-
|
|
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
|
+
}
|
|
1608
2233
|
if (!typeInfo) {
|
|
1609
2234
|
return [];
|
|
1610
2235
|
}
|
|
@@ -1613,29 +2238,98 @@ function typeMethods(t) {
|
|
|
1613
2238
|
}
|
|
1614
2239
|
return [];
|
|
1615
2240
|
}
|
|
1616
|
-
function
|
|
2241
|
+
function methodSignatureByName(t, name) {
|
|
1617
2242
|
const methods = typeMethods(t);
|
|
1618
2243
|
const index = methods.findIndex((method) => method.name === name);
|
|
1619
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) {
|
|
1620
2252
|
return [zeroMethod(), false];
|
|
1621
2253
|
}
|
|
1622
|
-
return [methodFromSignature(
|
|
2254
|
+
return [methodFromSignature(signature, index, t), true];
|
|
1623
2255
|
}
|
|
1624
2256
|
function typeAssignableTo(t, u) {
|
|
1625
2257
|
if (u === null) {
|
|
1626
2258
|
return false;
|
|
1627
2259
|
}
|
|
1628
|
-
|
|
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);
|
|
1629
2319
|
}
|
|
1630
2320
|
class StructType {
|
|
1631
2321
|
_name;
|
|
1632
2322
|
_fields;
|
|
1633
|
-
|
|
2323
|
+
_pkgPath;
|
|
2324
|
+
_string;
|
|
2325
|
+
constructor(_name, _fields = [], _pkgPath = '', _string = _name) {
|
|
1634
2326
|
this._name = _name;
|
|
1635
2327
|
this._fields = _fields;
|
|
2328
|
+
this._pkgPath = _pkgPath;
|
|
2329
|
+
this._string = _string;
|
|
1636
2330
|
}
|
|
1637
2331
|
String() {
|
|
1638
|
-
return this.
|
|
2332
|
+
return this._string;
|
|
1639
2333
|
}
|
|
1640
2334
|
Kind() {
|
|
1641
2335
|
return Struct;
|
|
@@ -1644,8 +2338,7 @@ class StructType {
|
|
|
1644
2338
|
return this._fields.every((field) => field.type.Comparable());
|
|
1645
2339
|
}
|
|
1646
2340
|
Size() {
|
|
1647
|
-
|
|
1648
|
-
return this._fields.reduce((sum, field) => sum + field.type.Size(), 0);
|
|
2341
|
+
return structDescriptorSize(this._fields);
|
|
1649
2342
|
}
|
|
1650
2343
|
Elem() {
|
|
1651
2344
|
throw new Error('reflect: Elem of invalid type');
|
|
@@ -1653,7 +2346,28 @@ class StructType {
|
|
|
1653
2346
|
NumField() {
|
|
1654
2347
|
return this._fields.length;
|
|
1655
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
|
+
}
|
|
1656
2364
|
PkgPath() {
|
|
2365
|
+
if (this._pkgPath !== '') {
|
|
2366
|
+
return this._pkgPath;
|
|
2367
|
+
}
|
|
2368
|
+
if (this._name === '') {
|
|
2369
|
+
return '';
|
|
2370
|
+
}
|
|
1657
2371
|
// Extract package path from full type name (e.g., "main.Person" -> "main")
|
|
1658
2372
|
const dotIndex = this._name.lastIndexOf('.');
|
|
1659
2373
|
if (dotIndex > 0) {
|
|
@@ -1662,6 +2376,9 @@ class StructType {
|
|
|
1662
2376
|
return '';
|
|
1663
2377
|
}
|
|
1664
2378
|
Name() {
|
|
2379
|
+
if (this._name === '') {
|
|
2380
|
+
return '';
|
|
2381
|
+
}
|
|
1665
2382
|
// Extract type name from full type name (e.g., "main.Person" -> "Person")
|
|
1666
2383
|
const dotIndex = this._name.lastIndexOf('.');
|
|
1667
2384
|
if (dotIndex >= 0) {
|
|
@@ -1676,12 +2393,56 @@ class StructType {
|
|
|
1676
2393
|
const f = this._fields[i];
|
|
1677
2394
|
return new StructField({
|
|
1678
2395
|
Name: f.name,
|
|
1679
|
-
PkgPath:
|
|
2396
|
+
PkgPath: f.pkgPath,
|
|
1680
2397
|
Type: f.type,
|
|
1681
2398
|
Tag: f.tag ? new StructTag(f.tag) : undefined,
|
|
1682
|
-
|
|
2399
|
+
Offset: f.offset,
|
|
2400
|
+
Index: [...f.index],
|
|
2401
|
+
Anonymous: f.anonymous,
|
|
1683
2402
|
});
|
|
1684
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
|
+
}
|
|
1685
2446
|
FieldByName(name) {
|
|
1686
2447
|
return typeFieldByName(this, name);
|
|
1687
2448
|
}
|
|
@@ -1698,7 +2459,7 @@ class StructType {
|
|
|
1698
2459
|
if (u.Kind() !== Interface) {
|
|
1699
2460
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1700
2461
|
}
|
|
1701
|
-
return typeImplementsInterface(this
|
|
2462
|
+
return typeImplementsInterface(this, u);
|
|
1702
2463
|
}
|
|
1703
2464
|
AssignableTo(u) {
|
|
1704
2465
|
return typeAssignableTo(this, u);
|
|
@@ -1727,7 +2488,7 @@ class StructType {
|
|
|
1727
2488
|
Bits() {
|
|
1728
2489
|
throw new Error('reflect: call of reflect.Type.Bits on struct Type');
|
|
1729
2490
|
}
|
|
1730
|
-
static createTypeFromFieldInfo(ti) {
|
|
2491
|
+
static createTypeFromFieldInfo(ti, seen = new Set()) {
|
|
1731
2492
|
if (typeof ti === 'string') {
|
|
1732
2493
|
return basicTypeFromName(ti === 'number' ? 'int' : ti);
|
|
1733
2494
|
}
|
|
@@ -1740,18 +2501,21 @@ class StructType {
|
|
|
1740
2501
|
return basicTypeFromName(name === 'number' ? 'int' : name, typeName);
|
|
1741
2502
|
case 'slice':
|
|
1742
2503
|
if (ti.elemType) {
|
|
1743
|
-
return new SliceType(StructType.createTypeFromFieldInfo(ti.elemType));
|
|
2504
|
+
return new SliceType(StructType.createTypeFromFieldInfo(ti.elemType, seen));
|
|
1744
2505
|
}
|
|
1745
2506
|
return new SliceType(new BasicType(Invalid, 'unknown', 8));
|
|
1746
2507
|
case 'pointer':
|
|
1747
2508
|
if (ti.elemType) {
|
|
1748
|
-
return new PointerType(StructType.createTypeFromFieldInfo(ti.elemType));
|
|
2509
|
+
return new PointerType(StructType.createTypeFromFieldInfo(ti.elemType, seen));
|
|
1749
2510
|
}
|
|
1750
2511
|
return new PointerType(new BasicType(Invalid, 'unknown', 8));
|
|
1751
2512
|
case 'interface':
|
|
1752
|
-
return
|
|
1753
|
-
case 'struct':
|
|
1754
|
-
|
|
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
|
+
}
|
|
1755
2519
|
default:
|
|
1756
2520
|
return new BasicType(Invalid, name, 8);
|
|
1757
2521
|
}
|
|
@@ -1801,18 +2565,66 @@ function basicTypeFromName(name, typeName = '') {
|
|
|
1801
2565
|
return new BasicType(Invalid, name, 8, typeName);
|
|
1802
2566
|
}
|
|
1803
2567
|
}
|
|
1804
|
-
function
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
2568
|
+
function typeFromGoTypeName(typeName) {
|
|
2569
|
+
const trimmed = typeName.trim();
|
|
2570
|
+
if (trimmed === '')
|
|
2571
|
+
return null;
|
|
2572
|
+
if (trimmed.startsWith('<-chan ')) {
|
|
2573
|
+
return new ChannelType(typeFromGoTypeName(trimmed.slice(7)) ?? anyType(), RecvDir);
|
|
2574
|
+
}
|
|
2575
|
+
if (trimmed.startsWith('chan<- ')) {
|
|
2576
|
+
return new ChannelType(typeFromGoTypeName(trimmed.slice(7)) ?? anyType(), SendDir);
|
|
2577
|
+
}
|
|
2578
|
+
if (trimmed.startsWith('chan ')) {
|
|
2579
|
+
return new ChannelType(typeFromGoTypeName(trimmed.slice(5)) ?? anyType(), BothDir);
|
|
2580
|
+
}
|
|
2581
|
+
if (trimmed.startsWith('[]')) {
|
|
2582
|
+
return new SliceType(typeFromGoTypeName(trimmed.slice(2)) ?? anyType());
|
|
2583
|
+
}
|
|
2584
|
+
if (trimmed.startsWith('*')) {
|
|
2585
|
+
return new PointerType(typeFromGoTypeName(trimmed.slice(1)) ?? anyType());
|
|
2586
|
+
}
|
|
2587
|
+
if (trimmed === 'struct{}' || trimmed === 'struct {}') {
|
|
2588
|
+
return new StructType('', [], '', 'struct {}');
|
|
2589
|
+
}
|
|
2590
|
+
if (trimmed === 'interface{}' || trimmed === 'any') {
|
|
2591
|
+
return anyType();
|
|
2592
|
+
}
|
|
2593
|
+
if (trimmed === 'error') {
|
|
2594
|
+
return new InterfaceType('error', 'error');
|
|
2595
|
+
}
|
|
2596
|
+
const registered = builtinGetTypeByName(trimmed);
|
|
2597
|
+
if (registered) {
|
|
2598
|
+
return typeFromTypeInfo(registered);
|
|
2599
|
+
}
|
|
2600
|
+
const basic = basicTypeFromName(trimmed);
|
|
2601
|
+
if (basic.Kind() !== Invalid) {
|
|
2602
|
+
return basic;
|
|
2603
|
+
}
|
|
2604
|
+
return null;
|
|
2605
|
+
}
|
|
2606
|
+
function channelTypeFromGoTypeName(typeName) {
|
|
2607
|
+
const typ = typeFromGoTypeName(typeName);
|
|
2608
|
+
if (typ?.Kind() === Chan) {
|
|
2609
|
+
return typ;
|
|
2610
|
+
}
|
|
2611
|
+
return null;
|
|
2612
|
+
}
|
|
2613
|
+
function anyType() {
|
|
2614
|
+
return new BasicType(Interface, 'interface{}', 16);
|
|
2615
|
+
}
|
|
2616
|
+
function structFieldsFromTypeInfo(ti, seen = new Set()) {
|
|
2617
|
+
return (ti.fields || []).map((fieldInfo, index) => {
|
|
1813
2618
|
return {
|
|
1814
|
-
name,
|
|
1815
|
-
|
|
2619
|
+
name: fieldInfo.name,
|
|
2620
|
+
key: structFieldRuntimeKey(fieldInfo),
|
|
2621
|
+
type: typeFromTypeInfoWithSeen(fieldInfo.type, seen),
|
|
2622
|
+
tag: fieldInfo.tag,
|
|
2623
|
+
pkgPath: fieldInfo.pkgPath ?? '',
|
|
2624
|
+
anonymous: fieldInfo.anonymous ?? false,
|
|
2625
|
+
index: fieldInfo.index ? [...fieldInfo.index] : [index],
|
|
2626
|
+
offset: fieldInfo.offset ?? index * 8,
|
|
2627
|
+
exported: fieldInfo.exported ?? (fieldInfo.pkgPath ?? '') === '',
|
|
1816
2628
|
};
|
|
1817
2629
|
});
|
|
1818
2630
|
}
|
|
@@ -1852,6 +2664,21 @@ class ChannelType {
|
|
|
1852
2664
|
NumField() {
|
|
1853
2665
|
return 0;
|
|
1854
2666
|
}
|
|
2667
|
+
NumIn() {
|
|
2668
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
2669
|
+
}
|
|
2670
|
+
In(_i) {
|
|
2671
|
+
return nonFunctionTypePanic('In', this);
|
|
2672
|
+
}
|
|
2673
|
+
NumOut() {
|
|
2674
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
2675
|
+
}
|
|
2676
|
+
Out(_i) {
|
|
2677
|
+
return nonFunctionTypePanic('Out', this);
|
|
2678
|
+
}
|
|
2679
|
+
IsVariadic() {
|
|
2680
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
2681
|
+
}
|
|
1855
2682
|
PkgPath() {
|
|
1856
2683
|
return '';
|
|
1857
2684
|
}
|
|
@@ -1878,7 +2705,7 @@ class ChannelType {
|
|
|
1878
2705
|
if (u.Kind() !== Interface) {
|
|
1879
2706
|
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
1880
2707
|
}
|
|
1881
|
-
return
|
|
2708
|
+
return typeImplementsInterface(this, u);
|
|
1882
2709
|
}
|
|
1883
2710
|
AssignableTo(u) {
|
|
1884
2711
|
return typeAssignableTo(this, u);
|
|
@@ -1915,9 +2742,11 @@ class ChannelType {
|
|
|
1915
2742
|
class InterfaceType {
|
|
1916
2743
|
_name;
|
|
1917
2744
|
_registeredName;
|
|
1918
|
-
|
|
2745
|
+
_methods;
|
|
2746
|
+
constructor(_name = 'interface{}', _registeredName, _methods = []) {
|
|
1919
2747
|
this._name = _name;
|
|
1920
2748
|
this._registeredName = _registeredName;
|
|
2749
|
+
this._methods = _methods;
|
|
1921
2750
|
}
|
|
1922
2751
|
String() {
|
|
1923
2752
|
return this._name;
|
|
@@ -1937,6 +2766,21 @@ class InterfaceType {
|
|
|
1937
2766
|
NumField() {
|
|
1938
2767
|
return 0;
|
|
1939
2768
|
}
|
|
2769
|
+
NumIn() {
|
|
2770
|
+
return nonFunctionTypePanic('NumIn', this);
|
|
2771
|
+
}
|
|
2772
|
+
In(_i) {
|
|
2773
|
+
return nonFunctionTypePanic('In', this);
|
|
2774
|
+
}
|
|
2775
|
+
NumOut() {
|
|
2776
|
+
return nonFunctionTypePanic('NumOut', this);
|
|
2777
|
+
}
|
|
2778
|
+
Out(_i) {
|
|
2779
|
+
return nonFunctionTypePanic('Out', this);
|
|
2780
|
+
}
|
|
2781
|
+
IsVariadic() {
|
|
2782
|
+
return nonFunctionTypePanic('IsVariadic', this);
|
|
2783
|
+
}
|
|
1940
2784
|
PkgPath() {
|
|
1941
2785
|
if (this._name === 'interface{}' || this._name.startsWith('interface {')) {
|
|
1942
2786
|
return '';
|
|
@@ -1969,8 +2813,14 @@ class InterfaceType {
|
|
|
1969
2813
|
Key() {
|
|
1970
2814
|
throw new Error('reflect: Key of non-map type');
|
|
1971
2815
|
}
|
|
1972
|
-
Implements(
|
|
1973
|
-
|
|
2816
|
+
Implements(u) {
|
|
2817
|
+
if (!u) {
|
|
2818
|
+
return false;
|
|
2819
|
+
}
|
|
2820
|
+
if (u.Kind() !== Interface) {
|
|
2821
|
+
throw new Error('reflect: non-interface type passed to Type.Implements');
|
|
2822
|
+
}
|
|
2823
|
+
return typeImplementsInterface(this, u);
|
|
1974
2824
|
}
|
|
1975
2825
|
AssignableTo(u) {
|
|
1976
2826
|
return typeAssignableTo(this, u);
|
|
@@ -2002,6 +2852,9 @@ class InterfaceType {
|
|
|
2002
2852
|
registeredName() {
|
|
2003
2853
|
return this._registeredName;
|
|
2004
2854
|
}
|
|
2855
|
+
methodSignatures() {
|
|
2856
|
+
return this._methods;
|
|
2857
|
+
}
|
|
2005
2858
|
}
|
|
2006
2859
|
function getTypeOf(value) {
|
|
2007
2860
|
// Check for typed nil before checking for plain null
|
|
@@ -2043,22 +2896,19 @@ function getTypeOf(value) {
|
|
|
2043
2896
|
if ((typeInfo.kind === 'function' || typeInfo.kind === 'Function') &&
|
|
2044
2897
|
typeInfo.params &&
|
|
2045
2898
|
typeInfo.results) {
|
|
2899
|
+
if (funcWithMeta.__goTypeName && !typeInfo.name) {
|
|
2900
|
+
return functionTypeFromInfo({
|
|
2901
|
+
...typeInfo,
|
|
2902
|
+
name: funcWithMeta.__goTypeName,
|
|
2903
|
+
});
|
|
2904
|
+
}
|
|
2046
2905
|
return functionTypeFromInfo(typeInfo);
|
|
2047
2906
|
}
|
|
2048
2907
|
}
|
|
2049
2908
|
// Then check for __goTypeName which indicates a typed function
|
|
2050
2909
|
if (funcWithMeta.__goTypeName) {
|
|
2051
|
-
// This is a typed Go function - try to reconstruct the signature
|
|
2052
2910
|
const typeName = funcWithMeta.__goTypeName;
|
|
2053
|
-
|
|
2054
|
-
if (typeName === 'Greeter') {
|
|
2055
|
-
return new FunctionType('func(string) string');
|
|
2056
|
-
}
|
|
2057
|
-
else if (typeName === 'Adder') {
|
|
2058
|
-
return new FunctionType('func(int, int) int');
|
|
2059
|
-
}
|
|
2060
|
-
// Generic fallback for typed functions
|
|
2061
|
-
return new FunctionType(`func`); // Could be enhanced with parameter parsing
|
|
2911
|
+
return new FunctionType({ name: typeName });
|
|
2062
2912
|
}
|
|
2063
2913
|
// For untyped functions, try to parse the signature
|
|
2064
2914
|
const funcStr = value.toString();
|
|
@@ -2098,6 +2948,15 @@ function getTypeOf(value) {
|
|
|
2098
2948
|
value.__goTypeInfo) {
|
|
2099
2949
|
return typeFromTypeInfo(value.__goTypeInfo);
|
|
2100
2950
|
}
|
|
2951
|
+
if ('__goType' in value) {
|
|
2952
|
+
const goType = value.__goType;
|
|
2953
|
+
if (typeof goType === 'string') {
|
|
2954
|
+
const channelType = channelTypeFromGoTypeName(goType);
|
|
2955
|
+
if (channelType) {
|
|
2956
|
+
return channelType;
|
|
2957
|
+
}
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2101
2960
|
if ('real' in value &&
|
|
2102
2961
|
'imag' in value &&
|
|
2103
2962
|
typeof value.real === 'number' &&
|
|
@@ -2165,34 +3024,31 @@ function getTypeOf(value) {
|
|
|
2165
3024
|
}
|
|
2166
3025
|
}
|
|
2167
3026
|
// Check if it has a constructor with __typeInfo for proper struct names
|
|
3027
|
+
if (value &&
|
|
3028
|
+
typeof value === 'object' &&
|
|
3029
|
+
value.constructor &&
|
|
3030
|
+
'__reflectType' in value.constructor) {
|
|
3031
|
+
const reflectType = value.constructor
|
|
3032
|
+
.__reflectType;
|
|
3033
|
+
if (reflectType) {
|
|
3034
|
+
return reflectType;
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
2168
3037
|
if (value &&
|
|
2169
3038
|
typeof value === 'object' &&
|
|
2170
3039
|
value.constructor &&
|
|
2171
3040
|
'__typeInfo' in value.constructor) {
|
|
2172
3041
|
const typeInfo = value.constructor.__typeInfo;
|
|
2173
|
-
if (typeInfo && typeInfo
|
|
2174
|
-
const
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
const regTypeInfo = builtinGetTypeByName(typeName);
|
|
2178
|
-
let fields = [];
|
|
2179
|
-
if (regTypeInfo && isStructTypeInfo(regTypeInfo)) {
|
|
2180
|
-
fields = Object.entries(regTypeInfo.fields || {}).map(([name, fieldInfo]) => {
|
|
2181
|
-
// Check if fieldInfo is a StructFieldInfo with type and tag
|
|
2182
|
-
if (isStructFieldInfo(fieldInfo)) {
|
|
2183
|
-
return {
|
|
2184
|
-
name: fieldInfo.name ?? name,
|
|
2185
|
-
type: StructType.createTypeFromFieldInfo(fieldInfo.type),
|
|
2186
|
-
tag: fieldInfo.tag,
|
|
2187
|
-
};
|
|
2188
|
-
}
|
|
2189
|
-
// Otherwise it's just the type info directly (backwards compatible)
|
|
2190
|
-
return {
|
|
2191
|
-
name,
|
|
2192
|
-
type: StructType.createTypeFromFieldInfo(fieldInfo),
|
|
2193
|
-
};
|
|
2194
|
-
});
|
|
3042
|
+
if (typeInfo && isStructTypeInfo(typeInfo)) {
|
|
3043
|
+
const name = typeInfo.name ?? '';
|
|
3044
|
+
if (name === '') {
|
|
3045
|
+
return new StructType('', structFieldsFromTypeInfo(typeInfo));
|
|
2195
3046
|
}
|
|
3047
|
+
const typeName = name.includes('.') ? name : `main.${name}`;
|
|
3048
|
+
const regTypeInfo = builtinGetTypeByName(typeName);
|
|
3049
|
+
const fields = regTypeInfo && isStructTypeInfo(regTypeInfo) ?
|
|
3050
|
+
structFieldsFromTypeInfo(regTypeInfo)
|
|
3051
|
+
: structFieldsFromTypeInfo(typeInfo);
|
|
2196
3052
|
return new StructType(typeName, fields);
|
|
2197
3053
|
}
|
|
2198
3054
|
}
|
|
@@ -2242,86 +3098,497 @@ export function MapOf(key, elem) {
|
|
|
2242
3098
|
export function ChanOf(dir, t) {
|
|
2243
3099
|
return internType(new ChannelType(t, dir));
|
|
2244
3100
|
}
|
|
3101
|
+
export function StructOf(fields) {
|
|
3102
|
+
const inputFields = $.asArray(fields);
|
|
3103
|
+
const descriptors = [];
|
|
3104
|
+
const names = new Set();
|
|
3105
|
+
let pkgPath = '';
|
|
3106
|
+
let offset = 0;
|
|
3107
|
+
for (const [idx, field] of inputFields.entries()) {
|
|
3108
|
+
validateStructOfField(field, idx);
|
|
3109
|
+
if (field.PkgPath !== '') {
|
|
3110
|
+
if (pkgPath === '') {
|
|
3111
|
+
pkgPath = field.PkgPath;
|
|
3112
|
+
}
|
|
3113
|
+
else if (pkgPath !== field.PkgPath) {
|
|
3114
|
+
throw new Error(`reflect.Struct: fields with different PkgPath ${pkgPath} and ${field.PkgPath}`);
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
if (names.has(field.Name) && field.Name !== '_') {
|
|
3118
|
+
throw new Error(`reflect.StructOf: duplicate field ${field.Name}`);
|
|
3119
|
+
}
|
|
3120
|
+
names.add(field.Name);
|
|
3121
|
+
const fieldOffset = alignOffset(offset, typeAlignment(field.Type));
|
|
3122
|
+
const tag = field.Tag?.toString();
|
|
3123
|
+
const descriptor = {
|
|
3124
|
+
name: field.Name,
|
|
3125
|
+
key: field.Name === '_' ? `_${idx}` : field.Name,
|
|
3126
|
+
type: field.Type,
|
|
3127
|
+
...(tag ? { tag } : {}),
|
|
3128
|
+
pkgPath: field.PkgPath,
|
|
3129
|
+
anonymous: field.Anonymous,
|
|
3130
|
+
index: [idx],
|
|
3131
|
+
offset: fieldOffset,
|
|
3132
|
+
exported: field.IsExported(),
|
|
3133
|
+
};
|
|
3134
|
+
descriptors.push(descriptor);
|
|
3135
|
+
offset = fieldOffset + field.Type.Size();
|
|
3136
|
+
}
|
|
3137
|
+
return internType(new StructType('', descriptors, '', structTypeString(descriptors)));
|
|
3138
|
+
}
|
|
3139
|
+
function validateStructOfField(field, idx) {
|
|
3140
|
+
if (field.Name === '') {
|
|
3141
|
+
throw new Error(`reflect.StructOf: field ${idx} has no name`);
|
|
3142
|
+
}
|
|
3143
|
+
if (!isValidStructFieldName(field.Name)) {
|
|
3144
|
+
throw new Error(`reflect.StructOf: field ${idx} has invalid name`);
|
|
3145
|
+
}
|
|
3146
|
+
if (!field.Type) {
|
|
3147
|
+
throw new Error(`reflect.StructOf: field ${idx} has no type`);
|
|
3148
|
+
}
|
|
3149
|
+
if (field.Anonymous && field.PkgPath !== '') {
|
|
3150
|
+
throw new Error(`reflect.StructOf: field "${field.Name}" is anonymous but has PkgPath set`);
|
|
3151
|
+
}
|
|
3152
|
+
if (field.IsExported() && isUnexportedStructFieldName(field.Name)) {
|
|
3153
|
+
throw new Error(`reflect.StructOf: field "${field.Name}" is unexported but missing PkgPath`);
|
|
3154
|
+
}
|
|
3155
|
+
validateAnonymousStructOfField(field);
|
|
3156
|
+
}
|
|
3157
|
+
function isValidStructFieldName(name) {
|
|
3158
|
+
return /^[\p{L}_][\p{L}\p{N}_]*$/u.test(name);
|
|
3159
|
+
}
|
|
3160
|
+
function isUnexportedStructFieldName(name) {
|
|
3161
|
+
const first = name.charCodeAt(0);
|
|
3162
|
+
return name[0] === '_' || (first >= 97 && first <= 122);
|
|
3163
|
+
}
|
|
3164
|
+
function validateAnonymousStructOfField(field) {
|
|
3165
|
+
if (!field.Anonymous) {
|
|
3166
|
+
return;
|
|
3167
|
+
}
|
|
3168
|
+
const typ = field.Type;
|
|
3169
|
+
if (typ.Kind() === Ptr) {
|
|
3170
|
+
const elem = typ.Elem();
|
|
3171
|
+
if (elem.Kind() === Ptr || elem.Kind() === Interface) {
|
|
3172
|
+
throw new Error(`reflect.StructOf: illegal embedded field type ${typ.String()}`);
|
|
3173
|
+
}
|
|
3174
|
+
if (embeddedMethodCount(typ) > 0) {
|
|
3175
|
+
throw new Error('reflect: embedded type with methods not implemented');
|
|
3176
|
+
}
|
|
3177
|
+
return;
|
|
3178
|
+
}
|
|
3179
|
+
if (embeddedMethodCount(typ) > 0) {
|
|
3180
|
+
throw new Error('reflect: embedded type with methods not implemented');
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
function embeddedMethodCount(typ) {
|
|
3184
|
+
if (typ.Kind() === Ptr) {
|
|
3185
|
+
return Math.max(typ.NumMethod(), typ.Elem().NumMethod());
|
|
3186
|
+
}
|
|
3187
|
+
return typ.NumMethod();
|
|
3188
|
+
}
|
|
3189
|
+
function structTypeString(fields) {
|
|
3190
|
+
if (fields.length === 0) {
|
|
3191
|
+
return 'struct {}';
|
|
3192
|
+
}
|
|
3193
|
+
return `struct { ${fields.map(structFieldString).join('; ')} }`;
|
|
3194
|
+
}
|
|
3195
|
+
function structFieldString(field) {
|
|
3196
|
+
const tag = field.tag ? ` ${JSON.stringify(field.tag)}` : '';
|
|
3197
|
+
const prefix = field.anonymous ? '' : `${field.name} `;
|
|
3198
|
+
return `${prefix}${field.type.String()}${tag}`;
|
|
3199
|
+
}
|
|
3200
|
+
export function FuncOf(inTypes, outTypes, variadic) {
|
|
3201
|
+
const params = $.asArray(inTypes).map(funcOfType);
|
|
3202
|
+
const results = $.asArray(outTypes).map(funcOfType);
|
|
3203
|
+
if (variadic &&
|
|
3204
|
+
(params.length === 0 || params[params.length - 1].Kind() !== Slice)) {
|
|
3205
|
+
throw new Error('reflect.FuncOf: last arg of variadic func must be slice');
|
|
3206
|
+
}
|
|
3207
|
+
if (params.length + results.length > 128) {
|
|
3208
|
+
throw new Error('reflect.FuncOf: too many arguments');
|
|
3209
|
+
}
|
|
3210
|
+
return internType(new FunctionType({ params, results, variadic }));
|
|
3211
|
+
}
|
|
3212
|
+
function funcOfType(typ) {
|
|
3213
|
+
if (!typ) {
|
|
3214
|
+
throw new Error('reflect.FuncOf: nil Type');
|
|
3215
|
+
}
|
|
3216
|
+
return typ;
|
|
3217
|
+
}
|
|
2245
3218
|
export function TypeFor(typeArgs) {
|
|
2246
3219
|
const descriptor = typeArgs?.T;
|
|
3220
|
+
const methodSignatures = genericMethodSignatures(descriptor);
|
|
2247
3221
|
if (descriptor?.type) {
|
|
2248
|
-
return internType(typeFromTypeInfo(descriptor.type));
|
|
3222
|
+
return internType(typeWithMethodSignatures(typeFromTypeInfo(descriptor.type), methodSignatures));
|
|
2249
3223
|
}
|
|
2250
|
-
if (
|
|
2251
|
-
|
|
2252
|
-
if (methods.length !== 0) {
|
|
2253
|
-
return internType(new InterfaceType(`interface { ${methods.map((method) => method + '()').join('; ')} }`));
|
|
2254
|
-
}
|
|
3224
|
+
if (methodSignatures.length !== 0) {
|
|
3225
|
+
return internType(new InterfaceType(interfaceTypeString(methodSignatures), undefined, methodSignatures));
|
|
2255
3226
|
}
|
|
2256
3227
|
if (descriptor?.zero) {
|
|
2257
3228
|
return internType(getTypeOf(descriptor.zero()));
|
|
2258
3229
|
}
|
|
2259
3230
|
return internType(new InterfaceType('interface{}'));
|
|
2260
3231
|
}
|
|
3232
|
+
function genericMethodSignatures(descriptor) {
|
|
3233
|
+
if (!descriptor) {
|
|
3234
|
+
return [];
|
|
3235
|
+
}
|
|
3236
|
+
if (descriptor.methodSignatures && descriptor.methodSignatures.length !== 0) {
|
|
3237
|
+
return descriptor.methodSignatures;
|
|
3238
|
+
}
|
|
3239
|
+
if (!descriptor.methods) {
|
|
3240
|
+
return [];
|
|
3241
|
+
}
|
|
3242
|
+
return Object.keys(descriptor.methods).map((method) => ({
|
|
3243
|
+
name: method,
|
|
3244
|
+
args: [],
|
|
3245
|
+
returns: [],
|
|
3246
|
+
}));
|
|
3247
|
+
}
|
|
3248
|
+
function typeWithMethodSignatures(typ, methods) {
|
|
3249
|
+
if (methods.length === 0) {
|
|
3250
|
+
return typ;
|
|
3251
|
+
}
|
|
3252
|
+
if (typ instanceof BasicType) {
|
|
3253
|
+
typ.mergeMethodSignatures(methods);
|
|
3254
|
+
return typ;
|
|
3255
|
+
}
|
|
3256
|
+
if (typ instanceof PointerType) {
|
|
3257
|
+
typ.mergeMethodSignatures(methods);
|
|
3258
|
+
return typ;
|
|
3259
|
+
}
|
|
3260
|
+
if (typ instanceof FunctionType) {
|
|
3261
|
+
typ.mergeMethodSignatures(methods);
|
|
3262
|
+
return typ;
|
|
3263
|
+
}
|
|
3264
|
+
return typ;
|
|
3265
|
+
}
|
|
2261
3266
|
function typeFromTypeInfo(info) {
|
|
3267
|
+
return typeFromTypeInfoWithSeen(info, new Set());
|
|
3268
|
+
}
|
|
3269
|
+
function typeFromTypeInfoWithSeen(info, seen) {
|
|
2262
3270
|
if (typeof info === 'string') {
|
|
2263
3271
|
const registered = builtinGetTypeByName(info);
|
|
2264
3272
|
if (registered) {
|
|
2265
|
-
|
|
3273
|
+
const typ = typeFromTypeInfoWithSeen(registered, seen);
|
|
3274
|
+
return internType(typ);
|
|
3275
|
+
}
|
|
3276
|
+
return internType(StructType.createTypeFromFieldInfo(info, seen));
|
|
3277
|
+
}
|
|
3278
|
+
const recursiveName = recursiveTypeInfoName(info);
|
|
3279
|
+
if (recursiveName !== '') {
|
|
3280
|
+
const constructing = constructingRegisteredTypes.get(recursiveName);
|
|
3281
|
+
if (constructing) {
|
|
3282
|
+
return constructing;
|
|
3283
|
+
}
|
|
3284
|
+
if (seen.has(recursiveName)) {
|
|
3285
|
+
return internType(shallowTypeFromRegisteredInfo(recursiveName, info));
|
|
3286
|
+
}
|
|
3287
|
+
if (info.kind === $.TypeKind.Struct) {
|
|
3288
|
+
const typ = new StructType(recursiveName, []);
|
|
3289
|
+
constructingRegisteredTypes.set(recursiveName, typ);
|
|
3290
|
+
seen.add(recursiveName);
|
|
3291
|
+
try {
|
|
3292
|
+
typ.replaceDescriptors(structFieldsFromTypeInfo(info, seen));
|
|
3293
|
+
return internType(typ);
|
|
3294
|
+
}
|
|
3295
|
+
finally {
|
|
3296
|
+
seen.delete(recursiveName);
|
|
3297
|
+
constructingRegisteredTypes.delete(recursiveName);
|
|
3298
|
+
}
|
|
2266
3299
|
}
|
|
2267
|
-
|
|
3300
|
+
seen.add(recursiveName);
|
|
3301
|
+
const typ = typeFromStructuredTypeInfoWithSeen(info, seen);
|
|
3302
|
+
seen.delete(recursiveName);
|
|
3303
|
+
return internType(typ);
|
|
2268
3304
|
}
|
|
3305
|
+
return internType(typeFromStructuredTypeInfoWithSeen(info, seen));
|
|
3306
|
+
}
|
|
3307
|
+
function recursiveTypeInfoName(info) {
|
|
3308
|
+
if (info.kind === $.TypeKind.Basic) {
|
|
3309
|
+
return info.typeName ?? '';
|
|
3310
|
+
}
|
|
3311
|
+
return info.name ?? '';
|
|
3312
|
+
}
|
|
3313
|
+
function typeFromStructuredTypeInfoWithSeen(info, seen) {
|
|
2269
3314
|
switch (info.kind) {
|
|
2270
3315
|
case $.TypeKind.Array:
|
|
2271
|
-
return
|
|
3316
|
+
return new ArrayType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), info.length);
|
|
2272
3317
|
case $.TypeKind.Basic:
|
|
2273
|
-
return
|
|
3318
|
+
return StructType.createTypeFromFieldInfo(info, seen);
|
|
2274
3319
|
case $.TypeKind.Channel:
|
|
2275
|
-
return
|
|
3320
|
+
return new ChannelType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), chanDirFromTypeInfo(info.direction));
|
|
2276
3321
|
case $.TypeKind.Function:
|
|
2277
|
-
return
|
|
3322
|
+
return functionTypeFromInfo(info, seen);
|
|
2278
3323
|
case $.TypeKind.Interface:
|
|
2279
|
-
return
|
|
3324
|
+
return interfaceTypeFromInfo(info, seen);
|
|
2280
3325
|
case $.TypeKind.Map:
|
|
2281
|
-
return
|
|
3326
|
+
return new MapType(typeFromTypeInfoWithSeen(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
|
|
2282
3327
|
case $.TypeKind.Slice:
|
|
2283
|
-
return
|
|
3328
|
+
return new SliceType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
|
|
2284
3329
|
case $.TypeKind.Struct:
|
|
2285
|
-
return
|
|
3330
|
+
return StructType.createTypeFromFieldInfo(info, seen);
|
|
2286
3331
|
case $.TypeKind.Pointer:
|
|
2287
|
-
return
|
|
3332
|
+
return new PointerType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
|
|
2288
3333
|
default:
|
|
2289
|
-
return
|
|
3334
|
+
return StructType.createTypeFromFieldInfo(info, seen);
|
|
2290
3335
|
}
|
|
2291
3336
|
}
|
|
2292
|
-
function
|
|
2293
|
-
|
|
2294
|
-
|
|
3337
|
+
function shallowTypeFromRegisteredInfo(name, info) {
|
|
3338
|
+
switch (info.kind) {
|
|
3339
|
+
case $.TypeKind.Interface:
|
|
3340
|
+
return new InterfaceType(name, name, info.methods ?? []);
|
|
3341
|
+
case $.TypeKind.Struct:
|
|
3342
|
+
return new StructType(name, []);
|
|
3343
|
+
case $.TypeKind.Function:
|
|
3344
|
+
return new FunctionType({ name });
|
|
3345
|
+
case $.TypeKind.Basic:
|
|
3346
|
+
return StructType.createTypeFromFieldInfo({
|
|
3347
|
+
kind: $.TypeKind.Basic,
|
|
3348
|
+
name: info.name ?? 'unknown',
|
|
3349
|
+
typeName: info.typeName ?? name,
|
|
3350
|
+
});
|
|
3351
|
+
default:
|
|
3352
|
+
return StructType.createTypeFromFieldInfo(name);
|
|
2295
3353
|
}
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
return '...' + typeName;
|
|
3354
|
+
}
|
|
3355
|
+
function functionTypeFromInfo(info, seen = new Set()) {
|
|
3356
|
+
const params = (info.params ?? []).map((param) => typeFromTypeInfoWithSeen(param, seen));
|
|
3357
|
+
const results = (info.results ?? []).map((result) => typeFromTypeInfoWithSeen(result, seen));
|
|
3358
|
+
return new FunctionType({
|
|
3359
|
+
name: info.name,
|
|
3360
|
+
params,
|
|
3361
|
+
results,
|
|
3362
|
+
variadic: info.isVariadic ?? false,
|
|
2306
3363
|
});
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
3364
|
+
}
|
|
3365
|
+
function functionTypeInfoFromType(typ) {
|
|
3366
|
+
const params = [];
|
|
3367
|
+
for (let i = 0; i < typ.NumIn(); i++) {
|
|
3368
|
+
params.push(typeInfoFromReflectType(typ.In(i)));
|
|
3369
|
+
}
|
|
3370
|
+
const results = [];
|
|
3371
|
+
for (let i = 0; i < typ.NumOut(); i++) {
|
|
3372
|
+
results.push(typeInfoFromReflectType(typ.Out(i)));
|
|
3373
|
+
}
|
|
3374
|
+
const info = {
|
|
3375
|
+
kind: $.TypeKind.Function,
|
|
3376
|
+
params,
|
|
3377
|
+
results,
|
|
3378
|
+
};
|
|
3379
|
+
if (typ.Name() !== '') {
|
|
3380
|
+
info.name = typ.String();
|
|
3381
|
+
}
|
|
3382
|
+
if (typ.IsVariadic()) {
|
|
3383
|
+
info.isVariadic = true;
|
|
3384
|
+
}
|
|
3385
|
+
return info;
|
|
3386
|
+
}
|
|
3387
|
+
export function typeInfoFromReflectType(typ) {
|
|
3388
|
+
if (typ.PkgPath() !== '' && typ.Name() !== '') {
|
|
3389
|
+
return typ.String();
|
|
3390
|
+
}
|
|
3391
|
+
switch (typ.Kind()) {
|
|
3392
|
+
case Bool:
|
|
3393
|
+
case Int:
|
|
3394
|
+
case Int8:
|
|
3395
|
+
case Int16:
|
|
3396
|
+
case Int32:
|
|
3397
|
+
case Int64:
|
|
3398
|
+
case Uint:
|
|
3399
|
+
case Uint8:
|
|
3400
|
+
case Uint16:
|
|
3401
|
+
case Uint32:
|
|
3402
|
+
case Uint64:
|
|
3403
|
+
case Uintptr:
|
|
3404
|
+
case Float32:
|
|
3405
|
+
case Float64:
|
|
3406
|
+
case Complex64:
|
|
3407
|
+
case Complex128:
|
|
3408
|
+
case String:
|
|
3409
|
+
case UnsafePointer:
|
|
3410
|
+
return { kind: $.TypeKind.Basic, name: typ.String() };
|
|
3411
|
+
case Interface:
|
|
3412
|
+
return {
|
|
3413
|
+
kind: $.TypeKind.Interface,
|
|
3414
|
+
methods: typeMethods(typ).map((method) => ({
|
|
3415
|
+
name: method.name,
|
|
3416
|
+
args: method.args,
|
|
3417
|
+
returns: method.returns,
|
|
3418
|
+
})),
|
|
3419
|
+
};
|
|
3420
|
+
case Slice:
|
|
3421
|
+
return {
|
|
3422
|
+
kind: $.TypeKind.Slice,
|
|
3423
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3424
|
+
};
|
|
3425
|
+
case Array:
|
|
3426
|
+
return {
|
|
3427
|
+
kind: $.TypeKind.Array,
|
|
3428
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3429
|
+
length: typ.Len(),
|
|
3430
|
+
};
|
|
3431
|
+
case Ptr:
|
|
3432
|
+
return {
|
|
3433
|
+
kind: $.TypeKind.Pointer,
|
|
3434
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3435
|
+
};
|
|
3436
|
+
case Map:
|
|
3437
|
+
return {
|
|
3438
|
+
kind: $.TypeKind.Map,
|
|
3439
|
+
keyType: typeInfoFromReflectType(typ.Key()),
|
|
3440
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3441
|
+
};
|
|
3442
|
+
case Chan:
|
|
3443
|
+
return {
|
|
3444
|
+
kind: $.TypeKind.Channel,
|
|
3445
|
+
elemType: typeInfoFromReflectType(typ.Elem()),
|
|
3446
|
+
direction: channelDirectionFromString(typ.String()),
|
|
3447
|
+
};
|
|
3448
|
+
case Func:
|
|
3449
|
+
return functionTypeInfoFromType(typ);
|
|
3450
|
+
case Struct: {
|
|
3451
|
+
const fields = typ instanceof StructType ?
|
|
3452
|
+
typ.descriptors()
|
|
3453
|
+
: globalThis.Array.from({ length: typ.NumField() }, (_unused, idx) => {
|
|
3454
|
+
const field = typ.Field(idx);
|
|
3455
|
+
return {
|
|
3456
|
+
name: field.Name,
|
|
3457
|
+
key: structFieldStorageKey(typ, idx),
|
|
3458
|
+
type: field.Type,
|
|
3459
|
+
tag: field.Tag?.toString(),
|
|
3460
|
+
pkgPath: field.PkgPath,
|
|
3461
|
+
anonymous: field.Anonymous,
|
|
3462
|
+
index: [...field.Index],
|
|
3463
|
+
offset: field.Offset,
|
|
3464
|
+
exported: field.IsExported(),
|
|
3465
|
+
};
|
|
3466
|
+
});
|
|
3467
|
+
return {
|
|
3468
|
+
kind: $.TypeKind.Struct,
|
|
3469
|
+
name: typ.Name() === '' ? '' : typ.String(),
|
|
3470
|
+
methods: [],
|
|
3471
|
+
fields: fields.map((field) => ({
|
|
3472
|
+
name: field.name,
|
|
3473
|
+
key: field.key,
|
|
3474
|
+
type: typeInfoFromReflectType(field.type),
|
|
3475
|
+
...(field.tag ? { tag: field.tag } : {}),
|
|
3476
|
+
...(field.pkgPath ? { pkgPath: field.pkgPath } : {}),
|
|
3477
|
+
...(field.anonymous ? { anonymous: true } : {}),
|
|
3478
|
+
index: [...field.index],
|
|
3479
|
+
offset: field.offset,
|
|
3480
|
+
exported: field.exported,
|
|
3481
|
+
})),
|
|
3482
|
+
};
|
|
3483
|
+
}
|
|
3484
|
+
default:
|
|
3485
|
+
return typ.String();
|
|
2311
3486
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
3487
|
+
}
|
|
3488
|
+
function channelDirectionFromString(typeName) {
|
|
3489
|
+
if (typeName.startsWith('<-chan ')) {
|
|
3490
|
+
return 'receive';
|
|
3491
|
+
}
|
|
3492
|
+
if (typeName.startsWith('chan<- ')) {
|
|
3493
|
+
return 'send';
|
|
3494
|
+
}
|
|
3495
|
+
return 'both';
|
|
3496
|
+
}
|
|
3497
|
+
function interfaceTypeFromInfo(info, seen = new Set()) {
|
|
3498
|
+
const methods = info.methods ?? [];
|
|
3499
|
+
if (methods.length === 0) {
|
|
3500
|
+
return new InterfaceType('interface{}', info.name, methods);
|
|
2314
3501
|
}
|
|
2315
|
-
return new
|
|
3502
|
+
return new InterfaceType(interfaceTypeString(methods, seen), info.name, methods);
|
|
2316
3503
|
}
|
|
2317
|
-
function
|
|
2318
|
-
return
|
|
3504
|
+
function interfaceTypeString(methods, seen = new Set()) {
|
|
3505
|
+
return `interface { ${methods
|
|
3506
|
+
.map((method) => interfaceMethodString(method, seen))
|
|
3507
|
+
.join('; ')} }`;
|
|
2319
3508
|
}
|
|
2320
|
-
function
|
|
2321
|
-
|
|
2322
|
-
|
|
3509
|
+
function interfaceMethodString(method, seen) {
|
|
3510
|
+
const args = method.args.map((arg) => methodArgString(arg, seen)).join(', ');
|
|
3511
|
+
const returns = method.returns.map((arg) => methodArgString(arg, seen));
|
|
3512
|
+
if (returns.length === 0) {
|
|
3513
|
+
return `${method.name}(${args})`;
|
|
3514
|
+
}
|
|
3515
|
+
if (returns.length === 1) {
|
|
3516
|
+
return `${method.name}(${args}) ${returns[0]}`;
|
|
3517
|
+
}
|
|
3518
|
+
return `${method.name}(${args}) (${returns.join(', ')})`;
|
|
3519
|
+
}
|
|
3520
|
+
function structTypeInfoString(info, seen) {
|
|
3521
|
+
if (info.name) {
|
|
3522
|
+
return info.name;
|
|
3523
|
+
}
|
|
3524
|
+
const fields = info.fields ?? [];
|
|
3525
|
+
if (fields.length === 0) {
|
|
3526
|
+
return 'struct {}';
|
|
3527
|
+
}
|
|
3528
|
+
return `struct { ${fields
|
|
3529
|
+
.map((field) => structFieldInfoString(field, seen))
|
|
3530
|
+
.join('; ')} }`;
|
|
3531
|
+
}
|
|
3532
|
+
function structFieldInfoString(field, seen) {
|
|
3533
|
+
const tag = field.tag ? ` ${JSON.stringify(field.tag)}` : '';
|
|
3534
|
+
const prefix = field.anonymous ? '' : `${field.name} `;
|
|
3535
|
+
return `${prefix}${typeInfoString(field.type, seen)}${tag}`;
|
|
3536
|
+
}
|
|
3537
|
+
function methodArgString(arg, seen) {
|
|
3538
|
+
return typeInfoString(arg.type, seen);
|
|
3539
|
+
}
|
|
3540
|
+
function typeInfoString(info, seen) {
|
|
3541
|
+
if (typeof info === 'string') {
|
|
3542
|
+
return info;
|
|
3543
|
+
}
|
|
3544
|
+
switch (info.kind) {
|
|
3545
|
+
case $.TypeKind.Basic:
|
|
3546
|
+
return info.typeName ?? info.name ?? 'unknown';
|
|
3547
|
+
case $.TypeKind.Interface: {
|
|
3548
|
+
const name = info.name ?? '';
|
|
3549
|
+
if (name !== '' && seen.has(name)) {
|
|
3550
|
+
return name;
|
|
3551
|
+
}
|
|
3552
|
+
if (info.methods.length === 0) {
|
|
3553
|
+
return 'interface{}';
|
|
3554
|
+
}
|
|
3555
|
+
if (name !== '') {
|
|
3556
|
+
seen.add(name);
|
|
3557
|
+
}
|
|
3558
|
+
const text = interfaceTypeString(info.methods, seen);
|
|
3559
|
+
if (name !== '') {
|
|
3560
|
+
seen.delete(name);
|
|
3561
|
+
}
|
|
3562
|
+
return text;
|
|
3563
|
+
}
|
|
3564
|
+
case $.TypeKind.Struct:
|
|
3565
|
+
return structTypeInfoString(info, seen);
|
|
3566
|
+
case $.TypeKind.Pointer:
|
|
3567
|
+
return `*${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3568
|
+
case $.TypeKind.Slice:
|
|
3569
|
+
return `[]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3570
|
+
case $.TypeKind.Array:
|
|
3571
|
+
return `[${info.length}]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3572
|
+
case $.TypeKind.Map:
|
|
3573
|
+
return `map[${typeInfoString(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3574
|
+
case $.TypeKind.Function: {
|
|
3575
|
+
const params = (info.params ?? [])
|
|
3576
|
+
.map((param) => typeInfoString(param, seen))
|
|
3577
|
+
.join(', ');
|
|
3578
|
+
const results = (info.results ?? []).map((result) => typeInfoString(result, seen));
|
|
3579
|
+
if (results.length === 0) {
|
|
3580
|
+
return `func(${params})`;
|
|
3581
|
+
}
|
|
3582
|
+
if (results.length === 1) {
|
|
3583
|
+
return `func(${params}) ${results[0]}`;
|
|
3584
|
+
}
|
|
3585
|
+
return `func(${params}) (${results.join(', ')})`;
|
|
3586
|
+
}
|
|
3587
|
+
case $.TypeKind.Channel:
|
|
3588
|
+
return `chan ${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
|
|
3589
|
+
default:
|
|
3590
|
+
return 'unknown';
|
|
2323
3591
|
}
|
|
2324
|
-
return new InterfaceType(`interface { ${info.methods.map((method) => method.name + '()').join('; ')} }`, info.name);
|
|
2325
3592
|
}
|
|
2326
3593
|
function chanDirFromTypeInfo(direction) {
|
|
2327
3594
|
switch (direction) {
|
|
@@ -2339,35 +3606,15 @@ function chanDirFromTypeInfo(direction) {
|
|
|
2339
3606
|
*/
|
|
2340
3607
|
export function getInterfaceTypeByName(name) {
|
|
2341
3608
|
const typeInfo = builtinGetTypeByName(name);
|
|
2342
|
-
if (typeInfo && typeInfo
|
|
2343
|
-
return new InterfaceType(name, name);
|
|
3609
|
+
if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
|
|
3610
|
+
return new InterfaceType(name, name, typeInfo.methods ?? []);
|
|
2344
3611
|
}
|
|
2345
3612
|
return new InterfaceType('interface{}');
|
|
2346
3613
|
}
|
|
2347
3614
|
export function getInterfaceLiteralTypeByName(name) {
|
|
2348
3615
|
const typeInfo = builtinGetTypeByName(name);
|
|
2349
|
-
if (typeInfo && typeInfo
|
|
2350
|
-
|
|
2351
|
-
if (methods.length === 0) {
|
|
2352
|
-
return new InterfaceType('interface{}', name);
|
|
2353
|
-
}
|
|
2354
|
-
const methodSigs = methods
|
|
2355
|
-
.map((m) => {
|
|
2356
|
-
const args = m.args
|
|
2357
|
-
?.map((a) => (typeof a === 'string' ? a : 'any'))
|
|
2358
|
-
.join(', ') || '';
|
|
2359
|
-
const returns = m.returns?.map((r) => typeof r === 'string' ? r : 'any');
|
|
2360
|
-
let returnSig = '';
|
|
2361
|
-
if (returns && returns.length === 1) {
|
|
2362
|
-
returnSig = ` ${returns[0]}`;
|
|
2363
|
-
}
|
|
2364
|
-
else if (returns && returns.length > 1) {
|
|
2365
|
-
returnSig = ` (${returns.join(', ')})`;
|
|
2366
|
-
}
|
|
2367
|
-
return `${m.name}(${args})${returnSig}`;
|
|
2368
|
-
})
|
|
2369
|
-
.join('; ');
|
|
2370
|
-
return new InterfaceType(`interface { ${methodSigs} }`, name);
|
|
3616
|
+
if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
|
|
3617
|
+
return interfaceTypeFromInfo(typeInfo);
|
|
2371
3618
|
}
|
|
2372
3619
|
return new InterfaceType('interface{}');
|
|
2373
3620
|
}
|