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