typinfo.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  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
  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,
  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. EPropertyError = class(Exception);
  272. function GetClassMembers(aTIClass: TTypeInfoClass): TTypeMemberDynArray;
  273. function GetClassMember(aTIClass: TTypeInfoClass; const aName: String): TTypeMember;
  274. function GetInstanceMethod(Instance: TObject; const aName: String): Pointer;
  275. function GetClassMethods(aTIClass: TTypeInfoClass): TTypeMemberMethodDynArray;
  276. function CreateMethod(Instance: TObject; FuncName: String): Pointer; external name 'rtl.createCallback';
  277. function GetPropInfos(aTIClass: TTypeInfoClass): TTypeMemberPropertyDynArray;
  278. function GetPropInfo(TI: TTypeInfoClass; const PropName: String): TTypeMemberProperty;
  279. function GetPropInfo(TI: TTypeInfoClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  280. function GetPropInfo(Instance: TObject; const PropName: String): TTypeMemberProperty;
  281. function GetPropInfo(Instance: TObject; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  282. function GetPropInfo(aClass: TClass; const PropName: String): TTypeMemberProperty;
  283. function GetPropInfo(aClass: TClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  284. function FindPropInfo(Instance: TObject; const PropName: String): TTypeMemberProperty;
  285. function FindPropInfo(Instance: TObject; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  286. function FindPropInfo(aClass: TClass; const PropName: String): TTypeMemberProperty;
  287. function FindPropInfo(aClass: TClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  288. // Property information routines.
  289. Function IsStoredProp(Instance: TObject; const PropInfo: TTypeMemberProperty): Boolean;
  290. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  291. function IsPublishedProp(Instance: TObject; const PropName: String): Boolean;
  292. function IsPublishedProp(aClass: TClass; const PropName: String): Boolean;
  293. function PropType(Instance: TObject; const PropName: string): TTypeKind;
  294. function PropType(aClass: TClass; const PropName: string): TTypeKind;
  295. function PropIsType(Instance: TObject; const PropName: string; const TypeKind: TTypeKind): Boolean;
  296. function PropIsType(aClass: TClass; const PropName: string; const TypeKind: TTypeKind): Boolean;
  297. function GetJSValueProp(Instance: TObject; const PropName: String): JSValue;
  298. function GetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty): JSValue;
  299. procedure SetJSValueProp(Instance: TObject; const PropName: String; Value: JSValue);
  300. procedure SetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: JSValue);
  301. function GetNativeIntProp(Instance: TObject; const PropName: String): NativeInt;
  302. function GetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty): NativeInt;
  303. procedure SetNativeIntProp(Instance: TObject; const PropName: String; Value: NativeInt);
  304. procedure SetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: NativeInt);
  305. function GetStringProp(Instance: TObject; const PropName: String): String;
  306. function GetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String;
  307. procedure SetStringProp(Instance: TObject; const PropName: String; Value: String);
  308. procedure SetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: String);
  309. function GetBoolProp(Instance: TObject; const PropName: String): boolean;
  310. function GetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty): boolean;
  311. procedure SetBoolProp(Instance: TObject; const PropName: String; Value: boolean);
  312. procedure SetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: boolean);
  313. function GetObjectProp(Instance: TObject; const PropName: String): TObject;
  314. function GetObjectProp(Instance: TObject; const PropName: String; MinClass : TClass): TObject;
  315. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty): TObject;
  316. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; MinClass : TClass): TObject;
  317. procedure SetObjectProp(Instance: TObject; const PropName: String; Value: TObject) ;
  318. procedure SetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: TObject);
  319. Function GetFloatProp(Instance: TObject; const PropName: string): Double;
  320. Function GetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty) : Double;
  321. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Double);
  322. Procedure SetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty; Value : Double);
  323. implementation
  324. function GetClassMembers(aTIClass: TTypeInfoClass): TTypeMemberDynArray;
  325. var
  326. C: TTypeInfoClass;
  327. i, Cnt, j: Integer;
  328. begin
  329. Cnt:=0;
  330. C:=aTIClass;
  331. while C<>nil do
  332. begin
  333. inc(Cnt,length(C.Names));
  334. C:=C.Ancestor;
  335. end;
  336. SetLength(Result,Cnt);
  337. C:=aTIClass;
  338. i:=0;
  339. while C<>nil do
  340. begin
  341. for j:=0 to length(C.Names)-1 do
  342. begin
  343. Result[i]:=C.Members[C.Names[j]];
  344. inc(i);
  345. end;
  346. C:=C.Ancestor;
  347. end;
  348. end;
  349. function GetClassMember(aTIClass: TTypeInfoClass; const aName: String): TTypeMember;
  350. var
  351. C: TTypeInfoClass;
  352. i: Integer;
  353. begin
  354. // quick search: case sensitive
  355. C:=aTIClass;
  356. while C<>nil do
  357. begin
  358. if TJSObject(C.Members).hasOwnProperty(aName) then
  359. exit(C.Members[aName]);
  360. C:=C.Ancestor;
  361. end;
  362. // slow search: case insensitive
  363. C:=aTIClass;
  364. while C<>nil do
  365. begin
  366. for i:=0 to length(C.Names)-1 do
  367. if CompareText(C.Names[i],aName)=0 then
  368. exit(C.Members[C.Names[i]]);
  369. C:=C.Ancestor;
  370. end;
  371. Result:=nil;
  372. end;
  373. function GetInstanceMethod(Instance: TObject; const aName: String): Pointer;
  374. var
  375. TI: TTypeMember;
  376. begin
  377. if Instance=nil then exit(nil);
  378. TI:=GetClassMember(TypeInfo(Instance),aName);
  379. if not (TI is TTypeMemberMethod) then exit(nil);
  380. Result:=CreateMethod(Instance,TI.Name); // Note: use TI.Name for the correct case!
  381. end;
  382. function GetClassMethods(aTIClass: TTypeInfoClass): TTypeMemberMethodDynArray;
  383. var
  384. C: TTypeInfoClass;
  385. i, Cnt, j: Integer;
  386. begin
  387. Cnt:=0;
  388. C:=aTIClass;
  389. while C<>nil do
  390. begin
  391. inc(Cnt,C.MethodCount);
  392. C:=C.Ancestor;
  393. end;
  394. SetLength(Result,Cnt);
  395. C:=aTIClass;
  396. i:=0;
  397. while C<>nil do
  398. begin
  399. for j:=0 to C.MethodCount-1 do
  400. begin
  401. Result[i]:=TTypeMemberMethod(C.Members[C.Methods[j]]);
  402. inc(i);
  403. end;
  404. C:=C.Ancestor;
  405. end;
  406. end;
  407. function GetPropInfos(aTIClass: TTypeInfoClass): TTypeMemberPropertyDynArray;
  408. var
  409. C: TTypeInfoClass;
  410. i, Cnt, j: Integer;
  411. begin
  412. Cnt:=0;
  413. C:=aTIClass;
  414. while C<>nil do
  415. begin
  416. inc(Cnt,C.PropCount);
  417. C:=C.Ancestor;
  418. end;
  419. SetLength(Result,Cnt);
  420. C:=aTIClass;
  421. i:=0;
  422. while C<>nil do
  423. begin
  424. for j:=0 to C.PropCount-1 do
  425. begin
  426. Result[i]:=TTypeMemberProperty(C.Members[C.Properties[j]]);
  427. inc(i);
  428. end;
  429. C:=C.Ancestor;
  430. end;
  431. end;
  432. function GetPropInfo(TI: TTypeInfoClass; const PropName: String
  433. ): TTypeMemberProperty;
  434. var
  435. m: TTypeMember;
  436. i: Integer;
  437. C: TTypeInfoClass;
  438. begin
  439. // quick search case sensitive
  440. C:=TI;
  441. while C<>nil do
  442. begin
  443. m:=C.Members[PropName];
  444. if m is TTypeMemberProperty then
  445. exit(TTypeMemberProperty(m));
  446. C:=C.Ancestor;
  447. end;
  448. // slow search case insensitive
  449. Result:=nil;
  450. repeat
  451. for i:=0 to TI.PropCount-1 do
  452. if CompareText(PropName,TI.Properties[i])=0 then
  453. begin
  454. m:=TI.Members[TI.Properties[i]];
  455. if m is TTypeMemberProperty then
  456. Result:=TTypeMemberProperty(m);
  457. exit;
  458. end;
  459. TI:=TI.Ancestor;
  460. until TI=nil;
  461. end;
  462. function GetPropInfo(TI: TTypeInfoClass; const PropName: String;
  463. const Kinds: TTypeKinds): TTypeMemberProperty;
  464. begin
  465. Result:=GetPropInfo(TI,PropName);
  466. if (Kinds<>[]) and (Result<>nil) and not (Result.TypeInfo.Kind in Kinds) then
  467. Result:=nil;
  468. end;
  469. function GetPropInfo(Instance: TObject; const PropName: String
  470. ): TTypeMemberProperty;
  471. begin
  472. Result:=GetPropInfo(TypeInfo(Instance),PropName,[]);
  473. end;
  474. function GetPropInfo(Instance: TObject; const PropName: String;
  475. const Kinds: TTypeKinds): TTypeMemberProperty;
  476. begin
  477. Result:=GetPropInfo(TypeInfo(Instance),PropName,Kinds);
  478. end;
  479. function GetPropInfo(aClass: TClass; const PropName: String
  480. ): TTypeMemberProperty;
  481. begin
  482. Result:=GetPropInfo(TypeInfo(AClass),PropName,[]);
  483. end;
  484. function GetPropInfo(aClass: TClass; const PropName: String;
  485. const Kinds: TTypeKinds): TTypeMemberProperty;
  486. begin
  487. Result:=GetPropInfo(TypeInfo(AClass),PropName,Kinds);
  488. end;
  489. function FindPropInfo(Instance: TObject; const PropName: String
  490. ): TTypeMemberProperty;
  491. begin
  492. Result:=GetPropInfo(TypeInfo(Instance), PropName);
  493. if Result=nil then
  494. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  495. end;
  496. function FindPropInfo(Instance: TObject; const PropName: String;
  497. const Kinds: TTypeKinds): TTypeMemberProperty;
  498. begin
  499. Result:=GetPropInfo(TypeInfo(Instance), PropName, Kinds);
  500. if Result=nil then
  501. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  502. end;
  503. function FindPropInfo(aClass: TClass; const PropName: String
  504. ): TTypeMemberProperty;
  505. begin
  506. Result:=GetPropInfo(TypeInfo(aClass), PropName);
  507. if Result=nil then
  508. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  509. end;
  510. function FindPropInfo(aClass: TClass; const PropName: String;
  511. const Kinds: TTypeKinds): TTypeMemberProperty;
  512. begin
  513. Result:=GetPropInfo(TypeInfo(aClass), PropName, Kinds);
  514. if Result=nil then
  515. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  516. end;
  517. function IsStoredProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  518. ): Boolean;
  519. type
  520. TIsStored = function: Boolean of object;
  521. begin
  522. case PropInfo.Flags and 12 of
  523. 0: Result:=true;
  524. 4: Result:=false;
  525. 8: Result:=Boolean(TJSObject(Instance)[PropInfo.Stored]);
  526. else Result:=TIsStored(TJSObject(Instance)[PropInfo.Stored])();
  527. end;
  528. end;
  529. function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  530. begin
  531. Result:=IsStoredProp(Instance,FindPropInfo(Instance,PropName));
  532. end;
  533. function IsPublishedProp(Instance: TObject; const PropName: String): Boolean;
  534. begin
  535. Result:=GetPropInfo(Instance,PropName)<>nil;
  536. end;
  537. function IsPublishedProp(aClass: TClass; const PropName: String): Boolean;
  538. begin
  539. Result:=GetPropInfo(aClass,PropName)<>nil;
  540. end;
  541. function PropType(Instance: TObject; const PropName: string): TTypeKind;
  542. begin
  543. Result:=FindPropInfo(Instance,PropName).TypeInfo.Kind;
  544. end;
  545. function PropType(aClass: TClass; const PropName: string): TTypeKind;
  546. begin
  547. Result:=FindPropInfo(aClass,PropName).TypeInfo.Kind;
  548. end;
  549. function PropIsType(Instance: TObject; const PropName: string;
  550. const TypeKind: TTypeKind): Boolean;
  551. begin
  552. Result:=PropType(Instance,PropName)=TypeKind;
  553. end;
  554. function PropIsType(aClass: TClass; const PropName: string;
  555. const TypeKind: TTypeKind): Boolean;
  556. begin
  557. Result:=PropType(aClass,PropName)=TypeKind;
  558. end;
  559. type
  560. TGetterKind = (
  561. gkNone,
  562. gkField,
  563. gkFunction,
  564. gkFunctionWithParams
  565. );
  566. function GetPropGetterKind(const PropInfo: TTypeMemberProperty): TGetterKind;
  567. begin
  568. if PropInfo.Getter='' then
  569. Result:=gkNone
  570. else if (pfGetFunction and PropInfo.Flags)>0 then
  571. begin
  572. if length(PropInfo.Params)>0 then
  573. Result:=gkFunctionWithParams
  574. else
  575. Result:=gkFunction;
  576. end
  577. else
  578. Result:=gkField;
  579. end;
  580. type
  581. TSetterKind = (
  582. skNone,
  583. skField,
  584. skProcedure,
  585. skProcedureWithParams
  586. );
  587. function GetPropSetterKind(const PropInfo: TTypeMemberProperty): TSetterKind;
  588. begin
  589. if PropInfo.Setter='' then
  590. Result:=skNone
  591. else if (pfSetProcedure and PropInfo.Flags)>0 then
  592. begin
  593. if length(PropInfo.Params)>0 then
  594. Result:=skProcedureWithParams
  595. else
  596. Result:=skProcedure;
  597. end
  598. else
  599. Result:=skField;
  600. end;
  601. function GetJSValueProp(Instance: TObject; const PropName: String): JSValue;
  602. begin
  603. Result:=GetJSValueProp(Instance,FindPropInfo(Instance,PropName));
  604. end;
  605. function GetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  606. ): JSValue;
  607. type
  608. TGetter = function: JSValue of object;
  609. TGetterWithIndex = function(Index: JSValue): JSValue of object;
  610. var
  611. gk: TGetterKind;
  612. begin
  613. gk:=GetPropGetterKind(PropInfo);
  614. case gk of
  615. gkNone:
  616. raise EPropertyError.CreateFmt(SCantReadPropertyS, [PropInfo.Name]);
  617. gkField:
  618. Result:=TJSObject(Instance)[PropInfo.Getter];
  619. gkFunction:
  620. if (pfHasIndex and PropInfo.Flags)>0 then
  621. Result:=TGetterWithIndex(TJSObject(Instance)[PropInfo.Getter])(PropInfo.Index)
  622. else
  623. Result:=TGetter(TJSObject(Instance)[PropInfo.Getter])();
  624. gkFunctionWithParams:
  625. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  626. end;
  627. end;
  628. procedure SetJSValueProp(Instance: TObject; const PropName: String;
  629. Value: JSValue);
  630. begin
  631. SetJSValueProp(Instance,FindPropInfo(Instance,PropName),Value);
  632. end;
  633. procedure SetJSValueProp(Instance: TObject;
  634. const PropInfo: TTypeMemberProperty; Value: JSValue);
  635. type
  636. TSetter = procedure(Value: JSValue) of object;
  637. TSetterWithIndex = procedure(Index, Value: JSValue) of object;
  638. var
  639. sk: TSetterKind;
  640. begin
  641. sk:=GetPropSetterKind(PropInfo);
  642. case sk of
  643. skNone:
  644. raise EPropertyError.CreateFmt(SCantWritePropertyS, [PropInfo.Name]);
  645. skField:
  646. TJSObject(Instance)[PropInfo.Setter]:=Value;
  647. skProcedure:
  648. if (pfHasIndex and PropInfo.Flags)>0 then
  649. TSetterWithIndex(TJSObject(Instance)[PropInfo.Setter])(PropInfo.Index,Value)
  650. else
  651. TSetter(TJSObject(Instance)[PropInfo.Setter])(Value);
  652. skProcedureWithParams:
  653. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  654. end;
  655. end;
  656. function GetNativeIntProp(Instance: TObject; const PropName: String): NativeInt;
  657. begin
  658. Result:=GetNativeIntProp(Instance,FindPropInfo(Instance,PropName));
  659. end;
  660. function GetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  661. ): NativeInt;
  662. begin
  663. Result:=NativeInt(GetJSValueProp(Instance,PropInfo));
  664. end;
  665. procedure SetNativeIntProp(Instance: TObject; const PropName: String;
  666. Value: NativeInt);
  667. begin
  668. SetJSValueProp(Instance,FindPropInfo(Instance,PropName),Value);
  669. end;
  670. procedure SetNativeIntProp(Instance: TObject;
  671. const PropInfo: TTypeMemberProperty; Value: NativeInt);
  672. begin
  673. SetJSValueProp(Instance,PropInfo,Value);
  674. end;
  675. function GetStringProp(Instance: TObject; const PropName: String): String;
  676. begin
  677. Result:=GetStringProp(Instance,FindPropInfo(Instance,PropName));
  678. end;
  679. function GetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  680. ): String;
  681. begin
  682. Result:=String(GetJSValueProp(Instance,PropInfo));
  683. end;
  684. procedure SetStringProp(Instance: TObject; const PropName: String; Value: String
  685. );
  686. begin
  687. SetStringProp(Instance,FindPropInfo(Instance,PropName),Value);
  688. end;
  689. procedure SetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  690. Value: String);
  691. begin
  692. SetJSValueProp(Instance,PropInfo,Value);
  693. end;
  694. function GetBoolProp(Instance: TObject; const PropName: String): boolean;
  695. begin
  696. Result:=GetBoolProp(Instance,FindPropInfo(Instance,PropName));
  697. end;
  698. function GetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  699. ): boolean;
  700. begin
  701. Result:=Boolean(GetJSValueProp(Instance,PropInfo));
  702. end;
  703. procedure SetBoolProp(Instance: TObject; const PropName: String; Value: boolean
  704. );
  705. begin
  706. SetBoolProp(Instance,FindPropInfo(Instance,PropName),Value);
  707. end;
  708. procedure SetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  709. Value: boolean);
  710. begin
  711. SetJSValueProp(Instance,PropInfo,Value);
  712. end;
  713. function GetObjectProp(Instance: TObject; const PropName: String): TObject;
  714. begin
  715. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName));
  716. end;
  717. function GetObjectProp(Instance: TObject; const PropName: String; MinClass : TClass): TObject;
  718. begin
  719. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName));
  720. if (MinClass<>Nil) and (Result<>Nil) Then
  721. if not Result.InheritsFrom(MinClass) then
  722. Result:=Nil;
  723. end;
  724. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty): TObject;
  725. begin
  726. Result:=GetObjectProp(Instance,PropInfo,Nil);
  727. end;
  728. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; MinClass : TClass): TObject;
  729. Var
  730. O : TObject;
  731. begin
  732. O:=TObject(GetJSValueProp(Instance,PropInfo));
  733. if (MinClass<>Nil) and not O.InheritsFrom(MinClass) then
  734. Result:=Nil
  735. else
  736. Result:=O;
  737. end;
  738. procedure SetObjectProp(Instance: TObject; const PropName: String; Value: TObject) ;
  739. begin
  740. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  741. end;
  742. procedure SetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: TObject);
  743. begin
  744. SetJSValueProp(Instance,PropInfo,Value);
  745. end;
  746. Function GetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty) : Double;
  747. begin
  748. Result:=Double(GetJSValueProp(Instance,PropInfo));
  749. end;
  750. Function GetFloatProp(Instance: TObject; const PropName: string): Double;
  751. begin
  752. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName));
  753. end;
  754. Procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Double);
  755. begin
  756. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  757. end;
  758. Procedure SetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty; Value : Double);
  759. begin
  760. SetJSValueProp(Instance,PropInfo,Value);
  761. end;
  762. end.