typinfo.pas 48 KB

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