2
0

rtti.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336
  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.FData := nil;
  607. Result.FTypeInfo := nil;
  608. end;
  609. { TRttiStructuredType }
  610. function TRttiStructuredType.GetMethods: TRttiMethodArray;
  611. var
  612. A, Start: Integer;
  613. BaseClass: TRttiStructuredType;
  614. Declared: TRttiMethodArray;
  615. begin
  616. BaseClass := Self;
  617. Result := nil;
  618. while Assigned(BaseClass) do
  619. begin
  620. Declared := BaseClass.GetDeclaredMethods;
  621. Start := Length(Result);
  622. SetLength(Result, Start + Length(Declared));
  623. for A := Low(Declared) to High(Declared) do
  624. Result[Start + A] := Declared[A];
  625. BaseClass := BaseClass.GetAncestor;
  626. end;
  627. end;
  628. function TRttiStructuredType.GetMethods(const aName: String): TRttiMethodArray;
  629. var
  630. Method: TRttiMethod;
  631. MethodCount: Integer;
  632. begin
  633. MethodCount := 0;
  634. for Method in GetMethods do
  635. if aName = Method.Name then
  636. Inc(MethodCount);
  637. SetLength(Result, MethodCount);
  638. for Method in GetMethods do
  639. if aName = Method.Name then
  640. begin
  641. Dec(MethodCount);
  642. Result[MethodCount] := Method;
  643. end;
  644. end;
  645. function TRttiStructuredType.GetProperties: TRttiPropertyArray;
  646. var
  647. A, Start: Integer;
  648. BaseClass: TRttiStructuredType;
  649. Declared: TRttiPropertyArray;
  650. begin
  651. BaseClass := Self;
  652. Result := nil;
  653. while Assigned(BaseClass) do
  654. begin
  655. Declared := BaseClass.GetDeclaredProperties;
  656. Start := Length(Result);
  657. SetLength(Result, Start + Length(Declared));
  658. for A := Low(Declared) to High(Declared) do
  659. Result[Start + A] := Declared[A];
  660. BaseClass := BaseClass.GetAncestor;
  661. end;
  662. end;
  663. function TRttiStructuredType.GetMethod(const aName: String): TRttiMethod;
  664. var
  665. Method: TRttiMethod;
  666. begin
  667. for Method in GetMethods do
  668. if aName = Method.Name then
  669. Exit(Method);
  670. end;
  671. function TRttiStructuredType.GetProperty(const AName: string): TRttiProperty;
  672. var
  673. Prop: TRttiProperty;
  674. begin
  675. for Prop in GetProperties do
  676. if Prop.Name = AName then
  677. Exit(Prop);
  678. end;
  679. function TRttiStructuredType.GetDeclaredProperties: TRttiPropertyArray;
  680. var
  681. A, PropCount: Integer;
  682. begin
  683. if not Assigned(FProperties) then
  684. begin
  685. PropCount := StructTypeInfo.PropCount;
  686. SetLength(FProperties, PropCount);
  687. for A := 0 to Pred(PropCount) do
  688. FProperties[A] := TRttiProperty.Create(Self, StructTypeInfo.GetProp(A));
  689. end;
  690. Result := FProperties;
  691. end;
  692. function TRttiStructuredType.GetStructTypeInfo: TTypeInfoStruct;
  693. begin
  694. Result:=TTypeInfoStruct(FTypeInfo);
  695. end;
  696. constructor TRttiStructuredType.Create(ATypeInfo: PTypeInfo);
  697. begin
  698. if not (TTypeInfo(ATypeInfo) is TTypeInfoStruct) then
  699. raise EInvalidCast.Create('');
  700. inherited Create(ATypeInfo);
  701. end;
  702. destructor TRttiStructuredType.Destroy;
  703. var
  704. Method: TRttiMethod;
  705. Prop: TRttiProperty;
  706. begin
  707. for Method in FMethods do
  708. Method.Free;
  709. for Prop in FProperties do
  710. Prop.Free;
  711. inherited Destroy;
  712. end;
  713. function TRttiStructuredType.GetDeclaredMethods: TRttiMethodArray;
  714. var
  715. A, MethodCount: Integer;
  716. BaseClass: TRttiStructuredType;
  717. begin
  718. if not Assigned(FMethods) then
  719. begin
  720. MethodCount := StructTypeInfo.MethodCount;
  721. SetLength(FMethods, MethodCount);
  722. for A := 0 to Pred(MethodCount) do
  723. FMethods[A] := TRttiMethod.Create(Self, StructTypeInfo.GetMethod(A));
  724. end;
  725. Result := FMethods;
  726. end;
  727. { TRttiInstanceType }
  728. function TRttiInstanceType.GetClassTypeInfo: TTypeInfoClass;
  729. begin
  730. Result:=TTypeInfoClass(FTypeInfo);
  731. end;
  732. function TRttiInstanceType.GetMetaClassType: TClass;
  733. begin
  734. Result:=ClassTypeInfo.ClassType;
  735. end;
  736. function TRttiInstanceType.GetAncestor: TRttiStructuredType;
  737. begin
  738. Result := GRttiContext.GetType(ClassTypeInfo.Ancestor) as TRttiStructuredType;
  739. end;
  740. constructor TRttiInstanceType.Create(ATypeInfo: PTypeInfo);
  741. begin
  742. if not (TTypeInfo(ATypeInfo) is TTypeInfoClass) then
  743. raise EInvalidCast.Create('');
  744. inherited Create(ATypeInfo);
  745. end;
  746. function TRttiInstanceType.GetIsInstance: boolean;
  747. begin
  748. Result:=True;
  749. end;
  750. { TRttiInterfaceType }
  751. constructor TRttiInterfaceType.Create(ATypeInfo: PTypeInfo);
  752. begin
  753. if not (TTypeInfo(ATypeInfo) is TTypeInfoInterface) then
  754. raise EInvalidCast.Create('');
  755. inherited Create(ATypeInfo);
  756. end;
  757. function TRttiInterfaceType.GetGUID: TGUID;
  758. var
  759. Guid: String;
  760. begin
  761. Guid := String(InterfaceTypeInfo.InterfaceType['$guid']);
  762. TryStringToGUID(Guid, Result);
  763. end;
  764. function TRttiInterfaceType.GetInterfaceTypeInfo: TTypeInfoInterface;
  765. begin
  766. Result := TTypeInfoInterface(FTypeInfo);
  767. end;
  768. function TRttiInterfaceType.GetAncestor: TRttiStructuredType;
  769. begin
  770. Result := GRttiContext.GetType(InterfaceTypeInfo.Ancestor) as TRttiStructuredType;
  771. end;
  772. { TRTTIContext }
  773. class constructor TRTTIContext.Init;
  774. begin
  775. GRttiContext:=TRTTIContext.Create;
  776. end;
  777. class function TRTTIContext.Create: TRTTIContext;
  778. begin
  779. Result.FPool:=TJSObject.new;
  780. end;
  781. procedure TRTTIContext.Free;
  782. var
  783. key: string;
  784. o: TRttiType;
  785. begin
  786. for key in FPool do
  787. if FPool.hasOwnProperty(key) then begin
  788. o:=TRTTIType(FPool[key]);
  789. o.Free;
  790. end;
  791. FPool:=nil;
  792. end;
  793. function TRTTIContext.GetType(aTypeInfo: PTypeInfo): TRTTIType;
  794. var
  795. RttiTypeClass: array[TTypeKind] of TRttiTypeClass = (
  796. nil, // tkUnknown
  797. TRttiOrdinalType, // tkInteger
  798. TRttiOrdinalType, // tkChar
  799. TRttiType, // tkString
  800. TRttiEnumerationType, // tkEnumeration
  801. TRttiType, // tkSet
  802. TRttiOrdinalType, // tkDouble
  803. TRttiEnumerationType, // tkBool
  804. TRttiType, // tkProcVar
  805. nil, // tkMethod
  806. TRttiType, // tkArray
  807. TRttiDynamicArrayType, // tkDynArray
  808. TRttiType, // tkRecord
  809. TRttiInstanceType, // tkClass
  810. TRttiType, // tkClassRef
  811. TRttiType, // tkPointer
  812. TRttiType, // tkJSValue
  813. TRttiType, // tkRefToProcVar
  814. TRttiInterfaceType, // tkInterface
  815. TRttiType, // tkHelper
  816. TRttiInstanceType // tkExtClass
  817. );
  818. t: TTypeinfo absolute aTypeInfo;
  819. Name: String;
  820. begin
  821. if aTypeInfo=nil then exit(nil);
  822. Name:=t.Name;
  823. if isModule(t.Module) then
  824. Name:=t.Module.Name+'.'+Name;
  825. if FPool.hasOwnProperty(Name) then
  826. Result:=TRttiType(FPool[Name])
  827. else
  828. begin
  829. Result := RttiTypeClass[T.Kind].Create(aTypeInfo);
  830. FPool[Name]:=Result;
  831. end;
  832. end;
  833. function TRTTIContext.GetType(aClass: TClass): TRTTIType;
  834. begin
  835. if aClass=nil then exit(nil);
  836. Result:=GetType(TypeInfo(aClass));
  837. end;
  838. { TRttiObject }
  839. function TRttiObject.GetAttributes: TCustomAttributeArray;
  840. begin
  841. Result:=nil;
  842. end;
  843. { TRttiNamedObject }
  844. function TRttiNamedObject.GetName: string;
  845. begin
  846. Result:='';
  847. end;
  848. { TRttiMember }
  849. function TRttiMember.GetName: string;
  850. begin
  851. Result:=FTypeInfo.Name;
  852. end;
  853. function TRttiMember.GetVisibility: TMemberVisibility;
  854. begin
  855. Result:=mvPublished;
  856. end;
  857. constructor TRttiMember.Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  858. begin
  859. if not (ATypeInfo is TTypeMember) then
  860. raise EInvalidCast.Create('');
  861. inherited Create();
  862. FParent := AParent;
  863. FTypeInfo:=ATypeInfo;
  864. end;
  865. function TRttiMember.GetAttributes: TCustomAttributeArray;
  866. begin
  867. Result:=inherited GetAttributes;
  868. end;
  869. function TRttiMember.GetMemberTypeInfo: TTypeMember;
  870. begin
  871. Result := TTypeMember(FTypeInfo);
  872. end;
  873. { TRttiField }
  874. function TRttiField.GetFieldType: TRttiType;
  875. begin
  876. Result := GRttiContext.GetType(FTypeInfo);
  877. end;
  878. { TRttiMethod }
  879. function TRttiMethod.GetMethodTypeInfo: TTypeMemberMethod;
  880. begin
  881. Result := TTypeMemberMethod(FTypeInfo);
  882. end;
  883. function TRttiMethod.GetIsClassMethod: boolean;
  884. begin
  885. Result:=MethodTypeInfo.MethodKind in [mkClassFunction,mkClassProcedure];
  886. end;
  887. function TRttiMethod.GetIsConstructor: boolean;
  888. begin
  889. Result:=MethodTypeInfo.MethodKind=mkConstructor;
  890. end;
  891. function TRttiMethod.GetIsDestructor: boolean;
  892. begin
  893. Result:=MethodTypeInfo.MethodKind=mkDestructor;
  894. end;
  895. function TRttiMethod.GetIsExternal: boolean;
  896. begin
  897. Result:=(MethodTypeInfo.ProcSig.Flags and 4)>0; // pfExternal
  898. end;
  899. function TRttiMethod.GetIsStatic: boolean;
  900. begin
  901. Result:=(MethodTypeInfo.ProcSig.Flags and 1)>0; // pfStatic
  902. end;
  903. function TRttiMethod.GetIsVarArgs: boolean;
  904. begin
  905. Result:=(MethodTypeInfo.ProcSig.Flags and 2)>0; // pfVarargs
  906. end;
  907. function TRttiMethod.GetMethodKind: TMethodKind;
  908. begin
  909. Result:=MethodTypeInfo.MethodKind;;
  910. end;
  911. function TRttiMethod.GetReturnType: TRttiType;
  912. begin
  913. Result := GRttiContext.GetType(MethodTypeInfo.ProcSig.ResultType);
  914. end;
  915. { TRttiProperty }
  916. constructor TRttiProperty.Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  917. begin
  918. if not (ATypeInfo is TTypeMemberProperty) then
  919. raise EInvalidCast.Create('');
  920. inherited;
  921. end;
  922. function TRttiProperty.GetPropertyTypeInfo: TTypeMemberProperty;
  923. begin
  924. Result := TTypeMemberProperty(FTypeInfo);
  925. end;
  926. function TRttiProperty.GetValue(Instance: TObject): TValue;
  927. begin
  928. Result := TValue.FromJSValue(GetJSValueProp(Instance, PropertyTypeInfo));
  929. end;
  930. procedure TRttiProperty.SetValue(Instance: TObject; const AValue: TValue);
  931. begin
  932. SetJSValueProp(Instance, PropertyTypeInfo, AValue);
  933. end;
  934. procedure TRttiProperty.SetValue(Instance: TObject; const AValue: JSValue);
  935. begin
  936. SetJSValueProp(Instance, PropertyTypeInfo, AValue);
  937. end;
  938. function TRttiProperty.GetPropertyType: TRttiType;
  939. begin
  940. Result := GRttiContext.GetType(PropertyTypeInfo.TypeInfo);
  941. end;
  942. function TRttiProperty.GetIsWritable: boolean;
  943. begin
  944. Result := PropertyTypeInfo.Setter<>'';
  945. end;
  946. function TRttiProperty.GetIsReadable: boolean;
  947. begin
  948. Result := PropertyTypeInfo.Getter<>'';
  949. end;
  950. function TRttiProperty.GetVisibility: TMemberVisibility;
  951. begin
  952. // At this moment only pulished rtti-property-info is supported by pas2js
  953. Result := mvPublished;
  954. end;
  955. { TRttiType }
  956. function TRttiType.GetName: string;
  957. begin
  958. Result:=FTypeInfo.Name;
  959. end;
  960. function TRttiType.GetIsInstance: boolean;
  961. begin
  962. Result:=false;
  963. end;
  964. function TRttiType.GetIsOrdinal: boolean;
  965. begin
  966. Result:=false;
  967. end;
  968. function TRttiType.GetIsRecord: boolean;
  969. begin
  970. Result:=false;
  971. end;
  972. function TRttiType.GetIsSet: boolean;
  973. begin
  974. Result:=false;
  975. end;
  976. function TRttiType.GetTypeKind: TTypeKind;
  977. begin
  978. Result:=FTypeInfo.Kind;
  979. end;
  980. constructor TRttiType.Create(ATypeInfo: PTypeInfo);
  981. begin
  982. inherited Create();
  983. FTypeInfo:=TTypeInfo(ATypeInfo);
  984. end;
  985. destructor TRttiType.Destroy;
  986. var
  987. o: TCustomAttribute;
  988. begin
  989. for o in FAttributes do
  990. o.Free;
  991. FAttributes:=nil;
  992. inherited Destroy;
  993. end;
  994. function TRttiType.GetAttributes: TCustomAttributeArray;
  995. begin
  996. FAttributes:=GetRTTIAttributes(FTypeInfo.Attributes);
  997. Result:=FAttributes;
  998. end;
  999. function TRttiType.GetDeclaredProperties: TRttiPropertyArray;
  1000. begin
  1001. Result:=nil;
  1002. end;
  1003. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  1004. begin
  1005. Result:=nil;
  1006. if AName='' then ;
  1007. end;
  1008. function TRttiType.GetMethods: TRttiMethodArray;
  1009. begin
  1010. Result:=nil;
  1011. end;
  1012. function TRttiType.GetMethods(const aName: String): TRttiMethodArray;
  1013. begin
  1014. Result:=nil;
  1015. end;
  1016. function TRttiType.GetMethod(const aName: String): TRttiMethod;
  1017. begin
  1018. Result:=nil;
  1019. if aName='' then ;
  1020. end;
  1021. function TRttiType.GetDeclaredMethods: TRttiMethodArray;
  1022. begin
  1023. Result:=nil;
  1024. end;
  1025. function TRttiType.GetDeclaredFields: TRttiFieldArray;
  1026. begin
  1027. Result:=nil;
  1028. end;
  1029. function TRttiType.GetField(const AName: string): TRttiField;
  1030. begin
  1031. Result:=nil;
  1032. if AName='' then ;
  1033. end;
  1034. { TVirtualInterface }
  1035. constructor TVirtualInterface.Create(InterfaceTypeInfo: Pointer); assembler;
  1036. asm
  1037. var IntfType = InterfaceTypeInfo.interface;
  1038. if (IntfType.$kind !== 'com') rtl.raiseE('EInvalidCast');
  1039. var guid = IntfType.$guid;
  1040. var i = Object.create(IntfType); // needed by IntfVar is IntfType
  1041. i.$o = this;
  1042. // copy IInterface methods: _AddRef, _Release, QueryInterface
  1043. var iinterfaceguid = '{00000000-0000-0000-C000-000000000046}';
  1044. var map = this.$intfmaps[iinterfaceguid];
  1045. for (var key in map){
  1046. var v = map[key];
  1047. if (typeof(v)!=='function') continue;
  1048. i[key] = map[key];
  1049. }
  1050. // all other methods call OnInvoke
  1051. do {
  1052. var names = IntfType.$names;
  1053. if (!names) break;
  1054. for (var j=0; j<names.length; j++){
  1055. let fnname = names[j];
  1056. if (i[fnname]) continue;
  1057. i[fnname] = function(){ return this.$o.FOnInvoke(fnname,arguments); };
  1058. }
  1059. IntfType = Object.getPrototypeOf(IntfType);
  1060. } while(IntfType!=null);
  1061. // create a new list of interface map, supporting IInterface and IntfType
  1062. this.$intfmaps = {};
  1063. this.$intfmaps[iinterfaceguid] = map;
  1064. this.$intfmaps[guid] = {};
  1065. // store the implementation of IntfType (used by the as-operator)
  1066. this.$interfaces = {};
  1067. this.$interfaces[guid] = i;
  1068. end;
  1069. constructor TVirtualInterface.Create(InterfaceTypeInfo: Pointer;
  1070. const InvokeEvent: TVirtualInterfaceInvokeEvent);
  1071. begin
  1072. Create(InterfaceTypeInfo);
  1073. OnInvoke:=InvokeEvent;
  1074. end;
  1075. function TVirtualInterface.QueryInterface(const iid: TGuid; out obj): Integer;
  1076. begin
  1077. Result := inherited QueryInterface(iid, obj);
  1078. end;
  1079. function Invoke(ACodeAddress: Pointer; const AArgs: TJSValueDynArray;
  1080. ACallConv: TCallConv; AResultType: PTypeInfo; AIsStatic: Boolean;
  1081. AIsConstructor: Boolean): TValue;
  1082. begin
  1083. if ACallConv=ccReg then ;
  1084. if AIsStatic then ;
  1085. if AIsConstructor then
  1086. raise EInvoke.Create('not supported');
  1087. if isFunction(ACodeAddress) then
  1088. begin
  1089. Result.FData := TJSFunction(ACodeAddress).apply(nil, AArgs);
  1090. if AResultType<>nil then
  1091. Result.FTypeInfo:=AResultType
  1092. else
  1093. Result.FTypeInfo:=TypeInfo(JSValue);
  1094. end
  1095. else
  1096. raise EInvoke.Create(SErrInvokeInvalidCodeAddr);
  1097. end;
  1098. end.