rtti.pas 45 KB

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