2
0

typinfo.pas 48 KB

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