typinfo.pas 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559
  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 undefined
  36. Module: TTypeInfoModule external name '$module'; // can be undefined
  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 null
  118. ResultType: TTypeInfo external name 'resulttype'; // can be null
  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 undefined
  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 null or undefined
  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'(TTypeInfoClass)
  241. public
  242. JSClassName: String external name 'jsclass';
  243. end;
  244. { TTypeInfoClassRef - class-of, Kind = tkClassRef }
  245. TTypeInfoClassRef = class external name 'rtl.tTypeInfoClassRef'(TTypeInfo)
  246. public
  247. InstanceType: TTypeInfo external name 'instancetype';
  248. end;
  249. { TTypeInfoPointer - Kind = tkPointer }
  250. TTypeInfoPointer = class external name 'rtl.tTypeInfoPointer'(TTypeInfo)
  251. public
  252. RefType: TTypeInfo external name 'reftype'; // can be null
  253. end;
  254. { TTypeInfoInterface - Kind = tkInterface }
  255. TTypeInfoInterface = class external name 'rtl.tTypeInfoInterface'(TTypeInfoStruct)
  256. public
  257. InterfaceType: TJSObject external name 'interface';
  258. Ancestor: TTypeInfoInterface external name 'ancestor';
  259. end;
  260. { TTypeInfoHelper - Kind = tkHelper }
  261. TTypeInfoHelper = class external name 'rtl.tTypeInfoHelper'(TTypeInfoStruct)
  262. public
  263. HelperType: TJSObject external name 'helper';
  264. Ancestor: TTypeInfoHelper external name 'ancestor';
  265. HelperFor: TTypeInfo external name 'helperfor';
  266. end;
  267. EPropertyError = class(Exception);
  268. function GetTypeName(TypeInfo: TTypeInfo): string;
  269. function GetClassMembers(aTIStruct: TTypeInfoStruct): TTypeMemberDynArray;
  270. function GetClassMember(aTIStruct: TTypeInfoStruct; const aName: String): TTypeMember;
  271. function GetInstanceMethod(Instance: TObject; const aName: String): Pointer;
  272. function GetClassMethods(aTIStruct: TTypeInfoStruct): TTypeMemberMethodDynArray;
  273. function CreateMethod(Instance: TObject; FuncName: String): Pointer; external name 'rtl.createCallback';
  274. function GetInterfaceMembers(aTIInterface: TTypeInfoInterface): TTypeMemberDynArray;
  275. function GetInterfaceMember(aTIInterface: TTypeInfoInterface; const aName: String): TTypeMember;
  276. function GetInterfaceMethods(aTIInterface: TTypeInfoInterface): TTypeMemberMethodDynArray;
  277. function GetRTTIAttributes(const Attributes: TTypeInfoAttributes): TCustomAttributeArray;
  278. function GetPropInfos(aTIStruct: TTypeInfoStruct): TTypeMemberPropertyDynArray;
  279. function GetPropList(aTIStruct: TTypeInfoStruct; TypeKinds: TTypeKinds; Sorted: boolean = true): TTypeMemberPropertyDynArray;
  280. function GetPropList(aTIStruct: TTypeInfoStruct): TTypeMemberPropertyDynArray;
  281. function GetPropList(AClass: TClass): TTypeMemberPropertyDynArray;
  282. function GetPropList(Instance: TObject): TTypeMemberPropertyDynArray;
  283. function GetPropInfo(TI: TTypeInfoStruct; const PropName: String): TTypeMemberProperty;
  284. function GetPropInfo(TI: TTypeInfoStruct; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  285. function GetPropInfo(Instance: TObject; const PropName: String): TTypeMemberProperty;
  286. function GetPropInfo(Instance: TObject; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  287. function GetPropInfo(aClass: TClass; const PropName: String): TTypeMemberProperty;
  288. function GetPropInfo(aClass: TClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  289. function FindPropInfo(Instance: TObject; const PropName: String): TTypeMemberProperty;
  290. function FindPropInfo(Instance: TObject; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  291. function FindPropInfo(aClass: TClass; const PropName: String): TTypeMemberProperty;
  292. function FindPropInfo(aClass: TClass; const PropName: String; const Kinds: TTypeKinds): TTypeMemberProperty;
  293. // Property information routines.
  294. Function IsStoredProp(Instance: TObject; const PropInfo: TTypeMemberProperty): Boolean;
  295. Function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  296. function IsPublishedProp(Instance: TObject; const PropName: String): Boolean;
  297. function IsPublishedProp(aClass: TClass; const PropName: String): Boolean;
  298. function PropType(Instance: TObject; const PropName: string): TTypeKind;
  299. function PropType(aClass: TClass; const PropName: string): TTypeKind;
  300. function PropIsType(Instance: TObject; const PropName: string; const TypeKind: TTypeKind): Boolean;
  301. function PropIsType(aClass: TClass; const PropName: string; const TypeKind: TTypeKind): Boolean;
  302. function GetJSValueProp(Instance: TJSObject; TI: TTypeInfoStruct; const PropName: String): JSValue;
  303. function GetJSValueProp(Instance: TJSObject; const PropInfo: TTypeMemberProperty): JSValue;
  304. function GetJSValueProp(Instance: TObject; const PropName: String): JSValue;
  305. function GetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty): JSValue;
  306. procedure SetJSValueProp(Instance: TJSObject; TI: TTypeInfoStruct; const PropName: String; Value: JSValue);
  307. procedure SetJSValueProp(Instance: TJSObject; const PropInfo: TTypeMemberProperty; Value: JSValue);
  308. procedure SetJSValueProp(Instance: TObject; const PropName: String; Value: JSValue);
  309. procedure SetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: JSValue);
  310. function GetNativeIntProp(Instance: TObject; const PropName: String): NativeInt;
  311. function GetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty): NativeInt;
  312. procedure SetNativeIntProp(Instance: TObject; const PropName: String; Value: NativeInt);
  313. procedure SetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: NativeInt);
  314. function GetOrdProp(Instance: TObject; const PropName: String): longint;
  315. function GetOrdProp(Instance: TObject; const PropInfo: TTypeMemberProperty): longint;
  316. procedure SetOrdProp(Instance: TObject; const PropName: String; Value: longint);
  317. procedure SetOrdProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: longint);
  318. function GetEnumProp(Instance: TObject; const PropName: String): String;
  319. function GetEnumProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String;
  320. procedure SetEnumProp(Instance: TObject; const PropName: String; const Value: String);
  321. procedure SetEnumProp(Instance: TObject; const PropInfo: TTypeMemberProperty; const Value: String);
  322. // Auxiliary routines, which may be useful
  323. function GetEnumName(TypeInfo: TTypeInfoEnum; Value: Integer): String;
  324. function GetEnumValue(TypeInfo: TTypeInfoEnum; const Name: string): Longint;
  325. function GetEnumNameCount(TypeInfo: TTypeInfoEnum): Longint;
  326. function GetSetProp(Instance: TObject; const PropName: String): String; overload;
  327. function GetSetProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String; overload;
  328. function GetSetPropArray(Instance: TObject; const PropName: String): TIntegerDynArray; overload;
  329. function GetSetPropArray(Instance: TObject; const PropInfo: TTypeMemberProperty): TIntegerDynArray; overload;
  330. procedure SetSetPropArray(Instance: TObject; const PropName: String; const Arr: TIntegerDynArray); overload;
  331. procedure SetSetPropArray(Instance: TObject; const PropInfo: TTypeMemberProperty; const Arr: TIntegerDynArray); overload;
  332. function GetBoolProp(Instance: TObject; const PropName: String): boolean;
  333. function GetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty): boolean;
  334. procedure SetBoolProp(Instance: TObject; const PropName: String; Value: boolean);
  335. procedure SetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: boolean);
  336. function GetStrProp(Instance: TObject; const PropName: String): String;
  337. function GetStrProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String;
  338. procedure SetStrProp(Instance: TObject; const PropName: String; Value: String);
  339. procedure SetStrProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: String);
  340. function GetStringProp(Instance: TObject; const PropName: String): String; deprecated; // use GetStrProp
  341. function GetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String; deprecated; // use GetStrProp
  342. procedure SetStringProp(Instance: TObject; const PropName: String; Value: String); deprecated; // use GetStrProp
  343. procedure SetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: String); deprecated; // use GetStrProp
  344. function GetFloatProp(Instance: TObject; const PropName: string): Double;
  345. function GetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty) : Double;
  346. procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Double);
  347. procedure SetFloatProp(Instance: TObject; PropInfo : TTypeMemberProperty; Value : Double);
  348. function GetObjectProp(Instance: TObject; const PropName: String): TObject;
  349. function GetObjectProp(Instance: TObject; const PropName: String; MinClass: TClass): TObject;
  350. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty): TObject;
  351. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; MinClass: TClass): TObject;
  352. procedure SetObjectProp(Instance: TObject; const PropName: String; Value: TObject) ;
  353. procedure SetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: TObject);
  354. function GetMethodProp(Instance: TObject; PropInfo: TTypeMemberProperty): TMethod;
  355. function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  356. procedure SetMethodProp(Instance: TObject; PropInfo: TTypeMemberProperty; const Value : TMethod);
  357. procedure SetMethodProp(Instance: TObject; const PropName: string; const Value: TMethod);
  358. function GetInterfaceProp(Instance: TObject; const PropName: string): IInterface;
  359. function GetInterfaceProp(Instance: TObject; PropInfo: TTypeMemberProperty): IInterface;
  360. procedure SetInterfaceProp(Instance: TObject; const PropName: string; const Value: IInterface);
  361. procedure SetInterfaceProp(Instance: TObject; PropInfo: TTypeMemberProperty; const Value: IInterface);
  362. function GetRawInterfaceProp(Instance: TObject; const PropName: string): Pointer;
  363. function GetRawInterfaceProp(Instance: TObject; PropInfo: TTypeMemberProperty): Pointer;
  364. procedure SetRawInterfaceProp(Instance: TObject; const PropName: string; const Value: Pointer);
  365. procedure SetRawInterfaceProp(Instance: TObject; PropInfo: TTypeMemberProperty; const Value: Pointer);
  366. implementation
  367. function GetTypeName(TypeInfo: TTypeInfo): string;
  368. begin
  369. Result := TypeInfo.Name;
  370. end;
  371. function GetClassMembers(aTIStruct: TTypeInfoStruct): TTypeMemberDynArray;
  372. var
  373. C: TTypeInfoStruct;
  374. i: Integer;
  375. PropName: String;
  376. Names: TJSObject;
  377. begin
  378. Result:=nil;
  379. Names:=TJSObject.new;
  380. C:=aTIStruct;
  381. while C<>nil do
  382. begin
  383. for i:=0 to length(C.Names)-1 do
  384. begin
  385. PropName:=C.Names[i];
  386. if Names.hasOwnProperty(PropName) then continue;
  387. TJSArray(Result).push(C.Members[PropName]);
  388. Names[PropName]:=true;
  389. end;
  390. if not (C is TTypeInfoClass) then break;
  391. C:=TTypeInfoClass(C).Ancestor;
  392. end;
  393. end;
  394. function GetClassMember(aTIStruct: TTypeInfoStruct; const aName: String): TTypeMember;
  395. var
  396. C: TTypeInfoStruct;
  397. i: Integer;
  398. begin
  399. // quick search: case sensitive
  400. C:=aTIStruct;
  401. while C<>nil do
  402. begin
  403. if TJSObject(C.Members).hasOwnProperty(aName) then
  404. exit(C.Members[aName]);
  405. if not (C is TTypeInfoClass) then break;
  406. C:=TTypeInfoClass(C).Ancestor;
  407. end;
  408. // slow search: case insensitive
  409. C:=aTIStruct;
  410. while C<>nil do
  411. begin
  412. for i:=0 to length(C.Names)-1 do
  413. if CompareText(C.Names[i],aName)=0 then
  414. exit(C.Members[C.Names[i]]);
  415. if not (C is TTypeInfoClass) then break;
  416. C:=TTypeInfoClass(C).Ancestor;
  417. end;
  418. Result:=nil;
  419. end;
  420. function GetInstanceMethod(Instance: TObject; const aName: String): Pointer;
  421. var
  422. TI: TTypeMember;
  423. begin
  424. if Instance=nil then exit(nil);
  425. TI:=GetClassMember(TypeInfo(Instance),aName);
  426. if not (TI is TTypeMemberMethod) then exit(nil);
  427. Result:=CreateMethod(Instance,TI.Name); // Note: use TI.Name for the correct case!
  428. end;
  429. function GetClassMethods(aTIStruct: TTypeInfoStruct): TTypeMemberMethodDynArray;
  430. var
  431. C: TTypeInfoStruct;
  432. i, Cnt, j: Integer;
  433. begin
  434. Cnt:=0;
  435. C:=aTIStruct;
  436. while C<>nil do
  437. begin
  438. inc(Cnt,C.MethodCount);
  439. if not (C is TTypeInfoClass) then break;
  440. C:=TTypeInfoClass(C).Ancestor;
  441. end;
  442. SetLength(Result,Cnt);
  443. C:=aTIStruct;
  444. i:=0;
  445. while C<>nil do
  446. begin
  447. for j:=0 to C.MethodCount-1 do
  448. begin
  449. Result[i]:=TTypeMemberMethod(C.Members[C.Methods[j]]);
  450. inc(i);
  451. end;
  452. if not (C is TTypeInfoClass) then break;
  453. C:=TTypeInfoClass(C).Ancestor;
  454. end;
  455. end;
  456. function GetInterfaceMembers(aTIInterface: TTypeInfoInterface
  457. ): TTypeMemberDynArray;
  458. var
  459. Intf: TTypeInfoInterface;
  460. i, Cnt, j: Integer;
  461. begin
  462. Cnt:=0;
  463. Intf:=aTIInterface;
  464. while Intf<>nil do
  465. begin
  466. inc(Cnt,length(Intf.Names));
  467. Intf:=Intf.Ancestor;
  468. end;
  469. SetLength(Result,Cnt);
  470. Intf:=aTIInterface;
  471. i:=0;
  472. while Intf<>nil do
  473. begin
  474. for j:=0 to length(Intf.Names)-1 do
  475. begin
  476. Result[i]:=Intf.Members[Intf.Names[j]];
  477. inc(i);
  478. end;
  479. Intf:=Intf.Ancestor;
  480. end;
  481. end;
  482. function GetInterfaceMember(aTIInterface: TTypeInfoInterface;
  483. const aName: String): TTypeMember;
  484. var
  485. Intf: TTypeInfoInterface;
  486. i: Integer;
  487. begin
  488. // quick search: case sensitive
  489. Intf:=aTIInterface;
  490. while Intf<>nil do
  491. begin
  492. if TJSObject(Intf.Members).hasOwnProperty(aName) then
  493. exit(Intf.Members[aName]);
  494. Intf:=Intf.Ancestor;
  495. end;
  496. // slow search: case insensitive
  497. Intf:=aTIInterface;
  498. while Intf<>nil do
  499. begin
  500. for i:=0 to length(Intf.Names)-1 do
  501. if CompareText(Intf.Names[i],aName)=0 then
  502. exit(Intf.Members[Intf.Names[i]]);
  503. Intf:=Intf.Ancestor;
  504. end;
  505. Result:=nil;
  506. end;
  507. function GetInterfaceMethods(aTIInterface: TTypeInfoInterface
  508. ): TTypeMemberMethodDynArray;
  509. var
  510. Intf: TTypeInfoInterface;
  511. i, Cnt, j: Integer;
  512. begin
  513. Cnt:=0;
  514. Intf:=aTIInterface;
  515. while Intf<>nil do
  516. begin
  517. inc(Cnt,Intf.MethodCount);
  518. Intf:=Intf.Ancestor;
  519. end;
  520. SetLength(Result,Cnt);
  521. Intf:=aTIInterface;
  522. i:=0;
  523. while Intf<>nil do
  524. begin
  525. for j:=0 to Intf.MethodCount-1 do
  526. begin
  527. Result[i]:=TTypeMemberMethod(Intf.Members[Intf.Methods[j]]);
  528. inc(i);
  529. end;
  530. Intf:=Intf.Ancestor;
  531. end;
  532. end;
  533. type
  534. TCreatorAttribute = class external name 'attr'
  535. class function Create(const ProcName: string): TCustomAttribute; overload; external name '$create';
  536. class function Create(const ProcName: string; Params: jsvalue): TCustomAttribute; overload; external name '$create';
  537. end;
  538. TCreatorAttributeClass = class of TCreatorAttribute;
  539. function GetRTTIAttributes(const Attributes: TTypeInfoAttributes
  540. ): TCustomAttributeArray;
  541. var
  542. i, len: Integer;
  543. AttrClass: TCreatorAttributeClass;
  544. ProcName: String;
  545. Attr: TCustomAttribute;
  546. begin
  547. Result:=nil;
  548. if Attributes=Undefined then exit;
  549. i:=0;
  550. len:=length(Attributes);
  551. while i<len do
  552. begin
  553. AttrClass:=TCreatorAttributeClass(Attributes[i]);
  554. inc(i);
  555. ProcName:=String(Attributes[i]);
  556. inc(i);
  557. if (i<len) and isArray(Attributes[i]) then
  558. begin
  559. Attr:=AttrClass.Create(ProcName,Attributes[i]);
  560. inc(i);
  561. end
  562. else
  563. Attr:=AttrClass.Create(ProcName);
  564. Insert(Attr,Result,length(Result));
  565. end;
  566. end;
  567. function GetPropInfos(aTIStruct: TTypeInfoStruct): TTypeMemberPropertyDynArray;
  568. var
  569. C: TTypeInfoStruct;
  570. i: Integer;
  571. Names: TJSObject;
  572. PropName: String;
  573. begin
  574. Result:=nil;
  575. C:=aTIStruct;
  576. Names:=TJSObject.new;
  577. while C<>nil do
  578. begin
  579. for i:=0 to C.PropCount-1 do
  580. begin
  581. PropName:=C.Properties[i];
  582. if Names.hasOwnProperty(PropName) then continue;
  583. TJSArray(Result).push(TTypeMemberProperty(C.Members[PropName]));
  584. Names[PropName]:=true;
  585. end;
  586. if not (C is TTypeInfoClass) then
  587. break;
  588. C:=TTypeInfoClass(C).Ancestor;
  589. end;
  590. end;
  591. function GetPropList(aTIStruct: TTypeInfoStruct; TypeKinds: TTypeKinds;
  592. Sorted: boolean): TTypeMemberPropertyDynArray;
  593. function NameSort(a,b: JSValue): NativeInt;
  594. begin
  595. if TTypeMemberProperty(a).Name<TTypeMemberProperty(b).Name then
  596. Result:=-1
  597. else if TTypeMemberProperty(a).Name>TTypeMemberProperty(b).Name then
  598. Result:=1
  599. else
  600. Result:=0;
  601. end;
  602. var
  603. C: TTypeInfoStruct;
  604. i: Integer;
  605. Names: TJSObject;
  606. PropName: String;
  607. Prop: TTypeMemberProperty;
  608. begin
  609. Result:=nil;
  610. C:=aTIStruct;
  611. Names:=TJSObject.new;
  612. while C<>nil do
  613. begin
  614. for i:=0 to C.PropCount-1 do
  615. begin
  616. PropName:=C.Properties[i];
  617. if Names.hasOwnProperty(PropName) then continue;
  618. Prop:=TTypeMemberProperty(C.Members[PropName]);
  619. if not (Prop.TypeInfo.Kind in TypeKinds) then continue;
  620. TJSArray(Result).push(Prop);
  621. Names[PropName]:=true;
  622. end;
  623. if not (C is TTypeInfoClass) then
  624. break;
  625. C:=TTypeInfoClass(C).Ancestor;
  626. end;
  627. if Sorted then
  628. TJSArray(Result).sort(@NameSort);
  629. end;
  630. function GetPropList(aTIStruct: TTypeInfoStruct): TTypeMemberPropertyDynArray;
  631. begin
  632. Result:=GetPropInfos(aTIStruct);
  633. end;
  634. function GetPropList(AClass: TClass): TTypeMemberPropertyDynArray;
  635. begin
  636. Result:=GetPropInfos(TypeInfo(AClass));
  637. end;
  638. function GetPropList(Instance: TObject): TTypeMemberPropertyDynArray;
  639. begin
  640. Result:=GetPropList(Instance.ClassType);
  641. end;
  642. function GetPropInfo(TI: TTypeInfoStruct; const PropName: String
  643. ): TTypeMemberProperty;
  644. var
  645. m: TTypeMember;
  646. i: Integer;
  647. C: TTypeInfoStruct;
  648. begin
  649. // quick search case sensitive
  650. C:=TI;
  651. while C<>nil do
  652. begin
  653. m:=C.Members[PropName];
  654. if m is TTypeMemberProperty then
  655. exit(TTypeMemberProperty(m));
  656. if not (C is TTypeInfoClass) then
  657. break;
  658. C:=TTypeInfoClass(C).Ancestor;
  659. end;
  660. // slow search case insensitive
  661. Result:=nil;
  662. repeat
  663. for i:=0 to TI.PropCount-1 do
  664. if CompareText(PropName,TI.Properties[i])=0 then
  665. begin
  666. m:=TI.Members[TI.Properties[i]];
  667. if m is TTypeMemberProperty then
  668. Result:=TTypeMemberProperty(m);
  669. exit;
  670. end;
  671. if not (TI is TTypeInfoClass) then
  672. break;
  673. TI:=TTypeInfoClass(TI).Ancestor;
  674. until TI=nil;
  675. end;
  676. function GetPropInfo(TI: TTypeInfoStruct; const PropName: String;
  677. const Kinds: TTypeKinds): TTypeMemberProperty;
  678. begin
  679. Result:=GetPropInfo(TI,PropName);
  680. if (Kinds<>[]) and (Result<>nil) and not (Result.TypeInfo.Kind in Kinds) then
  681. Result:=nil;
  682. end;
  683. function GetPropInfo(Instance: TObject; const PropName: String
  684. ): TTypeMemberProperty;
  685. begin
  686. Result:=GetPropInfo(TypeInfo(Instance),PropName,[]);
  687. end;
  688. function GetPropInfo(Instance: TObject; const PropName: String;
  689. const Kinds: TTypeKinds): TTypeMemberProperty;
  690. begin
  691. Result:=GetPropInfo(TypeInfo(Instance),PropName,Kinds);
  692. end;
  693. function GetPropInfo(aClass: TClass; const PropName: String
  694. ): TTypeMemberProperty;
  695. begin
  696. Result:=GetPropInfo(TypeInfo(AClass),PropName,[]);
  697. end;
  698. function GetPropInfo(aClass: TClass; const PropName: String;
  699. const Kinds: TTypeKinds): TTypeMemberProperty;
  700. begin
  701. Result:=GetPropInfo(TypeInfo(AClass),PropName,Kinds);
  702. end;
  703. function FindPropInfo(Instance: TObject; const PropName: String
  704. ): TTypeMemberProperty;
  705. begin
  706. Result:=GetPropInfo(TypeInfo(Instance), PropName);
  707. if Result=nil then
  708. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  709. end;
  710. function FindPropInfo(Instance: TObject; const PropName: String;
  711. const Kinds: TTypeKinds): TTypeMemberProperty;
  712. begin
  713. Result:=GetPropInfo(TypeInfo(Instance), PropName, Kinds);
  714. if Result=nil then
  715. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  716. end;
  717. function FindPropInfo(aClass: TClass; const PropName: String
  718. ): TTypeMemberProperty;
  719. begin
  720. Result:=GetPropInfo(TypeInfo(aClass), PropName);
  721. if Result=nil then
  722. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  723. end;
  724. function FindPropInfo(aClass: TClass; const PropName: String;
  725. const Kinds: TTypeKinds): TTypeMemberProperty;
  726. begin
  727. Result:=GetPropInfo(TypeInfo(aClass), PropName, Kinds);
  728. if Result=nil then
  729. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  730. end;
  731. function IsStoredProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  732. ): Boolean;
  733. type
  734. TIsStored = function: Boolean of object;
  735. begin
  736. case PropInfo.Flags and 12 of
  737. 0: Result:=true;
  738. 4: Result:=false;
  739. 8: Result:=Boolean(TJSObject(Instance)[PropInfo.Stored]);
  740. else Result:=TIsStored(TJSObject(Instance)[PropInfo.Stored])();
  741. end;
  742. end;
  743. function IsStoredProp(Instance: TObject; const PropName: string): Boolean;
  744. begin
  745. Result:=IsStoredProp(Instance,FindPropInfo(Instance,PropName));
  746. end;
  747. function IsPublishedProp(Instance: TObject; const PropName: String): Boolean;
  748. begin
  749. Result:=GetPropInfo(Instance,PropName)<>nil;
  750. end;
  751. function IsPublishedProp(aClass: TClass; const PropName: String): Boolean;
  752. begin
  753. Result:=GetPropInfo(aClass,PropName)<>nil;
  754. end;
  755. function PropType(Instance: TObject; const PropName: string): TTypeKind;
  756. begin
  757. Result:=FindPropInfo(Instance,PropName).TypeInfo.Kind;
  758. end;
  759. function PropType(aClass: TClass; const PropName: string): TTypeKind;
  760. begin
  761. Result:=FindPropInfo(aClass,PropName).TypeInfo.Kind;
  762. end;
  763. function PropIsType(Instance: TObject; const PropName: string;
  764. const TypeKind: TTypeKind): Boolean;
  765. begin
  766. Result:=PropType(Instance,PropName)=TypeKind;
  767. end;
  768. function PropIsType(aClass: TClass; const PropName: string;
  769. const TypeKind: TTypeKind): Boolean;
  770. begin
  771. Result:=PropType(aClass,PropName)=TypeKind;
  772. end;
  773. type
  774. TGetterKind = (
  775. gkNone,
  776. gkField,
  777. gkFunction,
  778. gkFunctionWithParams
  779. );
  780. function GetPropGetterKind(const PropInfo: TTypeMemberProperty): TGetterKind;
  781. begin
  782. if PropInfo.Getter='' then
  783. Result:=gkNone
  784. else if (pfGetFunction and PropInfo.Flags)>0 then
  785. begin
  786. if length(PropInfo.Params)>0 then
  787. // array property
  788. Result:=gkFunctionWithParams
  789. else
  790. Result:=gkFunction;
  791. end
  792. else
  793. Result:=gkField;
  794. end;
  795. type
  796. TSetterKind = (
  797. skNone,
  798. skField,
  799. skProcedure,
  800. skProcedureWithParams
  801. );
  802. function GetPropSetterKind(const PropInfo: TTypeMemberProperty): TSetterKind;
  803. begin
  804. if PropInfo.Setter='' then
  805. Result:=skNone
  806. else if (pfSetProcedure and PropInfo.Flags)>0 then
  807. begin
  808. if length(PropInfo.Params)>0 then
  809. // array property
  810. Result:=skProcedureWithParams
  811. else
  812. Result:=skProcedure;
  813. end
  814. else
  815. Result:=skField;
  816. end;
  817. function GetJSValueProp(Instance: TJSObject; TI: TTypeInfoStruct;
  818. const PropName: String): JSValue;
  819. var
  820. PropInfo: TTypeMemberProperty;
  821. begin
  822. PropInfo:=GetPropInfo(TI,PropName);
  823. if PropInfo=nil then
  824. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  825. Result:=GetJSValueProp(Instance,PropInfo);
  826. end;
  827. function GetJSValueProp(Instance: TJSObject;
  828. const PropInfo: TTypeMemberProperty): JSValue;
  829. type
  830. TGetter = function: JSValue of object;
  831. TGetterWithIndex = function(Index: JSValue): JSValue of object;
  832. var
  833. gk: TGetterKind;
  834. begin
  835. gk:=GetPropGetterKind(PropInfo);
  836. case gk of
  837. gkNone:
  838. raise EPropertyError.CreateFmt(SCantReadPropertyS, [PropInfo.Name]);
  839. gkField:
  840. Result:=Instance[PropInfo.Getter];
  841. gkFunction:
  842. if (pfHasIndex and PropInfo.Flags)>0 then
  843. Result:=TGetterWithIndex(Instance[PropInfo.Getter])(PropInfo.Index)
  844. else
  845. Result:=TGetter(Instance[PropInfo.Getter])();
  846. gkFunctionWithParams:
  847. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  848. end;
  849. end;
  850. function GetJSValueProp(Instance: TObject; const PropName: String): JSValue;
  851. begin
  852. Result:=GetJSValueProp(Instance,FindPropInfo(Instance,PropName));
  853. end;
  854. function GetJSValueProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  855. ): JSValue;
  856. begin
  857. Result:=GetJSValueProp(TJSObject(Instance),PropInfo);
  858. end;
  859. procedure SetJSValueProp(Instance: TJSObject; TI: TTypeInfoStruct;
  860. const PropName: String; Value: JSValue);
  861. var
  862. PropInfo: TTypeMemberProperty;
  863. begin
  864. PropInfo:=GetPropInfo(TI,PropName);
  865. if PropInfo=nil then
  866. raise EPropertyError.CreateFmt(SErrPropertyNotFound, [PropName]);
  867. SetJSValueProp(Instance,PropInfo,Value);
  868. end;
  869. procedure SetJSValueProp(Instance: TJSObject;
  870. const PropInfo: TTypeMemberProperty; Value: JSValue);
  871. type
  872. TSetter = procedure(Value: JSValue) of object;
  873. TSetterWithIndex = procedure(Index, Value: JSValue) of object;
  874. var
  875. sk: TSetterKind;
  876. begin
  877. sk:=GetPropSetterKind(PropInfo);
  878. case sk of
  879. skNone:
  880. raise EPropertyError.CreateFmt(SCantWritePropertyS, [PropInfo.Name]);
  881. skField:
  882. Instance[PropInfo.Setter]:=Value;
  883. skProcedure:
  884. if (pfHasIndex and PropInfo.Flags)>0 then
  885. TSetterWithIndex(Instance[PropInfo.Setter])(PropInfo.Index,Value)
  886. else
  887. TSetter(Instance[PropInfo.Setter])(Value);
  888. skProcedureWithParams:
  889. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  890. end;
  891. end;
  892. procedure SetJSValueProp(Instance: TObject; const PropName: String;
  893. Value: JSValue);
  894. begin
  895. SetJSValueProp(Instance,FindPropInfo(Instance,PropName),Value);
  896. end;
  897. procedure SetJSValueProp(Instance: TObject;
  898. const PropInfo: TTypeMemberProperty; Value: JSValue);
  899. begin
  900. SetJSValueProp(TJSObject(Instance),PropInfo,Value);
  901. end;
  902. function GetNativeIntProp(Instance: TObject; const PropName: String): NativeInt;
  903. begin
  904. Result:=GetNativeIntProp(Instance,FindPropInfo(Instance,PropName));
  905. end;
  906. function GetNativeIntProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  907. ): NativeInt;
  908. begin
  909. Result:=NativeInt(GetJSValueProp(Instance,PropInfo));
  910. end;
  911. procedure SetNativeIntProp(Instance: TObject; const PropName: String;
  912. Value: NativeInt);
  913. begin
  914. SetJSValueProp(Instance,FindPropInfo(Instance,PropName),Value);
  915. end;
  916. procedure SetNativeIntProp(Instance: TObject;
  917. const PropInfo: TTypeMemberProperty; Value: NativeInt);
  918. begin
  919. SetJSValueProp(Instance,PropInfo,Value);
  920. end;
  921. function GetOrdProp(Instance: TObject; const PropName: String): longint;
  922. begin
  923. Result:=GetOrdProp(Instance,FindPropInfo(Instance,PropName));
  924. end;
  925. function GetOrdProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  926. ): longint;
  927. var
  928. o: TJSObject;
  929. Key: String;
  930. n: NativeInt;
  931. begin
  932. if PropInfo.TypeInfo.Kind=tkSet then
  933. begin
  934. // a set is a JS object, with the following property: o[ElementDecimal]=true
  935. o:=TJSObject(GetJSValueProp(Instance,PropInfo));
  936. Result:=0;
  937. for Key in o do
  938. begin
  939. n:=parseInt(Key,10);
  940. if n<32 then
  941. Result:=Result+(1 shl n);
  942. end;
  943. end else
  944. Result:=longint(GetJSValueProp(Instance,PropInfo));
  945. end;
  946. procedure SetOrdProp(Instance: TObject; const PropName: String; Value: longint);
  947. begin
  948. SetOrdProp(Instance,FindPropInfo(Instance,PropName),Value);
  949. end;
  950. procedure SetOrdProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  951. Value: longint);
  952. var
  953. o: TJSObject;
  954. i: Integer;
  955. begin
  956. if PropInfo.TypeInfo.Kind=tkSet then
  957. begin
  958. o:=TJSObject.new;
  959. for i:=0 to 31 do
  960. if (1 shl i) and Value>0 then
  961. o[str(i)]:=true;
  962. SetJSValueProp(Instance,PropInfo,o);
  963. end else
  964. SetJSValueProp(Instance,PropInfo,Value);
  965. end;
  966. function GetEnumProp(Instance: TObject; const PropName: String): String;
  967. begin
  968. Result:=GetEnumProp(Instance,FindPropInfo(Instance,PropName));
  969. end;
  970. function GetEnumProp(Instance: TObject; const PropInfo: TTypeMemberProperty): String;
  971. var
  972. n: NativeInt;
  973. TIEnum: TTypeInfoEnum;
  974. begin
  975. TIEnum:=PropInfo.TypeInfo as TTypeInfoEnum;
  976. n:=NativeInt(GetJSValueProp(Instance,PropInfo));
  977. if (n>=TIEnum.MinValue) and (n<=TIEnum.MaxValue) then
  978. Result:=TIEnum.EnumType.IntToName[n]
  979. else
  980. Result:=str(n);
  981. end;
  982. procedure SetEnumProp(Instance: TObject; const PropName: String;
  983. const Value: String);
  984. begin
  985. SetEnumProp(Instance,FindPropInfo(Instance,PropName),Value);
  986. end;
  987. procedure SetEnumProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  988. const Value: String);
  989. var
  990. TIEnum: TTypeInfoEnum;
  991. n: NativeInt;
  992. begin
  993. TIEnum:=PropInfo.TypeInfo as TTypeInfoEnum;
  994. n:=TIEnum.EnumType.NameToInt[Value];
  995. if not isUndefined(n) then
  996. SetJSValueProp(Instance,PropInfo,n);
  997. end;
  998. function GetEnumName(TypeInfo: TTypeInfoEnum; Value: Integer): String;
  999. begin
  1000. Result:=TypeInfo.EnumType.IntToName[Value];
  1001. end;
  1002. function GetEnumValue(TypeInfo: TTypeInfoEnum; const Name: string): Longint;
  1003. begin
  1004. Result:=TypeInfo.EnumType.NameToInt[Name];
  1005. end;
  1006. function GetEnumNameCount(TypeInfo: TTypeInfoEnum): Longint;
  1007. var
  1008. o: TJSObject;
  1009. l, r: LongInt;
  1010. begin
  1011. o:=TJSObject(TypeInfo.EnumType);
  1012. // as of pas2js 1.0 the RTTI does not contain a min/max value
  1013. // -> use exponential search
  1014. // ToDo: adapt this once enums with gaps are supported
  1015. Result:=1;
  1016. while o.hasOwnProperty(String(JSValue(Result))) do
  1017. Result:=Result*2;
  1018. l:=Result div 2;
  1019. r:=Result;
  1020. while l<=r do
  1021. begin
  1022. Result:=(l+r) div 2;
  1023. if o.hasOwnProperty(String(JSValue(Result))) then
  1024. l:=Result+1
  1025. else
  1026. r:=Result-1;
  1027. end;
  1028. if o.hasOwnProperty(String(JSValue(Result))) then
  1029. inc(Result);
  1030. end;
  1031. function GetSetProp(Instance: TObject; const PropName: String): String;
  1032. begin
  1033. Result:=GetSetProp(Instance,FindPropInfo(Instance,PropName));
  1034. end;
  1035. function GetSetProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  1036. ): String;
  1037. var
  1038. o: TJSObject;
  1039. key, Value: String;
  1040. n: NativeInt;
  1041. TIEnum: TTypeInfoEnum;
  1042. TISet: TTypeInfoSet;
  1043. begin
  1044. Result:='';
  1045. // get enum type if available
  1046. TISet:=PropInfo.TypeInfo as TTypeInfoSet;
  1047. TIEnum:=nil;
  1048. if TISet.CompType is TTypeInfoEnum then
  1049. TIEnum:=TTypeInfoEnum(TISet.CompType);
  1050. // read value
  1051. o:=TJSObject(GetJSValueProp(Instance,PropInfo));
  1052. // a set is a JS object, where included element is stored as: o[ElementDecimal]=true
  1053. for Key in o do
  1054. begin
  1055. n:=parseInt(Key,10);
  1056. if (TIEnum<>nil) and (n>=TIEnum.MinValue) and (n<=TIEnum.MaxValue) then
  1057. Value:=TIEnum.EnumType.IntToName[n]
  1058. else
  1059. Value:=str(n);
  1060. if Result<>'' then Result:=Result+',';
  1061. Result:=Result+Value;
  1062. end;
  1063. Result:='['+Result+']';
  1064. end;
  1065. function GetSetPropArray(Instance: TObject; const PropName: String
  1066. ): TIntegerDynArray;
  1067. begin
  1068. Result:=GetSetPropArray(Instance,FindPropInfo(Instance,PropName));
  1069. end;
  1070. function GetSetPropArray(Instance: TObject; const PropInfo: TTypeMemberProperty
  1071. ): TIntegerDynArray;
  1072. var
  1073. o: TJSObject;
  1074. Key: string;
  1075. begin
  1076. Result:=[];
  1077. // read value
  1078. o:=TJSObject(GetJSValueProp(Instance,PropInfo));
  1079. // a set is a JS object, where included element is stored as: o[ElementDecimal]=true
  1080. for Key in o do
  1081. TJSArray(Result).push(parseInt(Key,10));
  1082. end;
  1083. procedure SetSetPropArray(Instance: TObject; const PropName: String;
  1084. const Arr: TIntegerDynArray);
  1085. begin
  1086. SetSetPropArray(Instance,FindPropInfo(Instance,PropName),Arr);
  1087. end;
  1088. procedure SetSetPropArray(Instance: TObject;
  1089. const PropInfo: TTypeMemberProperty; const Arr: TIntegerDynArray);
  1090. var
  1091. o: TJSObject;
  1092. i: integer;
  1093. begin
  1094. o:=TJSObject.new;
  1095. for i in Arr do
  1096. o[str(i)]:=true;
  1097. SetJSValueProp(Instance,PropInfo,o);
  1098. end;
  1099. function GetStrProp(Instance: TObject; const PropName: String): String;
  1100. begin
  1101. Result:=GetStrProp(Instance,FindPropInfo(Instance,PropName));
  1102. end;
  1103. function GetStrProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  1104. ): String;
  1105. begin
  1106. Result:=String(GetJSValueProp(Instance,PropInfo));
  1107. end;
  1108. procedure SetStrProp(Instance: TObject; const PropName: String; Value: String
  1109. );
  1110. begin
  1111. SetStrProp(Instance,FindPropInfo(Instance,PropName),Value);
  1112. end;
  1113. procedure SetStrProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  1114. Value: String);
  1115. begin
  1116. SetJSValueProp(Instance,PropInfo,Value);
  1117. end;
  1118. function GetStringProp(Instance: TObject; const PropName: String): String;
  1119. begin
  1120. Result:=GetStrProp(Instance,PropName);
  1121. end;
  1122. function GetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  1123. ): String;
  1124. begin
  1125. Result:=GetStrProp(Instance,PropInfo);
  1126. end;
  1127. procedure SetStringProp(Instance: TObject; const PropName: String; Value: String
  1128. );
  1129. begin
  1130. SetStrProp(Instance,PropName,Value);
  1131. end;
  1132. procedure SetStringProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  1133. Value: String);
  1134. begin
  1135. SetStrProp(Instance,PropInfo,Value);
  1136. end;
  1137. function GetBoolProp(Instance: TObject; const PropName: String): boolean;
  1138. begin
  1139. Result:=GetBoolProp(Instance,FindPropInfo(Instance,PropName));
  1140. end;
  1141. function GetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty
  1142. ): boolean;
  1143. begin
  1144. Result:=Boolean(GetJSValueProp(Instance,PropInfo));
  1145. end;
  1146. procedure SetBoolProp(Instance: TObject; const PropName: String; Value: boolean
  1147. );
  1148. begin
  1149. SetBoolProp(Instance,FindPropInfo(Instance,PropName),Value);
  1150. end;
  1151. procedure SetBoolProp(Instance: TObject; const PropInfo: TTypeMemberProperty;
  1152. Value: boolean);
  1153. begin
  1154. SetJSValueProp(Instance,PropInfo,Value);
  1155. end;
  1156. function GetObjectProp(Instance: TObject; const PropName: String): TObject;
  1157. begin
  1158. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName));
  1159. end;
  1160. function GetObjectProp(Instance: TObject; const PropName: String; MinClass : TClass): TObject;
  1161. begin
  1162. Result:=GetObjectProp(Instance,FindPropInfo(Instance,PropName));
  1163. if (MinClass<>Nil) and (Result<>Nil) Then
  1164. if not Result.InheritsFrom(MinClass) then
  1165. Result:=Nil;
  1166. end;
  1167. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty): TObject;
  1168. begin
  1169. Result:=GetObjectProp(Instance,PropInfo,Nil);
  1170. end;
  1171. function GetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; MinClass : TClass): TObject;
  1172. Var
  1173. O : TObject;
  1174. begin
  1175. O:=TObject(GetJSValueProp(Instance,PropInfo));
  1176. if (MinClass<>Nil) and not O.InheritsFrom(MinClass) then
  1177. Result:=Nil
  1178. else
  1179. Result:=O;
  1180. end;
  1181. procedure SetObjectProp(Instance: TObject; const PropName: String; Value: TObject) ;
  1182. begin
  1183. SetObjectProp(Instance,FindPropInfo(Instance,PropName),Value);
  1184. end;
  1185. procedure SetObjectProp(Instance: TObject; const PropInfo: TTypeMemberProperty; Value: TObject);
  1186. begin
  1187. SetJSValueProp(Instance,PropInfo,Value);
  1188. end;
  1189. function GetMethodProp(Instance: TObject; PropInfo: TTypeMemberProperty
  1190. ): TMethod;
  1191. var
  1192. v, fn: JSValue;
  1193. begin
  1194. Result.Code:=nil;
  1195. Result.Data:=nil;
  1196. v:=GetJSValueProp(Instance,PropInfo);
  1197. if not isFunction(v) then exit;
  1198. Result.Data:=Pointer(TJSObject(v)['scope']);
  1199. fn:=TJSObject(v)['fn'];
  1200. if isString(fn) then
  1201. begin
  1202. if Result.Data<>nil then
  1203. // named callback
  1204. Result.Code:=CodePointer(TJSObject(Result.Data)[String(fn)])
  1205. else
  1206. // this is not an rtl callback, return the value
  1207. Result.Code:=CodePointer(v);
  1208. end
  1209. else
  1210. // anonymous callback
  1211. Result.Code:=CodePointer(fn);
  1212. end;
  1213. function GetMethodProp(Instance: TObject; const PropName: string): TMethod;
  1214. begin
  1215. Result:=GetMethodProp(Instance,FindPropInfo(Instance,PropName));
  1216. end;
  1217. function createCallbackPtr(scope: Pointer; fn: CodePointer): TJSFunction; external name 'rtl.createCallback';
  1218. function createCallbackStr(scope: Pointer; fn: string): TJSFunction; external name 'rtl.createCallback';
  1219. procedure SetMethodProp(Instance: TObject; PropInfo: TTypeMemberProperty;
  1220. const Value: TMethod);
  1221. var
  1222. cb: TJSFunction;
  1223. Code: Pointer;
  1224. begin
  1225. // Note: Value.Data=nil is allowed and can be used by designer code
  1226. Code:=Value.Code;
  1227. if Code=nil then
  1228. cb:=nil
  1229. else if isFunction(Code) then
  1230. begin
  1231. if (TJSObject(Code)['scope']=Value.Data)
  1232. and (isFunction(TJSObject(Code)['fn']) or isString(TJSObject(Code)['fn']))
  1233. then
  1234. begin
  1235. // Value.Code is already the needed callback
  1236. cb:=TJSFunction(Code);
  1237. end
  1238. else if isString(TJSObject(Code)['fn']) then
  1239. // named callback, different scope
  1240. cb:=createCallbackStr(Value.Data,string(TJSObject(Code)['fn']))
  1241. else
  1242. // normal function
  1243. cb:=createCallbackPtr(Value.Data,Code);
  1244. end
  1245. else
  1246. // not a valid value -> for compatibility set it anyway
  1247. cb:=createCallbackPtr(Value.Data,Code);
  1248. SetJSValueProp(Instance,PropInfo,cb);
  1249. end;
  1250. procedure SetMethodProp(Instance: TObject; const PropName: string;
  1251. const Value: TMethod);
  1252. begin
  1253. SetMethodProp(Instance,FindPropInfo(Instance,PropName),Value);
  1254. end;
  1255. function GetInterfaceProp(Instance: TObject; const PropName: string
  1256. ): IInterface;
  1257. begin
  1258. Result:=GetInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  1259. end;
  1260. function GetInterfaceProp(Instance: TObject; PropInfo: TTypeMemberProperty
  1261. ): IInterface;
  1262. type
  1263. TGetter = function: IInterface of object;
  1264. TGetterWithIndex = function(Index: JSValue): IInterface of object;
  1265. var
  1266. gk: TGetterKind;
  1267. begin
  1268. if Propinfo.TypeInfo.Kind<>tkInterface then
  1269. raise Exception.Create('Cannot get RAW interface from IInterface interface');
  1270. gk:=GetPropGetterKind(PropInfo);
  1271. case gk of
  1272. gkNone:
  1273. raise EPropertyError.CreateFmt(SCantReadPropertyS, [PropInfo.Name]);
  1274. gkField:
  1275. Result:=IInterface(TJSObject(Instance)[PropInfo.Getter]);
  1276. gkFunction:
  1277. if (pfHasIndex and PropInfo.Flags)>0 then
  1278. Result:=TGetterWithIndex(TJSObject(Instance)[PropInfo.Getter])(PropInfo.Index)
  1279. else
  1280. Result:=TGetter(TJSObject(Instance)[PropInfo.Getter])();
  1281. gkFunctionWithParams:
  1282. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  1283. end;
  1284. end;
  1285. procedure SetInterfaceProp(Instance: TObject; const PropName: string;
  1286. const Value: IInterface);
  1287. begin
  1288. SetInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  1289. end;
  1290. procedure SetInterfaceProp(Instance: TObject; PropInfo: TTypeMemberProperty;
  1291. const Value: IInterface);
  1292. type
  1293. TSetter = procedure(Value: IInterface) of object;
  1294. TSetterWithIndex = procedure(Index: JSValue; Value: IInterface) of object;
  1295. procedure setIntfP(Instance: TObject; const PropName: string; value: jsvalue); external name 'rtl.setIntfP';
  1296. var
  1297. sk: TSetterKind;
  1298. Setter: String;
  1299. begin
  1300. if Propinfo.TypeInfo.Kind<>tkInterface then
  1301. raise Exception.Create('Cannot set RAW interface from IInterface interface');
  1302. sk:=GetPropSetterKind(PropInfo);
  1303. Setter:=PropInfo.Setter;
  1304. case sk of
  1305. skNone:
  1306. raise EPropertyError.CreateFmt(SCantWritePropertyS, [PropInfo.Name]);
  1307. skField:
  1308. setIntfP(Instance,Setter,Value);
  1309. skProcedure:
  1310. if (pfHasIndex and PropInfo.Flags)>0 then
  1311. TSetterWithIndex(TJSObject(Instance)[Setter])(PropInfo.Index,Value)
  1312. else
  1313. TSetter(TJSObject(Instance)[Setter])(Value);
  1314. skProcedureWithParams:
  1315. raise EPropertyError.CreateFmt(SIndexedPropertyNeedsParams, [PropInfo.Name]);
  1316. end;
  1317. end;
  1318. function GetRawInterfaceProp(Instance: TObject; const PropName: string
  1319. ): Pointer;
  1320. begin
  1321. Result:=GetRawInterfaceProp(Instance,FindPropInfo(Instance,PropName));
  1322. end;
  1323. function GetRawInterfaceProp(Instance: TObject; PropInfo: TTypeMemberProperty
  1324. ): Pointer;
  1325. begin
  1326. Result:=Pointer(GetJSValueProp(Instance,PropInfo));
  1327. end;
  1328. procedure SetRawInterfaceProp(Instance: TObject; const PropName: string;
  1329. const Value: Pointer);
  1330. begin
  1331. SetRawInterfaceProp(Instance,FindPropInfo(Instance,PropName),Value);
  1332. end;
  1333. procedure SetRawInterfaceProp(Instance: TObject; PropInfo: TTypeMemberProperty;
  1334. const Value: Pointer);
  1335. begin
  1336. SetJSValueProp(Instance,PropInfo,Value);
  1337. end;
  1338. function GetFloatProp(Instance: TObject; PropInfo: TTypeMemberProperty): Double;
  1339. begin
  1340. Result:=Double(GetJSValueProp(Instance,PropInfo));
  1341. end;
  1342. function GetFloatProp(Instance: TObject; const PropName: string): Double;
  1343. begin
  1344. Result:=GetFloatProp(Instance,FindPropInfo(Instance,PropName));
  1345. end;
  1346. procedure SetFloatProp(Instance: TObject; const PropName: string; Value: Double
  1347. );
  1348. begin
  1349. SetFloatProp(Instance,FindPropInfo(Instance,PropName),Value);
  1350. end;
  1351. procedure SetFloatProp(Instance: TObject; PropInfo: TTypeMemberProperty;
  1352. Value: Double);
  1353. begin
  1354. SetJSValueProp(Instance,PropInfo,Value);
  1355. end;
  1356. end.