rtti.pas 33 KB

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