typinfo.pas 49 KB

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