typinfo.pas 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (c) 2018 by Mattias Gaertner
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit TypInfo;
  11. {$mode objfpc}
  12. {$modeswitch externalclass}
  13. interface
  14. uses
  15. SysUtils, Types, RTLConsts, JS;
  16. type
  17. // if you change the following enumeration type in any way
  18. // you also have to change the rtl.js in an appropriate way !
  19. TTypeKind = (
  20. tkUnknown, // 0
  21. tkInteger, // 1
  22. tkChar, // 2 in Delphi/FPC tkWChar, tkUChar
  23. tkString, // 3 in Delphi/FPC tkSString, tkWString or tkUString
  24. tkEnumeration, // 4
  25. tkSet, // 5
  26. tkDouble, // 6
  27. tkBool, // 7
  28. tkProcVar, // 8
  29. tkMethod, // 9 proc var of object
  30. tkArray, // 10 static array
  31. tkDynArray, // 11
  32. tkRecord, // 12
  33. tkClass, // 13
  34. tkClassRef, // 14
  35. tkPointer, // 15
  36. tkJSValue, // 16
  37. tkRefToProcVar, // 17
  38. tkInterface, // 18
  39. //tkObject,
  40. //tkSString,tkLString,tkAString,tkWString,
  41. //tkVariant,
  42. //tkWChar,
  43. //tkInt64,
  44. //tkQWord,
  45. //tkInterfaceRaw,
  46. //tkUString,tkUChar,
  47. tkHelper // 19
  48. //tkFile,
  49. );
  50. TTypeKinds = set of TTypeKind;
  51. // TCallConv for compatibility with Delphi/FPC, ignored under pas2js
  52. TCallConv = (ccReg, ccCdecl, ccPascal, ccStdCall, ccSafeCall, ccCppdecl,
  53. ccFar16, ccOldFPCCall, ccInternProc, ccSysCall, ccSoftFloat, ccMWPascal);
  54. const
  55. tkFloat = tkDouble; // for compatibility with Delphi/FPC
  56. tkProcedure = tkProcVar; // for compatibility with Delphi
  57. tkAny = [Low(TTypeKind)..High(TTypeKind)];
  58. tkMethods = [tkMethod];
  59. tkProperties = tkAny-tkMethods-[tkUnknown];
  60. type
  61. { TTypeInfo }
  62. TTypeInfo = class external name 'rtl.tTypeInfo'
  63. public
  64. Name: String external name 'name';
  65. Kind: TTypeKind external name 'kind';
  66. end;
  67. TTypeInfoClassOf = class of TTypeInfo;
  68. PTypeInfo = Pointer; // for compatibility with Delphi/FPC, under pas2js it is a TTypeInfo
  69. TOrdType = (
  70. otSByte, // 0
  71. otUByte, // 1
  72. otSWord, // 2
  73. otUWord, // 3
  74. otSLong, // 4
  75. otULong, // 5
  76. otSIntDouble, // 6 NativeInt
  77. otUIntDouble // 7 NativeUInt
  78. );
  79. { TTypeInfoInteger - Kind = tkInteger }
  80. TTypeInfoInteger = class external name 'rtl.tTypeInfoInteger'(TTypeInfo)
  81. public
  82. MinValue: NativeInt external name 'minvalue';
  83. MaxValue: NativeInt external name 'maxvalue';
  84. OrdType : TOrdType external name 'ordtype';
  85. end;
  86. { TEnumType }
  87. TEnumType = class external name 'anonymous'
  88. private
  89. function GetIntToName(Index: NativeInt): String; external name '[]';
  90. function GetNameToInt(Name: String): NativeInt; external name '[]';
  91. public
  92. property IntToName[Index: NativeInt]: String read GetIntToName;
  93. property NameToInt[Name: String]: NativeInt read GetNameToInt;
  94. end;
  95. { TTypeInfoEnum - Kind = tkEnumeration }
  96. TTypeInfoEnum = class external name 'rtl.tTypeInfoEnum'(TTypeInfoInteger)
  97. public
  98. // not supported: BaseType: TTypeInfo
  99. EnumType: TEnumType external name 'enumtype';
  100. end;
  101. { TTypeInfoSet - Kind = tkSet }
  102. TTypeInfoSet = class external name 'rtl.tTypeInfoSet'(TTypeInfo)
  103. public
  104. // not supported: BaseType: TTypeInfo
  105. CompType: TTypeInfo external name 'comptype';
  106. end;
  107. { TTypeInfoStaticArray - Kind = tkArray }
  108. TTypeInfoStaticArray = class external name 'rtl.tTypeInfoStaticArray'(TTypeInfo)
  109. public
  110. Dims: TIntegerDynArray;
  111. ElType: TTypeInfo external name 'eltype';
  112. end;
  113. { TTypeInfoDynArray - Kind = tkDynArray }
  114. TTypeInfoDynArray = class external name 'rtl.tTypeInfoDynArray'(TTypeInfo)
  115. public
  116. DimCount: NativeInt external name 'dimcount';
  117. ElType: TTypeInfo external name 'eltype';
  118. end;
  119. TParamFlag = (
  120. pfVar, // 2^0 = 1
  121. pfConst, // 2^1 = 2
  122. pfOut, // 2^2 = 4
  123. pfArray // 2^3 = 8
  124. //pfAddress,pfReference,
  125. );
  126. TParamFlags = set of TParamFlag;
  127. { TProcedureParam }
  128. TProcedureParam = class external name 'anonymous'
  129. public
  130. Name: String external name 'name';
  131. TypeInfo: TTypeInfo external name 'typeinfo';
  132. Flags: NativeInt external name 'flags'; // TParamFlags as bit vector
  133. end;
  134. TProcedureParams = array of TProcedureParam;
  135. TProcedureFlag = (
  136. pfStatic, // 2^0 = 1
  137. pfVarargs, // 2^1 = 2
  138. pfExternal // 2^2 = 4 name may be an expression
  139. );
  140. TProcedureFlags = set of TProcedureFlag;
  141. { TProcedureSignature }
  142. TProcedureSignature = class external name 'anonymous'
  143. public
  144. Params: TProcedureParams external name 'params'; // can be null
  145. ResultType: TTypeInfo external name 'resulttype'; // can be null
  146. Flags: NativeInt external name 'flags'; // TProcedureFlags as bit vector
  147. end;
  148. { TTypeInfoProcVar - Kind = tkProcVar }
  149. TTypeInfoProcVar = class external name 'rtl.tTypeInfoProcVar'(TTypeInfo)
  150. public
  151. ProcSig: TProcedureSignature external name 'procsig';
  152. end;
  153. { TTypeInfoRefToProcVar - Kind = tkRefToProcVar }
  154. TTypeInfoRefToProcVar = class external name 'rtl.tTypeInfoRefToProcVar'(TTypeInfoProcVar)
  155. end;
  156. TMethodKind = (
  157. mkProcedure, // 0 default
  158. mkFunction, // 1
  159. mkConstructor, // 2
  160. mkDestructor, // 3
  161. mkClassProcedure,// 4
  162. mkClassFunction // 5
  163. //mkClassConstructor,mkClassDestructor,mkOperatorOverload
  164. );
  165. TMethodKinds = set of TMethodKind;
  166. { TTypeInfoMethodVar - Kind = tkMethod }
  167. TTypeInfoMethodVar = class external name 'rtl.tTypeInfoMethodVar'(TTypeInfoProcVar)
  168. public
  169. MethodKind: TMethodKind external name 'methodkind';
  170. end;
  171. TTypeMemberKind = (
  172. tmkUnknown, // 0
  173. tmkField, // 1
  174. tmkMethod, // 2
  175. tmkProperty // 3
  176. );
  177. TTypeMemberKinds = set of TTypeMemberKind;
  178. { TTypeMember }
  179. TTypeMember = class external name 'rtl.tTypeMember'
  180. public
  181. Name: String external name 'name';
  182. Kind: TTypeMemberKind external name 'kind';
  183. end;
  184. TTypeMemberDynArray = array of TTypeMember;
  185. { TTypeMemberField - Kind = tmkField }
  186. TTypeMemberField = class external name 'rtl.tTypeMemberField'(TTypeMember)
  187. public
  188. TypeInfo: TTypeInfo external name 'typeinfo';
  189. end;
  190. { TTypeMemberMethod - Kind = tmkMethod }
  191. TTypeMemberMethod = class external name 'rtl.tTypeMemberMethod'(TTypeMember)
  192. public
  193. MethodKind: TMethodKind external name 'methodkind';
  194. ProcSig: TProcedureSignature external name 'procsig';
  195. end;
  196. TTypeMemberMethodDynArray = array of TTypeMemberMethod;
  197. const
  198. pfGetFunction = 1; // getter is a function
  199. pfSetProcedure = 2; // setter is a procedure
  200. // stored is a 2-bit vector:
  201. pfStoredFalse = 4; // stored false, never
  202. pfStoredField = 8; // stored field, field name is in Stored
  203. pfStoredFunction = 12; // stored function, function name is in Stored
  204. pfHasIndex = 16; { if getter is function, append Index as last param
  205. if setter is function, append Index as second last param }
  206. type
  207. { TTypeMemberProperty - Kind = tmkProperty }
  208. TTypeMemberProperty = class external name 'rtl.tTypeMemberProperty'(TTypeMember)
  209. public
  210. TypeInfo: TTypeInfo external name 'typeinfo';
  211. Flags: NativeInt external name 'flags'; // bit vector, see pf constants above
  212. Params: TProcedureParams external name 'params'; // can be null or undefined
  213. Index: JSValue external name 'index'; // can be undefined
  214. Getter: String external name 'getter'; // name of field or function
  215. Setter: String external name 'setter'; // name of field or function
  216. Stored: String external name 'stored'; // name of field or function, can be undefined
  217. Default: JSValue external name 'Default'; // can be undefined
  218. end;
  219. TTypeMemberPropertyDynArray = array of TTypeMemberProperty;
  220. { TTypeMembers }
  221. TTypeMembers = class external name 'rtl.tTypeMembers'
  222. private
  223. function GetItems(Name: String): TTypeMember; external name '[]';
  224. procedure SetItems(Name: String; const AValue: TTypeMember); external name '[]';
  225. public
  226. property Members[Name: String]: TTypeMember read GetItems write SetItems; default;
  227. end;
  228. { TTypeInfoStruct }
  229. TTypeInfoStruct = class external name 'rtl.tTypeInfoStruct'(TTypeInfo)
  230. private
  231. FFieldCount: NativeInt external name 'fields.length';
  232. FMethodCount: NativeInt external name 'methods.length';
  233. FPropCount: NativeInt external name 'properties.length';
  234. public
  235. Members: TTypeMembers external name 'members';
  236. Names: TStringDynArray external name 'names'; // all member names with TTypeInfo
  237. Fields: TStringDynArray external name 'fields';
  238. Methods: TStringDynArray external name 'methods';
  239. Properties: TStringDynArray external name 'properties';
  240. property FieldCount: NativeInt read FFieldCount;
  241. function GetField(Index: NativeInt): TTypeMemberField; external name 'getField';
  242. function AddField(aName: String; aType: TTypeInfo; Options: TJSObject = nil
  243. ): TTypeMemberField; external name 'addField';
  244. property MethodCount: NativeInt read FMethodCount;
  245. function GetMethod(Index: NativeInt): TTypeMemberMethod; external name 'getMethod';
  246. function AddMethod(aName: String; MethodKind: TMethodKind = mkProcedure;
  247. Params: TJSArray = nil; ResultType: TTypeInfo = nil;
  248. Options: TJSObject = nil): TTypeMemberMethod; external name 'addMethod';
  249. property PropCount: NativeInt read FPropCount;
  250. function GetProp(Index: NativeInt): TTypeMemberProperty; external name 'getProperty';
  251. function AddProperty(aName: String; Flags: NativeInt; ResultType: TTypeInfo;
  252. Getter, Setter: String; Options: TJSObject = nil): TTypeMemberProperty; external name 'addProperty';
  253. end;
  254. { TTypeInfoRecord - Kind = tkRecord }
  255. TTypeInfoRecord = class external name 'rtl.tTypeInfoRecord'(TTypeInfoStruct)
  256. public
  257. RecordType: TJSObject external name 'record';
  258. end;
  259. { TTypeInfoClass - Kind = tkClass }
  260. TTypeInfoClass = class external name 'rtl.tTypeInfoClass'(TTypeInfoStruct)
  261. public
  262. ClassType: TClass external name 'class';
  263. Ancestor: TTypeInfoClass external name 'ancestor';
  264. end;
  265. { TTypeInfoClassRef - class-of, Kind = tkClassRef }
  266. TTypeInfoClassRef = class external name 'rtl.tTypeInfoClassRef'(TTypeInfo)
  267. public
  268. InstanceType: TTypeInfo external name 'instancetype';
  269. end;
  270. { TTypeInfoPointer - Kind = tkPointer }
  271. TTypeInfoPointer = class external name 'rtl.tTypeInfoPointer'(TTypeInfo)
  272. public
  273. RefType: TTypeInfo external name 'reftype'; // can be null
  274. end;
  275. { TTypeInfoInterface - Kind = tkInterface }
  276. TTypeInfoInterface = class external name 'rtl.tTypeInfoInterface'(TTypeInfoStruct)
  277. public
  278. InterfaceType: TJSObject external name 'interface';
  279. Ancestor: TTypeInfoInterface external name 'ancestor';
  280. end;
  281. { TTypeInfoHelper - Kind = tkHelper }
  282. TTypeInfoHelper = class external name 'rtl.tTypeInfoHelper'(TTypeInfoStruct)
  283. public
  284. HelperType: TJSObject external name 'helper';
  285. Ancestor: TTypeInfoHelper external name 'ancestor';
  286. HelperFor: TTypeInfo external name 'helperfor';
  287. end;
  288. EPropertyError = class(Exception);
  289. function GetClassMembers(aTIStruct: TTypeInfoStruct): TTypeMemberDynArray;
  290. function GetClassMember(aTIStruct: TTypeInfoStruct; const aName: String): TTypeMember;
  291. function GetInstanceMethod(Instance: TObject; const aName: String): Pointer;
  292. function GetClassMethods(aTIStruct: TTypeInfoStruct): TTypeMemberMethodDynArray;
  293. function CreateMethod(Instance: TObject; FuncName: String): Pointer; external name 'rtl.createCallback';
  294. function GetInterfaceMembers(aTIInterface: TTypeInfoInterface): TTypeMemberDynArray;
  295. function GetInterfaceMember(aTIInterface: TTypeInfoInterface; const aName: String): TTypeMember;
  296. function GetInterfaceMethods(aTIInterface: TTypeInfoInterface): TTypeMemberMethodDynArray;
  297. function GetPropInfos(aTIStruct: TTypeInfoStruct): TTypeMemberPropertyDynArray;
  298. function GetPropList(aTIStruct: TTypeInfoStruct; TypeKinds: TTypeKinds; Sorted: boolean = true): TTypeMemberPropertyDynArray;
  299. function GetPropList(aTIStruct: TTypeInfoStruct): TTypeMemberPropertyDynArray;
  300. function GetPropList(AClass: TClass): TTypeMemberPropertyDynArray;
  301. function GetPropList(Instance: TObject): TTypeMemberPropertyDynArray;
  302. function GetPropInfo(TI: TTypeInfoStruct; const PropName: String): TTypeMemberProperty;
  303. function GetPropInfo(TI: TTypeInfoStruct; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  304. function GetPropInfo(Instance: TObject; const PropName: String): TTypeMemberProperty;
  305. function GetPropInfo(Instance: TObject; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  306. function GetPropInfo(aClass: TClass; const PropName: String): TTypeMemberProperty;
  307. function GetPropInfo(aClass: TClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  308. function FindPropInfo(Instance: TObject; const PropName: String): TTypeMemberProperty;
  309. function FindPropInfo(Instance: TObject; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  310. function FindPropInfo(aClass: TClass; const PropName: String): TTypeMemberProperty;
  311. function FindPropInfo(aClass: TClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  312. // Property information routines.
  313. Function IsStoredProp(Instance: TObject; const PropInfo: TTypeMemberProperty): Boolean;
  314. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  315. function IsPublishedProp(Instance: TObject; const PropName: String): Boolean;
  316. function IsPublishedProp(aClass: TClass; const PropName: String): Boolean;
  317. function PropType(Instance: TObject; const PropName: string): TTypeKind;
  318. function PropType(aClass: TClass; const PropName: string): TTypeKind;
  319. function PropIsType(Instance: TObject; const PropName: string; const TypeKind: TTypeKind): Boolean;
  320. function PropIsType(aClass: TClass; const PropName: string; const TypeKind: TTypeKind): Boolean;
  321. function GetJSValueProp(Instance: TJSObject; TI: TTypeInfoStruct; const PropName: String): JSValue;
  322. function GetJSValueProp(Instance: TJSObject; const PropInfo: TTypeMemberProperty): JSValue;
  323. function GetJSValueProp(Instance: TObject; const PropName: String): JSValue;
  324. function GetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty): JSValue;
  325. procedure SetJSValueProp(Instance: TJSObject; TI: TTypeInfoStruct; const PropName: String; Value: JSValue);
  326. procedure SetJSValueProp(Instance: TJSObject; const PropInfo: TTypeMemberProperty; Value: JSValue);
  327. procedure SetJSValueProp(Instance: TObject; const PropName: String; Value: JSValue);
  328. procedure SetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: JSValue);
  329. function GetNativeIntProp(Instance: TObject; const PropName: String): NativeInt;
  330. function GetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty): NativeInt;
  331. procedure SetNativeIntProp(Instance: TObject; const PropName: String; Value: NativeInt);
  332. procedure SetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: NativeInt);
  333. function GetOrdProp(Instance: TObject; const PropName: String): longint;
  334. function GetOrdProp(Instance: TObject; const PropInfo: TTypeMemberProperty): longint;
  335. procedure SetOrdProp(Instance: TObject; const PropName: String; Value: longint);
  336. procedure SetOrdProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: longint);
  337. function GetEnumProp(Instance: TObject; const PropName: String): String;
  338. function GetEnumProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String;
  339. procedure SetEnumProp(Instance: TObject; const PropName: String; const Value: String);
  340. procedure SetEnumProp(Instance: TObject; const PropInfo: TTypeMemberProperty; const Value: String);
  341. // Auxiliary routines, which may be useful
  342. function GetEnumName(TypeInfo: TTypeInfoEnum; Value: Integer): String;
  343. function GetEnumValue(TypeInfo: TTypeInfoEnum; const Name: string): Longint;
  344. function GetEnumNameCount(TypeInfo: TTypeInfoEnum): Longint;
  345. function GetSetProp(Instance: TObject; const PropName: String): String; overload;
  346. function GetSetProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String; overload;
  347. function GetSetPropArray(Instance: TObject; const PropName: String): TIntegerDynArray; overload;
  348. function GetSetPropArray(Instance: TObject; const PropInfo: TTypeMemberProperty): TIntegerDynArray; overload;
  349. procedure SetSetPropArray(Instance: TObject; const PropName: String; const Arr: TIntegerDynArray); overload;
  350. procedure SetSetPropArray(Instance: TObject; const PropInfo: TTypeMemberProperty; const Arr: TIntegerDynArray); overload;
  351. function GetStrProp(Instance: TObject; const PropName: String): String;
  352. function GetStrProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String;
  353. procedure SetStrProp(Instance: TObject; const PropName: String; Value: String);
  354. procedure SetStrProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: String);
  355. function GetStringProp(Instance: TObject; const PropName: String): String; deprecated; // use GetStrProp
  356. function GetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String; deprecated; // use GetStrProp
  357. procedure SetStringProp(Instance: TObject; const PropName: String; Value: String); deprecated; // use GetStrProp
  358. procedure SetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: String); deprecated; // use GetStrProp
  359. function GetBoolProp(Instance: TObject; const PropName: String): boolean;
  360. function GetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty): boolean;
  361. procedure SetBoolProp(Instance: TObject; const PropName: String; Value: boolean);
  362. procedure SetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: boolean);
  363. function GetObjectProp(Instance: TObject; const PropName: String): TObject;
  364. function GetObjectProp(Instance: TObject; const PropName: String; MinClass : TClass): TObject;
  365. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty): TObject;
  366. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; MinClass : TClass): TObject;
  367. procedure SetObjectProp(Instance: TObject; const PropName: String; Value: TObject) ;
  368. procedure SetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: TObject);
  369. Function GetFloatProp(Instance: TObject; const PropName: string): Double;
  370. Function GetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty) : Double;
  371. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Double);
  372. Procedure SetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty; Value : Double);
  373. implementation
  374. function GetClassMembers(aTIStruct: TTypeInfoStruct): TTypeMemberDynArray;
  375. var
  376. C: TTypeInfoStruct;
  377. i: Integer;
  378. PropName: String;
  379. Names: TJSObject;
  380. begin
  381. Result:=nil;
  382. Names:=TJSObject.new;
  383. C:=aTIStruct;
  384. while C<>nil do
  385. begin
  386. for i:=0 to length(C.Names)-1 do
  387. begin
  388. PropName:=C.Names[i];
  389. if Names.hasOwnProperty(PropName) then continue;
  390. TJSArray(Result).push(C.Members[PropName]);
  391. Names[PropName]:=true;
  392. end;
  393. if not (C is TTypeInfoClass) then break;
  394. C:=TTypeInfoClass(C).Ancestor;
  395. end;
  396. end;
  397. function GetClassMember(aTIStruct: TTypeInfoStruct; const aName: String): TTypeMember;
  398. var
  399. C: TTypeInfoStruct;
  400. i: Integer;
  401. begin
  402. // quick search: case sensitive
  403. C:=aTIStruct;
  404. while C<>nil do
  405. begin
  406. if TJSObject(C.Members).hasOwnProperty(aName) then
  407. exit(C.Members[aName]);
  408. if not (C is TTypeInfoClass) then break;
  409. C:=TTypeInfoClass(C).Ancestor;
  410. end;
  411. // slow search: case insensitive
  412. C:=aTIStruct;
  413. while C<>nil do
  414. begin
  415. for i:=0 to length(C.Names)-1 do
  416. if CompareText(C.Names[i],aName)=0 then
  417. exit(C.Members[C.Names[i]]);
  418. if not (C is TTypeInfoClass) then break;
  419. C:=TTypeInfoClass(C).Ancestor;
  420. end;
  421. Result:=nil;
  422. end;
  423. function GetInstanceMethod(Instance: TObject; const aName: String): Pointer;
  424. var
  425. TI: TTypeMember;
  426. begin
  427. if Instance=nil then exit(nil);
  428. TI:=GetClassMember(TypeInfo(Instance),aName);
  429. if not (TI is TTypeMemberMethod) then exit(nil);
  430. Result:=CreateMethod(Instance,TI.Name); // Note: use TI.Name for the correct case!
  431. end;
  432. function GetClassMethods(aTIStruct: TTypeInfoStruct): TTypeMemberMethodDynArray;
  433. var
  434. C: TTypeInfoStruct;
  435. i, Cnt, j: Integer;
  436. begin
  437. Cnt:=0;
  438. C:=aTIStruct;
  439. while C<>nil do
  440. begin
  441. inc(Cnt,C.MethodCount);
  442. if not (C is TTypeInfoClass) then break;
  443. C:=TTypeInfoClass(C).Ancestor;
  444. end;
  445. SetLength(Result,Cnt);
  446. C:=aTIStruct;
  447. i:=0;
  448. while C<>nil do
  449. begin
  450. for j:=0 to C.MethodCount-1 do
  451. begin
  452. Result[i]:=TTypeMemberMethod(C.Members[C.Methods[j]]);
  453. inc(i);
  454. end;
  455. if not (C is TTypeInfoClass) then break;
  456. C:=TTypeInfoClass(C).Ancestor;
  457. end;
  458. end;
  459. function GetInterfaceMembers(aTIInterface: TTypeInfoInterface
  460. ): TTypeMemberDynArray;
  461. var
  462. Intf: TTypeInfoInterface;
  463. i, Cnt, j: Integer;
  464. begin
  465. Cnt:=0;
  466. Intf:=aTIInterface;
  467. while Intf<>nil do
  468. begin
  469. inc(Cnt,length(Intf.Names));
  470. Intf:=Intf.Ancestor;
  471. end;
  472. SetLength(Result,Cnt);
  473. Intf:=aTIInterface;
  474. i:=0;
  475. while Intf<>nil do
  476. begin
  477. for j:=0 to length(Intf.Names)-1 do
  478. begin
  479. Result[i]:=Intf.Members[Intf.Names[j]];
  480. inc(i);
  481. end;
  482. Intf:=Intf.Ancestor;
  483. end;
  484. end;
  485. function GetInterfaceMember(aTIInterface: TTypeInfoInterface;
  486. const aName: String): TTypeMember;
  487. var
  488. Intf: TTypeInfoInterface;
  489. i: Integer;
  490. begin
  491. // quick search: case sensitive
  492. Intf:=aTIInterface;
  493. while Intf<>nil do
  494. begin
  495. if TJSObject(Intf.Members).hasOwnProperty(aName) then
  496. exit(Intf.Members[aName]);
  497. Intf:=Intf.Ancestor;
  498. end;
  499. // slow search: case insensitive
  500. Intf:=aTIInterface;
  501. while Intf<>nil do
  502. begin
  503. for i:=0 to length(Intf.Names)-1 do
  504. if CompareText(Intf.Names[i],aName)=0 then
  505. exit(Intf.Members[Intf.Names[i]]);
  506. Intf:=Intf.Ancestor;
  507. end;
  508. Result:=nil;
  509. end;
  510. function GetInterfaceMethods(aTIInterface: TTypeInfoInterface
  511. ): TTypeMemberMethodDynArray;
  512. var
  513. Intf: TTypeInfoInterface;
  514. i, Cnt, j: Integer;
  515. begin
  516. Cnt:=0;
  517. Intf:=aTIInterface;
  518. while Intf<>nil do
  519. begin
  520. inc(Cnt,Intf.MethodCount);
  521. Intf:=Intf.Ancestor;
  522. end;
  523. SetLength(Result,Cnt);
  524. Intf:=aTIInterface;
  525. i:=0;
  526. while Intf<>nil do
  527. begin
  528. for j:=0 to Intf.MethodCount-1 do
  529. begin
  530. Result[i]:=TTypeMemberMethod(Intf.Members[Intf.Methods[j]]);
  531. inc(i);
  532. end;
  533. Intf:=Intf.Ancestor;
  534. end;
  535. end;
  536. function GetPropInfos(aTIStruct: TTypeInfoStruct): TTypeMemberPropertyDynArray;
  537. var
  538. C: TTypeInfoStruct;
  539. i: Integer;
  540. Names: TJSObject;
  541. PropName: String;
  542. begin
  543. Result:=nil;
  544. C:=aTIStruct;
  545. Names:=TJSObject.new;
  546. while C<>nil do
  547. begin
  548. for i:=0 to C.PropCount-1 do
  549. begin
  550. PropName:=C.Properties[i];
  551. if Names.hasOwnProperty(PropName) then continue;
  552. TJSArray(Result).push(TTypeMemberProperty(C.Members[PropName]));
  553. Names[PropName]:=true;
  554. end;
  555. if not (C is TTypeInfoClass) then
  556. break;
  557. C:=TTypeInfoClass(C).Ancestor;
  558. end;
  559. end;
  560. function GetPropList(aTIStruct: TTypeInfoStruct; TypeKinds: TTypeKinds;
  561. Sorted: boolean): TTypeMemberPropertyDynArray;
  562. function NameSort(a,b: JSValue): NativeInt;
  563. begin
  564. if TTypeMemberProperty(a).Name<TTypeMemberProperty(b).Name then
  565. Result:=-1
  566. else if TTypeMemberProperty(a).Name>TTypeMemberProperty(b).Name then
  567. Result:=1
  568. else
  569. Result:=0;
  570. end;
  571. var
  572. C: TTypeInfoStruct;
  573. i: Integer;
  574. Names: TJSObject;
  575. PropName: String;
  576. Prop: TTypeMemberProperty;
  577. begin
  578. Result:=nil;
  579. C:=aTIStruct;
  580. Names:=TJSObject.new;
  581. while C<>nil do
  582. begin
  583. for i:=0 to C.PropCount-1 do
  584. begin
  585. PropName:=C.Properties[i];
  586. if Names.hasOwnProperty(PropName) then continue;
  587. Prop:=TTypeMemberProperty(C.Members[PropName]);
  588. if not (Prop.TypeInfo.Kind in TypeKinds) then continue;
  589. TJSArray(Result).push(Prop);
  590. Names[PropName]:=true;
  591. end;
  592. if not (C is TTypeInfoClass) then
  593. break;
  594. C:=TTypeInfoClass(C).Ancestor;
  595. end;
  596. if Sorted then
  597. TJSArray(Result).sort(@NameSort);
  598. end;
  599. function GetPropList(aTIStruct: TTypeInfoStruct): TTypeMemberPropertyDynArray;
  600. begin
  601. Result:=GetPropInfos(aTIStruct);
  602. end;
  603. function GetPropList(AClass: TClass): TTypeMemberPropertyDynArray;
  604. begin
  605. Result:=GetPropInfos(TypeInfo(AClass));
  606. end;
  607. function GetPropList(Instance: TObject): TTypeMemberPropertyDynArray;
  608. begin
  609. Result:=GetPropList(Instance.ClassType);
  610. end;
  611. function GetPropInfo(TI: TTypeInfoStruct; const PropName: String
  612. ): TTypeMemberProperty;
  613. var
  614. m: TTypeMember;
  615. i: Integer;
  616. C: TTypeInfoStruct;
  617. begin
  618. // quick search case sensitive
  619. C:=TI;
  620. while C<>nil do
  621. begin
  622. m:=C.Members[PropName];
  623. if m is TTypeMemberProperty then
  624. exit(TTypeMemberProperty(m));
  625. if not (C is TTypeInfoClass) then
  626. break;
  627. C:=TTypeInfoClass(C).Ancestor;
  628. end;
  629. // slow search case insensitive
  630. Result:=nil;
  631. repeat
  632. for i:=0 to TI.PropCount-1 do
  633. if CompareText(PropName,TI.Properties[i])=0 then
  634. begin
  635. m:=TI.Members[TI.Properties[i]];
  636. if m is TTypeMemberProperty then
  637. Result:=TTypeMemberProperty(m);
  638. exit;
  639. end;
  640. if not (TI is TTypeInfoClass) then
  641. break;
  642. TI:=TTypeInfoClass(TI).Ancestor;
  643. until TI=nil;
  644. end;
  645. function GetPropInfo(TI: TTypeInfoStruct; const PropName: String;
  646. const Kinds: TTypeKinds): TTypeMemberProperty;
  647. begin
  648. Result:=GetPropInfo(TI,PropName);
  649. if (Kinds<>[]) and (Result<>nil) and not (Result.TypeInfo.Kind in Kinds) then
  650. Result:=nil;
  651. end;
  652. function GetPropInfo(Instance: TObject; const PropName: String
  653. ): TTypeMemberProperty;
  654. begin
  655. Result:=GetPropInfo(TypeInfo(Instance),PropName,[]);
  656. end;
  657. function GetPropInfo(Instance: TObject; const PropName: String;
  658. const Kinds: TTypeKinds): TTypeMemberProperty;
  659. begin
  660. Result:=GetPropInfo(TypeInfo(Instance),PropName,Kinds);
  661. end;
  662. function GetPropInfo(aClass: TClass; const PropName: String
  663. ): TTypeMemberProperty;
  664. begin
  665. Result:=GetPropInfo(TypeInfo(AClass),PropName,[]);
  666. end;
  667. function GetPropInfo(aClass: TClass; const PropName: String;
  668. const Kinds: TTypeKinds): TTypeMemberProperty;
  669. begin
  670. Result:=GetPropInfo(TypeInfo(AClass),PropName,Kinds);
  671. end;
  672. function FindPropInfo(Instance: TObject; const PropName: String
  673. ): TTypeMemberProperty;
  674. begin
  675. Result:=GetPropInfo(TypeInfo(Instance), PropName);
  676. if Result=nil then
  677. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  678. end;
  679. function FindPropInfo(Instance: TObject; const PropName: String;
  680. const Kinds: TTypeKinds): TTypeMemberProperty;
  681. begin
  682. Result:=GetPropInfo(TypeInfo(Instance), PropName, Kinds);
  683. if Result=nil then
  684. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  685. end;
  686. function FindPropInfo(aClass: TClass; const PropName: String
  687. ): TTypeMemberProperty;
  688. begin
  689. Result:=GetPropInfo(TypeInfo(aClass), PropName);
  690. if Result=nil then
  691. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  692. end;
  693. function FindPropInfo(aClass: TClass; const PropName: String;
  694. const Kinds: TTypeKinds): TTypeMemberProperty;
  695. begin
  696. Result:=GetPropInfo(TypeInfo(aClass), PropName, Kinds);
  697. if Result=nil then
  698. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  699. end;
  700. function IsStoredProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  701. ): Boolean;
  702. type
  703. TIsStored = function: Boolean of object;
  704. begin
  705. case PropInfo.Flags and 12 of
  706. 0: Result:=true;
  707. 4: Result:=false;
  708. 8: Result:=Boolean(TJSObject(Instance)[PropInfo.Stored]);
  709. else Result:=TIsStored(TJSObject(Instance)[PropInfo.Stored])();
  710. end;
  711. end;
  712. function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  713. begin
  714. Result:=IsStoredProp(Instance,FindPropInfo(Instance,PropName));
  715. end;
  716. function IsPublishedProp(Instance: TObject; const PropName: String): Boolean;
  717. begin
  718. Result:=GetPropInfo(Instance,PropName)<>nil;
  719. end;
  720. function IsPublishedProp(aClass: TClass; const PropName: String): Boolean;
  721. begin
  722. Result:=GetPropInfo(aClass,PropName)<>nil;
  723. end;
  724. function PropType(Instance: TObject; const PropName: string): TTypeKind;
  725. begin
  726. Result:=FindPropInfo(Instance,PropName).TypeInfo.Kind;
  727. end;
  728. function PropType(aClass: TClass; const PropName: string): TTypeKind;
  729. begin
  730. Result:=FindPropInfo(aClass,PropName).TypeInfo.Kind;
  731. end;
  732. function PropIsType(Instance: TObject; const PropName: string;
  733. const TypeKind: TTypeKind): Boolean;
  734. begin
  735. Result:=PropType(Instance,PropName)=TypeKind;
  736. end;
  737. function PropIsType(aClass: TClass; const PropName: string;
  738. const TypeKind: TTypeKind): Boolean;
  739. begin
  740. Result:=PropType(aClass,PropName)=TypeKind;
  741. end;
  742. type
  743. TGetterKind = (
  744. gkNone,
  745. gkField,
  746. gkFunction,
  747. gkFunctionWithParams
  748. );
  749. function GetPropGetterKind(const PropInfo: TTypeMemberProperty): TGetterKind;
  750. begin
  751. if PropInfo.Getter='' then
  752. Result:=gkNone
  753. else if (pfGetFunction and PropInfo.Flags)>0 then
  754. begin
  755. if length(PropInfo.Params)>0 then
  756. Result:=gkFunctionWithParams
  757. else
  758. Result:=gkFunction;
  759. end
  760. else
  761. Result:=gkField;
  762. end;
  763. type
  764. TSetterKind = (
  765. skNone,
  766. skField,
  767. skProcedure,
  768. skProcedureWithParams
  769. );
  770. function GetPropSetterKind(const PropInfo: TTypeMemberProperty): TSetterKind;
  771. begin
  772. if PropInfo.Setter='' then
  773. Result:=skNone
  774. else if (pfSetProcedure and PropInfo.Flags)>0 then
  775. begin
  776. if length(PropInfo.Params)>0 then
  777. Result:=skProcedureWithParams
  778. else
  779. Result:=skProcedure;
  780. end
  781. else
  782. Result:=skField;
  783. end;
  784. function GetJSValueProp(Instance: TJSObject; TI: TTypeInfoStruct;
  785. const PropName: String): JSValue;
  786. var
  787. PropInfo: TTypeMemberProperty;
  788. begin
  789. PropInfo:=GetPropInfo(TI,PropName);
  790. if PropInfo=nil then
  791. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  792. Result:=GetJSValueProp(Instance,PropInfo);
  793. end;
  794. function GetJSValueProp(Instance: TJSObject;
  795. const PropInfo: TTypeMemberProperty): JSValue;
  796. type
  797. TGetter = function: JSValue of object;
  798. TGetterWithIndex = function(Index: JSValue): JSValue of object;
  799. var
  800. gk: TGetterKind;
  801. begin
  802. gk:=GetPropGetterKind(PropInfo);
  803. case gk of
  804. gkNone:
  805. raise EPropertyError.CreateFmt(SCantReadPropertyS, [PropInfo.Name]);
  806. gkField:
  807. Result:=Instance[PropInfo.Getter];
  808. gkFunction:
  809. if (pfHasIndex and PropInfo.Flags)>0 then
  810. Result:=TGetterWithIndex(Instance[PropInfo.Getter])(PropInfo.Index)
  811. else
  812. Result:=TGetter(Instance[PropInfo.Getter])();
  813. gkFunctionWithParams:
  814. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  815. end;
  816. end;
  817. function GetJSValueProp(Instance: TObject; const PropName: String): JSValue;
  818. begin
  819. Result:=GetJSValueProp(Instance,FindPropInfo(Instance,PropName));
  820. end;
  821. function GetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  822. ): JSValue;
  823. begin
  824. Result:=GetJSValueProp(TJSObject(Instance),PropInfo);
  825. end;
  826. procedure SetJSValueProp(Instance: TJSObject; TI: TTypeInfoStruct;
  827. const PropName: String; Value: JSValue);
  828. var
  829. PropInfo: TTypeMemberProperty;
  830. begin
  831. PropInfo:=GetPropInfo(TI,PropName);
  832. if PropInfo=nil then
  833. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  834. SetJSValueProp(Instance,PropInfo,Value);
  835. end;
  836. procedure SetJSValueProp(Instance: TJSObject;
  837. const PropInfo: TTypeMemberProperty; Value: JSValue);
  838. type
  839. TSetter = procedure(Value: JSValue) of object;
  840. TSetterWithIndex = procedure(Index, Value: JSValue) of object;
  841. var
  842. sk: TSetterKind;
  843. begin
  844. sk:=GetPropSetterKind(PropInfo);
  845. case sk of
  846. skNone:
  847. raise EPropertyError.CreateFmt(SCantWritePropertyS, [PropInfo.Name]);
  848. skField:
  849. Instance[PropInfo.Setter]:=Value;
  850. skProcedure:
  851. if (pfHasIndex and PropInfo.Flags)>0 then
  852. TSetterWithIndex(Instance[PropInfo.Setter])(PropInfo.Index,Value)
  853. else
  854. TSetter(Instance[PropInfo.Setter])(Value);
  855. skProcedureWithParams:
  856. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  857. end;
  858. end;
  859. procedure SetJSValueProp(Instance: TObject; const PropName: String;
  860. Value: JSValue);
  861. begin
  862. SetJSValueProp(Instance,FindPropInfo(Instance,PropName),Value);
  863. end;
  864. procedure SetJSValueProp(Instance: TObject;
  865. const PropInfo: TTypeMemberProperty; Value: JSValue);
  866. begin
  867. SetJSValueProp(TJSObject(Instance),PropInfo,Value);
  868. end;
  869. function GetNativeIntProp(Instance: TObject; const PropName: String): NativeInt;
  870. begin
  871. Result:=GetNativeIntProp(Instance,FindPropInfo(Instance,PropName));
  872. end;
  873. function GetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  874. ): NativeInt;
  875. begin
  876. Result:=NativeInt(GetJSValueProp(Instance,PropInfo));
  877. end;
  878. procedure SetNativeIntProp(Instance: TObject; const PropName: String;
  879. Value: NativeInt);
  880. begin
  881. SetJSValueProp(Instance,FindPropInfo(Instance,PropName),Value);
  882. end;
  883. procedure SetNativeIntProp(Instance: TObject;
  884. const PropInfo: TTypeMemberProperty; Value: NativeInt);
  885. begin
  886. SetJSValueProp(Instance,PropInfo,Value);
  887. end;
  888. function GetOrdProp(Instance: TObject; const PropName: String): longint;
  889. begin
  890. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  891. end;
  892. function GetOrdProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  893. ): longint;
  894. var
  895. o: TJSObject;
  896. Key: String;
  897. n: NativeInt;
  898. begin
  899. if PropInfo.TypeInfo.Kind=tkSet then
  900. begin
  901. // a set is a JS object, with the following property: o[ElementDecimal]=true
  902. o:=TJSObject(GetJSValueProp(Instance,PropInfo));
  903. Result:=0;
  904. for Key in o do
  905. begin
  906. n:=parseInt(Key,10);
  907. if n<32 then
  908. Result:=Result+(1 shl n);
  909. end;
  910. end else
  911. Result:=longint(GetJSValueProp(Instance,PropInfo));
  912. end;
  913. procedure SetOrdProp(Instance: TObject; const PropName: String; Value: longint);
  914. begin
  915. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  916. end;
  917. procedure SetOrdProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  918. Value: longint);
  919. var
  920. o: TJSObject;
  921. i: Integer;
  922. begin
  923. if PropInfo.TypeInfo.Kind=tkSet then
  924. begin
  925. o:=TJSObject.new;
  926. for i:=0 to 31 do
  927. if (1 shl i) and Value>0 then
  928. o[str(i)]:=true;
  929. SetJSValueProp(Instance,PropInfo,o);
  930. end else
  931. SetJSValueProp(Instance,PropInfo,Value);
  932. end;
  933. function GetEnumProp(Instance: TObject; const PropName: String): String;
  934. begin
  935. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  936. end;
  937. function GetEnumProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String;
  938. var
  939. n: NativeInt;
  940. TIEnum: TTypeInfoEnum;
  941. begin
  942. TIEnum:=PropInfo.TypeInfo as TTypeInfoEnum;
  943. n:=NativeInt(GetJSValueProp(Instance,PropInfo));
  944. if (n>=TIEnum.MinValue) and (n<=TIEnum.MaxValue) then
  945. Result:=TIEnum.EnumType.IntToName[n]
  946. else
  947. Result:=str(n);
  948. end;
  949. procedure SetEnumProp(Instance: TObject; const PropName: String;
  950. const Value: String);
  951. begin
  952. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  953. end;
  954. procedure SetEnumProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  955. const Value: String);
  956. var
  957. TIEnum: TTypeInfoEnum;
  958. n: NativeInt;
  959. begin
  960. TIEnum:=PropInfo.TypeInfo as TTypeInfoEnum;
  961. n:=TIEnum.EnumType.NameToInt[Value];
  962. if not isUndefined(n) then
  963. SetJSValueProp(Instance,PropInfo,n);
  964. end;
  965. function GetEnumName(TypeInfo: TTypeInfoEnum; Value: Integer): String;
  966. begin
  967. Result:=TypeInfo.EnumType.IntToName[Value];
  968. end;
  969. function GetEnumValue(TypeInfo: TTypeInfoEnum; const Name: string): Longint;
  970. begin
  971. Result:=TypeInfo.EnumType.NameToInt[Name];
  972. end;
  973. function GetEnumNameCount(TypeInfo: TTypeInfoEnum): Longint;
  974. var
  975. o: TJSObject;
  976. l, r: LongInt;
  977. begin
  978. o:=TJSObject(TypeInfo.EnumType);
  979. // as of pas2js 1.0 the RTTI does not contain a min/max value
  980. // -> use exponential search
  981. // ToDo: adapt this once enums with gaps are supported
  982. Result:=1;
  983. while o.hasOwnProperty(String(JSValue(Result))) do
  984. Result:=Result*2;
  985. l:=Result div 2;
  986. r:=Result;
  987. while l<=r do
  988. begin
  989. Result:=(l+r) div 2;
  990. if o.hasOwnProperty(String(JSValue(Result))) then
  991. l:=Result+1
  992. else
  993. r:=Result-1;
  994. end;
  995. if o.hasOwnProperty(String(JSValue(Result))) then
  996. inc(Result);
  997. end;
  998. function GetSetProp(Instance: TObject; const PropName: String): String;
  999. begin
  1000. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName));
  1001. end;
  1002. function GetSetProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  1003. ): String;
  1004. var
  1005. o: TJSObject;
  1006. key, Value: String;
  1007. n: NativeInt;
  1008. TIEnum: TTypeInfoEnum;
  1009. TISet: TTypeInfoSet;
  1010. begin
  1011. Result:='';
  1012. // get enum type if available
  1013. TISet:=PropInfo.TypeInfo as TTypeInfoSet;
  1014. TIEnum:=nil;
  1015. if TISet.CompType is TTypeInfoEnum then
  1016. TIEnum:=TTypeInfoEnum(TISet.CompType);
  1017. // read value
  1018. o:=TJSObject(GetJSValueProp(Instance,PropInfo));
  1019. // a set is a JS object, where included element is stored as: o[ElementDecimal]=true
  1020. for Key in o do
  1021. begin
  1022. n:=parseInt(Key,10);
  1023. if (TIEnum<>nil) and (n>=TIEnum.MinValue) and (n<=TIEnum.MaxValue) then
  1024. Value:=TIEnum.EnumType.IntToName[n]
  1025. else
  1026. Value:=str(n);
  1027. if Result<>'' then Result:=Result+',';
  1028. Result:=Result+Value;
  1029. end;
  1030. Result:='['+Result+']';
  1031. end;
  1032. function GetSetPropArray(Instance: TObject; const PropName: String
  1033. ): TIntegerDynArray;
  1034. begin
  1035. Result:=GetSetPropArray(Instance,FindPropInfo(Instance,PropName));
  1036. end;
  1037. function GetSetPropArray(Instance: TObject; const PropInfo: TTypeMemberProperty
  1038. ): TIntegerDynArray;
  1039. var
  1040. o: TJSObject;
  1041. Key: string;
  1042. begin
  1043. Result:=[];
  1044. // read value
  1045. o:=TJSObject(GetJSValueProp(Instance,PropInfo));
  1046. // a set is a JS object, where included element is stored as: o[ElementDecimal]=true
  1047. for Key in o do
  1048. TJSArray(Result).push(parseInt(Key,10));
  1049. end;
  1050. procedure SetSetPropArray(Instance: TObject; const PropName: String;
  1051. const Arr: TIntegerDynArray);
  1052. begin
  1053. SetSetPropArray(Instance,FindPropInfo(Instance,PropName),Arr);
  1054. end;
  1055. procedure SetSetPropArray(Instance: TObject;
  1056. const PropInfo: TTypeMemberProperty; const Arr: TIntegerDynArray);
  1057. var
  1058. o: TJSObject;
  1059. i: integer;
  1060. begin
  1061. o:=TJSObject.new;
  1062. for i in Arr do
  1063. o[str(i)]:=true;
  1064. SetJSValueProp(Instance,PropInfo,o);
  1065. end;
  1066. function GetStrProp(Instance: TObject; const PropName: String): String;
  1067. begin
  1068. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1069. end;
  1070. function GetStrProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  1071. ): String;
  1072. begin
  1073. Result:=String(GetJSValueProp(Instance,PropInfo));
  1074. end;
  1075. procedure SetStrProp(Instance: TObject; const PropName: String; Value: String
  1076. );
  1077. begin
  1078. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1079. end;
  1080. procedure SetStrProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  1081. Value: String);
  1082. begin
  1083. SetJSValueProp(Instance,PropInfo,Value);
  1084. end;
  1085. function GetStringProp(Instance: TObject; const PropName: String): String;
  1086. begin
  1087. Result:=GetStrProp(Instance,PropName);
  1088. end;
  1089. function GetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  1090. ): String;
  1091. begin
  1092. Result:=GetStrProp(Instance,PropInfo);
  1093. end;
  1094. procedure SetStringProp(Instance: TObject; const PropName: String; Value: String
  1095. );
  1096. begin
  1097. SetStrProp(Instance,PropName,Value);
  1098. end;
  1099. procedure SetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  1100. Value: String);
  1101. begin
  1102. SetStrProp(Instance,PropInfo,Value);
  1103. end;
  1104. function GetBoolProp(Instance: TObject; const PropName: String): boolean;
  1105. begin
  1106. Result:=GetBoolProp(Instance,FindPropInfo(Instance,PropName));
  1107. end;
  1108. function GetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  1109. ): boolean;
  1110. begin
  1111. Result:=Boolean(GetJSValueProp(Instance,PropInfo));
  1112. end;
  1113. procedure SetBoolProp(Instance: TObject; const PropName: String; Value: boolean
  1114. );
  1115. begin
  1116. SetBoolProp(Instance,FindPropInfo(Instance,PropName),Value);
  1117. end;
  1118. procedure SetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  1119. Value: boolean);
  1120. begin
  1121. SetJSValueProp(Instance,PropInfo,Value);
  1122. end;
  1123. function GetObjectProp(Instance: TObject; const PropName: String): TObject;
  1124. begin
  1125. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName));
  1126. end;
  1127. function GetObjectProp(Instance: TObject; const PropName: String; MinClass : TClass): TObject;
  1128. begin
  1129. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName));
  1130. if (MinClass<>Nil) and (Result<>Nil) Then
  1131. if not Result.InheritsFrom(MinClass) then
  1132. Result:=Nil;
  1133. end;
  1134. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty): TObject;
  1135. begin
  1136. Result:=GetObjectProp(Instance,PropInfo,Nil);
  1137. end;
  1138. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; MinClass : TClass): TObject;
  1139. Var
  1140. O : TObject;
  1141. begin
  1142. O:=TObject(GetJSValueProp(Instance,PropInfo));
  1143. if (MinClass<>Nil) and not O.InheritsFrom(MinClass) then
  1144. Result:=Nil
  1145. else
  1146. Result:=O;
  1147. end;
  1148. procedure SetObjectProp(Instance: TObject; const PropName: String; Value: TObject) ;
  1149. begin
  1150. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  1151. end;
  1152. procedure SetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: TObject);
  1153. begin
  1154. SetJSValueProp(Instance,PropInfo,Value);
  1155. end;
  1156. function GetFloatProp(Instance: TObject; PropInfo: TTypeMemberProperty): Double;
  1157. begin
  1158. Result:=Double(GetJSValueProp(Instance,PropInfo));
  1159. end;
  1160. function GetFloatProp(Instance: TObject; const PropName: string): Double;
  1161. begin
  1162. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName));
  1163. end;
  1164. procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Double
  1165. );
  1166. begin
  1167. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1168. end;
  1169. procedure SetFloatProp(Instance: TObject; PropInfo: TTypeMemberProperty;
  1170. Value: Double);
  1171. begin
  1172. SetJSValueProp(Instance,PropInfo,Value);
  1173. end;
  1174. end.