goscript 0.0.21 → 0.0.22
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/builtin/builtin.ts +298 -33
- package/compiler/assignment.go +407 -0
- package/compiler/compiler.go +160 -5883
- package/compiler/compiler_test.go +4 -0
- package/compiler/composite-lit.go +537 -0
- package/compiler/config.go +3 -0
- package/compiler/decl.go +223 -0
- package/compiler/expr-call.go +423 -0
- package/compiler/expr-selector.go +105 -0
- package/compiler/expr-star.go +90 -0
- package/compiler/expr-type.go +182 -0
- package/compiler/expr-value.go +119 -0
- package/compiler/expr.go +356 -0
- package/compiler/field.go +169 -0
- package/compiler/lit.go +99 -0
- package/compiler/primitive.go +142 -0
- package/compiler/{write-type-spec.go → spec-struct.go} +79 -203
- package/compiler/spec-value.go +194 -0
- package/compiler/spec.go +263 -0
- package/compiler/stmt-assign.go +411 -0
- package/compiler/stmt-for.go +178 -0
- package/compiler/stmt-range.go +237 -0
- package/compiler/stmt.go +907 -0
- package/compiler/type-assert.go +463 -0
- package/compiler/type-info.go +141 -0
- package/compiler/type.go +556 -0
- package/dist/builtin/builtin.d.ts +24 -6
- package/dist/builtin/builtin.js +215 -19
- package/dist/builtin/builtin.js.map +1 -1
- package/go.mod +2 -1
- package/go.sum +4 -2
- package/package.json +2 -2
- /package/compiler/{writer.go → code-writer.go} +0 -0
package/builtin/builtin.ts
CHANGED
|
@@ -724,12 +724,29 @@ export interface BaseTypeInfo {
|
|
|
724
724
|
zeroValue?: any
|
|
725
725
|
}
|
|
726
726
|
|
|
727
|
+
/**
|
|
728
|
+
* Represents an argument or a return value of a method.
|
|
729
|
+
*/
|
|
730
|
+
export interface MethodArg {
|
|
731
|
+
name?: string; // Name of the argument/return value, if available
|
|
732
|
+
type: TypeInfo | string; // TypeInfo object or string name of the type
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Represents the signature of a method, including its name, arguments, and return types.
|
|
737
|
+
*/
|
|
738
|
+
export interface MethodSignature {
|
|
739
|
+
name: string;
|
|
740
|
+
args: MethodArg[];
|
|
741
|
+
returns: MethodArg[];
|
|
742
|
+
}
|
|
743
|
+
|
|
727
744
|
/**
|
|
728
745
|
* Type information for struct types
|
|
729
746
|
*/
|
|
730
747
|
export interface StructTypeInfo extends BaseTypeInfo {
|
|
731
748
|
kind: TypeKind.Struct
|
|
732
|
-
methods:
|
|
749
|
+
methods: MethodSignature[] // Array of method signatures
|
|
733
750
|
ctor?: new (...args: any[]) => any
|
|
734
751
|
fields: Record<string, TypeInfo | string> // Field names and types for struct fields
|
|
735
752
|
}
|
|
@@ -739,7 +756,7 @@ export interface StructTypeInfo extends BaseTypeInfo {
|
|
|
739
756
|
*/
|
|
740
757
|
export interface InterfaceTypeInfo extends BaseTypeInfo {
|
|
741
758
|
kind: TypeKind.Interface
|
|
742
|
-
methods:
|
|
759
|
+
methods: MethodSignature[] // Array of method signatures
|
|
743
760
|
}
|
|
744
761
|
|
|
745
762
|
/**
|
|
@@ -790,6 +807,7 @@ export interface FunctionTypeInfo extends BaseTypeInfo {
|
|
|
790
807
|
kind: TypeKind.Function
|
|
791
808
|
params?: (string | TypeInfo)[]
|
|
792
809
|
results?: (string | TypeInfo)[]
|
|
810
|
+
isVariadic?: boolean // True if the function is variadic (e.g., ...T)
|
|
793
811
|
}
|
|
794
812
|
|
|
795
813
|
/**
|
|
@@ -860,14 +878,15 @@ const typeRegistry = new Map<string, TypeInfo>()
|
|
|
860
878
|
*
|
|
861
879
|
* @param name The name of the type.
|
|
862
880
|
* @param zeroValue The zero value for the type.
|
|
863
|
-
* @param methods
|
|
881
|
+
* @param methods Array of method signatures for the struct.
|
|
864
882
|
* @param ctor Constructor for the struct.
|
|
883
|
+
* @param fields Record of field names and their types.
|
|
865
884
|
* @returns The struct type information object.
|
|
866
885
|
*/
|
|
867
886
|
export const registerStructType = (
|
|
868
887
|
name: string,
|
|
869
888
|
zeroValue: any,
|
|
870
|
-
methods:
|
|
889
|
+
methods: MethodSignature[],
|
|
871
890
|
ctor: new (...args: any[]) => any,
|
|
872
891
|
fields: Record<string, TypeInfo | string> = {},
|
|
873
892
|
): StructTypeInfo => {
|
|
@@ -888,13 +907,13 @@ export const registerStructType = (
|
|
|
888
907
|
*
|
|
889
908
|
* @param name The name of the type.
|
|
890
909
|
* @param zeroValue The zero value for the type (usually null).
|
|
891
|
-
* @param methods
|
|
910
|
+
* @param methods Array of method signatures for the interface.
|
|
892
911
|
* @returns The interface type information object.
|
|
893
912
|
*/
|
|
894
913
|
export const registerInterfaceType = (
|
|
895
914
|
name: string,
|
|
896
915
|
zeroValue: any,
|
|
897
|
-
methods:
|
|
916
|
+
methods: MethodSignature[],
|
|
898
917
|
): InterfaceTypeInfo => {
|
|
899
918
|
const typeInfo: InterfaceTypeInfo = {
|
|
900
919
|
name,
|
|
@@ -935,6 +954,147 @@ function normalizeTypeInfo(info: string | TypeInfo): TypeInfo {
|
|
|
935
954
|
return info
|
|
936
955
|
}
|
|
937
956
|
|
|
957
|
+
function compareOptionalTypeInfo(
|
|
958
|
+
type1?: string | TypeInfo,
|
|
959
|
+
type2?: string | TypeInfo,
|
|
960
|
+
): boolean {
|
|
961
|
+
if (type1 === undefined && type2 === undefined) return true
|
|
962
|
+
if (type1 === undefined || type2 === undefined) return false
|
|
963
|
+
// Assuming areTypeInfosIdentical will handle normalization if needed,
|
|
964
|
+
// but type1 and type2 here are expected to be direct fields from TypeInfo objects.
|
|
965
|
+
return areTypeInfosIdentical(type1, type2)
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
function areFuncParamOrResultArraysIdentical(
|
|
969
|
+
arr1?: (string | TypeInfo)[],
|
|
970
|
+
arr2?: (string | TypeInfo)[]
|
|
971
|
+
): boolean {
|
|
972
|
+
if (arr1 === undefined && arr2 === undefined) return true
|
|
973
|
+
if (arr1 === undefined || arr2 === undefined) return false
|
|
974
|
+
if (arr1.length !== arr2.length) return false
|
|
975
|
+
for (let i = 0; i < arr1.length; i++) {
|
|
976
|
+
if (!areTypeInfosIdentical(arr1[i], arr2[i])) {
|
|
977
|
+
return false
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return true
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
function areFuncSignaturesIdentical(
|
|
984
|
+
func1: FunctionTypeInfo,
|
|
985
|
+
func2: FunctionTypeInfo,
|
|
986
|
+
): boolean {
|
|
987
|
+
if ((func1.isVariadic || false) !== (func2.isVariadic || false)) {
|
|
988
|
+
return false
|
|
989
|
+
}
|
|
990
|
+
return (
|
|
991
|
+
areFuncParamOrResultArraysIdentical(func1.params, func2.params) &&
|
|
992
|
+
areFuncParamOrResultArraysIdentical(func1.results, func2.results)
|
|
993
|
+
)
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
function areMethodArgsArraysIdentical(
|
|
997
|
+
args1?: MethodArg[],
|
|
998
|
+
args2?: MethodArg[],
|
|
999
|
+
): boolean {
|
|
1000
|
+
if (args1 === undefined && args2 === undefined) return true
|
|
1001
|
+
if (args1 === undefined || args2 === undefined) return false
|
|
1002
|
+
if (args1.length !== args2.length) return false
|
|
1003
|
+
for (let i = 0; i < args1.length; i++) {
|
|
1004
|
+
// Compare based on type only, names of args/results don't affect signature identity here.
|
|
1005
|
+
if (!areTypeInfosIdentical(args1[i].type, args2[i].type)) {
|
|
1006
|
+
return false
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
return true
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
export function areTypeInfosIdentical(
|
|
1013
|
+
type1InfoOrName: string | TypeInfo,
|
|
1014
|
+
type2InfoOrName: string | TypeInfo,
|
|
1015
|
+
): boolean {
|
|
1016
|
+
const t1Norm = normalizeTypeInfo(type1InfoOrName)
|
|
1017
|
+
const t2Norm = normalizeTypeInfo(type2InfoOrName)
|
|
1018
|
+
|
|
1019
|
+
if (t1Norm === t2Norm) return true // Object identity
|
|
1020
|
+
if (t1Norm.kind !== t2Norm.kind) return false
|
|
1021
|
+
|
|
1022
|
+
// If types have names, the names must match for identity.
|
|
1023
|
+
// If one has a name and the other doesn't, they are not identical.
|
|
1024
|
+
if (t1Norm.name !== t2Norm.name) return false
|
|
1025
|
+
|
|
1026
|
+
// If both are named and names match, for Basic, Struct, Interface, this is sufficient for identity.
|
|
1027
|
+
if (t1Norm.name !== undefined /* && t2Norm.name is also defined and equal */) {
|
|
1028
|
+
if (
|
|
1029
|
+
t1Norm.kind === TypeKind.Basic ||
|
|
1030
|
+
t1Norm.kind === TypeKind.Struct ||
|
|
1031
|
+
t1Norm.kind === TypeKind.Interface
|
|
1032
|
+
) {
|
|
1033
|
+
return true
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
// For other types (Pointer, Slice, etc.), or if both are anonymous (name is undefined),
|
|
1037
|
+
// structural comparison is needed.
|
|
1038
|
+
|
|
1039
|
+
switch (t1Norm.kind) {
|
|
1040
|
+
case TypeKind.Basic:
|
|
1041
|
+
// Names matched if they were defined, or both undefined (which means true by t1Norm.name !== t2Norm.name being false)
|
|
1042
|
+
return true
|
|
1043
|
+
case TypeKind.Pointer:
|
|
1044
|
+
return compareOptionalTypeInfo(
|
|
1045
|
+
(t1Norm as PointerTypeInfo).elemType,
|
|
1046
|
+
(t2Norm as PointerTypeInfo).elemType,
|
|
1047
|
+
)
|
|
1048
|
+
case TypeKind.Slice:
|
|
1049
|
+
return compareOptionalTypeInfo(
|
|
1050
|
+
(t1Norm as SliceTypeInfo).elemType,
|
|
1051
|
+
(t2Norm as SliceTypeInfo).elemType,
|
|
1052
|
+
)
|
|
1053
|
+
case TypeKind.Array:
|
|
1054
|
+
return (
|
|
1055
|
+
(t1Norm as ArrayTypeInfo).length === (t2Norm as ArrayTypeInfo).length &&
|
|
1056
|
+
compareOptionalTypeInfo(
|
|
1057
|
+
(t1Norm as ArrayTypeInfo).elemType,
|
|
1058
|
+
(t2Norm as ArrayTypeInfo).elemType,
|
|
1059
|
+
)
|
|
1060
|
+
)
|
|
1061
|
+
case TypeKind.Map:
|
|
1062
|
+
return (
|
|
1063
|
+
compareOptionalTypeInfo(
|
|
1064
|
+
(t1Norm as MapTypeInfo).keyType,
|
|
1065
|
+
(t2Norm as MapTypeInfo).keyType,
|
|
1066
|
+
) &&
|
|
1067
|
+
compareOptionalTypeInfo(
|
|
1068
|
+
(t1Norm as MapTypeInfo).elemType,
|
|
1069
|
+
(t2Norm as MapTypeInfo).elemType,
|
|
1070
|
+
)
|
|
1071
|
+
)
|
|
1072
|
+
case TypeKind.Channel:
|
|
1073
|
+
return (
|
|
1074
|
+
// Ensure direction property exists before comparing, or handle undefined if it can be
|
|
1075
|
+
((t1Norm as ChannelTypeInfo).direction || 'both') === ((t2Norm as ChannelTypeInfo).direction || 'both') &&
|
|
1076
|
+
compareOptionalTypeInfo(
|
|
1077
|
+
(t1Norm as ChannelTypeInfo).elemType,
|
|
1078
|
+
(t2Norm as ChannelTypeInfo).elemType,
|
|
1079
|
+
)
|
|
1080
|
+
)
|
|
1081
|
+
case TypeKind.Function:
|
|
1082
|
+
return areFuncSignaturesIdentical(
|
|
1083
|
+
t1Norm as FunctionTypeInfo,
|
|
1084
|
+
t2Norm as FunctionTypeInfo,
|
|
1085
|
+
)
|
|
1086
|
+
case TypeKind.Struct:
|
|
1087
|
+
case TypeKind.Interface:
|
|
1088
|
+
// If we reach here, names were undefined (both anonymous) or names matched but was not Basic/Struct/Interface.
|
|
1089
|
+
// For anonymous Struct/Interface, strict identity means full structural comparison.
|
|
1090
|
+
// For now, we consider anonymous types not identical unless they are the same object (caught above).
|
|
1091
|
+
// If they were named and matched, 'return true' was hit earlier for these kinds.
|
|
1092
|
+
return false
|
|
1093
|
+
default:
|
|
1094
|
+
return false
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
|
|
938
1098
|
/**
|
|
939
1099
|
* Validates that a map key matches the expected type info.
|
|
940
1100
|
*
|
|
@@ -993,16 +1153,20 @@ function matchesStructType(value: any, info: TypeInfo): boolean {
|
|
|
993
1153
|
return true
|
|
994
1154
|
}
|
|
995
1155
|
|
|
1156
|
+
// Check if the value has all methods defined in the struct's TypeInfo
|
|
1157
|
+
// This is a structural check, not a signature check here.
|
|
1158
|
+
// Signature checks are more relevant for interface satisfaction.
|
|
996
1159
|
if (info.methods && typeof value === 'object' && value !== null) {
|
|
997
|
-
const
|
|
998
|
-
(
|
|
1160
|
+
const allMethodsExist = info.methods.every(
|
|
1161
|
+
(methodSig) => typeof (value as any)[methodSig.name] === 'function',
|
|
999
1162
|
)
|
|
1000
|
-
if (
|
|
1001
|
-
return
|
|
1163
|
+
if (!allMethodsExist) {
|
|
1164
|
+
return false
|
|
1002
1165
|
}
|
|
1166
|
+
// Further signature checking could be added here if needed for struct-to-struct assignability
|
|
1003
1167
|
}
|
|
1004
1168
|
|
|
1005
|
-
if (typeof value === 'object' && value !== null) {
|
|
1169
|
+
if (typeof value === 'object' && value !== null && info.fields) {
|
|
1006
1170
|
const fieldNames = Object.keys(info.fields || {})
|
|
1007
1171
|
const valueFields = Object.keys(value)
|
|
1008
1172
|
|
|
@@ -1034,19 +1198,96 @@ function matchesStructType(value: any, info: TypeInfo): boolean {
|
|
|
1034
1198
|
* @param info The interface type info to match against.
|
|
1035
1199
|
* @returns True if the value matches the interface type, false otherwise.
|
|
1036
1200
|
*/
|
|
1201
|
+
/**
|
|
1202
|
+
* Checks if a value matches an interface type info by verifying it implements
|
|
1203
|
+
* all required methods with compatible signatures.
|
|
1204
|
+
*
|
|
1205
|
+
* @param value The value to check.
|
|
1206
|
+
* @param info The interface type info to match against.
|
|
1207
|
+
* @returns True if the value matches the interface type, false otherwise.
|
|
1208
|
+
*/
|
|
1037
1209
|
function matchesInterfaceType(value: any, info: TypeInfo): boolean {
|
|
1038
|
-
//
|
|
1039
|
-
if (
|
|
1040
|
-
|
|
1041
|
-
info.methods &&
|
|
1042
|
-
typeof value === 'object' &&
|
|
1043
|
-
value !== null
|
|
1044
|
-
) {
|
|
1045
|
-
return Array.from(info.methods).every(
|
|
1046
|
-
(method) => typeof (value as any)[method] === 'function',
|
|
1047
|
-
)
|
|
1210
|
+
// Check basic conditions first
|
|
1211
|
+
if (!isInterfaceTypeInfo(info) || typeof value !== 'object' || value === null) {
|
|
1212
|
+
return false
|
|
1048
1213
|
}
|
|
1049
|
-
|
|
1214
|
+
|
|
1215
|
+
// For interfaces, check if the value has all the required methods with compatible signatures
|
|
1216
|
+
return info.methods.every((requiredMethodSig) => {
|
|
1217
|
+
const actualMethod = (value as any)[requiredMethodSig.name]
|
|
1218
|
+
|
|
1219
|
+
// Method must exist and be a function
|
|
1220
|
+
if (typeof actualMethod !== 'function') {
|
|
1221
|
+
return false
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
// Check parameter count (basic arity check)
|
|
1225
|
+
// Note: This is a simplified check as JavaScript functions can have optional/rest parameters
|
|
1226
|
+
const declaredParamCount = actualMethod.length
|
|
1227
|
+
const requiredParamCount = requiredMethodSig.args.length
|
|
1228
|
+
|
|
1229
|
+
// Strict arity checking can be problematic in JS, so we'll be lenient
|
|
1230
|
+
// A method with fewer params than required is definitely incompatible
|
|
1231
|
+
if (declaredParamCount < requiredParamCount) {
|
|
1232
|
+
return false
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
// Check return types if we can determine them
|
|
1236
|
+
// This is challenging in JavaScript without runtime type information
|
|
1237
|
+
|
|
1238
|
+
// If the value has a __goTypeName property, it might be a registered type
|
|
1239
|
+
// with more type information available
|
|
1240
|
+
if (value.__goTypeName) {
|
|
1241
|
+
const valueTypeInfo = typeRegistry.get(value.__goTypeName)
|
|
1242
|
+
if (valueTypeInfo && isStructTypeInfo(valueTypeInfo)) {
|
|
1243
|
+
// Find the matching method in the value's type info
|
|
1244
|
+
const valueMethodSig = valueTypeInfo.methods.find(
|
|
1245
|
+
m => m.name === requiredMethodSig.name
|
|
1246
|
+
)
|
|
1247
|
+
|
|
1248
|
+
if (valueMethodSig) {
|
|
1249
|
+
// Compare return types
|
|
1250
|
+
if (valueMethodSig.returns.length !== requiredMethodSig.returns.length) {
|
|
1251
|
+
return false
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// Compare each return type for compatibility
|
|
1255
|
+
for (let i = 0; i < requiredMethodSig.returns.length; i++) {
|
|
1256
|
+
const requiredReturnType = normalizeTypeInfo(
|
|
1257
|
+
requiredMethodSig.returns[i].type
|
|
1258
|
+
)
|
|
1259
|
+
const valueReturnType = normalizeTypeInfo(
|
|
1260
|
+
valueMethodSig.returns[i].type
|
|
1261
|
+
)
|
|
1262
|
+
|
|
1263
|
+
// For interface return types, we need to check if the value's return type
|
|
1264
|
+
// implements the required interface
|
|
1265
|
+
if (isInterfaceTypeInfo(requiredReturnType)) {
|
|
1266
|
+
// This would be a recursive check, but we'll simplify for now
|
|
1267
|
+
// by just checking if the types are the same or if the value type
|
|
1268
|
+
// is registered as implementing the interface
|
|
1269
|
+
if (requiredReturnType.name !== valueReturnType.name) {
|
|
1270
|
+
// Check if valueReturnType implements requiredReturnType
|
|
1271
|
+
// This would require additional implementation tracking
|
|
1272
|
+
return false
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
// For non-interface types, check direct type compatibility
|
|
1276
|
+
else if (requiredReturnType.name !== valueReturnType.name) {
|
|
1277
|
+
return false
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// Similarly, we could check parameter types for compatibility
|
|
1282
|
+
// but we'll skip that for brevity
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
// If we can't determine detailed type information, we'll accept the method
|
|
1288
|
+
// as long as it exists with a compatible arity
|
|
1289
|
+
return true
|
|
1290
|
+
})
|
|
1050
1291
|
}
|
|
1051
1292
|
|
|
1052
1293
|
/**
|
|
@@ -1297,22 +1538,46 @@ export function typeAssert<T>(
|
|
|
1297
1538
|
|
|
1298
1539
|
if (
|
|
1299
1540
|
isStructTypeInfo(normalizedType) &&
|
|
1300
|
-
normalizedType.methods &&
|
|
1541
|
+
normalizedType.methods && normalizedType.methods.length > 0 &&
|
|
1301
1542
|
typeof value === 'object' &&
|
|
1302
1543
|
value !== null
|
|
1303
1544
|
) {
|
|
1304
|
-
// Check if the value implements all methods of the struct type
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
)
|
|
1545
|
+
// Check if the value implements all methods of the struct type with compatible signatures.
|
|
1546
|
+
// This is more for interface satisfaction by a struct.
|
|
1547
|
+
// For struct-to-struct assertion, usually instanceof or field checks are primary.
|
|
1548
|
+
const allMethodsMatch = normalizedType.methods.every((requiredMethodSig) => {
|
|
1549
|
+
const actualMethod = (value as any)[requiredMethodSig.name];
|
|
1550
|
+
if (typeof actualMethod !== 'function') {
|
|
1551
|
+
return false;
|
|
1552
|
+
}
|
|
1553
|
+
const valueTypeInfoVal = (value as any).$typeInfo
|
|
1554
|
+
if (valueTypeInfoVal) {
|
|
1555
|
+
const normalizedValueType = normalizeTypeInfo(valueTypeInfoVal)
|
|
1556
|
+
if (isStructTypeInfo(normalizedValueType) || isInterfaceTypeInfo(normalizedValueType)) {
|
|
1557
|
+
const actualValueMethodSig = normalizedValueType.methods.find(m => m.name === requiredMethodSig.name)
|
|
1558
|
+
if (actualValueMethodSig) {
|
|
1559
|
+
// Perform full signature comparison using MethodSignatures
|
|
1560
|
+
const paramsMatch = areMethodArgsArraysIdentical(requiredMethodSig.args, actualValueMethodSig.args)
|
|
1561
|
+
const resultsMatch = areMethodArgsArraysIdentical(requiredMethodSig.returns, actualValueMethodSig.returns)
|
|
1562
|
+
return paramsMatch && resultsMatch
|
|
1563
|
+
} else {
|
|
1564
|
+
// Value has TypeInfo listing methods, but this specific method isn't listed.
|
|
1565
|
+
// This implies a mismatch for strict signature check based on TypeInfo.
|
|
1566
|
+
return false
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1308
1570
|
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1571
|
+
// Fallback: Original behavior if value has no TypeInfo that lists methods,
|
|
1572
|
+
// or if the method wasn't found in its TypeInfo (covered by 'else' returning false above).
|
|
1573
|
+
// The original comment was: "For now, presence and function type is checked by matchesStructType/matchesInterfaceType"
|
|
1574
|
+
// This 'return true' implies that if we couldn't do a full signature check via TypeInfo,
|
|
1575
|
+
// we still consider it a match if the function simply exists on the object.
|
|
1576
|
+
return true;
|
|
1577
|
+
});
|
|
1312
1578
|
|
|
1313
|
-
if (allMethodsMatch
|
|
1314
|
-
|
|
1315
|
-
return { value: value as T, ok: true }
|
|
1579
|
+
if (allMethodsMatch) {
|
|
1580
|
+
return { value: value as T, ok: true };
|
|
1316
1581
|
}
|
|
1317
1582
|
}
|
|
1318
1583
|
|