typinfo.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (c) 2017 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,
  48. //tkFile,
  49. );
  50. TTypeKinds = set of TTypeKind;
  51. const
  52. tkFloat = tkDouble; // for compatibility with Delphi/FPC
  53. tkProcedure = tkProcVar; // for compatibility with Delphi
  54. tkAny = [Low(TTypeKind)..High(TTypeKind)];
  55. tkMethods = [tkMethod];
  56. tkProperties = tkAny-tkMethods-[tkUnknown];
  57. type
  58. { TTypeInfo }
  59. TTypeInfo = class external name 'rtl.tTypeInfo'
  60. public
  61. Name: String external name 'name';
  62. Kind: TTypeKind external name 'kind';
  63. end;
  64. TTypeInfoClassOf = class of TTypeInfo;
  65. TOrdType = (
  66. otSByte, // 0
  67. otUByte, // 1
  68. otSWord, // 2
  69. otUWord, // 3
  70. otSLong, // 4
  71. otULong, // 5
  72. otSIntDouble, // 6 NativeInt
  73. otUIntDouble // 7 NativeUInt
  74. );
  75. { TTypeInfoInteger - Kind = tkInteger }
  76. TTypeInfoInteger = class external name 'rtl.tTypeInfoInteger'(TTypeInfo)
  77. public
  78. MinValue: NativeInt external name 'minvalue';
  79. MaxValue: NativeInt external name 'maxvalue';
  80. OrdType : TOrdType external name 'ordtype';
  81. end;
  82. { TEnumType }
  83. TEnumType = class external name 'anonymous'
  84. private
  85. function GetIntToName(Index: NativeInt): String; external name '[]';
  86. function GetNameToInt(Name: String): NativeInt; external name '[]';
  87. public
  88. property IntToName[Index: NativeInt]: String read GetIntToName;
  89. property NameToInt[Name: String]: NativeInt read GetNameToInt;
  90. end;
  91. { TTypeInfoEnum - Kind = tkEnumeration }
  92. TTypeInfoEnum = class external name 'rtl.tTypeInfoEnum'(TTypeInfoInteger)
  93. public
  94. // not supported: OrdType : TOrdType, BaseType: TTypeInfo
  95. EnumType: TEnumType external name 'enumtype';
  96. end;
  97. { TTypeInfoSet - Kind = tkSet }
  98. TTypeInfoSet = class external name 'rtl.tTypeInfoSet'(TTypeInfo)
  99. public
  100. // not supported: OrdType : TOrdType, BaseType: TTypeInfo
  101. CompType: TTypeInfo external name 'comptype';
  102. end;
  103. { TTypeInfoStaticArray - Kind = tkArray }
  104. TTypeInfoStaticArray = class external name 'rtl.tTypeInfoStaticArray'(TTypeInfo)
  105. public
  106. Dims: TIntegerDynArray;
  107. ElType: TTypeInfo external name 'eltype';
  108. end;
  109. { TTypeInfoDynArray - Kind = tkDynArray }
  110. TTypeInfoDynArray = class external name 'rtl.tTypeInfoDynArray'(TTypeInfo)
  111. public
  112. DimCount: NativeInt external name 'dimcount';
  113. ElType: TTypeInfo external name 'eltype';
  114. end;
  115. TParamFlag = (
  116. pfVar, // 2^0 = 1
  117. pfConst, // 2^1 = 2
  118. pfOut, // 2^2 = 4
  119. pfArray // 2^3 = 8
  120. //pfAddress,pfReference,
  121. );
  122. TParamFlags = set of TParamFlag;
  123. { TProcedureParam }
  124. TProcedureParam = class external name 'anonymous'
  125. public
  126. Name: String external name 'name';
  127. TypeInfo: TTypeInfo external name 'typeinfo';
  128. Flags: NativeInt external name 'flags'; // TParamFlags as bit vector
  129. end;
  130. TProcedureParams = array of TProcedureParam;
  131. TProcedureFlag = (
  132. pfStatic, // 2^0 = 1
  133. pfVarargs, // 2^1 = 2
  134. pfExternal // 2^2 = 4 name may be an expression
  135. );
  136. TProcedureFlags = set of TProcedureFlag;
  137. { TProcedureSignature }
  138. TProcedureSignature = class external name 'anonymous'
  139. public
  140. Params: TProcedureParams external name 'params'; // can be null
  141. ResultType: TTypeInfo external name 'resulttype'; // can be null
  142. Flags: NativeInt external name 'flags'; // TProcedureFlags as bit vector
  143. end;
  144. { TTypeInfoProcVar - Kind = tkProcVar }
  145. TTypeInfoProcVar = class external name 'rtl.tTypeInfoProcVar'(TTypeInfo)
  146. public
  147. ProcSig: TProcedureSignature external name 'procsig';
  148. end;
  149. { TTypeInfoRefToProcVar - Kind = tkRefToProcVar }
  150. TTypeInfoRefToProcVar = class external name 'rtl.tTypeInfoRefToProcVar'(TTypeInfoProcVar)
  151. end;
  152. TMethodKind = (
  153. mkProcedure, // 0 default
  154. mkFunction, // 1
  155. mkConstructor, // 2
  156. mkDestructor, // 3
  157. mkClassProcedure,// 4
  158. mkClassFunction // 5
  159. //mkClassConstructor,mkClassDestructor,mkOperatorOverload
  160. );
  161. TMethodKinds = set of TMethodKind;
  162. { TTypeInfoMethodVar - Kind = tkMethod }
  163. TTypeInfoMethodVar = class external name 'rtl.tTypeInfoMethodVar'(TTypeInfoProcVar)
  164. public
  165. MethodKind: TMethodKind external name 'methodkind';
  166. end;
  167. TTypeMemberKind = (
  168. tmkUnknown, // 0
  169. tmkField, // 1
  170. tmkMethod, // 2
  171. tmkProperty // 3
  172. );
  173. TTypeMemberKinds = set of TTypeMemberKind;
  174. { TTypeMember }
  175. TTypeMember = class external name 'rtl.tTypeMember'
  176. public
  177. Name: String external name 'name';
  178. Kind: TTypeMemberKind external name 'kind';
  179. end;
  180. TTypeMemberDynArray = array of TTypeMember;
  181. { TTypeMemberField - Kind = tmkField }
  182. TTypeMemberField = class external name 'rtl.tTypeMemberField'(TTypeMember)
  183. public
  184. TypeInfo: TTypeInfo external name 'typeinfo';
  185. end;
  186. { TTypeMemberMethod - Kind = tmkMethod }
  187. TTypeMemberMethod = class external name 'rtl.tTypeMemberMethod'(TTypeMember)
  188. public
  189. MethodKind: TMethodKind external name 'methodkind';
  190. ProcSig: TProcedureSignature external name 'procsig';
  191. end;
  192. TTypeMemberMethodDynArray = array of TTypeMemberMethod;
  193. const
  194. pfGetFunction = 1; // getter is a function
  195. pfSetProcedure = 2; // setter is a procedure
  196. // stored is a 2-bit vector:
  197. pfStoredFalse = 4; // stored false, never
  198. pfStoredField = 8; // stored field, field name is in Stored
  199. pfStoredFunction = 12; // stored function, function name is in Stored
  200. pfHasIndex = 16; { if getter is function, append Index as last param
  201. if setter is function, append Index as second last param }
  202. type
  203. { TTypeMemberProperty - Kind = tmkProperty }
  204. TTypeMemberProperty = class external name 'rtl.tTypeMemberProperty'(TTypeMember)
  205. public
  206. TypeInfo: TTypeInfo external name 'typeinfo';
  207. Flags: NativeInt external name 'flags'; // bit vector, see pf constants above
  208. Params: TProcedureParams external name 'params'; // can be null
  209. Index: JSValue external name 'index'; // can be undefined
  210. Getter: String external name 'getter'; // name of field or function
  211. Setter: String external name 'setter'; // name of field or function
  212. Stored: String external name 'stored'; // name of field or function, can be undefined
  213. Default: JSValue external name 'Default'; // can be undefined
  214. end;
  215. TTypeMemberPropertyDynArray = array of TTypeMemberProperty;
  216. { TTypeMembers }
  217. TTypeMembers = class external name 'rtl.tTypeMembers'
  218. private
  219. function GetItems(Name: String): TTypeMember; external name '[]';
  220. procedure SetItems(Name: String; const AValue: TTypeMember); external name '[]';
  221. public
  222. property Members[Name: String]: TTypeMember read GetItems write SetItems; default;
  223. end;
  224. { TTypeInfoStruct }
  225. TTypeInfoStruct = class external name 'rtl.tTypeInfoStruct'(TTypeInfo)
  226. private
  227. FFieldCount: NativeInt external name 'fields.length';
  228. FMethodCount: NativeInt external name 'methods.length';
  229. FPropCount: NativeInt external name 'properties.length';
  230. public
  231. Members: TTypeMembers external name 'members';
  232. Names: TStringDynArray external name 'names'; // all member names with TTypeInfo
  233. Fields: TStringDynArray external name 'fields';
  234. Methods: TStringDynArray external name 'methods';
  235. Properties: TStringDynArray external name 'properties';
  236. property FieldCount: NativeInt read FFieldCount;
  237. function GetField(Index: NativeInt): TTypeMemberField; external name 'getField';
  238. function AddField(aName: String; aType: TTypeInfo; Options: TJSObject = nil
  239. ): TTypeMemberField; external name 'addField';
  240. property MethodCount: NativeInt read FMethodCount;
  241. function GetMethod(Index: NativeInt): TTypeMemberMethod; external name 'getMethod';
  242. function AddMethod(aName: String; MethodKind: TMethodKind = mkProcedure;
  243. Params: TJSArray = nil; ResultType: TTypeInfo = nil;
  244. Options: TJSObject = nil): TTypeMemberMethod; external name 'addMethod';
  245. property PropCount: NativeInt read FPropCount;
  246. function GetProp(Index: NativeInt): TTypeMemberProperty; external name 'getProperty';
  247. function AddProperty(aName: String; Flags: NativeInt; ResultType: TTypeInfo;
  248. Getter, Setter: String; Options: TJSObject = nil): TTypeMemberProperty; external name 'addProperty';
  249. end;
  250. { TTypeInfoRecord - Kind = tkRecord }
  251. TTypeInfoRecord = class external name 'rtl.tTypeInfoRecord'(TTypeInfoStruct)
  252. public
  253. RecordType: TJSObject external name 'record';
  254. end;
  255. { TTypeInfoClass - Kind = tkClass }
  256. TTypeInfoClass = class external name 'rtl.tTypeInfoClass'(TTypeInfoStruct)
  257. public
  258. ClassType: TClass external name 'class';
  259. Ancestor: TTypeInfoClass external name 'ancestor';
  260. end;
  261. { TTypeInfoClassRef - class-of, Kind = tkClassRef }
  262. TTypeInfoClassRef = class external name 'rtl.tTypeInfoClassRef'(TTypeInfo)
  263. public
  264. InstanceType: TTypeInfo external name 'instancetype';
  265. end;
  266. { TTypeInfoPointer - Kind = tkPointer }
  267. TTypeInfoPointer = class external name 'rtl.tTypeInfoPointer'(TTypeInfo)
  268. public
  269. RefType: TTypeInfo external name 'reftype'; // can be null
  270. end;
  271. { TTypeInfoInterface - Kind = tkInterface }
  272. TTypeInfoInterface = class external name 'rtl.tTypeInfoInterface'(TTypeInfoStruct)
  273. public
  274. InterfaceType: TJSObject external name 'interface';
  275. Ancestor: TTypeInfoInterface external name 'ancestor';
  276. end;
  277. EPropertyError = class(Exception);
  278. function GetClassMembers(aTIClass: TTypeInfoClass): TTypeMemberDynArray;
  279. function GetClassMember(aTIClass: TTypeInfoClass; const aName: String): TTypeMember;
  280. function GetInstanceMethod(Instance: TObject; const aName: String): Pointer;
  281. function GetClassMethods(aTIClass: TTypeInfoClass): TTypeMemberMethodDynArray;
  282. function CreateMethod(Instance: TObject; FuncName: String): Pointer; external name 'rtl.createCallback';
  283. function GetInterfaceMembers(aTIInterface: TTypeInfoInterface): TTypeMemberDynArray;
  284. function GetInterfaceMember(aTIInterface: TTypeInfoInterface; const aName: String): TTypeMember;
  285. function GetInterfaceMethods(aTIInterface: TTypeInfoInterface): TTypeMemberMethodDynArray;
  286. function GetPropInfos(aTIClass: TTypeInfoClass): TTypeMemberPropertyDynArray;
  287. function GetPropInfo(TI: TTypeInfoClass; const PropName: String): TTypeMemberProperty;
  288. function GetPropInfo(TI: TTypeInfoClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  289. function GetPropInfo(Instance: TObject; const PropName: String): TTypeMemberProperty;
  290. function GetPropInfo(Instance: TObject; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  291. function GetPropInfo(aClass: TClass; const PropName: String): TTypeMemberProperty;
  292. function GetPropInfo(aClass: TClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  293. function FindPropInfo(Instance: TObject; const PropName: String): TTypeMemberProperty;
  294. function FindPropInfo(Instance: TObject; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  295. function FindPropInfo(aClass: TClass; const PropName: String): TTypeMemberProperty;
  296. function FindPropInfo(aClass: TClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  297. // Property information routines.
  298. Function IsStoredProp(Instance: TObject; const PropInfo: TTypeMemberProperty): Boolean;
  299. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  300. function IsPublishedProp(Instance: TObject; const PropName: String): Boolean;
  301. function IsPublishedProp(aClass: TClass; const PropName: String): Boolean;
  302. function PropType(Instance: TObject; const PropName: string): TTypeKind;
  303. function PropType(aClass: TClass; const PropName: string): TTypeKind;
  304. function PropIsType(Instance: TObject; const PropName: string; const TypeKind: TTypeKind): Boolean;
  305. function PropIsType(aClass: TClass; const PropName: string; const TypeKind: TTypeKind): Boolean;
  306. function GetJSValueProp(Instance: TObject; const PropName: String): JSValue;
  307. function GetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty): JSValue;
  308. procedure SetJSValueProp(Instance: TObject; const PropName: String; Value: JSValue);
  309. procedure SetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: JSValue);
  310. function GetNativeIntProp(Instance: TObject; const PropName: String): NativeInt;
  311. function GetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty): NativeInt;
  312. procedure SetNativeIntProp(Instance: TObject; const PropName: String; Value: NativeInt);
  313. procedure SetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: NativeInt);
  314. function GetStringProp(Instance: TObject; const PropName: String): String;
  315. function GetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String;
  316. procedure SetStringProp(Instance: TObject; const PropName: String; Value: String);
  317. procedure SetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: String);
  318. function GetBoolProp(Instance: TObject; const PropName: String): boolean;
  319. function GetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty): boolean;
  320. procedure SetBoolProp(Instance: TObject; const PropName: String; Value: boolean);
  321. procedure SetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: boolean);
  322. function GetObjectProp(Instance: TObject; const PropName: String): TObject;
  323. function GetObjectProp(Instance: TObject; const PropName: String; MinClass : TClass): TObject;
  324. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty): TObject;
  325. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; MinClass : TClass): TObject;
  326. procedure SetObjectProp(Instance: TObject; const PropName: String; Value: TObject) ;
  327. procedure SetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: TObject);
  328. Function GetFloatProp(Instance: TObject; const PropName: string): Double;
  329. Function GetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty) : Double;
  330. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Double);
  331. Procedure SetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty; Value : Double);
  332. implementation
  333. function GetClassMembers(aTIClass: TTypeInfoClass): TTypeMemberDynArray;
  334. var
  335. C: TTypeInfoClass;
  336. i, Cnt, j: Integer;
  337. begin
  338. Cnt:=0;
  339. C:=aTIClass;
  340. while C<>nil do
  341. begin
  342. inc(Cnt,length(C.Names));
  343. C:=C.Ancestor;
  344. end;
  345. SetLength(Result,Cnt);
  346. C:=aTIClass;
  347. i:=0;
  348. while C<>nil do
  349. begin
  350. for j:=0 to length(C.Names)-1 do
  351. begin
  352. Result[i]:=C.Members[C.Names[j]];
  353. inc(i);
  354. end;
  355. C:=C.Ancestor;
  356. end;
  357. end;
  358. function GetClassMember(aTIClass: TTypeInfoClass; const aName: String): TTypeMember;
  359. var
  360. C: TTypeInfoClass;
  361. i: Integer;
  362. begin
  363. // quick search: case sensitive
  364. C:=aTIClass;
  365. while C<>nil do
  366. begin
  367. if TJSObject(C.Members).hasOwnProperty(aName) then
  368. exit(C.Members[aName]);
  369. C:=C.Ancestor;
  370. end;
  371. // slow search: case insensitive
  372. C:=aTIClass;
  373. while C<>nil do
  374. begin
  375. for i:=0 to length(C.Names)-1 do
  376. if CompareText(C.Names[i],aName)=0 then
  377. exit(C.Members[C.Names[i]]);
  378. C:=C.Ancestor;
  379. end;
  380. Result:=nil;
  381. end;
  382. function GetInstanceMethod(Instance: TObject; const aName: String): Pointer;
  383. var
  384. TI: TTypeMember;
  385. begin
  386. if Instance=nil then exit(nil);
  387. TI:=GetClassMember(TypeInfo(Instance),aName);
  388. if not (TI is TTypeMemberMethod) then exit(nil);
  389. Result:=CreateMethod(Instance,TI.Name); // Note: use TI.Name for the correct case!
  390. end;
  391. function GetClassMethods(aTIClass: TTypeInfoClass): TTypeMemberMethodDynArray;
  392. var
  393. C: TTypeInfoClass;
  394. i, Cnt, j: Integer;
  395. begin
  396. Cnt:=0;
  397. C:=aTIClass;
  398. while C<>nil do
  399. begin
  400. inc(Cnt,C.MethodCount);
  401. C:=C.Ancestor;
  402. end;
  403. SetLength(Result,Cnt);
  404. C:=aTIClass;
  405. i:=0;
  406. while C<>nil do
  407. begin
  408. for j:=0 to C.MethodCount-1 do
  409. begin
  410. Result[i]:=TTypeMemberMethod(C.Members[C.Methods[j]]);
  411. inc(i);
  412. end;
  413. C:=C.Ancestor;
  414. end;
  415. end;
  416. function GetInterfaceMembers(aTIInterface: TTypeInfoInterface
  417. ): TTypeMemberDynArray;
  418. var
  419. Intf: TTypeInfoInterface;
  420. i, Cnt, j: Integer;
  421. begin
  422. Cnt:=0;
  423. Intf:=aTIInterface;
  424. while Intf<>nil do
  425. begin
  426. inc(Cnt,length(Intf.Names));
  427. Intf:=Intf.Ancestor;
  428. end;
  429. SetLength(Result,Cnt);
  430. Intf:=aTIInterface;
  431. i:=0;
  432. while Intf<>nil do
  433. begin
  434. for j:=0 to length(Intf.Names)-1 do
  435. begin
  436. Result[i]:=Intf.Members[Intf.Names[j]];
  437. inc(i);
  438. end;
  439. Intf:=Intf.Ancestor;
  440. end;
  441. end;
  442. function GetInterfaceMember(aTIInterface: TTypeInfoInterface;
  443. const aName: String): TTypeMember;
  444. var
  445. Intf: TTypeInfoInterface;
  446. i: Integer;
  447. begin
  448. // quick search: case sensitive
  449. Intf:=aTIInterface;
  450. while Intf<>nil do
  451. begin
  452. if TJSObject(Intf.Members).hasOwnProperty(aName) then
  453. exit(Intf.Members[aName]);
  454. Intf:=Intf.Ancestor;
  455. end;
  456. // slow search: case insensitive
  457. Intf:=aTIInterface;
  458. while Intf<>nil do
  459. begin
  460. for i:=0 to length(Intf.Names)-1 do
  461. if CompareText(Intf.Names[i],aName)=0 then
  462. exit(Intf.Members[Intf.Names[i]]);
  463. Intf:=Intf.Ancestor;
  464. end;
  465. Result:=nil;
  466. end;
  467. function GetInterfaceMethods(aTIInterface: TTypeInfoInterface
  468. ): TTypeMemberMethodDynArray;
  469. var
  470. Intf: TTypeInfoInterface;
  471. i, Cnt, j: Integer;
  472. begin
  473. Cnt:=0;
  474. Intf:=aTIInterface;
  475. while Intf<>nil do
  476. begin
  477. inc(Cnt,Intf.MethodCount);
  478. Intf:=Intf.Ancestor;
  479. end;
  480. SetLength(Result,Cnt);
  481. Intf:=aTIInterface;
  482. i:=0;
  483. while Intf<>nil do
  484. begin
  485. for j:=0 to Intf.MethodCount-1 do
  486. begin
  487. Result[i]:=TTypeMemberMethod(Intf.Members[Intf.Methods[j]]);
  488. inc(i);
  489. end;
  490. Intf:=Intf.Ancestor;
  491. end;
  492. end;
  493. function GetPropInfos(aTIClass: TTypeInfoClass): TTypeMemberPropertyDynArray;
  494. var
  495. C: TTypeInfoClass;
  496. i, Cnt, j: Integer;
  497. begin
  498. Cnt:=0;
  499. C:=aTIClass;
  500. while C<>nil do
  501. begin
  502. inc(Cnt,C.PropCount);
  503. C:=C.Ancestor;
  504. end;
  505. SetLength(Result,Cnt);
  506. C:=aTIClass;
  507. i:=0;
  508. while C<>nil do
  509. begin
  510. for j:=0 to C.PropCount-1 do
  511. begin
  512. Result[i]:=TTypeMemberProperty(C.Members[C.Properties[j]]);
  513. inc(i);
  514. end;
  515. C:=C.Ancestor;
  516. end;
  517. end;
  518. function GetPropInfo(TI: TTypeInfoClass; const PropName: String
  519. ): TTypeMemberProperty;
  520. var
  521. m: TTypeMember;
  522. i: Integer;
  523. C: TTypeInfoClass;
  524. begin
  525. // quick search case sensitive
  526. C:=TI;
  527. while C<>nil do
  528. begin
  529. m:=C.Members[PropName];
  530. if m is TTypeMemberProperty then
  531. exit(TTypeMemberProperty(m));
  532. C:=C.Ancestor;
  533. end;
  534. // slow search case insensitive
  535. Result:=nil;
  536. repeat
  537. for i:=0 to TI.PropCount-1 do
  538. if CompareText(PropName,TI.Properties[i])=0 then
  539. begin
  540. m:=TI.Members[TI.Properties[i]];
  541. if m is TTypeMemberProperty then
  542. Result:=TTypeMemberProperty(m);
  543. exit;
  544. end;
  545. TI:=TI.Ancestor;
  546. until TI=nil;
  547. end;
  548. function GetPropInfo(TI: TTypeInfoClass; const PropName: String;
  549. const Kinds: TTypeKinds): TTypeMemberProperty;
  550. begin
  551. Result:=GetPropInfo(TI,PropName);
  552. if (Kinds<>[]) and (Result<>nil) and not (Result.TypeInfo.Kind in Kinds) then
  553. Result:=nil;
  554. end;
  555. function GetPropInfo(Instance: TObject; const PropName: String
  556. ): TTypeMemberProperty;
  557. begin
  558. Result:=GetPropInfo(TypeInfo(Instance),PropName,[]);
  559. end;
  560. function GetPropInfo(Instance: TObject; const PropName: String;
  561. const Kinds: TTypeKinds): TTypeMemberProperty;
  562. begin
  563. Result:=GetPropInfo(TypeInfo(Instance),PropName,Kinds);
  564. end;
  565. function GetPropInfo(aClass: TClass; const PropName: String
  566. ): TTypeMemberProperty;
  567. begin
  568. Result:=GetPropInfo(TypeInfo(AClass),PropName,[]);
  569. end;
  570. function GetPropInfo(aClass: TClass; const PropName: String;
  571. const Kinds: TTypeKinds): TTypeMemberProperty;
  572. begin
  573. Result:=GetPropInfo(TypeInfo(AClass),PropName,Kinds);
  574. end;
  575. function FindPropInfo(Instance: TObject; const PropName: String
  576. ): TTypeMemberProperty;
  577. begin
  578. Result:=GetPropInfo(TypeInfo(Instance), PropName);
  579. if Result=nil then
  580. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  581. end;
  582. function FindPropInfo(Instance: TObject; const PropName: String;
  583. const Kinds: TTypeKinds): TTypeMemberProperty;
  584. begin
  585. Result:=GetPropInfo(TypeInfo(Instance), PropName, Kinds);
  586. if Result=nil then
  587. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  588. end;
  589. function FindPropInfo(aClass: TClass; const PropName: String
  590. ): TTypeMemberProperty;
  591. begin
  592. Result:=GetPropInfo(TypeInfo(aClass), PropName);
  593. if Result=nil then
  594. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  595. end;
  596. function FindPropInfo(aClass: TClass; const PropName: String;
  597. const Kinds: TTypeKinds): TTypeMemberProperty;
  598. begin
  599. Result:=GetPropInfo(TypeInfo(aClass), PropName, Kinds);
  600. if Result=nil then
  601. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  602. end;
  603. function IsStoredProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  604. ): Boolean;
  605. type
  606. TIsStored = function: Boolean of object;
  607. begin
  608. case PropInfo.Flags and 12 of
  609. 0: Result:=true;
  610. 4: Result:=false;
  611. 8: Result:=Boolean(TJSObject(Instance)[PropInfo.Stored]);
  612. else Result:=TIsStored(TJSObject(Instance)[PropInfo.Stored])();
  613. end;
  614. end;
  615. function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  616. begin
  617. Result:=IsStoredProp(Instance,FindPropInfo(Instance,PropName));
  618. end;
  619. function IsPublishedProp(Instance: TObject; const PropName: String): Boolean;
  620. begin
  621. Result:=GetPropInfo(Instance,PropName)<>nil;
  622. end;
  623. function IsPublishedProp(aClass: TClass; const PropName: String): Boolean;
  624. begin
  625. Result:=GetPropInfo(aClass,PropName)<>nil;
  626. end;
  627. function PropType(Instance: TObject; const PropName: string): TTypeKind;
  628. begin
  629. Result:=FindPropInfo(Instance,PropName).TypeInfo.Kind;
  630. end;
  631. function PropType(aClass: TClass; const PropName: string): TTypeKind;
  632. begin
  633. Result:=FindPropInfo(aClass,PropName).TypeInfo.Kind;
  634. end;
  635. function PropIsType(Instance: TObject; const PropName: string;
  636. const TypeKind: TTypeKind): Boolean;
  637. begin
  638. Result:=PropType(Instance,PropName)=TypeKind;
  639. end;
  640. function PropIsType(aClass: TClass; const PropName: string;
  641. const TypeKind: TTypeKind): Boolean;
  642. begin
  643. Result:=PropType(aClass,PropName)=TypeKind;
  644. end;
  645. type
  646. TGetterKind = (
  647. gkNone,
  648. gkField,
  649. gkFunction,
  650. gkFunctionWithParams
  651. );
  652. function GetPropGetterKind(const PropInfo: TTypeMemberProperty): TGetterKind;
  653. begin
  654. if PropInfo.Getter='' then
  655. Result:=gkNone
  656. else if (pfGetFunction and PropInfo.Flags)>0 then
  657. begin
  658. if length(PropInfo.Params)>0 then
  659. Result:=gkFunctionWithParams
  660. else
  661. Result:=gkFunction;
  662. end
  663. else
  664. Result:=gkField;
  665. end;
  666. type
  667. TSetterKind = (
  668. skNone,
  669. skField,
  670. skProcedure,
  671. skProcedureWithParams
  672. );
  673. function GetPropSetterKind(const PropInfo: TTypeMemberProperty): TSetterKind;
  674. begin
  675. if PropInfo.Setter='' then
  676. Result:=skNone
  677. else if (pfSetProcedure and PropInfo.Flags)>0 then
  678. begin
  679. if length(PropInfo.Params)>0 then
  680. Result:=skProcedureWithParams
  681. else
  682. Result:=skProcedure;
  683. end
  684. else
  685. Result:=skField;
  686. end;
  687. function GetJSValueProp(Instance: TObject; const PropName: String): JSValue;
  688. begin
  689. Result:=GetJSValueProp(Instance,FindPropInfo(Instance,PropName));
  690. end;
  691. function GetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  692. ): JSValue;
  693. type
  694. TGetter = function: JSValue of object;
  695. TGetterWithIndex = function(Index: JSValue): JSValue of object;
  696. var
  697. gk: TGetterKind;
  698. begin
  699. gk:=GetPropGetterKind(PropInfo);
  700. case gk of
  701. gkNone:
  702. raise EPropertyError.CreateFmt(SCantReadPropertyS, [PropInfo.Name]);
  703. gkField:
  704. Result:=TJSObject(Instance)[PropInfo.Getter];
  705. gkFunction:
  706. if (pfHasIndex and PropInfo.Flags)>0 then
  707. Result:=TGetterWithIndex(TJSObject(Instance)[PropInfo.Getter])(PropInfo.Index)
  708. else
  709. Result:=TGetter(TJSObject(Instance)[PropInfo.Getter])();
  710. gkFunctionWithParams:
  711. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  712. end;
  713. end;
  714. procedure SetJSValueProp(Instance: TObject; const PropName: String;
  715. Value: JSValue);
  716. begin
  717. SetJSValueProp(Instance,FindPropInfo(Instance,PropName),Value);
  718. end;
  719. procedure SetJSValueProp(Instance: TObject;
  720. const PropInfo: TTypeMemberProperty; Value: JSValue);
  721. type
  722. TSetter = procedure(Value: JSValue) of object;
  723. TSetterWithIndex = procedure(Index, Value: JSValue) of object;
  724. var
  725. sk: TSetterKind;
  726. begin
  727. sk:=GetPropSetterKind(PropInfo);
  728. case sk of
  729. skNone:
  730. raise EPropertyError.CreateFmt(SCantWritePropertyS, [PropInfo.Name]);
  731. skField:
  732. TJSObject(Instance)[PropInfo.Setter]:=Value;
  733. skProcedure:
  734. if (pfHasIndex and PropInfo.Flags)>0 then
  735. TSetterWithIndex(TJSObject(Instance)[PropInfo.Setter])(PropInfo.Index,Value)
  736. else
  737. TSetter(TJSObject(Instance)[PropInfo.Setter])(Value);
  738. skProcedureWithParams:
  739. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  740. end;
  741. end;
  742. function GetNativeIntProp(Instance: TObject; const PropName: String): NativeInt;
  743. begin
  744. Result:=GetNativeIntProp(Instance,FindPropInfo(Instance,PropName));
  745. end;
  746. function GetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  747. ): NativeInt;
  748. begin
  749. Result:=NativeInt(GetJSValueProp(Instance,PropInfo));
  750. end;
  751. procedure SetNativeIntProp(Instance: TObject; const PropName: String;
  752. Value: NativeInt);
  753. begin
  754. SetJSValueProp(Instance,FindPropInfo(Instance,PropName),Value);
  755. end;
  756. procedure SetNativeIntProp(Instance: TObject;
  757. const PropInfo: TTypeMemberProperty; Value: NativeInt);
  758. begin
  759. SetJSValueProp(Instance,PropInfo,Value);
  760. end;
  761. function GetStringProp(Instance: TObject; const PropName: String): String;
  762. begin
  763. Result:=GetStringProp(Instance,FindPropInfo(Instance,PropName));
  764. end;
  765. function GetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  766. ): String;
  767. begin
  768. Result:=String(GetJSValueProp(Instance,PropInfo));
  769. end;
  770. procedure SetStringProp(Instance: TObject; const PropName: String; Value: String
  771. );
  772. begin
  773. SetStringProp(Instance,FindPropInfo(Instance,PropName),Value);
  774. end;
  775. procedure SetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  776. Value: String);
  777. begin
  778. SetJSValueProp(Instance,PropInfo,Value);
  779. end;
  780. function GetBoolProp(Instance: TObject; const PropName: String): boolean;
  781. begin
  782. Result:=GetBoolProp(Instance,FindPropInfo(Instance,PropName));
  783. end;
  784. function GetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  785. ): boolean;
  786. begin
  787. Result:=Boolean(GetJSValueProp(Instance,PropInfo));
  788. end;
  789. procedure SetBoolProp(Instance: TObject; const PropName: String; Value: boolean
  790. );
  791. begin
  792. SetBoolProp(Instance,FindPropInfo(Instance,PropName),Value);
  793. end;
  794. procedure SetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  795. Value: boolean);
  796. begin
  797. SetJSValueProp(Instance,PropInfo,Value);
  798. end;
  799. function GetObjectProp(Instance: TObject; const PropName: String): TObject;
  800. begin
  801. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName));
  802. end;
  803. function GetObjectProp(Instance: TObject; const PropName: String; MinClass : TClass): TObject;
  804. begin
  805. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName));
  806. if (MinClass<>Nil) and (Result<>Nil) Then
  807. if not Result.InheritsFrom(MinClass) then
  808. Result:=Nil;
  809. end;
  810. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty): TObject;
  811. begin
  812. Result:=GetObjectProp(Instance,PropInfo,Nil);
  813. end;
  814. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; MinClass : TClass): TObject;
  815. Var
  816. O : TObject;
  817. begin
  818. O:=TObject(GetJSValueProp(Instance,PropInfo));
  819. if (MinClass<>Nil) and not O.InheritsFrom(MinClass) then
  820. Result:=Nil
  821. else
  822. Result:=O;
  823. end;
  824. procedure SetObjectProp(Instance: TObject; const PropName: String; Value: TObject) ;
  825. begin
  826. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  827. end;
  828. procedure SetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: TObject);
  829. begin
  830. SetJSValueProp(Instance,PropInfo,Value);
  831. end;
  832. Function GetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty) : Double;
  833. begin
  834. Result:=Double(GetJSValueProp(Instance,PropInfo));
  835. end;
  836. Function GetFloatProp(Instance: TObject; const PropName: string): Double;
  837. begin
  838. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName));
  839. end;
  840. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Double);
  841. begin
  842. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  843. end;
  844. Procedure SetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty; Value : Double);
  845. begin
  846. SetJSValueProp(Instance,PropInfo,Value);
  847. end;
  848. end.