rtti.pas 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679
  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 RTTI;
  11. {$mode objfpc}
  12. {$ModeSwitch advancedrecords}
  13. interface
  14. uses
  15. JS, RTLConsts, Types, SysUtils, TypInfo;
  16. resourcestring
  17. SErrInvokeInvalidCodeAddr = 'CodeAddress is not a function';
  18. SErrTypeIsNotEnumerated = 'Type %s is not an enumerated type';
  19. type
  20. { TValue }
  21. TValue = record
  22. private
  23. FTypeInfo: TTypeInfo;
  24. FData: JSValue;
  25. function GetIsEmpty: boolean;
  26. function GetTypeKind: TTypeKind;
  27. public
  28. generic class function From<T>(const Value: T): TValue; static;
  29. class function FromJSValue(v: JSValue): TValue; static;
  30. property Kind: TTypeKind read GetTypeKind;
  31. property TypeInfo: TTypeInfo read FTypeInfo;
  32. property IsEmpty: boolean read GetIsEmpty; // check if nil or undefined
  33. generic function AsType<T>: T;
  34. function IsObject: boolean;
  35. function AsObject: TObject;
  36. function IsObjectInstance: boolean;
  37. function IsArray: boolean;
  38. function IsClass: boolean;
  39. function AsClass: TClass;
  40. function IsOrdinal: boolean;
  41. function AsOrdinal: NativeInt;
  42. function AsBoolean: boolean;
  43. //ToDo: function AsCurrency: Currency;
  44. function AsInteger: Integer;
  45. function AsNativeInt: NativeInt;
  46. function AsInterface: IInterface;
  47. function AsString: string;
  48. function AsUnicodeString: UnicodeString;
  49. function AsExtended: Extended;
  50. function ToString: String;
  51. function GetArrayLength: SizeInt;
  52. function GetArrayElement(aIndex: SizeInt): TValue;
  53. procedure SetArrayElement(aIndex: SizeInt; const AValue: TValue);
  54. procedure SetArrayLength(const Size: SizeInt);
  55. function IsType(ATypeInfo: PTypeInfo): boolean;
  56. function AsJSValue: JSValue;
  57. class function Empty: TValue; static;
  58. class function Make(TypeInfo: TTypeInfo; const Value: JSValue): TValue; static;
  59. class function Make(const Value: TValue): TValue; static;
  60. end;
  61. TRttiType = class;
  62. TRttiInstanceType = class;
  63. { TRTTIContext }
  64. TRTTIContext = record
  65. private
  66. FPool: TJSObject; // maps 'modulename.typename' to TRTTIType
  67. class constructor Init;
  68. public
  69. class function Create: TRTTIContext; static;
  70. procedure Free;
  71. function FindType(const AQualifiedName: String): TRttiType;
  72. function GetType(aTypeInfo: PTypeInfo): TRTTIType; overload;
  73. function GetType(aClass: TClass): TRTTIType; overload;
  74. end;
  75. { TRttiObject }
  76. TRttiObject = class abstract
  77. public
  78. //property Handle: Pointer read GetHandle; not supported in pas2js
  79. function GetAttributes: TCustomAttributeArray; virtual;
  80. end;
  81. { TRttiNamedObject }
  82. TRttiNamedObject = class(TRttiObject)
  83. protected
  84. function GetName: string; virtual;
  85. public
  86. property Name: string read GetName;
  87. end;
  88. { TRttiMember }
  89. TMemberVisibility=(
  90. mvPrivate,
  91. mvProtected,
  92. mvPublic,
  93. mvPublished);
  94. TRttiMember = class(TRttiNamedObject)
  95. private
  96. FTypeInfo: TTypeMember;
  97. FParent: TRttiType;
  98. protected
  99. function GetMemberTypeInfo: TTypeMember;
  100. function GetName: string; override;
  101. function GetVisibility: TMemberVisibility; virtual;
  102. public
  103. constructor Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  104. function GetAttributes: TCustomAttributeArray; override;
  105. property MemberTypeInfo: TTypeMember read GetMemberTypeInfo;
  106. property Visibility: TMemberVisibility read GetVisibility;
  107. property Parent: TRttiType read FParent;
  108. end;
  109. { TRttiField }
  110. TRttiField = class(TRttiMember)
  111. private
  112. function GetFieldType: TRttiType;
  113. function GetFieldTypeInfo: TTypeMemberField;
  114. public
  115. constructor Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  116. function GetValue(Instance: JSValue): TValue;
  117. procedure SetValue(Instance: JSValue; const AValue: TValue);
  118. property FieldType: TRttiType read GetFieldType;
  119. property FieldTypeInfo: TTypeMemberField read GetFieldTypeInfo;
  120. end;
  121. TRttiFieldArray = specialize TArray<TRttiField>;
  122. TRttiParameter = class(TRttiNamedObject)
  123. private
  124. FParamType: TRttiType;
  125. FFlags: TParamFlags;
  126. FName: String;
  127. protected
  128. function GetName: string; override;
  129. public
  130. property Flags: TParamFlags read FFlags;
  131. property ParamType: TRttiType read FParamType;
  132. end;
  133. TRttiParameterArray = specialize TArray<TRttiParameter>;
  134. { TRttiMethod }
  135. TRttiMethod = class(TRttiMember)
  136. private
  137. FParameters: TRttiParameterArray;
  138. function GetIsAsyncCall: Boolean;
  139. function GetIsClassMethod: Boolean;
  140. function GetIsConstructor: Boolean;
  141. function GetIsDestructor: Boolean;
  142. function GetIsExternal: Boolean;
  143. function GetIsSafeCall: Boolean;
  144. function GetIsStatic: Boolean;
  145. function GetIsVarArgs: Boolean;
  146. function GetMethodKind: TMethodKind;
  147. function GetMethodTypeInfo: TTypeMemberMethod;
  148. function GetProcedureFlags: TProcedureFlags;
  149. function GetReturnType: TRttiType;
  150. procedure LoadParameters;
  151. public
  152. function GetParameters: TRttiParameterArray;
  153. property IsAsyncCall: Boolean read GetIsAsyncCall;
  154. property IsClassMethod: Boolean read GetIsClassMethod;
  155. property IsConstructor: Boolean read GetIsConstructor;
  156. property IsDestructor: Boolean read GetIsDestructor;
  157. property IsExternal: Boolean read GetIsExternal;
  158. property IsSafeCall: Boolean read GetIsSafeCall;
  159. property IsStatic: Boolean read GetIsStatic;
  160. property MethodKind: TMethodKind read GetMethodKind;
  161. property MethodTypeInfo: TTypeMemberMethod read GetMethodTypeInfo;
  162. property ReturnType: TRttiType read GetReturnType;
  163. end;
  164. TRttiMethodArray = specialize TArray<TRttiMethod>;
  165. { TRttiProperty }
  166. TRttiProperty = class(TRttiMember)
  167. private
  168. function GetPropertyTypeInfo: TTypeMemberProperty;
  169. function GetPropertyType: TRttiType;
  170. function GetIsWritable: boolean;
  171. function GetIsReadable: boolean;
  172. protected
  173. function GetVisibility: TMemberVisibility; override;
  174. public
  175. constructor Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  176. function GetValue(Instance: JSValue): TValue;
  177. procedure SetValue(Instance: JSValue; const AValue: JSValue); overload;
  178. procedure SetValue(Instance: JSValue; const AValue: TValue); overload;
  179. procedure SetValue(Instance: TObject; const AValue: TValue); overload;
  180. property PropertyTypeInfo: TTypeMemberProperty read GetPropertyTypeInfo;
  181. property PropertyType: TRttiType read GetPropertyType;
  182. property IsReadable: boolean read GetIsReadable;
  183. property IsWritable: boolean read GetIsWritable;
  184. property Visibility: TMemberVisibility read GetVisibility;
  185. end;
  186. TRttiPropertyArray = specialize TArray<TRttiProperty>;
  187. { TRttiType }
  188. TRttiType = class(TRttiNamedObject)
  189. private
  190. FAttributes: TCustomAttributeArray;
  191. FTypeInfo: TTypeInfo;
  192. //FMethods: specialize TArray<TRttiMethod>;
  193. function GetAsInstance: TRttiInstanceType;
  194. protected
  195. function GetName: string; override;
  196. //function GetHandle: Pointer; override;
  197. function GetIsInstance: boolean;
  198. //function GetIsManaged: boolean; virtual;
  199. function GetIsOrdinal: boolean; virtual;
  200. function GetIsRecord: boolean; virtual;
  201. function GetIsSet: boolean; virtual;
  202. function GetTypeKind: TTypeKind; virtual;
  203. //function GetTypeSize: integer; virtual;
  204. //function GetBaseType: TRttiType; virtual;
  205. public
  206. constructor Create(ATypeInfo : PTypeInfo);
  207. destructor Destroy; override;
  208. function GetAttributes: TCustomAttributeArray; override;
  209. function GetField(const AName: string): TRttiField; virtual;
  210. function GetFields: TRttiFieldArray; virtual;
  211. function GetMethods: TRttiMethodArray; virtual;
  212. function GetMethods(const aName: String): TRttiMethodArray; virtual;
  213. function GetMethod(const aName: String): TRttiMethod; virtual;
  214. function GetProperty(const AName: string): TRttiProperty; virtual;
  215. //function GetIndexedProperty(const AName: string): TRttiIndexedProperty; virtual;
  216. function GetDeclaredProperties: TRttiPropertyArray; virtual;
  217. //function GetDeclaredIndexedProperties: TRttiIndexedPropertyArray; virtual;
  218. function GetDeclaredMethods: TRttiMethodArray; virtual;
  219. function GetDeclaredFields: TRttiFieldArray; virtual;
  220. property Handle: TTypeInfo read FTypeInfo;
  221. property IsInstance: boolean read GetIsInstance;
  222. //property isManaged: boolean read GetIsManaged;
  223. property IsOrdinal: boolean read GetIsOrdinal;
  224. property IsRecord: boolean read GetIsRecord;
  225. property IsSet: boolean read GetIsSet;
  226. //property BaseType: TRttiType read GetBaseType;
  227. property AsInstance: TRttiInstanceType read GetAsInstance;
  228. property TypeKind: TTypeKind read GetTypeKind;
  229. //property TypeSize: integer read GetTypeSize;
  230. end;
  231. TRttiTypeClass = class of TRttiType;
  232. { TRttiStructuredType }
  233. TRttiStructuredType = class abstract(TRttiType)
  234. private
  235. FMethods: TRttiMethodArray;
  236. FProperties: TRttiPropertyArray;
  237. protected
  238. function GetAncestor: TRttiStructuredType; virtual;
  239. function GetStructTypeInfo: TTypeInfoStruct;
  240. public
  241. constructor Create(ATypeInfo: PTypeInfo);
  242. destructor Destroy; override;
  243. function GetDeclaredMethods: TRttiMethodArray; override;
  244. function GetDeclaredProperties: TRttiPropertyArray; override;
  245. function GetMethod(const aName: String): TRttiMethod; override;
  246. function GetMethods: TRttiMethodArray; override;
  247. function GetMethods(const aName: String): TRttiMethodArray; override;
  248. function GetProperties: TRttiPropertyArray;
  249. function GetProperty(const AName: string): TRttiProperty; override;
  250. property StructTypeInfo: TTypeInfoStruct read GetStructTypeInfo;
  251. end;
  252. { TRttiInstanceType }
  253. TRttiInstanceType = class(TRttiStructuredType)
  254. private
  255. FFields: TRttiFieldArray;
  256. function GetClassTypeInfo: TTypeInfoClass;
  257. function GetMetaClassType: TClass;
  258. protected
  259. function GetAncestor: TRttiStructuredType; override;
  260. public
  261. constructor Create(ATypeInfo: PTypeInfo);
  262. function GetFields: TRttiFieldArray; override;
  263. function GetDeclaredFields: TRttiFieldArray; override;
  264. property ClassTypeInfo: TTypeInfoClass read GetClassTypeInfo;
  265. property MetaClassType: TClass read GetMetaClassType;
  266. end;
  267. { TRttiInterfaceType }
  268. TRttiInterfaceType = class(TRttiStructuredType)
  269. private
  270. function GetGUID: TGUID;
  271. function GetInterfaceTypeInfo: TTypeInfoInterface;
  272. protected
  273. function GetAncestor: TRttiStructuredType; override;
  274. public
  275. constructor Create(ATypeInfo: PTypeInfo);
  276. property GUID: TGUID read GetGUID;
  277. property InterfaceTypeInfo: TTypeInfoInterface read GetInterfaceTypeInfo;
  278. end;
  279. { TRttiRecordType }
  280. TRttiRecordType = class(TRttiStructuredType)
  281. private
  282. function GetRecordTypeInfo: TTypeInfoRecord;
  283. protected
  284. function GetIsRecord: Boolean; override;
  285. public
  286. constructor Create(ATypeInfo: PTypeInfo);
  287. property RecordTypeInfo: TTypeInfoRecord read GetRecordTypeInfo;
  288. end;
  289. { TRttiClassRefType }
  290. TRttiClassRefType = class(TRttiType)
  291. private
  292. function GetClassRefTypeInfo: TTypeInfoClassRef;
  293. function GetInstanceType: TRttiInstanceType;
  294. function GetMetaclassType: TClass;
  295. public
  296. constructor Create(ATypeInfo: PTypeInfo);
  297. property ClassRefTypeInfo: TTypeInfoClassRef read GetClassRefTypeInfo;
  298. property InstanceType: TRttiInstanceType read GetInstanceType;
  299. property MetaclassType: TClass read GetMetaclassType;
  300. end;
  301. { TRttiOrdinalType }
  302. TRttiOrdinalType = class(TRttiType)
  303. private
  304. function GetMaxValue: Integer; virtual;
  305. function GetMinValue: Integer; virtual;
  306. function GetOrdType: TOrdType;
  307. function GetOrdinalTypeInfo: TTypeInfoInteger;
  308. public
  309. constructor Create(ATypeInfo: PTypeInfo);
  310. property OrdType: TOrdType read GetOrdType;
  311. property MinValue: Integer read GetMinValue;
  312. property MaxValue: Integer read GetMaxValue;
  313. property OrdinalTypeInfo: TTypeInfoInteger read GetOrdinalTypeInfo;
  314. end;
  315. { TRttiEnumerationType }
  316. TRttiEnumerationType = class(TRttiOrdinalType)
  317. private
  318. function GetEnumerationTypeInfo: TTypeInfoEnum;
  319. public
  320. constructor Create(ATypeInfo: PTypeInfo);
  321. property EnumerationTypeInfo: TTypeInfoEnum read GetEnumerationTypeInfo;
  322. function GetNames: TStringArray;
  323. generic class function GetName<T>(AValue: T): String; reintroduce;
  324. generic class function GetValue<T>(const AValue: String): T;
  325. end;
  326. { TRttiDynamicArrayType }
  327. TRttiDynamicArrayType = class(TRttiType)
  328. private
  329. function GetDynArrayTypeInfo: TTypeInfoDynArray;
  330. function GetElementType: TRttiType;
  331. public
  332. constructor Create(ATypeInfo: PTypeInfo);
  333. property DynArrayTypeInfo: TTypeInfoDynArray read GetDynArrayTypeInfo;
  334. property ElementType: TRttiType read GetElementType;
  335. end;
  336. EInvoke = EJS;
  337. TVirtualInterfaceInvokeEvent = function(const aMethodName: string;
  338. const Args: TJSValueDynArray): JSValue of object;
  339. { TVirtualInterface: A class that can implement any IInterface. Any method
  340. call is handled by the OnInvoke event. }
  341. TVirtualInterface = class(TInterfacedObject, IInterface)
  342. private
  343. FOnInvoke: TVirtualInterfaceInvokeEvent;
  344. public
  345. constructor Create(InterfaceTypeInfo: Pointer); overload; assembler;
  346. constructor Create(InterfaceTypeInfo: Pointer;
  347. const InvokeEvent: TVirtualInterfaceInvokeEvent); overload;
  348. function QueryInterface(const iid: TGuid; out obj): Integer; override;
  349. property OnInvoke: TVirtualInterfaceInvokeEvent read FOnInvoke write FOnInvoke;
  350. end;
  351. procedure CreateVirtualCorbaInterface(InterfaceTypeInfo: Pointer;
  352. const MethodImplementation: TVirtualInterfaceInvokeEvent; out IntfVar); assembler;
  353. function Invoke(ACodeAddress: Pointer; const AArgs: TJSValueDynArray;
  354. ACallConv: TCallConv; AResultType: PTypeInfo; AIsStatic: Boolean;
  355. AIsConstructor: Boolean): TValue;
  356. implementation
  357. var
  358. GRttiContext: TRTTIContext;
  359. pas: TJSObject; external name 'pas';
  360. procedure CreateVirtualCorbaInterface(InterfaceTypeInfo: Pointer;
  361. const MethodImplementation: TVirtualInterfaceInvokeEvent; out IntfVar); assembler;
  362. asm
  363. var IntfType = InterfaceTypeInfo.interface;
  364. var i = Object.create(IntfType);
  365. var o = { $name: "virtual", $fullname: "virtual" };
  366. i.$o = o;
  367. do {
  368. var names = IntfType.$names;
  369. if (!names) break;
  370. for (var j=0; j<names.length; j++){
  371. let fnname = names[j];
  372. i[fnname] = function(){ return MethodImplementation(fnname,arguments); };
  373. }
  374. IntfType = Object.getPrototypeOf(IntfType);
  375. } while(IntfType!=null);
  376. IntfVar.set(i);
  377. end;
  378. { TRttiDynamicArrayType }
  379. function TRttiDynamicArrayType.GetDynArrayTypeInfo: TTypeInfoDynArray;
  380. begin
  381. Result := TTypeInfoDynArray(FTypeInfo);
  382. end;
  383. function TRttiDynamicArrayType.GetElementType: TRttiType;
  384. begin
  385. Result := GRttiContext.GetType(DynArrayTypeInfo.ElType);
  386. end;
  387. constructor TRttiDynamicArrayType.Create(ATypeInfo: PTypeInfo);
  388. begin
  389. if not (TTypeInfo(ATypeInfo) is TTypeInfoDynArray) then
  390. raise EInvalidCast.Create('');
  391. inherited Create(ATypeInfo);
  392. end;
  393. { TRttiOrdinalType }
  394. function TRttiOrdinalType.GetMaxValue: Integer;
  395. begin
  396. Result := OrdinalTypeInfo.MaxValue;
  397. end;
  398. function TRttiOrdinalType.GetMinValue: Integer;
  399. begin
  400. Result := OrdinalTypeInfo.MinValue;
  401. end;
  402. function TRttiOrdinalType.GetOrdType: TOrdType;
  403. begin
  404. Result := OrdinalTypeInfo.OrdType;
  405. end;
  406. function TRttiOrdinalType.GetOrdinalTypeInfo: TTypeInfoInteger;
  407. begin
  408. Result := TTypeInfoInteger(FTypeInfo);
  409. end;
  410. constructor TRttiOrdinalType.Create(ATypeInfo: PTypeInfo);
  411. begin
  412. if not (TTypeInfo(ATypeInfo) is TTypeInfoInteger) then
  413. raise EInvalidCast.Create('');
  414. inherited Create(ATypeInfo);
  415. end;
  416. { TRttiEnumerationType }
  417. function TRttiEnumerationType.GetEnumerationTypeInfo: TTypeInfoEnum;
  418. begin
  419. Result := TTypeInfoEnum(FTypeInfo);
  420. end;
  421. function TRttiEnumerationType.GetNames: TStringArray;
  422. var
  423. A, NamesSize: Integer;
  424. begin
  425. NamesSize := GetEnumNameCount(EnumerationTypeInfo);
  426. SetLength(Result, NamesSize);
  427. for A := 0 to Pred(NamesSize) do
  428. Result[A] := EnumerationTypeInfo.EnumType.IntToName[A + MinValue];
  429. end;
  430. generic class function TRttiEnumerationType.GetName<T>(AValue: T): String;
  431. Var
  432. P : PTypeInfo;
  433. begin
  434. P:=TypeInfo(T);
  435. if not (TTypeInfo(P).kind=tkEnumeration) then
  436. raise EInvalidCast.CreateFmt(SErrTypeIsNotEnumerated,[TTypeInfo(P).Name]);
  437. Result := GetEnumName(TTypeInfoEnum(P), Integer(JSValue(AValue)));
  438. end;
  439. generic class function TRttiEnumerationType.GetValue<T>(const AValue: String): T;
  440. Var
  441. P : PTypeInfo;
  442. begin
  443. P:=TypeInfo(T);
  444. if not (TTypeInfo(P).kind=tkEnumeration) then
  445. raise EInvalidCast.CreateFmt(SErrTypeIsNotEnumerated,[TTypeInfo(P).Name]);
  446. Result := T(JSValue(GetEnumValue(TTypeInfoEnum(TypeInfo(T)), AValue)));
  447. end;
  448. constructor TRttiEnumerationType.Create(ATypeInfo: PTypeInfo);
  449. begin
  450. if not (TTypeInfo(ATypeInfo) is TTypeInfoEnum) then
  451. raise EInvalidCast.Create('');
  452. inherited Create(ATypeInfo);
  453. end;
  454. { TValue }
  455. function TValue.GetTypeKind: TTypeKind;
  456. begin
  457. if TypeInfo=nil then
  458. Result:=tkUnknown
  459. else
  460. Result:=FTypeInfo.Kind;
  461. end;
  462. generic function TValue.AsType<T>: T;
  463. begin
  464. Result := T(AsJSValue)
  465. end;
  466. generic class function TValue.From<T>(const Value: T): TValue;
  467. begin
  468. Result := Make(System.TypeInfo(T), Value);
  469. end;
  470. class function TValue.Make(TypeInfo: TTypeInfo; const Value: JSValue): TValue;
  471. begin
  472. Result.FData := Value;
  473. Result.FTypeInfo := TypeInfo;
  474. end;
  475. class function TValue.Make(const Value: TValue): TValue;
  476. begin
  477. Result := TValue.Make(Value.TypeInfo, Value.AsJSValue);
  478. end;
  479. class function TValue.FromJSValue(v: JSValue): TValue;
  480. var
  481. i: NativeInt;
  482. TypeOfValue: TTypeInfo;
  483. begin
  484. case jsTypeOf(v) of
  485. 'number':
  486. if JS.isInteger(v) then
  487. begin
  488. i:=NativeInt(v);
  489. if (i>=low(integer)) and (i<=high(integer)) then
  490. TypeOfValue:=system.TypeInfo(Integer)
  491. else
  492. TypeOfValue:=system.TypeInfo(NativeInt);
  493. end
  494. else
  495. TypeOfValue:=system.TypeInfo(Double);
  496. 'string': TypeOfValue:=system.TypeInfo(String);
  497. 'boolean': TypeOfValue:=system.TypeInfo(Boolean);
  498. 'object':
  499. begin
  500. if v=nil then
  501. TypeOfValue:=system.TypeInfo(Pointer)
  502. else if JS.isClass(v) and JS.isExt(v,TObject) then
  503. TypeOfValue:=system.TypeInfo(TClass(v))
  504. else if JS.isObject(v) and JS.isExt(v,TObject) then
  505. TypeOfValue:=system.TypeInfo(TObject(v))
  506. else
  507. TypeOfValue:=system.TypeInfo(Pointer);
  508. if (TypeOfValue=JS.Undefined) or (TypeOfValue=nil) then
  509. TypeOfValue:=system.TypeInfo(Pointer);
  510. end
  511. else
  512. TypeOfValue:=system.TypeInfo(JSValue);
  513. end;
  514. Result := Make(TypeOfValue, v);
  515. end;
  516. function TValue.IsObject: boolean;
  517. begin
  518. Result:=IsEmpty or (TypeInfo.Kind=tkClass);
  519. end;
  520. function TValue.AsObject: TObject;
  521. begin
  522. if IsObject or (IsClass and not js.isObject(FData)) then
  523. Result := TObject(FData)
  524. else
  525. raise EInvalidCast.Create(SErrInvalidTypecast);
  526. end;
  527. function TValue.IsObjectInstance: boolean;
  528. begin
  529. Result:=(TypeInfo<>nil) and (TypeInfo.Kind=tkClass);
  530. end;
  531. function TValue.IsArray: boolean;
  532. begin
  533. case Kind of
  534. tkDynArray: Exit(True);
  535. tkArray: Exit(Length(TTypeInfoStaticArray(FTypeInfo).Dims) = 1);
  536. else Result := False;
  537. end;
  538. end;
  539. function TValue.IsClass: boolean;
  540. var
  541. k: TTypeKind;
  542. begin
  543. k:=Kind;
  544. Result := (k = tkClassRef)
  545. or ((k in [tkClass,tkUnknown]) and not JS.IsObject(FData));
  546. end;
  547. function TValue.AsClass: TClass;
  548. begin
  549. if IsClass then
  550. Result := TClass(FData)
  551. else
  552. raise EInvalidCast.Create(SErrInvalidTypecast);
  553. end;
  554. function TValue.IsOrdinal: boolean;
  555. var
  556. k: TTypeKind;
  557. begin
  558. k:=Kind;
  559. Result := (k in [tkInteger, tkBool]) or
  560. ((k in [tkClass, tkClassRef, tkUnknown]) and not JS.isObject(FData));
  561. end;
  562. function TValue.AsOrdinal: NativeInt;
  563. begin
  564. if IsOrdinal then
  565. Result:=NativeInt(FData)
  566. else
  567. raise EInvalidCast.Create(SErrInvalidTypecast);
  568. end;
  569. function TValue.AsBoolean: boolean;
  570. begin
  571. if (Kind = tkBool) then
  572. Result:=boolean(FData)
  573. else
  574. raise EInvalidCast.Create(SErrInvalidTypecast);
  575. end;
  576. function TValue.AsInteger: Integer;
  577. begin
  578. if JS.isInteger(FData) then
  579. Result:=NativeInt(FData)
  580. else
  581. raise EInvalidCast.Create(SErrInvalidTypecast);
  582. end;
  583. function TValue.AsNativeInt: NativeInt;
  584. begin
  585. if JS.isInteger(FData) then
  586. Result:=NativeInt(FData)
  587. else
  588. raise EInvalidCast.Create(SErrInvalidTypecast);
  589. end;
  590. function TValue.AsInterface: IInterface;
  591. var
  592. k: TTypeKind;
  593. begin
  594. k:=Kind;
  595. if k = tkInterface then
  596. Result := IInterface(FData)// ToDo
  597. else if (k in [tkClass, tkClassRef, tkUnknown]) and not JS.isObject(FData) then
  598. Result := Nil
  599. else
  600. raise EInvalidCast.Create(SErrInvalidTypecast);
  601. end;
  602. function TValue.AsString: string;
  603. begin
  604. if js.isString(FData) then
  605. Result:=String(FData)
  606. else
  607. raise EInvalidCast.Create(SErrInvalidTypecast);
  608. end;
  609. function TValue.AsUnicodeString: UnicodeString;
  610. begin
  611. Result:=AsString;
  612. end;
  613. function TValue.AsExtended: Extended;
  614. begin
  615. if js.isNumber(FData) then
  616. Result:=Double(FData)
  617. else
  618. raise EInvalidCast.Create(SErrInvalidTypecast);
  619. end;
  620. function TValue.ToString: String;
  621. begin
  622. case Kind of
  623. tkString: Result := AsString;
  624. tkInteger: Result := IntToStr(AsNativeInt);
  625. tkBool: Result := BoolToStr(AsBoolean, True);
  626. else
  627. Result := '';
  628. end;
  629. end;
  630. function TValue.GetArrayLength: SizeInt;
  631. begin
  632. if IsArray then
  633. Exit(Length(TJSValueDynArray(FData)));
  634. raise EInvalidCast.Create(SErrInvalidTypecast);
  635. end;
  636. function TValue.GetArrayElement(aIndex: SizeInt): TValue;
  637. begin
  638. if IsArray then
  639. begin
  640. case Kind of
  641. tkArray: Result.FTypeInfo:=TTypeInfoStaticArray(FTypeInfo).ElType;
  642. tkDynArray: Result.FTypeInfo:=TTypeInfoDynArray(FTypeInfo).ElType;
  643. end;
  644. Result.FData:=TJSValueDynArray(FData)[aIndex];
  645. end
  646. else
  647. raise EInvalidCast.Create(SErrInvalidTypecast);
  648. end;
  649. procedure TValue.SetArrayLength(const Size: SizeInt);
  650. var
  651. NewArray: TJSValueDynArray;
  652. begin
  653. NewArray := TJSValueDynArray(FData);
  654. SetLength(NewArray, Size);
  655. FData := NewArray;
  656. end;
  657. procedure TValue.SetArrayElement(aIndex: SizeInt; const AValue: TValue);
  658. begin
  659. if IsArray then
  660. TJSValueDynArray(FData)[aIndex] := AValue.AsJSValue
  661. else
  662. raise EInvalidCast.Create(SErrInvalidTypecast);
  663. end;
  664. function TValue.IsType(ATypeInfo: PTypeInfo): boolean;
  665. begin
  666. Result := ATypeInfo = TypeInfo;
  667. end;
  668. function TValue.GetIsEmpty: boolean;
  669. begin
  670. if (TypeInfo=nil) or (FData=Undefined) or (FData=nil) then
  671. exit(true);
  672. case TypeInfo.Kind of
  673. tkDynArray:
  674. Result:=TJSArray(FData).Length=0;
  675. else
  676. Result:=false;
  677. end;
  678. end;
  679. function TValue.AsJSValue: JSValue;
  680. begin
  681. Result := FData;
  682. end;
  683. class function TValue.Empty: TValue;
  684. begin
  685. Result.FData := nil;
  686. Result.FTypeInfo := nil;
  687. end;
  688. { TRttiStructuredType }
  689. function TRttiStructuredType.GetMethods: TRttiMethodArray;
  690. var
  691. A, Start: Integer;
  692. BaseClass: TRttiStructuredType;
  693. Declared: TRttiMethodArray;
  694. begin
  695. BaseClass := Self;
  696. Result := nil;
  697. while Assigned(BaseClass) do
  698. begin
  699. Declared := BaseClass.GetDeclaredMethods;
  700. Start := Length(Result);
  701. SetLength(Result, Start + Length(Declared));
  702. for A := Low(Declared) to High(Declared) do
  703. Result[Start + A] := Declared[A];
  704. BaseClass := BaseClass.GetAncestor;
  705. end;
  706. end;
  707. function TRttiStructuredType.GetMethods(const aName: String): TRttiMethodArray;
  708. var
  709. Method: TRttiMethod;
  710. MethodCount: Integer;
  711. begin
  712. MethodCount := 0;
  713. for Method in GetMethods do
  714. if aName = Method.Name then
  715. Inc(MethodCount);
  716. SetLength(Result, MethodCount);
  717. for Method in GetMethods do
  718. if aName = Method.Name then
  719. begin
  720. Dec(MethodCount);
  721. Result[MethodCount] := Method;
  722. end;
  723. end;
  724. function TRttiStructuredType.GetProperties: TRttiPropertyArray;
  725. var
  726. A, Start: Integer;
  727. BaseClass: TRttiStructuredType;
  728. Declared: TRttiPropertyArray;
  729. begin
  730. BaseClass := Self;
  731. Result := nil;
  732. while Assigned(BaseClass) do
  733. begin
  734. Declared := BaseClass.GetDeclaredProperties;
  735. Start := Length(Result);
  736. SetLength(Result, Start + Length(Declared));
  737. for A := Low(Declared) to High(Declared) do
  738. Result[Start + A] := Declared[A];
  739. BaseClass := BaseClass.GetAncestor;
  740. end;
  741. end;
  742. function TRttiStructuredType.GetMethod(const aName: String): TRttiMethod;
  743. var
  744. Method: TRttiMethod;
  745. begin
  746. for Method in GetMethods do
  747. if aName = Method.Name then
  748. Exit(Method);
  749. end;
  750. function TRttiStructuredType.GetProperty(const AName: string): TRttiProperty;
  751. var
  752. Prop: TRttiProperty;
  753. begin
  754. for Prop in GetProperties do
  755. if Prop.Name = AName then
  756. Exit(Prop);
  757. end;
  758. function TRttiStructuredType.GetDeclaredProperties: TRttiPropertyArray;
  759. var
  760. A, PropCount: Integer;
  761. begin
  762. if not Assigned(FProperties) then
  763. begin
  764. PropCount := StructTypeInfo.PropCount;
  765. SetLength(FProperties, PropCount);
  766. for A := 0 to Pred(PropCount) do
  767. FProperties[A] := TRttiProperty.Create(Self, StructTypeInfo.GetProp(A));
  768. end;
  769. Result := FProperties;
  770. end;
  771. function TRttiStructuredType.GetAncestor: TRttiStructuredType;
  772. begin
  773. Result := nil;
  774. end;
  775. function TRttiStructuredType.GetStructTypeInfo: TTypeInfoStruct;
  776. begin
  777. Result:=TTypeInfoStruct(FTypeInfo);
  778. end;
  779. constructor TRttiStructuredType.Create(ATypeInfo: PTypeInfo);
  780. begin
  781. if not (TTypeInfo(ATypeInfo) is TTypeInfoStruct) then
  782. raise EInvalidCast.Create('');
  783. inherited Create(ATypeInfo);
  784. end;
  785. destructor TRttiStructuredType.Destroy;
  786. var
  787. Method: TRttiMethod;
  788. Prop: TRttiProperty;
  789. begin
  790. for Method in FMethods do
  791. Method.Free;
  792. for Prop in FProperties do
  793. Prop.Free;
  794. inherited Destroy;
  795. end;
  796. function TRttiStructuredType.GetDeclaredMethods: TRttiMethodArray;
  797. var
  798. A, MethodCount: Integer;
  799. begin
  800. if not Assigned(FMethods) then
  801. begin
  802. MethodCount := StructTypeInfo.MethodCount;
  803. SetLength(FMethods, MethodCount);
  804. for A := 0 to Pred(MethodCount) do
  805. FMethods[A] := TRttiMethod.Create(Self, StructTypeInfo.GetMethod(A));
  806. end;
  807. Result := FMethods;
  808. end;
  809. { TRttiInstanceType }
  810. function TRttiInstanceType.GetClassTypeInfo: TTypeInfoClass;
  811. begin
  812. Result:=TTypeInfoClass(FTypeInfo);
  813. end;
  814. function TRttiInstanceType.GetMetaClassType: TClass;
  815. begin
  816. Result:=ClassTypeInfo.ClassType;
  817. end;
  818. function TRttiInstanceType.GetAncestor: TRttiStructuredType;
  819. begin
  820. Result := GRttiContext.GetType(ClassTypeInfo.Ancestor) as TRttiStructuredType;
  821. end;
  822. constructor TRttiInstanceType.Create(ATypeInfo: PTypeInfo);
  823. begin
  824. if not (TTypeInfo(ATypeInfo) is TTypeInfoClass) then
  825. raise EInvalidCast.Create('');
  826. inherited Create(ATypeInfo);
  827. end;
  828. function TRttiInstanceType.GetDeclaredFields: TRttiFieldArray;
  829. var
  830. A, FieldCount: Integer;
  831. begin
  832. if not Assigned(FFields) then
  833. begin
  834. FieldCount := StructTypeInfo.FieldCount;
  835. SetLength(FFields, FieldCount);
  836. for A := 0 to Pred(FieldCount) do
  837. FFields[A] := TRttiField.Create(Self, StructTypeInfo.GetField(A));
  838. end;
  839. Result := FFields;
  840. end;
  841. function TRttiInstanceType.GetFields: TRttiFieldArray;
  842. var
  843. A, Start: Integer;
  844. BaseClass: TRttiStructuredType;
  845. Declared: TRttiFieldArray;
  846. begin
  847. BaseClass := Self;
  848. Result := nil;
  849. while Assigned(BaseClass) do
  850. begin
  851. Declared := BaseClass.GetDeclaredFields;
  852. Start := Length(Result);
  853. SetLength(Result, Start + Length(Declared));
  854. for A := Low(Declared) to High(Declared) do
  855. Result[Start + A] := Declared[A];
  856. BaseClass := BaseClass.GetAncestor;
  857. end;
  858. end;
  859. { TRttiInterfaceType }
  860. constructor TRttiInterfaceType.Create(ATypeInfo: PTypeInfo);
  861. begin
  862. if not (TTypeInfo(ATypeInfo) is TTypeInfoInterface) then
  863. raise EInvalidCast.Create('');
  864. inherited Create(ATypeInfo);
  865. end;
  866. function TRttiInterfaceType.GetGUID: TGUID;
  867. var
  868. Guid: String;
  869. begin
  870. Guid := String(InterfaceTypeInfo.InterfaceType['$guid']);
  871. TryStringToGUID(Guid, Result);
  872. end;
  873. function TRttiInterfaceType.GetInterfaceTypeInfo: TTypeInfoInterface;
  874. begin
  875. Result := TTypeInfoInterface(FTypeInfo);
  876. end;
  877. function TRttiInterfaceType.GetAncestor: TRttiStructuredType;
  878. begin
  879. Result := GRttiContext.GetType(InterfaceTypeInfo.Ancestor) as TRttiStructuredType;
  880. end;
  881. { TRttiRecordType }
  882. function TRttiRecordType.GetRecordTypeInfo: TTypeInfoRecord;
  883. begin
  884. Result := TTypeInfoRecord(FTypeInfo);
  885. end;
  886. function TRttiRecordType.GetIsRecord: Boolean;
  887. begin
  888. Result := True;
  889. end;
  890. constructor TRttiRecordType.Create(ATypeInfo: PTypeInfo);
  891. begin
  892. if not (TTypeInfo(ATypeInfo) is TTypeInfoClass) then
  893. raise EInvalidCast.Create('');
  894. inherited Create(ATypeInfo);
  895. end;
  896. { TRttiClassRefType }
  897. constructor TRttiClassRefType.Create(ATypeInfo: PTypeInfo);
  898. begin
  899. if not (TTypeInfo(ATypeInfo) is TTypeInfoClassRef) then
  900. raise EInvalidCast.Create('');
  901. inherited Create(ATypeInfo);
  902. end;
  903. function TRttiClassRefType.GetClassRefTypeInfo: TTypeInfoClassRef;
  904. begin
  905. Result := TTypeInfoClassRef(FTypeInfo);
  906. end;
  907. function TRttiClassRefType.GetInstanceType: TRttiInstanceType;
  908. begin
  909. Result := GRttiContext.GetType(ClassRefTypeInfo.InstanceType) as TRttiInstanceType;
  910. end;
  911. function TRttiClassRefType.GetMetaclassType: TClass;
  912. begin
  913. Result := InstanceType.MetaClassType;
  914. end;
  915. { TRTTIContext }
  916. class constructor TRTTIContext.Init;
  917. begin
  918. GRttiContext:=TRTTIContext.Create;
  919. end;
  920. class function TRTTIContext.Create: TRTTIContext;
  921. begin
  922. Result.FPool:=TJSObject.new;
  923. end;
  924. procedure TRTTIContext.Free;
  925. var
  926. key: string;
  927. o: TRttiType;
  928. begin
  929. for key in FPool do
  930. if FPool.hasOwnProperty(key) then begin
  931. o:=TRTTIType(FPool[key]);
  932. o.Free;
  933. end;
  934. FPool:=nil;
  935. end;
  936. function TRTTIContext.GetType(aTypeInfo: PTypeInfo): TRTTIType;
  937. var
  938. RttiTypeClass: array[TTypeKind] of TRttiTypeClass = (
  939. nil, // tkUnknown
  940. TRttiOrdinalType, // tkInteger
  941. TRttiOrdinalType, // tkChar
  942. TRttiType, // tkString
  943. TRttiEnumerationType, // tkEnumeration
  944. TRttiType, // tkSet
  945. TRttiOrdinalType, // tkDouble
  946. TRttiEnumerationType, // tkBool
  947. TRttiType, // tkProcVar
  948. nil, // tkMethod
  949. TRttiType, // tkArray
  950. TRttiDynamicArrayType, // tkDynArray
  951. TRttiRecordType, // tkRecord
  952. TRttiInstanceType, // tkClass
  953. TRttiClassRefType, // tkClassRef
  954. TRttiType, // tkPointer
  955. TRttiType, // tkJSValue
  956. TRttiType, // tkRefToProcVar
  957. TRttiInterfaceType, // tkInterface
  958. TRttiType, // tkHelper
  959. TRttiInstanceType // tkExtClass
  960. );
  961. t: TTypeinfo absolute aTypeInfo;
  962. Name: String;
  963. begin
  964. if aTypeInfo=nil then exit(nil);
  965. Name:=t.Name;
  966. if isModule(t.Module) then
  967. Name:=t.Module.Name+'.'+Name;
  968. if GRttiContext.FPool.hasOwnProperty(Name) then
  969. Result:=TRttiType(GRttiContext.FPool[Name])
  970. else
  971. begin
  972. Result := RttiTypeClass[T.Kind].Create(aTypeInfo);
  973. GRttiContext.FPool[Name]:=Result;
  974. end;
  975. end;
  976. function TRTTIContext.GetType(aClass: TClass): TRTTIType;
  977. begin
  978. if aClass=nil then exit(nil);
  979. Result:=GetType(TypeInfo(aClass));
  980. end;
  981. function TRTTIContext.FindType(const AQualifiedName: String): TRttiType;
  982. var
  983. ModuleName, TypeName: String;
  984. Module: TTypeInfoModule;
  985. TypeFound: PTypeInfo;
  986. begin
  987. Result := nil;
  988. for ModuleName in TJSObject.Keys(pas) do
  989. if AQualifiedName.StartsWith(ModuleName + '.') then
  990. begin
  991. Module := TTypeInfoModule(pas[ModuleName]);
  992. TypeName := Copy(AQualifiedName, Length(ModuleName) + 2, Length(AQualifiedName));
  993. if Module.RTTI.HasOwnProperty(TypeName) then
  994. begin
  995. TypeFound := PTypeInfo(Module.RTTI[TypeName]);
  996. Exit(GetType(TypeFound));
  997. end;
  998. end;
  999. end;
  1000. { TRttiObject }
  1001. function TRttiObject.GetAttributes: TCustomAttributeArray;
  1002. begin
  1003. Result:=nil;
  1004. end;
  1005. { TRttiNamedObject }
  1006. function TRttiNamedObject.GetName: string;
  1007. begin
  1008. Result:='';
  1009. end;
  1010. { TRttiMember }
  1011. function TRttiMember.GetName: string;
  1012. begin
  1013. Result:=FTypeInfo.Name;
  1014. end;
  1015. function TRttiMember.GetVisibility: TMemberVisibility;
  1016. begin
  1017. Result:=mvPublished;
  1018. end;
  1019. constructor TRttiMember.Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  1020. begin
  1021. if not (ATypeInfo is TTypeMember) then
  1022. raise EInvalidCast.Create('');
  1023. inherited Create();
  1024. FParent := AParent;
  1025. FTypeInfo:=ATypeInfo;
  1026. end;
  1027. function TRttiMember.GetAttributes: TCustomAttributeArray;
  1028. begin
  1029. Result:=inherited GetAttributes;
  1030. end;
  1031. function TRttiMember.GetMemberTypeInfo: TTypeMember;
  1032. begin
  1033. Result := TTypeMember(FTypeInfo);
  1034. end;
  1035. { TRttiField }
  1036. constructor TRttiField.Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  1037. begin
  1038. if not (ATypeInfo is TTypeMemberField) then
  1039. raise EInvalidCast.Create('');
  1040. inherited;
  1041. end;
  1042. function TRttiField.GetFieldType: TRttiType;
  1043. begin
  1044. Result := GRttiContext.GetType(FTypeInfo);
  1045. end;
  1046. function TRttiField.GetFieldTypeInfo: TTypeMemberField;
  1047. begin
  1048. Result := TTypeMemberField(FTypeInfo);
  1049. end;
  1050. function TRttiField.GetValue(Instance: JSValue): TValue;
  1051. var
  1052. JSInstance: TJSObject absolute Instance;
  1053. begin
  1054. Result := TValue.FromJSValue(JSInstance[Name]);
  1055. end;
  1056. procedure TRttiField.SetValue(Instance: JSValue; const AValue: TValue);
  1057. var
  1058. JSInstance: TJSObject absolute Instance;
  1059. begin
  1060. JSInstance[Name] := AValue.AsJSValue;
  1061. end;
  1062. { TRttiParameter }
  1063. function TRttiParameter.GetName: String;
  1064. begin
  1065. Result := FName;
  1066. end;
  1067. { TRttiMethod }
  1068. function TRttiMethod.GetMethodTypeInfo: TTypeMemberMethod;
  1069. begin
  1070. Result := TTypeMemberMethod(FTypeInfo);
  1071. end;
  1072. function TRttiMethod.GetIsClassMethod: Boolean;
  1073. begin
  1074. Result:=MethodTypeInfo.MethodKind in [mkClassFunction,mkClassProcedure];
  1075. end;
  1076. function TRttiMethod.GetIsConstructor: Boolean;
  1077. begin
  1078. Result:=MethodTypeInfo.MethodKind=mkConstructor;
  1079. end;
  1080. function TRttiMethod.GetIsDestructor: Boolean;
  1081. begin
  1082. Result:=MethodTypeInfo.MethodKind=mkDestructor;
  1083. end;
  1084. function TRttiMethod.GetIsExternal: Boolean;
  1085. begin
  1086. Result := pfExternal in GetProcedureFlags;
  1087. end;
  1088. function TRttiMethod.GetIsStatic: Boolean;
  1089. begin
  1090. Result := pfStatic in GetProcedureFlags;
  1091. end;
  1092. function TRttiMethod.GetIsVarArgs: Boolean;
  1093. begin
  1094. Result := pfVarargs in GetProcedureFlags;
  1095. end;
  1096. function TRttiMethod.GetIsAsyncCall: Boolean;
  1097. begin
  1098. Result := pfAsync in GetProcedureFlags;
  1099. end;
  1100. function TRttiMethod.GetIsSafeCall: Boolean;
  1101. begin
  1102. Result := pfSafeCall in GetProcedureFlags;
  1103. end;
  1104. function TRttiMethod.GetMethodKind: TMethodKind;
  1105. begin
  1106. Result:=MethodTypeInfo.MethodKind;;
  1107. end;
  1108. function TRttiMethod.GetProcedureFlags: TProcedureFlags;
  1109. const
  1110. PROCEDURE_FLAGS: array of NativeInt = (1, 2, 4, 8, 16);
  1111. var
  1112. Flag, ProcedureFlags: NativeInt;
  1113. begin
  1114. ProcedureFlags := MethodTypeInfo.ProcSig.Flags;
  1115. Result := [];
  1116. for Flag := Low(PROCEDURE_FLAGS) to High(PROCEDURE_FLAGS) do
  1117. if PROCEDURE_FLAGS[Flag] and ProcedureFlags > 0 then
  1118. Result := Result + [TProcedureFlag(Flag)];
  1119. end;
  1120. function TRttiMethod.GetReturnType: TRttiType;
  1121. begin
  1122. Result := GRttiContext.GetType(MethodTypeInfo.ProcSig.ResultType);
  1123. end;
  1124. procedure TRttiMethod.LoadParameters;
  1125. const
  1126. FLAGS_CONVERSION: array[TParamFlag] of Integer = (1, 2, 4, 8, 16, 32);
  1127. var
  1128. A, Flag: Integer;
  1129. Param: TProcedureParam;
  1130. RttiParam: TRttiParameter;
  1131. begin
  1132. SetLength(FParameters, Length(MethodTypeInfo.ProcSig.Params));
  1133. for A := Low(FParameters) to High(FParameters) do
  1134. begin
  1135. Param := MethodTypeInfo.ProcSig.Params[A];
  1136. RttiParam := TRttiParameter.Create;
  1137. RttiParam.FName := Param.Name;
  1138. RttiParam.FParamType := GRttiContext.GetType(Param.TypeInfo);
  1139. for Flag in FLAGS_CONVERSION do
  1140. if Flag and Param.Flags > 0 then
  1141. RttiParam.FFlags := RttiParam.FFlags + [TParamFlag(A)];
  1142. FParameters[A] := RttiParam;
  1143. end;
  1144. end;
  1145. function TRttiMethod.GetParameters: TRttiParameterArray;
  1146. begin
  1147. if not Assigned(FParameters) then
  1148. LoadParameters;
  1149. Result := FParameters;
  1150. end;
  1151. { TRttiProperty }
  1152. constructor TRttiProperty.Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  1153. begin
  1154. if not (ATypeInfo is TTypeMemberProperty) then
  1155. raise EInvalidCast.Create('');
  1156. inherited;
  1157. end;
  1158. function TRttiProperty.GetPropertyTypeInfo: TTypeMemberProperty;
  1159. begin
  1160. Result := TTypeMemberProperty(FTypeInfo);
  1161. end;
  1162. function TRttiProperty.GetValue(Instance: JSValue): TValue;
  1163. var
  1164. JSObject: TJSObject absolute Instance;
  1165. begin
  1166. Result := TValue.Make(PropertyType.Handle, GetJSValueProp(JSObject, PropertyTypeInfo));
  1167. end;
  1168. procedure TRttiProperty.SetValue(Instance: JSValue; const AValue: TValue);
  1169. var
  1170. JSObject: TJSObject absolute Instance;
  1171. begin
  1172. SetJSValueProp(JSObject, PropertyTypeInfo, AValue.AsJSValue);
  1173. end;
  1174. procedure TRttiProperty.SetValue(Instance: JSValue; const AValue: JSValue);
  1175. var
  1176. JSObject: TJSObject absolute Instance;
  1177. begin
  1178. SetJSValueProp(JSObject, PropertyTypeInfo, AValue);
  1179. end;
  1180. procedure TRttiProperty.SetValue(Instance: TObject; const AValue: TValue);
  1181. begin
  1182. SetValue(JSValue(Instance), AValue);
  1183. end;
  1184. function TRttiProperty.GetPropertyType: TRttiType;
  1185. begin
  1186. Result := GRttiContext.GetType(PropertyTypeInfo.TypeInfo);
  1187. end;
  1188. function TRttiProperty.GetIsWritable: boolean;
  1189. begin
  1190. Result := PropertyTypeInfo.Setter<>'';
  1191. end;
  1192. function TRttiProperty.GetIsReadable: boolean;
  1193. begin
  1194. Result := PropertyTypeInfo.Getter<>'';
  1195. end;
  1196. function TRttiProperty.GetVisibility: TMemberVisibility;
  1197. begin
  1198. // At this moment only published rtti-property-info is supported by pas2js
  1199. Result := mvPublished;
  1200. end;
  1201. { TRttiType }
  1202. function TRttiType.GetName: string;
  1203. begin
  1204. Result:=FTypeInfo.Name;
  1205. end;
  1206. function TRttiType.GetIsInstance: boolean;
  1207. begin
  1208. Result:=Self is TRttiInstanceType;
  1209. end;
  1210. function TRttiType.GetIsOrdinal: boolean;
  1211. begin
  1212. Result:=false;
  1213. end;
  1214. function TRttiType.GetIsRecord: boolean;
  1215. begin
  1216. Result:=false;
  1217. end;
  1218. function TRttiType.GetIsSet: boolean;
  1219. begin
  1220. Result:=false;
  1221. end;
  1222. function TRttiType.GetTypeKind: TTypeKind;
  1223. begin
  1224. Result:=FTypeInfo.Kind;
  1225. end;
  1226. function TRttiType.GetAsInstance: TRttiInstanceType;
  1227. begin
  1228. Result := Self as TRttiInstanceType;
  1229. end;
  1230. constructor TRttiType.Create(ATypeInfo: PTypeInfo);
  1231. begin
  1232. inherited Create();
  1233. FTypeInfo:=TTypeInfo(ATypeInfo);
  1234. end;
  1235. destructor TRttiType.Destroy;
  1236. var
  1237. o: TCustomAttribute;
  1238. begin
  1239. for o in FAttributes do
  1240. o.Free;
  1241. FAttributes:=nil;
  1242. inherited Destroy;
  1243. end;
  1244. function TRttiType.GetAttributes: TCustomAttributeArray;
  1245. begin
  1246. FAttributes:=GetRTTIAttributes(FTypeInfo.Attributes);
  1247. Result:=FAttributes;
  1248. end;
  1249. function TRttiType.GetDeclaredProperties: TRttiPropertyArray;
  1250. begin
  1251. Result:=nil;
  1252. end;
  1253. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  1254. begin
  1255. Result:=nil;
  1256. if AName='' then ;
  1257. end;
  1258. function TRttiType.GetMethods: TRttiMethodArray;
  1259. begin
  1260. Result:=nil;
  1261. end;
  1262. function TRttiType.GetMethods(const aName: String): TRttiMethodArray;
  1263. begin
  1264. Result:=nil;
  1265. end;
  1266. function TRttiType.GetMethod(const aName: String): TRttiMethod;
  1267. begin
  1268. Result:=nil;
  1269. if aName='' then ;
  1270. end;
  1271. function TRttiType.GetDeclaredMethods: TRttiMethodArray;
  1272. begin
  1273. Result:=nil;
  1274. end;
  1275. function TRttiType.GetDeclaredFields: TRttiFieldArray;
  1276. begin
  1277. Result:=nil;
  1278. end;
  1279. function TRttiType.GetField(const AName: string): TRttiField;
  1280. var
  1281. AField: TRttiField;
  1282. begin
  1283. Result:=nil;
  1284. for AField in GetFields do
  1285. if AField.Name = AName then
  1286. Exit(AField);
  1287. end;
  1288. function TRttiType.GetFields: TRttiFieldArray;
  1289. begin
  1290. Result := nil;
  1291. end;
  1292. { TVirtualInterface }
  1293. constructor TVirtualInterface.Create(InterfaceTypeInfo: Pointer); assembler;
  1294. asm
  1295. var IntfType = InterfaceTypeInfo.interface;
  1296. if (IntfType.$kind !== 'com') rtl.raiseE('EInvalidCast');
  1297. var guid = IntfType.$guid;
  1298. var i = Object.create(IntfType); // needed by IntfVar is IntfType
  1299. i.$o = this;
  1300. // copy IInterface methods: _AddRef, _Release, QueryInterface
  1301. var iinterfaceguid = '{00000000-0000-0000-C000-000000000046}';
  1302. var map = this.$intfmaps[iinterfaceguid];
  1303. for (var key in map){
  1304. var v = map[key];
  1305. if (typeof(v)!=='function') continue;
  1306. i[key] = map[key];
  1307. }
  1308. // all other methods call OnInvoke
  1309. do {
  1310. var names = IntfType.$names;
  1311. if (!names) break;
  1312. for (var j=0; j<names.length; j++){
  1313. let fnname = names[j];
  1314. if (i[fnname]) continue;
  1315. i[fnname] = function(){ return this.$o.FOnInvoke(fnname,arguments); };
  1316. }
  1317. IntfType = Object.getPrototypeOf(IntfType);
  1318. } while(IntfType!=null);
  1319. // create a new list of interface map, supporting IInterface and IntfType
  1320. this.$intfmaps = {};
  1321. this.$intfmaps[iinterfaceguid] = map;
  1322. this.$intfmaps[guid] = {};
  1323. // store the implementation of IntfType (used by the as-operator)
  1324. this.$interfaces = {};
  1325. this.$interfaces[guid] = i;
  1326. end;
  1327. constructor TVirtualInterface.Create(InterfaceTypeInfo: Pointer;
  1328. const InvokeEvent: TVirtualInterfaceInvokeEvent);
  1329. begin
  1330. Create(InterfaceTypeInfo);
  1331. OnInvoke:=InvokeEvent;
  1332. end;
  1333. function TVirtualInterface.QueryInterface(const iid: TGuid; out obj): Integer;
  1334. begin
  1335. Result := inherited QueryInterface(iid, obj);
  1336. end;
  1337. function Invoke(ACodeAddress: Pointer; const AArgs: TJSValueDynArray;
  1338. ACallConv: TCallConv; AResultType: PTypeInfo; AIsStatic: Boolean;
  1339. AIsConstructor: Boolean): TValue;
  1340. begin
  1341. if ACallConv=ccReg then ;
  1342. if AIsStatic then ;
  1343. if AIsConstructor then
  1344. raise EInvoke.Create('not supported');
  1345. if isFunction(ACodeAddress) then
  1346. begin
  1347. Result.FData := TJSFunction(ACodeAddress).apply(nil, AArgs);
  1348. if AResultType<>nil then
  1349. Result.FTypeInfo:=AResultType
  1350. else
  1351. Result.FTypeInfo:=TypeInfo(JSValue);
  1352. end
  1353. else
  1354. raise EInvoke.Create(SErrInvokeInvalidCodeAddr);
  1355. end;
  1356. end.