typinfo.pas 48 KB

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