rtti.pas 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302
  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. {$IFNDEF FPC_DOTTEDUNITS}
  11. unit RTTI;
  12. {$ENDIF}
  13. {$mode objfpc}
  14. {$ModeSwitch advancedrecords}
  15. interface
  16. uses
  17. {$IFDEF FPC_DOTTEDUNITS}
  18. JSApi.JS, System.RTLConsts, System.Types, System.SysUtils, System.TypInfo;
  19. {$ELSE}
  20. JS, RTLConsts, Types, SysUtils, TypInfo;
  21. {$ENDIF}
  22. resourcestring
  23. SErrInvokeInvalidCodeAddr = 'CodeAddress is not a function';
  24. SErrTypeIsNotEnumerated = 'Type %s is not an enumerated type';
  25. type
  26. { TValue }
  27. TValue = record
  28. private
  29. FTypeInfo: TTypeInfo;
  30. FData: JSValue;
  31. FReferenceVariableData: Boolean;
  32. function GetData: JSValue;
  33. function GetIsEmpty: boolean;
  34. function GetTypeKind: TTypeKind;
  35. procedure SetData(const Value: JSValue);
  36. public
  37. class function Empty: TValue; static;
  38. generic class function From<T>(const Value: T): TValue; static;
  39. class function FromArray(TypeInfo: TTypeInfo; const Values: specialize TArray<TValue>): TValue; static;
  40. class function FromJSValue(v: JSValue): TValue; static;
  41. class function FromOrdinal(ATypeInfo: TTypeInfo; AValue: JSValue): TValue; static;
  42. class procedure Make(const ABuffer: JSValue; const ATypeInfo: PTypeInfo; var Result: TValue); overload; static;
  43. generic class procedure Make<T>(const Value: T; var Result: TValue); overload; static;
  44. function AsBoolean: boolean;
  45. function AsClass: TClass;
  46. //ToDo: function AsCurrency: Currency;
  47. function AsExtended: Extended;
  48. function AsInteger: Integer;
  49. function AsInterface: IInterface;
  50. function AsJSValue: JSValue;
  51. function AsNativeInt: NativeInt;
  52. function AsObject: TObject;
  53. function AsOrdinal: NativeInt;
  54. function AsString: string;
  55. generic function AsType<T>: T;
  56. function AsUnicodeString: UnicodeString;
  57. function Cast(ATypeInfo: TTypeInfo; const EmptyAsAnyType: Boolean = True): TValue; overload;
  58. generic function Cast<T>(const EmptyAsAnyType: Boolean = True): TValue; overload;
  59. function IsType(ATypeInfo: TTypeInfo; const EmptyAsAnyType: Boolean = True): Boolean; overload;
  60. generic function IsType<T>(const EmptyAsAnyType: Boolean = True): Boolean; overload;
  61. function GetArrayElement(aIndex: SizeInt): TValue;
  62. function GetArrayLength: SizeInt;
  63. function GetReferenceToRawData: Pointer;
  64. function IsArray: boolean;
  65. function IsClass: boolean;
  66. function IsObject: boolean;
  67. function IsObjectInstance: boolean;
  68. function IsOrdinal: boolean;
  69. function IsType(ATypeInfo: TTypeInfo): boolean;
  70. function ToString: String; overload;
  71. function ToString(const AFormatSettings: TFormatSettings): String; overload;
  72. function TryCast(ATypeInfo: TTypeInfo; out AResult: TValue; const EmptyAsAnyType: Boolean = True): Boolean;
  73. procedure SetArrayElement(aIndex: SizeInt; const AValue: TValue);
  74. procedure SetArrayLength(const Size: SizeInt);
  75. property IsEmpty: boolean read GetIsEmpty; // check if nil or undefined
  76. property Kind: TTypeKind read GetTypeKind;
  77. property TypeInfo: TTypeInfo read FTypeInfo;
  78. end;
  79. TRttiType = class;
  80. TRttiInstanceType = class;
  81. TRttiInstanceExternalType = class;
  82. { TRTTIContext }
  83. TRTTIContext = record
  84. public
  85. class function Create: TRTTIContext; static;
  86. procedure Free;
  87. function FindType(const AQualifiedName: String): TRttiType;
  88. function GetType(aTypeInfo: PTypeInfo): TRTTIType; overload;
  89. function GetType(aClass: TClass): TRTTIType; overload;
  90. function GetTypes: specialize TArray<TRttiType>;
  91. class procedure KeepContext; static;
  92. class procedure DropContext; static;
  93. end;
  94. { TRttiObject }
  95. TRttiObject = class abstract
  96. private
  97. FAttributesLoaded: Boolean;
  98. FAttributes: TCustomAttributeArray;
  99. FParent: TRttiObject;
  100. FHandle: Pointer;
  101. protected
  102. function LoadCustomAttributes: TCustomAttributeArray; virtual;
  103. public
  104. constructor Create(AParent: TRttiObject; AHandle: Pointer); virtual;
  105. destructor Destroy; override;
  106. function GetAttributes: TCustomAttributeArray;
  107. generic function GetAttribute<T: TCustomAttribute>: T;
  108. function GetAttribute(const Attribute: TCustomAttributeClass): TCustomAttribute;
  109. generic function HasAttribute<T: TCustomAttribute>: Boolean;
  110. function HasAttribute(const Attribute: TCustomAttributeClass): Boolean;
  111. property Attributes: TCustomAttributeArray read GetAttributes;
  112. property Handle: Pointer read FHandle;
  113. property Parent: TRttiObject read FParent;
  114. end;
  115. { TRttiNamedObject }
  116. TRttiNamedObject = class(TRttiObject)
  117. protected
  118. function GetName: string; virtual;
  119. public
  120. property Name: string read GetName;
  121. end;
  122. { TRttiMember }
  123. TMemberVisibility=(
  124. mvPrivate,
  125. mvProtected,
  126. mvPublic,
  127. mvPublished);
  128. TRttiMember = class(TRttiNamedObject)
  129. protected
  130. function GetMemberTypeInfo: TTypeMember;
  131. function GetName: String; override;
  132. function GetParent: TRttiType;
  133. function GetVisibility: TMemberVisibility; virtual;
  134. function LoadCustomAttributes: TCustomAttributeArray; override;
  135. public
  136. constructor Create(AParent: TRttiType; ATypeInfo: TTypeMember); reintroduce;
  137. property MemberTypeInfo: TTypeMember read GetMemberTypeInfo;
  138. property Parent: TRttiType read GetParent;
  139. property Visibility: TMemberVisibility read GetVisibility;
  140. end;
  141. { TRttiField }
  142. TRttiField = class(TRttiMember)
  143. private
  144. function GetFieldType: TRttiType;
  145. function GetFieldTypeInfo: TTypeMemberField;
  146. public
  147. constructor Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  148. function GetValue(Instance: JSValue): TValue;
  149. procedure SetValue(Instance: JSValue; const AValue: TValue);
  150. property FieldType: TRttiType read GetFieldType;
  151. property FieldTypeInfo: TTypeMemberField read GetFieldTypeInfo;
  152. end;
  153. TRttiFieldArray = specialize TArray<TRttiField>;
  154. { TRttiParameter }
  155. TRttiParameter = class(TRttiNamedObject)
  156. private
  157. FParamType: TRttiType;
  158. FFlags: TParamFlags;
  159. FName: String;
  160. protected
  161. function GetName: string; override;
  162. public
  163. property Flags: TParamFlags read FFlags;
  164. property ParamType: TRttiType read FParamType;
  165. end;
  166. TRttiParameterArray = specialize TArray<TRttiParameter>;
  167. { TRttiMethod }
  168. TRttiMethod = class(TRttiMember)
  169. private
  170. FParameters: TRttiParameterArray;
  171. FParametersLoaded: Boolean;
  172. function GetIsAsyncCall: Boolean;
  173. function GetIsClassMethod: Boolean;
  174. function GetIsConstructor: Boolean;
  175. function GetIsDestructor: Boolean;
  176. function GetIsExternal: Boolean;
  177. function GetIsSafeCall: Boolean;
  178. function GetIsStatic: Boolean;
  179. function GetIsVarArgs: Boolean;
  180. function GetMethodKind: TMethodKind;
  181. function GetMethodTypeInfo: TTypeMemberMethod;
  182. function GetProcedureFlags: TProcedureFlags;
  183. function GetReturnType: TRttiType;
  184. procedure LoadParameters;
  185. public
  186. function GetParameters: TRttiParameterArray;
  187. function Invoke(const Instance: TValue; const Args: array of TValue): TValue;
  188. function Invoke(const Instance: TObject; const Args: array of TValue): TValue;
  189. function Invoke(const aClass: TClass; const Args: array of TValue): TValue;
  190. property IsAsyncCall: Boolean read GetIsAsyncCall;
  191. property IsClassMethod: Boolean read GetIsClassMethod;
  192. property IsConstructor: Boolean read GetIsConstructor;
  193. property IsDestructor: Boolean read GetIsDestructor;
  194. property IsExternal: Boolean read GetIsExternal;
  195. property IsSafeCall: Boolean read GetIsSafeCall;
  196. property IsStatic: Boolean read GetIsStatic;
  197. property IsVarArgs: Boolean read GetIsVarArgs;
  198. property MethodKind: TMethodKind read GetMethodKind;
  199. property MethodTypeInfo: TTypeMemberMethod read GetMethodTypeInfo;
  200. property ReturnType: TRttiType read GetReturnType;
  201. end;
  202. TRttiMethodArray = specialize TArray<TRttiMethod>;
  203. { TRttiProperty }
  204. TRttiProperty = class(TRttiMember)
  205. private
  206. function GetPropertyTypeInfo: TTypeMemberProperty;
  207. function GetPropertyType: TRttiType;
  208. function GetIsWritable: boolean;
  209. function GetIsReadable: boolean;
  210. protected
  211. function GetVisibility: TMemberVisibility; override;
  212. public
  213. constructor Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  214. function GetValue(Instance: JSValue): TValue;
  215. procedure SetValue(Instance: JSValue; const AValue: TValue);
  216. property PropertyTypeInfo: TTypeMemberProperty read GetPropertyTypeInfo;
  217. property PropertyType: TRttiType read GetPropertyType;
  218. property IsReadable: boolean read GetIsReadable;
  219. property IsWritable: boolean read GetIsWritable;
  220. property Visibility: TMemberVisibility read GetVisibility;
  221. end;
  222. TRttiInstanceProperty = class(TRttiProperty)
  223. end;
  224. TRttiPropertyArray = specialize TArray<TRttiProperty>;
  225. { TRttiType }
  226. TRttiType = class(TRttiNamedObject)
  227. private
  228. //FMethods: specialize TArray<TRttiMethod>;
  229. function GetAsInstance: TRttiInstanceType;
  230. function GetAsInstanceExternal: TRttiInstanceExternalType;
  231. function GetDeclaringUnitName: string;
  232. function GetHandle: TTypeInfo;
  233. function GetQualifiedName: String;
  234. protected
  235. function GetName: string; override;
  236. //function GetHandle: Pointer; override;
  237. function GetIsInstance: Boolean;
  238. function GetIsInstanceExternal: Boolean;
  239. //function GetIsManaged: Boolean; virtual;
  240. function GetIsOrdinal: Boolean; virtual;
  241. function GetIsRecord: Boolean; virtual;
  242. function GetIsSet: Boolean; virtual;
  243. function GetTypeKind: TTypeKind; virtual;
  244. //function GetTypeSize: integer; virtual;
  245. function GetBaseType: TRttiType; virtual;
  246. function LoadCustomAttributes: TCustomAttributeArray; override;
  247. public
  248. function GetField(const AName: string): TRttiField; virtual;
  249. function GetFields: TRttiFieldArray; virtual;
  250. function GetMethods: TRttiMethodArray; virtual;
  251. function GetMethods(const aName: String): TRttiMethodArray; virtual;
  252. function GetMethod(const aName: String): TRttiMethod; virtual;
  253. function GetProperty(const AName: string): TRttiProperty; virtual;
  254. //function GetIndexedProperty(const AName: string): TRttiIndexedProperty; virtual;
  255. function GetProperties: TRttiPropertyArray; virtual;
  256. function GetDeclaredProperties: TRttiPropertyArray; virtual;
  257. //function GetDeclaredIndexedProperties: TRttiIndexedPropertyArray; virtual;
  258. function GetDeclaredMethods: TRttiMethodArray; virtual;
  259. function GetDeclaredFields: TRttiFieldArray; virtual;
  260. property Handle: TTypeInfo read GetHandle;
  261. property IsInstance: Boolean read GetIsInstance;
  262. property IsInstanceExternal: Boolean read GetIsInstanceExternal;
  263. //property isManaged: Boolean read GetIsManaged;
  264. property IsOrdinal: Boolean read GetIsOrdinal;
  265. property IsRecord: Boolean read GetIsRecord;
  266. property IsSet: Boolean read GetIsSet;
  267. property BaseType: TRttiType read GetBaseType;
  268. property AsInstance: TRttiInstanceType read GetAsInstance;
  269. property AsInstanceExternal: TRttiInstanceExternalType read GetAsInstanceExternal;
  270. property TypeKind: TTypeKind read GetTypeKind;
  271. //property TypeSize: integer read GetTypeSize;
  272. property DeclaringUnitName: string read GetDeclaringUnitName;
  273. property QualifiedName: String read GetQualifiedName;
  274. end;
  275. TRttiTypeClass = class of TRttiType;
  276. { TRttiStructuredType }
  277. TRttiStructuredType = class abstract(TRttiType)
  278. private
  279. FFields: TRttiFieldArray;
  280. FMethods: TRttiMethodArray;
  281. FProperties: TRttiPropertyArray;
  282. protected
  283. function GetAncestor: TRttiStructuredType; virtual;
  284. function GetStructTypeInfo: TTypeInfoStruct;
  285. public
  286. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  287. destructor Destroy; override;
  288. function GetDeclaredFields: TRttiFieldArray; override;
  289. function GetDeclaredMethods: TRttiMethodArray; override;
  290. function GetDeclaredProperties: TRttiPropertyArray; override;
  291. function GetFields: TRttiFieldArray; override;
  292. function GetMethod(const aName: String): TRttiMethod; override;
  293. function GetMethods: TRttiMethodArray; override;
  294. function GetMethods(const aName: String): TRttiMethodArray; override;
  295. function GetProperties: TRttiPropertyArray; override;
  296. function GetProperty(const AName: string): TRttiProperty; override;
  297. property StructTypeInfo: TTypeInfoStruct read GetStructTypeInfo;
  298. end;
  299. { TRttiInstanceType }
  300. TRttiInstanceType = class(TRttiStructuredType)
  301. private
  302. function GetAncestorType: TRttiInstanceType;
  303. function GetClassTypeInfo: TTypeInfoClass;
  304. function GetMetaClassType: TClass;
  305. protected
  306. function GetAncestor: TRttiStructuredType; override;
  307. function GetBaseType : TRttiType; override;
  308. public
  309. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  310. property BaseType : TRttiInstanceType read GetAncestorType;
  311. property Ancestor: TRttiInstanceType read GetAncestorType;
  312. property ClassTypeInfo: TTypeInfoClass read GetClassTypeInfo;
  313. property MetaClassType: TClass read GetMetaClassType;
  314. end;
  315. { TRttiInterfaceType }
  316. TRttiInterfaceType = class(TRttiStructuredType)
  317. private
  318. function GetAncestorType: TRttiInterfaceType;
  319. function GetGUID: TGUID;
  320. function GetInterfaceTypeInfo: TTypeInfoInterface;
  321. protected
  322. function GetAncestor: TRttiStructuredType; override;
  323. function GetBaseType : TRttiType; override;
  324. public
  325. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  326. property BaseType : TRttiInterfaceType read GetAncestorType;
  327. property Ancestor: TRttiInterfaceType read GetAncestorType;
  328. property GUID: TGUID read GetGUID;
  329. property InterfaceTypeInfo: TTypeInfoInterface read GetInterfaceTypeInfo;
  330. end;
  331. { TRttiRecordType }
  332. TRttiRecordType = class(TRttiStructuredType)
  333. private
  334. function GetRecordTypeInfo: TTypeInfoRecord;
  335. protected
  336. function GetIsRecord: Boolean; override;
  337. public
  338. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  339. property RecordTypeInfo: TTypeInfoRecord read GetRecordTypeInfo;
  340. end;
  341. { TRttiClassRefType }
  342. TRttiClassRefType = class(TRttiType)
  343. private
  344. function GetClassRefTypeInfo: TTypeInfoClassRef;
  345. function GetInstanceType: TRttiInstanceType;
  346. function GetMetaclassType: TClass;
  347. public
  348. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  349. property ClassRefTypeInfo: TTypeInfoClassRef read GetClassRefTypeInfo;
  350. property InstanceType: TRttiInstanceType read GetInstanceType;
  351. property MetaclassType: TClass read GetMetaclassType;
  352. end;
  353. { TRttiInstanceExternalType }
  354. TRttiInstanceExternalType = class(TRttiType)
  355. private
  356. function GetAncestor: TRttiInstanceExternalType;
  357. function GetExternalName: String;
  358. function GetExternalClassTypeInfo: TTypeInfoExtClass;
  359. public
  360. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  361. property Ancestor: TRttiInstanceExternalType read GetAncestor;
  362. property ExternalClassTypeInfo: TTypeInfoExtClass read GetExternalClassTypeInfo;
  363. property ExternalName: String read GetExternalName;
  364. end;
  365. { TRttiOrdinalType }
  366. TRttiOrdinalType = class(TRttiType)
  367. private
  368. function GetMaxValue: Integer; virtual;
  369. function GetMinValue: Integer; virtual;
  370. function GetOrdType: TOrdType;
  371. function GetOrdinalTypeInfo: TTypeInfoInteger;
  372. public
  373. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  374. property OrdType: TOrdType read GetOrdType;
  375. property MinValue: Integer read GetMinValue;
  376. property MaxValue: Integer read GetMaxValue;
  377. property OrdinalTypeInfo: TTypeInfoInteger read GetOrdinalTypeInfo;
  378. end;
  379. { TRttiEnumerationType }
  380. TRttiEnumerationType = class(TRttiOrdinalType)
  381. private
  382. function GetEnumerationTypeInfo: TTypeInfoEnum;
  383. public
  384. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  385. property EnumerationTypeInfo: TTypeInfoEnum read GetEnumerationTypeInfo;
  386. function GetNames: TStringArray;
  387. generic class function GetName<T>(AValue: T): String; reintroduce;
  388. generic class function GetValue<T>(const AValue: String): T;
  389. end;
  390. { TRttiDynamicArrayType }
  391. TRttiDynamicArrayType = class(TRttiType)
  392. private
  393. function GetDynArrayTypeInfo: TTypeInfoDynArray;
  394. function GetElementType: TRttiType;
  395. public
  396. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  397. property DynArrayTypeInfo: TTypeInfoDynArray read GetDynArrayTypeInfo;
  398. property ElementType: TRttiType read GetElementType;
  399. end;
  400. { TRttiPointerType }
  401. TRttiPointerType = class(TRttiType)
  402. private
  403. function GetRefType: TRttiType;
  404. function GetRefTypeInfo: TTypeInfoPointer;
  405. public
  406. constructor Create(AParent: TRttiObject; ATypeInfo: PTypeInfo); override;
  407. property RefType: TRttiType read GetRefType;
  408. property RefTypeInfo: TTypeInfoPointer read GetRefTypeInfo;
  409. end;
  410. EInvoke = EJS;
  411. TVirtualInterfaceInvokeEvent = reference to procedure(Method: TRttiMethod; const Args: specialize TArray<TValue>; out Result: TValue);
  412. TVirtualInterfaceInvokeEventJS = reference to function(const aMethodName: String; const Args: TJSValueDynArray): JSValue;
  413. { TVirtualInterface: A class that can implement any IInterface. Any method
  414. call is handled by the OnInvoke event. }
  415. TVirtualInterface = class(TInterfacedObject, IInterface)
  416. private
  417. FContext: TRttiContext;
  418. FInterfaceType: TRttiInterfaceType;
  419. FOnInvoke: TVirtualInterfaceInvokeEvent;
  420. FOnInvokeJS: TVirtualInterfaceInvokeEventJS;
  421. function Invoke(const MethodName: String; const Args: TJSValueDynArray): JSValue;
  422. public
  423. constructor Create(InterfaceTypeInfo: TTypeInfoInterface); overload;
  424. constructor Create(InterfaceTypeInfo: TTypeInfoInterface; const InvokeEvent: TVirtualInterfaceInvokeEvent); overload;
  425. constructor Create(InterfaceTypeInfo: TTypeInfoInterface; const InvokeEvent: TVirtualInterfaceInvokeEventJS); overload;
  426. destructor Destroy; override;
  427. function QueryInterface(const iid: TGuid; out obj): Integer; override;
  428. property OnInvoke: TVirtualInterfaceInvokeEvent read FOnInvoke write FOnInvoke;
  429. property OnInvokeJS: TVirtualInterfaceInvokeEventJS read FOnInvokeJS write FOnInvokeJS;
  430. end;
  431. procedure CreateVirtualCorbaInterface(InterfaceTypeInfo: Pointer;
  432. const MethodImplementation: TVirtualInterfaceInvokeEvent; out IntfVar); assembler;
  433. function Invoke(ACodeAddress: Pointer; const AArgs: TJSValueDynArray;
  434. ACallConv: TCallConv; AResultType: PTypeInfo; AIsStatic: Boolean;
  435. AIsConstructor: Boolean): TValue;
  436. implementation
  437. type
  438. TRttiPoolTypes = class
  439. private
  440. FReferenceCount: Integer;
  441. FTypes: TJSObject; // maps 'modulename.typename' to TRTTIType
  442. public
  443. constructor Create;
  444. destructor Destroy; override;
  445. function FindType(const AQualifiedName: String): TRttiType;
  446. function GetType(const ATypeInfo: PTypeInfo): TRTTIType; overload;
  447. function GetType(const AClass: TClass): TRTTIType; overload;
  448. class function AcquireContext: TJSObject; static;
  449. class procedure ReleaseContext; static;
  450. end;
  451. var
  452. Pool: TRttiPoolTypes;
  453. pas: TJSObject; external name 'pas';
  454. procedure CreateVirtualCorbaInterface(InterfaceTypeInfo: Pointer;
  455. const MethodImplementation: TVirtualInterfaceInvokeEvent; out IntfVar); assembler;
  456. asm
  457. var IntfType = InterfaceTypeInfo.interface;
  458. var i = Object.create(IntfType);
  459. var o = { $name: "virtual", $fullname: "virtual" };
  460. i.$o = o;
  461. do {
  462. var names = IntfType.$names;
  463. if (!names) break;
  464. for (var j=0; j<names.length; j++){
  465. let fnname = names[j];
  466. i[fnname] = function(){ return MethodImplementation(fnname,arguments); };
  467. }
  468. IntfType = Object.getPrototypeOf(IntfType);
  469. } while(IntfType!=null);
  470. IntfVar.set(i);
  471. end;
  472. { TRttiPoolTypes }
  473. constructor TRttiPoolTypes.Create;
  474. begin
  475. inherited;
  476. FTypes := TJSObject.new;
  477. end;
  478. destructor TRttiPoolTypes.Destroy;
  479. var
  480. Key: String;
  481. RttiObject: TRttiType;
  482. begin
  483. for key in FTypes do
  484. if FTypes.hasOwnProperty(key) then
  485. begin
  486. RttiObject := TRttiType(FTypes[key]);
  487. RttiObject.Free;
  488. end;
  489. end;
  490. function TRttiPoolTypes.FindType(const AQualifiedName: String): TRttiType;
  491. var
  492. ModuleName, TypeName: String;
  493. Module: TTypeInfoModule;
  494. TypeFound: PTypeInfo;
  495. begin
  496. if FTypes.hasOwnProperty(AQualifiedName) then
  497. Result := TRttiType(FTypes[AQualifiedName])
  498. else
  499. begin
  500. Result := nil;
  501. for ModuleName in TJSObject.Keys(pas) do
  502. if AQualifiedName.StartsWith(ModuleName + '.') then
  503. begin
  504. Module := TTypeInfoModule(pas[ModuleName]);
  505. TypeName := Copy(AQualifiedName, Length(ModuleName) + 2, Length(AQualifiedName));
  506. if Module.RTTI.HasOwnProperty(TypeName) then
  507. begin
  508. TypeFound := PTypeInfo(Module.RTTI[TypeName]);
  509. Exit(GetType(TypeFound));
  510. end;
  511. end;
  512. end;
  513. end;
  514. function TRttiPoolTypes.GetType(const ATypeInfo: PTypeInfo): TRTTIType;
  515. var
  516. RttiTypeClass: array[TTypeKind] of TRttiTypeClass = (
  517. nil, // tkUnknown
  518. TRttiOrdinalType, // tkInteger
  519. TRttiOrdinalType, // tkChar
  520. TRttiType, // tkString
  521. TRttiEnumerationType, // tkEnumeration
  522. TRttiType, // tkSet
  523. TRttiType, // tkDouble
  524. TRttiType, // tkBool
  525. TRttiType, // tkProcVar
  526. TRttiType, // tkMethod
  527. TRttiType, // tkArray
  528. TRttiDynamicArrayType, // tkDynArray
  529. TRttiRecordType, // tkRecord
  530. TRttiInstanceType, // tkClass
  531. TRttiClassRefType, // tkClassRef
  532. TRttiPointerType, // tkPointer
  533. TRttiType, // tkJSValue
  534. TRttiType, // tkRefToProcVar
  535. TRttiInterfaceType, // tkInterface
  536. TRttiType, // tkHelper
  537. TRttiInstanceExternalType // tkExtClass
  538. );
  539. TheType: TTypeInfo absolute ATypeInfo;
  540. Name: String;
  541. Parent: TRttiObject;
  542. begin
  543. if IsNull(ATypeInfo) or IsUndefined(ATypeInfo) then
  544. Exit(nil);
  545. Name := TheType.Name;
  546. if isModule(TheType.Module) then
  547. Name := TheType.Module.Name + '.' + Name;
  548. if FTypes.hasOwnProperty(Name) then
  549. Result := TRttiType(FTypes[Name])
  550. else
  551. begin
  552. if (TheType.Kind in [tkClass, tkInterface, tkHelper, tkExtClass]) and TJSObject(TheType).hasOwnProperty('ancestor') then
  553. Parent := GetType(PTypeInfo(TJSObject(TheType)['ancestor']))
  554. else
  555. Parent := nil;
  556. Result := RttiTypeClass[TheType.Kind].Create(Parent, ATypeInfo);
  557. FTypes[Name] := Result;
  558. end;
  559. end;
  560. function TRttiPoolTypes.GetType(const AClass: TClass): TRTTIType;
  561. begin
  562. if AClass = nil then
  563. Exit(nil);
  564. Result := GetType(TypeInfo(AClass));
  565. end;
  566. class function TRttiPoolTypes.AcquireContext: TJSObject;
  567. begin
  568. if not Assigned(Pool) then
  569. Pool := TRttiPoolTypes.Create;
  570. Result := Pool.FTypes;
  571. Inc(Pool.FReferenceCount);
  572. end;
  573. class procedure TRttiPoolTypes.ReleaseContext;
  574. begin
  575. Dec(Pool.FReferenceCount);
  576. if Pool.FReferenceCount = 0 then
  577. FreeAndNil(Pool);
  578. end;
  579. { TRttiDynamicArrayType }
  580. function TRttiDynamicArrayType.GetDynArrayTypeInfo: TTypeInfoDynArray;
  581. begin
  582. Result := TTypeInfoDynArray(inherited Handle);
  583. end;
  584. function TRttiDynamicArrayType.GetElementType: TRttiType;
  585. begin
  586. Result := Pool.GetType(DynArrayTypeInfo.ElType);
  587. end;
  588. constructor TRttiDynamicArrayType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  589. begin
  590. if not (TTypeInfo(ATypeInfo) is TTypeInfoDynArray) then
  591. raise EInvalidCast.Create('');
  592. inherited;
  593. end;
  594. { TRttiOrdinalType }
  595. function TRttiOrdinalType.GetMaxValue: Integer;
  596. begin
  597. Result := OrdinalTypeInfo.MaxValue;
  598. end;
  599. function TRttiOrdinalType.GetMinValue: Integer;
  600. begin
  601. Result := OrdinalTypeInfo.MinValue;
  602. end;
  603. function TRttiOrdinalType.GetOrdType: TOrdType;
  604. begin
  605. Result := OrdinalTypeInfo.OrdType;
  606. end;
  607. function TRttiOrdinalType.GetOrdinalTypeInfo: TTypeInfoInteger;
  608. begin
  609. Result := TTypeInfoInteger(inherited Handle);
  610. end;
  611. constructor TRttiOrdinalType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  612. begin
  613. if not (TTypeInfo(ATypeInfo) is TTypeInfoInteger) then
  614. raise EInvalidCast.Create('');
  615. inherited;
  616. end;
  617. { TRttiEnumerationType }
  618. function TRttiEnumerationType.GetEnumerationTypeInfo: TTypeInfoEnum;
  619. begin
  620. Result := TTypeInfoEnum(inherited Handle);
  621. end;
  622. function TRttiEnumerationType.GetNames: TStringArray;
  623. var
  624. A, NamesSize: Integer;
  625. begin
  626. NamesSize := GetEnumNameCount(EnumerationTypeInfo);
  627. SetLength(Result, NamesSize);
  628. for A := 0 to Pred(NamesSize) do
  629. Result[A] := EnumerationTypeInfo.EnumType.IntToName[A + MinValue];
  630. end;
  631. generic class function TRttiEnumerationType.GetName<T>(AValue: T): String;
  632. Var
  633. P : PTypeInfo;
  634. begin
  635. P:=TypeInfo(T);
  636. if not (TTypeInfo(P).kind=tkEnumeration) then
  637. raise EInvalidCast.CreateFmt(SErrTypeIsNotEnumerated,[TTypeInfo(P).Name]);
  638. Result := GetEnumName(TTypeInfoEnum(P), Integer(JSValue(AValue)));
  639. end;
  640. generic class function TRttiEnumerationType.GetValue<T>(const AValue: String): T;
  641. Var
  642. P : PTypeInfo;
  643. begin
  644. P:=TypeInfo(T);
  645. if not (TTypeInfo(P).kind=tkEnumeration) then
  646. raise EInvalidCast.CreateFmt(SErrTypeIsNotEnumerated,[TTypeInfo(P).Name]);
  647. Result := T(JSValue(GetEnumValue(TTypeInfoEnum(TypeInfo(T)), AValue)));
  648. end;
  649. constructor TRttiEnumerationType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  650. begin
  651. if not (TTypeInfo(ATypeInfo) is TTypeInfoEnum) then
  652. raise EInvalidCast.Create('');
  653. inherited;
  654. end;
  655. { TValue }
  656. function TValue.GetTypeKind: TTypeKind;
  657. begin
  658. if TypeInfo=nil then
  659. Result:=tkUnknown
  660. else
  661. Result:=FTypeInfo.Kind;
  662. end;
  663. generic function TValue.AsType<T>: T;
  664. begin
  665. if IsEmpty then
  666. Result := Default(T)
  667. else
  668. Result := T(AsJSValue)
  669. end;
  670. generic class function TValue.From<T>(const Value: T): TValue;
  671. begin
  672. Make(Value, System.TypeInfo(T), Result);
  673. end;
  674. class procedure TValue.Make(const ABuffer: JSValue; const ATypeInfo: PTypeInfo; var Result: TValue);
  675. begin
  676. Result.FTypeInfo := ATypeInfo;
  677. if Result.FTypeInfo.Kind = tkRecord then
  678. if Assigned(ABuffer) then
  679. Result.FData := TTypeInfoRecord(ATypeInfo).RecordInfo.Assign(ABuffer)
  680. else
  681. Result.FData := TTypeInfoRecord(ATypeInfo).RecordInfo.New
  682. else
  683. Result.FData := ABuffer;
  684. end;
  685. generic class procedure TValue.Make<T>(const Value: T; var Result: TValue);
  686. begin
  687. TValue.Make(Value, System.TypeInfo(T), Result);
  688. end;
  689. function TValue.Cast(ATypeInfo: TTypeInfo; const EmptyAsAnyType: Boolean): TValue;
  690. begin
  691. if not TryCast(ATypeInfo, Result, EmptyAsAnyType) then
  692. raise EInvalidCast.Create('');
  693. end;
  694. generic function TValue.Cast<T>(const EmptyAsAnyType: Boolean): TValue;
  695. begin
  696. Result := Cast(System.TypeInfo(T), EmptyAsAnyType);
  697. end;
  698. function TValue.IsType(ATypeInfo: TTypeInfo; const EmptyAsAnyType: Boolean): Boolean;
  699. var
  700. AnyValue: TValue;
  701. begin
  702. Result := TryCast(ATypeInfo, AnyValue, EmptyAsAnyType);
  703. end;
  704. generic function TValue.IsType<T>(const EmptyAsAnyType: Boolean): Boolean;
  705. begin
  706. Result := IsType(System.TypeInfo(T), EmptyAsAnyType);
  707. end;
  708. function TValue.TryCast(ATypeInfo: TTypeInfo; out AResult: TValue; const EmptyAsAnyType: Boolean): Boolean;
  709. function ConversionAccepted: TTypeKinds;
  710. begin
  711. case TypeInfo.Kind of
  712. tkString: Exit([tkChar, tkString]);
  713. tkDouble: Exit([tkInteger, tkDouble]);
  714. tkEnumeration: Exit([tkInteger, tkEnumeration]);
  715. else Exit([TypeInfo.Kind]);
  716. end;
  717. end;
  718. begin
  719. if EmptyAsAnyType and IsEmpty then
  720. begin
  721. AResult := TValue.Empty;
  722. if ATypeInfo <> nil then
  723. begin
  724. AResult.FTypeInfo := ATypeInfo;
  725. case ATypeInfo.Kind of
  726. tkBool: AResult.SetData(False);
  727. tkChar: AResult.SetData(#0);
  728. tkString: AResult.SetData(EmptyStr);
  729. tkDouble,
  730. tkEnumeration,
  731. tkInteger: AResult.SetData(0);
  732. end;
  733. Exit(True);
  734. end;
  735. end;
  736. if not EmptyAsAnyType and (FTypeInfo = nil) then
  737. Exit(False);
  738. if FTypeInfo = ATypeInfo then
  739. begin
  740. AResult := Self;
  741. Exit(True);
  742. end;
  743. if ATypeInfo = nil then
  744. Exit(False);
  745. if ATypeInfo = System.TypeInfo(TValue) then
  746. begin
  747. TValue.Make(Self, System.TypeInfo(TValue), AResult);
  748. Exit(True);
  749. end;
  750. Result := ATypeInfo.Kind in ConversionAccepted;
  751. if Result then
  752. begin
  753. AResult.SetData(FData);
  754. AResult.FTypeInfo := ATypeInfo;
  755. end;
  756. end;
  757. class function TValue.FromJSValue(v: JSValue): TValue;
  758. var
  759. i: NativeInt;
  760. TypeOfValue: TTypeInfo;
  761. begin
  762. case jsTypeOf(v) of
  763. 'number':
  764. if {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isInteger(v) then
  765. begin
  766. i:=NativeInt(v);
  767. if (i>=low(integer)) and (i<=high(integer)) then
  768. TypeOfValue:=System.TypeInfo(Integer)
  769. else
  770. TypeOfValue:=System.TypeInfo(NativeInt);
  771. end
  772. else
  773. TypeOfValue:=system.TypeInfo(Double);
  774. 'string': TypeOfValue:=System.TypeInfo(String);
  775. 'boolean': TypeOfValue:=System.TypeInfo(Boolean);
  776. 'object':
  777. if v=nil then
  778. Exit(TValue.Empty)
  779. else if {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isClass(v) and {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isExt(v,TObject) then
  780. TypeOfValue:=System.TypeInfo(TClass(v))
  781. else if {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isObject(v) and {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isExt(v,TObject) then
  782. TypeOfValue:=System.TypeInfo(TObject(v))
  783. else if isRecord(v) then
  784. TypeOfValue:=System.TypeInfo(TObject(v))
  785. else if TJSArray.IsArray(V) then
  786. TypeOfValue:=System.TypeInfo(TObject(v))
  787. else
  788. raise EInvalidCast.Create('Type not recognized in FromJSValue!');
  789. else
  790. TypeOfValue:=System.TypeInfo(JSValue);
  791. end;
  792. Make(v, TypeOfValue, Result);
  793. end;
  794. class function TValue.FromArray(TypeInfo: TTypeInfo; const Values: specialize TArray<TValue>): TValue;
  795. var
  796. A: Integer;
  797. DynTypeInfo: TTypeInfoDynArray absolute TypeInfo;
  798. NewArray: TJSArray;
  799. ElementType: TTypeInfo;
  800. begin
  801. if TypeInfo.Kind <> tkDynArray then
  802. raise EInvalidCast.Create('Type not an array in FromArray!');
  803. ElementType := DynTypeInfo.ElType;
  804. NewArray := TJSArray.new;
  805. NewArray.Length := Length(Values);
  806. for A := 0 to High(Values) do
  807. NewArray[A] := Values[A].Cast(ElementType).AsJSValue;
  808. Result.SetData(NewArray);
  809. Result.FTypeInfo := TypeInfo;
  810. end;
  811. class function TValue.FromOrdinal(ATypeInfo: TTypeInfo; AValue: JSValue): TValue;
  812. begin
  813. if (ATypeInfo = nil) or not (ATypeInfo.Kind in [tkBool, tkEnumeration, tkInteger]) then
  814. raise EInvalidCast.Create('Invalid type in FromOrdinal');
  815. if ATypeInfo.Kind = tkBool then
  816. TValue.Make(AValue = True, ATypeInfo, Result)
  817. else
  818. TValue.Make(NativeInt(AValue), ATypeInfo, Result);
  819. end;
  820. function TValue.IsObject: boolean;
  821. begin
  822. Result:=IsEmpty or (TypeInfo.Kind=tkClass);
  823. end;
  824. function TValue.AsObject: TObject;
  825. begin
  826. if IsObject or (IsClass and not {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.IsObject(GetData)) then
  827. Result := TObject(GetData)
  828. else
  829. raise EInvalidCast.Create(SErrInvalidTypecast);
  830. end;
  831. function TValue.IsObjectInstance: boolean;
  832. begin
  833. Result:=(TypeInfo<>nil) and (TypeInfo.Kind=tkClass);
  834. end;
  835. function TValue.IsArray: boolean;
  836. begin
  837. case Kind of
  838. tkDynArray: Exit(True);
  839. tkArray: Exit(Length(TTypeInfoStaticArray(FTypeInfo).Dims) = 1);
  840. else Result := False;
  841. end;
  842. end;
  843. function TValue.IsClass: boolean;
  844. var
  845. k: TTypeKind;
  846. begin
  847. k:=Kind;
  848. Result := (k = tkClassRef) or ((k in [tkClass,tkUnknown]) and not {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.IsObject(GetData));
  849. end;
  850. function TValue.AsClass: TClass;
  851. begin
  852. if IsClass then
  853. Result := TClass(GetData)
  854. else
  855. raise EInvalidCast.Create(SErrInvalidTypecast);
  856. end;
  857. function TValue.IsOrdinal: boolean;
  858. begin
  859. Result := IsEmpty or (Kind in [tkBool, tkInteger, tkChar, tkEnumeration]);
  860. end;
  861. function TValue.AsOrdinal: NativeInt;
  862. begin
  863. if IsOrdinal then
  864. Result:=NativeInt(GetData)
  865. else
  866. raise EInvalidCast.Create(SErrInvalidTypecast);
  867. end;
  868. function TValue.AsBoolean: boolean;
  869. begin
  870. if (Kind = tkBool) then
  871. Result:=boolean(GetData)
  872. else
  873. raise EInvalidCast.Create(SErrInvalidTypecast);
  874. end;
  875. function TValue.AsInteger: Integer;
  876. begin
  877. if {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isInteger(GetData) then
  878. Result:=NativeInt(GetData)
  879. else
  880. raise EInvalidCast.Create(SErrInvalidTypecast);
  881. end;
  882. function TValue.AsNativeInt: NativeInt;
  883. begin
  884. if {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isInteger(GetData) then
  885. Result:=NativeInt(GetData)
  886. else
  887. raise EInvalidCast.Create(SErrInvalidTypecast);
  888. end;
  889. function TValue.AsInterface: IInterface;
  890. var
  891. k: TTypeKind;
  892. begin
  893. k:=Kind;
  894. if k = tkInterface then
  895. Result := IInterface(GetData)// ToDo
  896. else if (k in [tkClass, tkClassRef, tkUnknown]) and not {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isObject(GetData) then
  897. Result := Nil
  898. else
  899. raise EInvalidCast.Create(SErrInvalidTypecast);
  900. end;
  901. function TValue.AsString: string;
  902. begin
  903. if {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isString(GetData) then
  904. Result:=String(GetData)
  905. else
  906. raise EInvalidCast.Create(SErrInvalidTypecast);
  907. end;
  908. function TValue.AsUnicodeString: UnicodeString;
  909. begin
  910. Result:=AsString;
  911. end;
  912. function TValue.AsExtended: Extended;
  913. begin
  914. if {$IFDEF FPC_DOTTEDUNITS}JSApi.{$ENDIF}JS.isNumber(GetData) then
  915. Result:=Double(GetData)
  916. else
  917. raise EInvalidCast.Create(SErrInvalidTypecast);
  918. end;
  919. function TValue.ToString: String;
  920. begin
  921. Result := ToString(FormatSettings);
  922. end;
  923. function TValue.ToString(const AFormatSettings: TFormatSettings): String;
  924. begin
  925. if IsEmpty then
  926. Exit('(empty)');
  927. case Kind of
  928. tkBool: Result := BoolToStr(AsBoolean, True);
  929. tkClass:
  930. begin
  931. if Assigned(AsObject) then
  932. Result := AsObject.ClassName
  933. else
  934. Result := '(empty)';
  935. end;
  936. tkClassRef: Result := AsClass.ClassName;
  937. tkEnumeration: Result := GetEnumName(TTypeInfoEnum(TypeInfo), AsOrdinal);
  938. tkFloat: Result := FloatToStr(AsExtended, AFormatSettings);
  939. tkInteger: Result := IntToStr(AsNativeInt);
  940. tkString: Result := AsString;
  941. else
  942. Result := '';
  943. end;
  944. end;
  945. function TValue.GetArrayLength: SizeInt;
  946. begin
  947. if IsArray then
  948. Exit(Length(TJSValueDynArray(GetData)));
  949. raise EInvalidCast.Create(SErrInvalidTypecast);
  950. end;
  951. function TValue.GetArrayElement(aIndex: SizeInt): TValue;
  952. begin
  953. if IsArray then
  954. begin
  955. case Kind of
  956. tkArray: Result.FTypeInfo:=TTypeInfoStaticArray(FTypeInfo).ElType;
  957. tkDynArray: Result.FTypeInfo:=TTypeInfoDynArray(FTypeInfo).ElType;
  958. end;
  959. Result.SetData(TJSValueDynArray(GetData)[aIndex]);
  960. end
  961. else
  962. raise EInvalidCast.Create(SErrInvalidTypecast);
  963. end;
  964. procedure TValue.SetArrayLength(const Size: SizeInt);
  965. var
  966. NewArray: TJSValueDynArray;
  967. begin
  968. NewArray := TJSValueDynArray(GetData);
  969. SetLength(NewArray, Size);
  970. SetData(NewArray);
  971. end;
  972. procedure TValue.SetArrayElement(aIndex: SizeInt; const AValue: TValue);
  973. begin
  974. if IsArray then
  975. TJSValueDynArray(GetData)[aIndex] := AValue.AsJSValue
  976. else
  977. raise EInvalidCast.Create(SErrInvalidTypecast);
  978. end;
  979. function TValue.GetReferenceToRawData: Pointer;
  980. begin
  981. Result := Pointer(GetData);
  982. end;
  983. function TValue.IsType(ATypeInfo: TTypeInfo): boolean;
  984. begin
  985. Result := ATypeInfo = TypeInfo;
  986. end;
  987. function TValue.GetData: JSValue;
  988. begin
  989. if FReferenceVariableData then
  990. Result := TReferenceVariable(FData).Get
  991. else
  992. Result := FData;
  993. end;
  994. procedure TValue.SetData(const Value: JSValue);
  995. begin
  996. if FReferenceVariableData then
  997. TReferenceVariable(FData).&Set(Value)
  998. else
  999. FData := Value;
  1000. end;
  1001. function TValue.GetIsEmpty: boolean;
  1002. begin
  1003. if (TypeInfo=nil) or (GetData=Undefined) or (GetData=nil) then
  1004. exit(true);
  1005. case TypeInfo.Kind of
  1006. tkDynArray:
  1007. Result:=GetArrayLength=0;
  1008. else
  1009. Result:=false;
  1010. end;
  1011. end;
  1012. function TValue.AsJSValue: JSValue;
  1013. begin
  1014. Result := GetData;
  1015. end;
  1016. class function TValue.Empty: TValue;
  1017. begin
  1018. Result.SetData(nil);
  1019. Result.FTypeInfo := nil;
  1020. end;
  1021. { TRttiStructuredType }
  1022. function TRttiStructuredType.GetMethods: TRttiMethodArray;
  1023. var
  1024. A, Start: Integer;
  1025. BaseClass: TRttiStructuredType;
  1026. Declared: TRttiMethodArray;
  1027. begin
  1028. BaseClass := Self;
  1029. Result := nil;
  1030. while Assigned(BaseClass) do
  1031. begin
  1032. Declared := BaseClass.GetDeclaredMethods;
  1033. Start := Length(Result);
  1034. SetLength(Result, Start + Length(Declared));
  1035. for A := Low(Declared) to High(Declared) do
  1036. Result[Start + A] := Declared[A];
  1037. BaseClass := BaseClass.GetAncestor;
  1038. end;
  1039. end;
  1040. function TRttiStructuredType.GetMethods(const aName: String): TRttiMethodArray;
  1041. var
  1042. Method: TRttiMethod;
  1043. MethodCount: Integer;
  1044. begin
  1045. MethodCount := 0;
  1046. for Method in GetMethods do
  1047. if aName = Method.Name then
  1048. Inc(MethodCount);
  1049. SetLength(Result, MethodCount);
  1050. for Method in GetMethods do
  1051. if aName = Method.Name then
  1052. begin
  1053. Dec(MethodCount);
  1054. Result[MethodCount] := Method;
  1055. end;
  1056. end;
  1057. function TRttiStructuredType.GetProperties: TRttiPropertyArray;
  1058. var
  1059. A, Start: Integer;
  1060. BaseClass: TRttiStructuredType;
  1061. Declared: TRttiPropertyArray;
  1062. begin
  1063. BaseClass := Self;
  1064. Result := nil;
  1065. while Assigned(BaseClass) do
  1066. begin
  1067. Declared := BaseClass.GetDeclaredProperties;
  1068. Start := Length(Result);
  1069. SetLength(Result, Start + Length(Declared));
  1070. for A := Low(Declared) to High(Declared) do
  1071. Result[Start + A] := Declared[A];
  1072. BaseClass := BaseClass.GetAncestor;
  1073. end;
  1074. end;
  1075. function TRttiStructuredType.GetMethod(const aName: String): TRttiMethod;
  1076. var
  1077. Method: TRttiMethod;
  1078. begin
  1079. for Method in GetMethods do
  1080. if aName = Method.Name then
  1081. Exit(Method);
  1082. end;
  1083. function TRttiStructuredType.GetProperty(const AName: string): TRttiProperty;
  1084. var
  1085. Prop: TRttiProperty;
  1086. lName: String;
  1087. begin
  1088. lName := LowerCase(AName);
  1089. for Prop in GetProperties do
  1090. if lowercase(Prop.Name) = lName then
  1091. Exit(Prop);
  1092. Result:=nil;
  1093. end;
  1094. function TRttiStructuredType.GetDeclaredProperties: TRttiPropertyArray;
  1095. var
  1096. A, PropCount: Integer;
  1097. begin
  1098. if not Assigned(FProperties) then
  1099. begin
  1100. PropCount := StructTypeInfo.PropCount;
  1101. SetLength(FProperties, PropCount);
  1102. for A := 0 to Pred(PropCount) do
  1103. FProperties[A] := TRttiProperty.Create(Self, StructTypeInfo.GetProp(A));
  1104. end;
  1105. Result := FProperties;
  1106. end;
  1107. function TRttiStructuredType.GetAncestor: TRttiStructuredType;
  1108. begin
  1109. Result := nil;
  1110. end;
  1111. function TRttiStructuredType.GetStructTypeInfo: TTypeInfoStruct;
  1112. begin
  1113. Result:=TTypeInfoStruct(inherited Handle);
  1114. end;
  1115. constructor TRttiStructuredType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  1116. begin
  1117. if not (TTypeInfo(ATypeInfo) is TTypeInfoStruct) then
  1118. raise EInvalidCast.Create('');
  1119. inherited;
  1120. end;
  1121. destructor TRttiStructuredType.Destroy;
  1122. var
  1123. Method: TRttiMethod;
  1124. Prop: TRttiProperty;
  1125. begin
  1126. for Method in FMethods do
  1127. Method.Free;
  1128. for Prop in FProperties do
  1129. Prop.Free;
  1130. inherited Destroy;
  1131. end;
  1132. function TRttiStructuredType.GetDeclaredMethods: TRttiMethodArray;
  1133. var
  1134. A, MethodCount: Integer;
  1135. begin
  1136. if not Assigned(FMethods) then
  1137. begin
  1138. MethodCount := StructTypeInfo.MethodCount;
  1139. SetLength(FMethods, MethodCount);
  1140. for A := 0 to Pred(MethodCount) do
  1141. FMethods[A] := TRttiMethod.Create(Self, StructTypeInfo.GetMethod(A));
  1142. end;
  1143. Result := FMethods;
  1144. end;
  1145. function TRttiStructuredType.GetDeclaredFields: TRttiFieldArray;
  1146. var
  1147. A, FieldCount: Integer;
  1148. begin
  1149. if not Assigned(FFields) then
  1150. begin
  1151. FieldCount := StructTypeInfo.FieldCount;
  1152. SetLength(FFields, FieldCount);
  1153. for A := 0 to Pred(FieldCount) do
  1154. FFields[A] := TRttiField.Create(Self, StructTypeInfo.GetField(A));
  1155. end;
  1156. Result := FFields;
  1157. end;
  1158. function TRttiStructuredType.GetFields: TRttiFieldArray;
  1159. var
  1160. A, Start: Integer;
  1161. BaseClass: TRttiStructuredType;
  1162. Declared: TRttiFieldArray;
  1163. begin
  1164. BaseClass := Self;
  1165. Result := nil;
  1166. while Assigned(BaseClass) do
  1167. begin
  1168. Declared := BaseClass.GetDeclaredFields;
  1169. Start := Length(Result);
  1170. SetLength(Result, Start + Length(Declared));
  1171. for A := Low(Declared) to High(Declared) do
  1172. Result[Start + A] := Declared[A];
  1173. BaseClass := BaseClass.GetAncestor;
  1174. end;
  1175. end;
  1176. { TRttiInstanceType }
  1177. function TRttiInstanceType.GetClassTypeInfo: TTypeInfoClass;
  1178. begin
  1179. Result:=TTypeInfoClass(inherited Handle);
  1180. end;
  1181. function TRttiInstanceType.GetMetaClassType: TClass;
  1182. begin
  1183. Result:=ClassTypeInfo.ClassType;
  1184. end;
  1185. function TRttiInstanceType.GetAncestor: TRttiStructuredType;
  1186. begin
  1187. Result := GetAncestorType;
  1188. end;
  1189. function TRttiInstanceType.GetBaseType: TRttiType;
  1190. begin
  1191. Result:=GetAncestorType;
  1192. end;
  1193. function TRttiInstanceType.GetAncestorType: TRttiInstanceType;
  1194. begin
  1195. Result := inherited Parent as TRttiInstanceType;
  1196. end;
  1197. constructor TRttiInstanceType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  1198. begin
  1199. if not (TTypeInfo(ATypeInfo) is TTypeInfoClass) then
  1200. raise EInvalidCast.Create('');
  1201. inherited;
  1202. end;
  1203. { TRttiInterfaceType }
  1204. constructor TRttiInterfaceType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  1205. begin
  1206. if not (TTypeInfo(ATypeInfo) is TTypeInfoInterface) then
  1207. raise EInvalidCast.Create('');
  1208. inherited;
  1209. end;
  1210. function TRttiInterfaceType.GetGUID: TGUID;
  1211. var
  1212. GUID: String;
  1213. begin
  1214. GUID := InterfaceTypeInfo.InterfaceInfo.GUID;
  1215. TryStringToGUID(GUID, Result);
  1216. end;
  1217. function TRttiInterfaceType.GetInterfaceTypeInfo: TTypeInfoInterface;
  1218. begin
  1219. Result := TTypeInfoInterface(inherited Handle);
  1220. end;
  1221. function TRttiInterfaceType.GetAncestor: TRttiStructuredType;
  1222. begin
  1223. Result := GetAncestorType;
  1224. end;
  1225. function TRttiInterfaceType.GetBaseType: TRttiType;
  1226. begin
  1227. Result := GetAncestorType;
  1228. end;
  1229. function TRttiInterfaceType.GetAncestorType: TRttiInterfaceType;
  1230. begin
  1231. Result := Pool.GetType(InterfaceTypeInfo.Ancestor) as TRttiInterfaceType;
  1232. end;
  1233. { TRttiRecordType }
  1234. function TRttiRecordType.GetRecordTypeInfo: TTypeInfoRecord;
  1235. begin
  1236. Result := TTypeInfoRecord(inherited Handle);
  1237. end;
  1238. function TRttiRecordType.GetIsRecord: Boolean;
  1239. begin
  1240. Result := True;
  1241. end;
  1242. constructor TRttiRecordType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  1243. begin
  1244. if not (TTypeInfo(ATypeInfo) is TTypeInfoRecord) then
  1245. raise EInvalidCast.Create('');
  1246. inherited;
  1247. end;
  1248. { TRttiClassRefType }
  1249. constructor TRttiClassRefType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  1250. begin
  1251. if not (TTypeInfo(ATypeInfo) is TTypeInfoClassRef) then
  1252. raise EInvalidCast.Create('');
  1253. inherited;
  1254. end;
  1255. function TRttiClassRefType.GetClassRefTypeInfo: TTypeInfoClassRef;
  1256. begin
  1257. Result := TTypeInfoClassRef(inherited Handle);
  1258. end;
  1259. function TRttiClassRefType.GetInstanceType: TRttiInstanceType;
  1260. begin
  1261. Result := Pool.GetType(ClassRefTypeInfo.InstanceType) as TRttiInstanceType;
  1262. end;
  1263. function TRttiClassRefType.GetMetaclassType: TClass;
  1264. begin
  1265. Result := InstanceType.MetaClassType;
  1266. end;
  1267. { TRttiInstanceExternalType }
  1268. function TRttiInstanceExternalType.GetAncestor: TRttiInstanceExternalType;
  1269. begin
  1270. Result := Pool.GetType(ExternalClassTypeInfo.Ancestor) as TRttiInstanceExternalType;
  1271. end;
  1272. function TRttiInstanceExternalType.GetExternalClassTypeInfo: TTypeInfoExtClass;
  1273. begin
  1274. Result := TTypeInfoExtClass(inherited Handle);
  1275. end;
  1276. function TRttiInstanceExternalType.GetExternalName: String;
  1277. begin
  1278. Result := ExternalClassTypeInfo.JSClassName;
  1279. end;
  1280. constructor TRttiInstanceExternalType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  1281. begin
  1282. if not (TTypeInfo(ATypeInfo) is TTypeInfoExtClass) then
  1283. raise EInvalidCast.Create('');
  1284. inherited;
  1285. end;
  1286. { TRTTIContext }
  1287. class function TRTTIContext.Create: TRTTIContext;
  1288. begin
  1289. Pool.AcquireContext;
  1290. end;
  1291. procedure TRTTIContext.Free;
  1292. begin
  1293. Pool.ReleaseContext;
  1294. end;
  1295. function TRTTIContext.GetType(aTypeInfo: PTypeInfo): TRttiType;
  1296. begin
  1297. Result := Pool.GetType(aTypeInfo);
  1298. end;
  1299. function TRTTIContext.GetType(aClass: TClass): TRTTIType;
  1300. begin
  1301. Result := Pool.GetType(aClass);
  1302. end;
  1303. function TRTTIContext.FindType(const AQualifiedName: String): TRttiType;
  1304. begin
  1305. Result := Pool.FindType(AQualifiedName);
  1306. end;
  1307. function TRTTIContext.GetTypes: specialize TArray<TRttiType>;
  1308. var
  1309. ModuleName, ClassName: String;
  1310. ModuleTypes: TSectionRTTI;
  1311. begin
  1312. for ModuleName in TJSObject.Keys(pas) do
  1313. begin
  1314. ModuleTypes := TTypeInfoModule(pas[ModuleName]).RTTI;
  1315. for ClassName in ModuleTypes do
  1316. if ClassName[1] <> '$' then
  1317. GetType(PTypeInfo(ModuleTypes[ClassName]));
  1318. end;
  1319. Result := specialize TArray<TRttiType>(TJSObject.Values(Pool.FTypes));
  1320. end;
  1321. class procedure TRTTIContext.KeepContext;
  1322. begin
  1323. Pool.AcquireContext;
  1324. end;
  1325. class procedure TRTTIContext.DropContext;
  1326. begin
  1327. Pool.ReleaseContext;
  1328. end;
  1329. { TRttiObject }
  1330. constructor TRttiObject.Create(AParent: TRttiObject; AHandle: Pointer);
  1331. begin
  1332. FParent := AParent;
  1333. FHandle := AHandle;
  1334. end;
  1335. destructor TRttiObject.Destroy;
  1336. var
  1337. Attribute: TCustomAttribute;
  1338. begin
  1339. for Attribute in FAttributes do
  1340. Attribute.Free;
  1341. FAttributes := nil;
  1342. inherited Destroy;
  1343. end;
  1344. function TRttiObject.LoadCustomAttributes: TCustomAttributeArray;
  1345. begin
  1346. Result := nil;
  1347. end;
  1348. function TRttiObject.GetAttributes: TCustomAttributeArray;
  1349. begin
  1350. if not FAttributesLoaded then
  1351. begin
  1352. FAttributes := LoadCustomAttributes;
  1353. FAttributesLoaded := True;
  1354. end;
  1355. Result := FAttributes;
  1356. end;
  1357. function TRttiObject.GetAttribute(const Attribute: TCustomAttributeClass): TCustomAttribute;
  1358. var
  1359. CustomAttribute: TCustomAttribute;
  1360. begin
  1361. Result := nil;
  1362. for CustomAttribute in GetAttributes do
  1363. if CustomAttribute is Attribute then
  1364. Exit(CustomAttribute);
  1365. end;
  1366. generic function TRttiObject.GetAttribute<T>: T;
  1367. begin
  1368. Result := T(GetAttribute(TCustomAttributeClass(T.ClassType)));
  1369. end;
  1370. function TRttiObject.HasAttribute(const Attribute: TCustomAttributeClass): Boolean;
  1371. begin
  1372. Result := GetAttribute(Attribute) <> nil;
  1373. end;
  1374. generic function TRttiObject.HasAttribute<T>: Boolean;
  1375. begin
  1376. Result := HasAttribute(TCustomAttributeClass(T.ClassType));
  1377. end;
  1378. { TRttiNamedObject }
  1379. function TRttiNamedObject.GetName: string;
  1380. begin
  1381. Result:='';
  1382. end;
  1383. { TRttiMember }
  1384. function TRttiMember.GetName: string;
  1385. begin
  1386. Result := MemberTypeInfo.Name;
  1387. end;
  1388. function TRttiMember.GetParent: TRttiType;
  1389. begin
  1390. Result := TRttiType(inherited Parent);
  1391. end;
  1392. function TRttiMember.GetVisibility: TMemberVisibility;
  1393. begin
  1394. Result := mvPublished;
  1395. end;
  1396. constructor TRttiMember.Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  1397. begin
  1398. if not (ATypeInfo is TTypeMember) then
  1399. raise EInvalidCast.Create('');
  1400. inherited Create(AParent, ATypeInfo);
  1401. end;
  1402. function TRttiMember.LoadCustomAttributes: TCustomAttributeArray;
  1403. begin
  1404. Result := GetRTTIAttributes(MemberTypeInfo.Attributes);
  1405. end;
  1406. function TRttiMember.GetMemberTypeInfo: TTypeMember;
  1407. begin
  1408. Result := TTypeMember(inherited Handle);
  1409. end;
  1410. { TRttiField }
  1411. constructor TRttiField.Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  1412. begin
  1413. if not (ATypeInfo is TTypeMemberField) then
  1414. raise EInvalidCast.Create('');
  1415. inherited;
  1416. end;
  1417. function TRttiField.GetFieldType: TRttiType;
  1418. begin
  1419. Result := Pool.GetType(FieldTypeInfo.TypeInfo);
  1420. end;
  1421. function TRttiField.GetFieldTypeInfo: TTypeMemberField;
  1422. begin
  1423. Result := TTypeMemberField(inherited Handle);
  1424. end;
  1425. function TRttiField.GetValue(Instance: JSValue): TValue;
  1426. var
  1427. JSInstance: TJSObject absolute Instance;
  1428. begin
  1429. Result := TValue.FromJSValue(JSInstance[Name]);
  1430. end;
  1431. procedure TRttiField.SetValue(Instance: JSValue; const AValue: TValue);
  1432. var
  1433. JSInstance: TJSObject absolute Instance;
  1434. begin
  1435. JSInstance[Name] := AValue.Cast(FieldType.Handle, True).ASJSValue;
  1436. end;
  1437. { TRttiParameter }
  1438. function TRttiParameter.GetName: String;
  1439. begin
  1440. Result := FName;
  1441. end;
  1442. { TRttiMethod }
  1443. function TRttiMethod.GetMethodTypeInfo: TTypeMemberMethod;
  1444. begin
  1445. Result := TTypeMemberMethod(inherited Handle);
  1446. end;
  1447. function TRttiMethod.GetIsClassMethod: Boolean;
  1448. begin
  1449. Result:=MethodTypeInfo.MethodKind in [mkClassFunction,mkClassProcedure];
  1450. end;
  1451. function TRttiMethod.GetIsConstructor: Boolean;
  1452. begin
  1453. Result:=MethodTypeInfo.MethodKind=mkConstructor;
  1454. end;
  1455. function TRttiMethod.GetIsDestructor: Boolean;
  1456. begin
  1457. Result:=MethodTypeInfo.MethodKind=mkDestructor;
  1458. end;
  1459. function TRttiMethod.GetIsExternal: Boolean;
  1460. begin
  1461. Result := pfExternal in GetProcedureFlags;
  1462. end;
  1463. function TRttiMethod.GetIsStatic: Boolean;
  1464. begin
  1465. Result := pfStatic in GetProcedureFlags;
  1466. end;
  1467. function TRttiMethod.GetIsVarArgs: Boolean;
  1468. begin
  1469. Result := pfVarargs in GetProcedureFlags;
  1470. end;
  1471. function TRttiMethod.GetIsAsyncCall: Boolean;
  1472. begin
  1473. Result := (pfAsync in GetProcedureFlags) or Assigned(ReturnType) and ReturnType.IsInstanceExternal and (ReturnType.AsInstanceExternal.ExternalName = 'Promise');
  1474. end;
  1475. function TRttiMethod.GetIsSafeCall: Boolean;
  1476. begin
  1477. Result := pfSafeCall in GetProcedureFlags;
  1478. end;
  1479. function TRttiMethod.GetMethodKind: TMethodKind;
  1480. begin
  1481. Result:=MethodTypeInfo.MethodKind;;
  1482. end;
  1483. function TRttiMethod.GetProcedureFlags: TProcedureFlags;
  1484. const
  1485. PROCEDURE_FLAGS: array[TProcedureFlag] of NativeInt = (1, 2, 4, 8, 16);
  1486. var
  1487. Flag: TProcedureFlag;
  1488. ProcedureFlags: NativeInt;
  1489. begin
  1490. ProcedureFlags := MethodTypeInfo.ProcSig.Flags;
  1491. Result := [];
  1492. for Flag := Low(PROCEDURE_FLAGS) to High(PROCEDURE_FLAGS) do
  1493. if PROCEDURE_FLAGS[Flag] and ProcedureFlags > 0 then
  1494. Result := Result + [Flag];
  1495. end;
  1496. function TRttiMethod.GetReturnType: TRttiType;
  1497. begin
  1498. Result := Pool.GetType(MethodTypeInfo.ProcSig.ResultType);
  1499. end;
  1500. procedure TRttiMethod.LoadParameters;
  1501. const
  1502. FLAGS_CONVERSION: array[TParamFlag] of NativeInt = (1, 2, 4, 8, 16, 32);
  1503. var
  1504. A: Integer;
  1505. Flag: TParamFlag;
  1506. Param: TProcedureParam;
  1507. RttiParam: TRttiParameter;
  1508. MethodParams: TProcedureParams;
  1509. begin
  1510. FParametersLoaded := True;
  1511. MethodParams := MethodTypeInfo.ProcSig.Params;
  1512. SetLength(FParameters, Length(MethodParams));
  1513. for A := Low(FParameters) to High(FParameters) do
  1514. begin
  1515. Param := MethodParams[A];
  1516. RttiParam := TRttiParameter.Create(Self, Param);
  1517. RttiParam.FName := Param.Name;
  1518. RttiParam.FParamType := Pool.GetType(Param.TypeInfo);
  1519. for Flag := Low(FLAGS_CONVERSION) to High(FLAGS_CONVERSION) do
  1520. if FLAGS_CONVERSION[Flag] and Param.Flags > 0 then
  1521. RttiParam.FFlags := RttiParam.FFlags + [Flag];
  1522. FParameters[A] := RttiParam;
  1523. end;
  1524. end;
  1525. function TRttiMethod.GetParameters: TRttiParameterArray;
  1526. begin
  1527. if not FParametersLoaded then
  1528. LoadParameters;
  1529. Result := FParameters;
  1530. end;
  1531. function TRttiMethod.Invoke(const Instance: TValue; const Args: array of TValue): TValue;
  1532. var
  1533. A: Integer;
  1534. AArgs: TJSValueDynArray;
  1535. ReturnValue: JSValue;
  1536. begin
  1537. SetLength(AArgs, Length(Args));
  1538. for A := Low(Args) to High(Args) do
  1539. AArgs[A] := Args[A].AsJSValue;
  1540. ReturnValue := TJSFunction(TJSObject(Instance.AsJSValue)[Name]).apply(TJSObject(Instance.AsJSValue), AArgs);
  1541. if Assigned(ReturnType) then
  1542. TValue.Make(ReturnValue, ReturnType.Handle, Result)
  1543. else if IsConstructor then
  1544. TValue.Make(ReturnValue, Instance.TypeInfo, Result)
  1545. end;
  1546. function TRttiMethod.Invoke(const Instance: TObject; const Args: array of TValue): TValue;
  1547. var
  1548. v: TValue;
  1549. begin
  1550. TValue.Make(Instance, Instance.ClassInfo, v);
  1551. Result := Invoke(v, Args);
  1552. end;
  1553. function TRttiMethod.Invoke(const aClass: TClass; const Args: array of TValue): TValue;
  1554. var
  1555. v: TValue;
  1556. begin
  1557. TValue.Make(aClass, aClass.ClassInfo, v);
  1558. Result := Invoke(V, Args);
  1559. end;
  1560. { TRttiProperty }
  1561. constructor TRttiProperty.Create(AParent: TRttiType; ATypeInfo: TTypeMember);
  1562. begin
  1563. if not (ATypeInfo is TTypeMemberProperty) then
  1564. raise EInvalidCast.Create('');
  1565. inherited;
  1566. end;
  1567. function TRttiProperty.GetPropertyTypeInfo: TTypeMemberProperty;
  1568. begin
  1569. Result := TTypeMemberProperty(inherited Handle);
  1570. end;
  1571. function TRttiProperty.GetValue(Instance: JSValue): TValue;
  1572. var
  1573. JSObject: TJSObject absolute Instance;
  1574. begin
  1575. TValue.Make(GetJSValueProp(JSObject, PropertyTypeInfo), PropertyType.Handle, Result);
  1576. end;
  1577. procedure TRttiProperty.SetValue(Instance: JSValue; const AValue: TValue);
  1578. var
  1579. JSInstance: TJSObject absolute Instance;
  1580. begin
  1581. SetJSValueProp(JSInstance, PropertyTypeInfo, AValue.Cast(PropertyType.Handle, True).AsJSValue);
  1582. end;
  1583. function TRttiProperty.GetPropertyType: TRttiType;
  1584. begin
  1585. Result := Pool.GetType(PropertyTypeInfo.TypeInfo);
  1586. end;
  1587. function TRttiProperty.GetIsWritable: boolean;
  1588. begin
  1589. Result := PropertyTypeInfo.Setter<>'';
  1590. end;
  1591. function TRttiProperty.GetIsReadable: boolean;
  1592. begin
  1593. Result := PropertyTypeInfo.Getter<>'';
  1594. end;
  1595. function TRttiProperty.GetVisibility: TMemberVisibility;
  1596. begin
  1597. // At this moment only published rtti-property-info is supported by pas2js
  1598. Result := mvPublished;
  1599. end;
  1600. { TRttiType }
  1601. function TRttiType.GetName: string;
  1602. begin
  1603. Result := Handle.Name;
  1604. end;
  1605. function TRttiType.GetIsInstance: boolean;
  1606. begin
  1607. Result:=Self is TRttiInstanceType;
  1608. end;
  1609. function TRttiType.GetIsInstanceExternal: boolean;
  1610. begin
  1611. Result:=Self is TRttiInstanceExternalType;
  1612. end;
  1613. function TRttiType.GetIsOrdinal: boolean;
  1614. begin
  1615. Result:=false;
  1616. end;
  1617. function TRttiType.GetIsRecord: boolean;
  1618. begin
  1619. Result:=false;
  1620. end;
  1621. function TRttiType.GetIsSet: boolean;
  1622. begin
  1623. Result:=false;
  1624. end;
  1625. function TRttiType.GetTypeKind: TTypeKind;
  1626. begin
  1627. Result:=Handle.Kind;
  1628. end;
  1629. function TRttiType.GetHandle: TTypeInfo;
  1630. begin
  1631. Result := TTypeInfo(inherited Handle);
  1632. end;
  1633. function TRttiType.GetBaseType: TRttiType;
  1634. begin
  1635. Result:=Nil;
  1636. end;
  1637. function TRttiType.GetAsInstance: TRttiInstanceType;
  1638. begin
  1639. Result := Self as TRttiInstanceType;
  1640. end;
  1641. function TRttiType.GetAsInstanceExternal: TRttiInstanceExternalType;
  1642. begin
  1643. Result := Self as TRttiInstanceExternalType;
  1644. end;
  1645. function TRttiType.LoadCustomAttributes: TCustomAttributeArray;
  1646. begin
  1647. Result:=GetRTTIAttributes(Handle.Attributes);
  1648. end;
  1649. function TRttiType.GetDeclaredProperties: TRttiPropertyArray;
  1650. begin
  1651. Result:=nil;
  1652. end;
  1653. function TRttiType.GetProperties: TRttiPropertyArray;
  1654. begin
  1655. Result:=nil;
  1656. end;
  1657. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  1658. begin
  1659. Result:=nil;
  1660. if AName='' then ;
  1661. end;
  1662. function TRttiType.GetMethods: TRttiMethodArray;
  1663. begin
  1664. Result:=nil;
  1665. end;
  1666. function TRttiType.GetMethods(const aName: String): TRttiMethodArray;
  1667. begin
  1668. Result:=nil;
  1669. end;
  1670. function TRttiType.GetMethod(const aName: String): TRttiMethod;
  1671. begin
  1672. Result:=nil;
  1673. if aName='' then ;
  1674. end;
  1675. function TRttiType.GetDeclaredMethods: TRttiMethodArray;
  1676. begin
  1677. Result:=nil;
  1678. end;
  1679. function TRttiType.GetDeclaredFields: TRttiFieldArray;
  1680. begin
  1681. Result:=nil;
  1682. end;
  1683. function TRttiType.GetField(const AName: string): TRttiField;
  1684. var
  1685. AField: TRttiField;
  1686. begin
  1687. Result:=nil;
  1688. for AField in GetFields do
  1689. if AField.Name = AName then
  1690. Exit(AField);
  1691. end;
  1692. function TRttiType.GetFields: TRttiFieldArray;
  1693. begin
  1694. Result := nil;
  1695. end;
  1696. function TRttiType.GetDeclaringUnitName: String;
  1697. begin
  1698. Result := Handle.Module.Name;
  1699. end;
  1700. function TRttiType.GetQualifiedName: String;
  1701. begin
  1702. Result := Format('%s.%s', [DeclaringUnitName, Name]);
  1703. end;
  1704. { TRttiPointerType }
  1705. constructor TRttiPointerType.Create(AParent: TRttiObject; ATypeInfo: PTypeInfo);
  1706. begin
  1707. if not (TTypeInfo(ATypeInfo) is TTypeInfoPointer) then
  1708. raise EInvalidCast.Create('');
  1709. inherited;
  1710. end;
  1711. function TRttiPointerType.GetRefType: TRttiType;
  1712. begin
  1713. Result := Pool.GetType(RefTypeInfo.RefType);
  1714. end;
  1715. function TRttiPointerType.GetRefTypeInfo: TTypeInfoPointer;
  1716. begin
  1717. Result := TTypeInfoPointer(inherited Handle);
  1718. end;
  1719. { TVirtualInterface }
  1720. constructor TVirtualInterface.Create(InterfaceTypeInfo: TTypeInfoInterface);
  1721. var
  1722. SelfInterfaceObject, InterfaceObject: TInterfaceObject;
  1723. Method: TRttiMethod;
  1724. MethodName: String;
  1725. begin
  1726. FContext := TRttiContext.Create;
  1727. FInterfaceType := FContext.GetType(InterfaceTypeInfo) as TRttiInterfaceType;
  1728. if FInterfaceType.InterfaceTypeInfo.InterfaceInfo.kind <> 'com' then
  1729. raise EInvalidCast.Create;
  1730. InterfaceObject := TInterfaceObject(TJSObject.Create(FInterfaceType.InterfaceTypeInfo.InterfaceInfo));
  1731. InterfaceObject.Obj := Self;
  1732. for Method in FInterfaceType.GetMethods do
  1733. begin
  1734. asm
  1735. let MethodName = Method.GetName();
  1736. end;
  1737. InterfaceObject[MethodName] :=
  1738. function: JSValue
  1739. begin
  1740. Result := TVirtualInterface(TInterfaceObject(JSThis).Obj).Invoke(MethodName, TJSValueDynArray(JSValue(JSArguments)));
  1741. end;
  1742. end;
  1743. InterfaceObject['_AddRef'] := @_AddRef;
  1744. InterfaceObject['_Release'] := @_Release;
  1745. InterfaceObject['QueryInterface'] := @QueryInterface;
  1746. SelfInterfaceObject := TInterfaceObject(TJSObject(Self));
  1747. SelfInterfaceObject.InterfaceMaps := TJSObject.New;
  1748. SelfInterfaceObject.InterfaceMaps[GUIDToString(IInterface)] := InterfaceObject;
  1749. SelfInterfaceObject.InterfaceMaps[FInterfaceType.Guid.ToString] := TJSObject.New;
  1750. SelfInterfaceObject.Interfaces := TJSObject.New;
  1751. SelfInterfaceObject.Interfaces[FInterfaceType.Guid.ToString] := InterfaceObject;
  1752. end;
  1753. constructor TVirtualInterface.Create(InterfaceTypeInfo: TTypeInfoInterface; const InvokeEvent: TVirtualInterfaceInvokeEvent);
  1754. begin
  1755. Create(InterfaceTypeInfo);
  1756. OnInvoke := InvokeEvent;
  1757. end;
  1758. constructor TVirtualInterface.Create(InterfaceTypeInfo: TTypeInfoInterface; const InvokeEvent: TVirtualInterfaceInvokeEventJS);
  1759. begin
  1760. Create(InterfaceTypeInfo);
  1761. OnInvokeJS := InvokeEvent;
  1762. end;
  1763. destructor TVirtualInterface.Destroy;
  1764. begin
  1765. FContext.Free;
  1766. inherited;
  1767. end;
  1768. function TVirtualInterface.QueryInterface(const iid: TGuid; out obj): Integer;
  1769. begin
  1770. Result := inherited QueryInterface(iid, obj);
  1771. end;
  1772. function TVirtualInterface.Invoke(const MethodName: String; const Args: TJSValueDynArray): JSValue;
  1773. var
  1774. Method: TRttiMethod;
  1775. Return: TValue;
  1776. function GenerateParams: specialize TArray<TValue>;
  1777. var
  1778. A: Integer;
  1779. Param: TRttiParameter;
  1780. Parameters: specialize TArray<TRttiParameter>;
  1781. begin
  1782. Parameters := Method.GetParameters;
  1783. SetLength(Result, Length(Parameters));
  1784. for A := Low(Parameters) to High(Parameters) do
  1785. begin
  1786. Param := Parameters[A];
  1787. TValue.Make(Args[A], Param.ParamType.Handle, Result[A]);
  1788. Result[A].FReferenceVariableData := (pfVar in Param.Flags) or (pfOut in Param.Flags);
  1789. end;
  1790. end;
  1791. begin
  1792. if Assigned(FOnInvokeJS) then
  1793. Result := FOnInvokeJS(MethodName, Args)
  1794. else
  1795. begin
  1796. Method := FInterfaceType.GetMethod(MethodName);
  1797. FOnInvoke(Method, GenerateParams, Return);
  1798. Result := Return.AsJSValue;
  1799. end;
  1800. end;
  1801. function Invoke(ACodeAddress: Pointer; const AArgs: TJSValueDynArray;
  1802. ACallConv: TCallConv; AResultType: PTypeInfo; AIsStatic: Boolean;
  1803. AIsConstructor: Boolean): TValue;
  1804. begin
  1805. if ACallConv=ccReg then ;
  1806. if AIsStatic then ;
  1807. if AIsConstructor then
  1808. raise EInvoke.Create('not supported');
  1809. if isFunction(ACodeAddress) then
  1810. begin
  1811. Result.FData := TJSFunction(ACodeAddress).apply(nil, AArgs);
  1812. if AResultType<>nil then
  1813. Result.FTypeInfo:=AResultType
  1814. else
  1815. Result.FTypeInfo:=TypeInfo(JSValue);
  1816. end
  1817. else
  1818. raise EInvoke.Create(SErrInvokeInvalidCodeAddr);
  1819. end;
  1820. end.