system.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  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 System;
  11. {$mode objfpc}
  12. {$modeswitch externalclass}
  13. interface
  14. {$IFDEF NodeJS}
  15. var
  16. LineEnding: string = #10;
  17. sLineBreak: string = #10;
  18. {$ELSE}
  19. const
  20. LineEnding = #10;
  21. sLineBreak = LineEnding;
  22. {$ENDIF}
  23. Var
  24. PathDelim : Char = '/';
  25. AllowDirectorySeparators : Set of Char = ['/'];
  26. AllowDriveSeparators : Set of Char = [':'];
  27. ExtensionSeparator : Char = '.';
  28. const
  29. MaxSmallint = 32767;
  30. MinSmallint = -32768;
  31. MaxShortInt = 127;
  32. MinShortInt = -128;
  33. MaxByte = $FF;
  34. MaxWord = $FFFF;
  35. MaxLongint = $7fffffff;
  36. MaxCardinal = LongWord($ffffffff);
  37. Maxint = MaxLongint;
  38. IsMultiThread = false;
  39. {*****************************************************************************
  40. Base types
  41. *****************************************************************************}
  42. type
  43. Integer = LongInt;
  44. Cardinal = LongWord;
  45. DWord = LongWord;
  46. SizeInt = NativeInt;
  47. SizeUInt = NativeUInt;
  48. PtrInt = NativeInt;
  49. PtrUInt = NativeUInt;
  50. ValSInt = NativeInt;
  51. ValUInt = NativeUInt;
  52. ValReal = Double;
  53. Real = type Double;
  54. Extended = type Double;
  55. TDateTime = type double;
  56. TTime = type TDateTime;
  57. TDate = type TDateTime;
  58. Int64 = type NativeInt unimplemented; // only 53 bits at runtime
  59. UInt64 = type NativeUInt unimplemented; // only 52 bits at runtime
  60. QWord = type NativeUInt unimplemented; // only 52 bits at runtime
  61. Single = type Double unimplemented;
  62. Comp = type NativeInt unimplemented;
  63. NativeLargeInt = NativeInt;
  64. NativeLargeUInt = NativeUInt;
  65. UnicodeString = type String;
  66. WideString = type String;
  67. WideChar = char;
  68. UnicodeChar = char;
  69. TDynArrayIndex = NativeInt;
  70. TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR);
  71. {*****************************************************************************
  72. TObject, TClass, IUnknown, IInterface, TInterfacedObject
  73. *****************************************************************************}
  74. type
  75. TGuid = record
  76. D1: DWord;
  77. D2: word;
  78. D3: word;
  79. D4: array[0..7] of byte;
  80. end;
  81. TGUIDString = type string;
  82. TClass = class of TObject;
  83. { TObject }
  84. TObject = class
  85. private
  86. class var FClassName: String; external name '$classname';
  87. class var FClassParent: TClass; external name '$ancestor';
  88. class var FUnitName: String; external name '$module.$name';
  89. public
  90. constructor Create;
  91. destructor Destroy; virtual;
  92. // Free is using compiler magic.
  93. // Reasons:
  94. // 1. In JS calling obj.Free when obj=nil would crash.
  95. // 2. In JS freeing memory requires to set all references to nil.
  96. // Therefore any obj.free call is replaced by the compiler with some rtl magic.
  97. procedure Free;
  98. class function ClassType: TClass; assembler;
  99. class property ClassName: String read FClassName;
  100. class function ClassNameIs(const Name: string): boolean;
  101. class property ClassParent: TClass read FClassParent;
  102. class function InheritsFrom(aClass: TClass): boolean; assembler;
  103. class property UnitName: String read FUnitName;
  104. procedure AfterConstruction; virtual;
  105. procedure BeforeDestruction; virtual;
  106. function GetInterface(const iid: TGuid; out obj): boolean;
  107. function GetInterface(const iidstr: String; out obj): boolean; inline;
  108. function GetInterfaceByStr(const iidstr: String; out obj): boolean;
  109. function GetInterfaceWeak(const iid: TGuid; out obj): boolean; // equal to GetInterface but the interface returned is not referenced
  110. function Equals(Obj: TObject): boolean; virtual;
  111. function ToString: String; virtual;
  112. end;
  113. const
  114. { IInterface }
  115. S_OK = 0;
  116. S_FALSE = 1;
  117. E_NOINTERFACE = -2147467262; // FPC: longint($80004002)
  118. E_UNEXPECTED = -2147418113; // FPC: longint($8000FFFF)
  119. E_NOTIMPL = -2147467263; // FPC: longint($80004001)
  120. type
  121. {$Interfaces COM}
  122. IUnknown = interface
  123. ['{00000000-0000-0000-C000-000000000046}']
  124. function QueryInterface(const iid: TGuid; out obj): Integer;
  125. function _AddRef: Integer;
  126. function _Release: Integer;
  127. end;
  128. IInterface = IUnknown;
  129. {$M+}
  130. IInvokable = interface(IInterface)
  131. end;
  132. {$M-}
  133. { Enumerator support }
  134. IEnumerator = interface(IInterface)
  135. function GetCurrent: TObject;
  136. function MoveNext: Boolean;
  137. procedure Reset;
  138. property Current: TObject read GetCurrent;
  139. end;
  140. IEnumerable = interface(IInterface)
  141. function GetEnumerator: IEnumerator;
  142. end;
  143. { TInterfacedObject }
  144. TInterfacedObject = class(TObject,IUnknown)
  145. protected
  146. fRefCount: Integer;
  147. { implement methods of IUnknown }
  148. function QueryInterface(const iid: TGuid; out obj): Integer; virtual;
  149. function _AddRef: Integer; virtual;
  150. function _Release: Integer; virtual;
  151. public
  152. procedure BeforeDestruction; override;
  153. property RefCount: Integer read fRefCount;
  154. end;
  155. TInterfacedClass = class of TInterfacedObject;
  156. { TAggregatedObject - sub or satellite object using same interface as controller }
  157. TAggregatedObject = class(TObject)
  158. private
  159. fController: Pointer;
  160. function GetController: IUnknown;
  161. protected
  162. { implement methods of IUnknown }
  163. function QueryInterface(const iid: TGuid; out obj): Integer; virtual;
  164. function _AddRef: Integer; virtual;
  165. function _Release: Integer; virtual;
  166. public
  167. constructor Create(const aController: IUnknown); reintroduce;
  168. property Controller: IUnknown read GetController;
  169. end;
  170. { TContainedObject }
  171. TContainedObject = class(TAggregatedObject,IInterface)
  172. protected
  173. function QueryInterface(const iid: TGuid; out obj): Integer; override;
  174. end;
  175. const
  176. { for safe as operator support }
  177. IObjectInstance: TGuid = '{D91C9AF4-3C93-420F-A303-BF5BA82BFD23}';
  178. function GUIDToString(const GUID: TGUID): string; external name 'rtl.guidrToStr';
  179. {*****************************************************************************
  180. Init / Exit / ExitProc
  181. *****************************************************************************}
  182. var
  183. ExitCode: Integer; external name 'rtl.exitcode';
  184. IsConsole: Boolean = {$IFDEF NodeJS}true{$ELSE}false{$ENDIF};
  185. FirstDotAtFileNameStartIsExtension : Boolean = False;
  186. type
  187. TOnParamCount = function: Longint;
  188. TOnParamStr = function(Index: Longint): String;
  189. var
  190. OnParamCount: TOnParamCount;
  191. OnParamStr: TOnParamStr;
  192. function ParamCount: Longint;
  193. function ParamStr(Index: Longint): String;
  194. {*****************************************************************************
  195. Math
  196. *****************************************************************************}
  197. const
  198. PI: Double; external name 'Math.PI';
  199. MathE: Double; external name 'Math.E'; // Euler's number
  200. MathLN10: Double; external name 'Math.LN10'; // ln(10)
  201. MathLN2: Double; external name 'Math.LN2'; // ln(2)
  202. MathLog10E: Double; external name 'Math.Log10E'; // log10(e)
  203. MathLog2E: Double; external name 'Math.LOG2E'; // log2(e)
  204. MathSQRT1_2: Double; external name 'Math.SQRT1_2'; // sqrt(0.5)
  205. MathSQRT2: Double; external name 'Math.SQRT2'; // sqrt(2)
  206. function Abs(const A: integer): integer; overload; external name 'Math.abs';
  207. function Abs(const A: NativeInt): integer; overload; external name 'Math.abs';
  208. function Abs(const A: Double): Double; overload; external name 'Math.abs';
  209. function ArcTan(const A, B: Double): Double; external name 'Math.atan';
  210. function Cos(const A: Double): Double; external name 'Math.cos';
  211. function Exp(const A: Double): Double; external name 'Math.exp';
  212. function Frac(const A: Double): Double; assembler;
  213. function Ln(const A: Double): Double; external name 'Math.log';
  214. function Odd(const A: Integer): Boolean; assembler;
  215. function Random(const Range: Integer): Integer; overload; assembler;
  216. function Random: Double; overload; external name 'Math.random';
  217. function Round(const A: Double): NativeInt; external name 'Math.round';
  218. function Sin(const A: Double): Double; external name 'Math.sin';
  219. function Sqr(const A: Integer): Integer; assembler; overload;
  220. function Sqr(const A: Double): Double; assembler; overload;
  221. function sqrt(const A: Double): Double; external name 'Math.sqrt';
  222. function Trunc(const A: Double): NativeInt;
  223. {*****************************************************************************
  224. String functions
  225. *****************************************************************************}
  226. const
  227. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
  228. function Int(const A: Double): double;
  229. function Copy(const S: string; Index, Size: Integer): String; assembler; overload;
  230. function Copy(const S: string; Index: Integer): String; assembler; overload;
  231. procedure Delete(var S: String; Index, Size: Integer); assembler; overload;
  232. function Pos(const Search, InString: String): Integer; assembler; overload;
  233. function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
  234. procedure Insert(const Insertion: String; var Target: String; Index: Integer); overload;
  235. function upcase(c : char) : char; assembler;
  236. function HexStr(Val: NativeInt; cnt: byte): string; external name 'rtl.hexStr'; overload;
  237. procedure val(const S: String; out NI : NativeInt; out Code: Integer); overload;
  238. procedure val(const S: String; out NI : NativeUInt; out Code: Integer); overload;
  239. procedure val(const S: String; out SI : ShortInt; out Code: Integer); overload;
  240. procedure val(const S: String; out B : Byte; out Code: Integer); overload;
  241. procedure val(const S: String; out SI : smallint; out Code: Integer); overload;
  242. procedure val(const S: String; out W : word; out Code : Integer); overload;
  243. procedure val(const S: String; out I : integer; out Code : Integer); overload;
  244. procedure val(const S: String; out C : Cardinal; out Code: Integer); overload;
  245. procedure val(const S: String; out d : double; out Code : Integer); overload;
  246. procedure val(const S: String; out b : boolean; out Code: Integer); overload;
  247. function StringOfChar(c: Char; l: NativeInt): String;
  248. function Lo(i: word): byte; overload;
  249. function Lo(i: smallint): byte; overload;
  250. function Lo(i: longword): word; overload;
  251. function Lo(i: longint): word; overload;
  252. function Hi(i: word): byte; overload;
  253. function Hi(i: smallint): byte; overload;
  254. function Hi(i: longword): word; overload;
  255. function Hi(i: longint): word; overload;
  256. {*****************************************************************************
  257. Other functions
  258. *****************************************************************************}
  259. procedure Write; varargs; // ToDo: should be compiler built-in function
  260. procedure Writeln; varargs; // ToDo: should be compiler built-in function
  261. Type
  262. TConsoleHandler = Procedure (S : JSValue; NewLine : Boolean);
  263. Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
  264. function Assigned(const V: JSValue): boolean; assembler; overload;
  265. function StrictEqual(const A: JSValue; const B): boolean; assembler;
  266. function StrictInequal(const A: JSValue; const B): boolean; assembler;
  267. implementation
  268. type
  269. { TJSObj - simple access to JS Object }
  270. TJSObj = class external name 'Object'
  271. private
  272. function GetProperties(Name: String): JSValue; external name '[]';
  273. procedure SetProperties(Name: String; const AValue: JSValue); external name '[]';
  274. public
  275. //constructor new;
  276. //function hasOwnProperty(prop: String): boolean;
  277. property Properties[Name: String]: JSValue read GetProperties write SetProperties; default;
  278. end;
  279. // function parseInt(s: String; Radix: NativeInt): NativeInt; external name 'parseInt'; // may result NaN
  280. function isNaN(i: JSValue): boolean; external name 'isNaN'; // may result NaN
  281. // needed by ClassNameIs, the real SameText is in SysUtils
  282. function SameText(const s1, s2: String): Boolean; assembler;
  283. asm
  284. return s1.toLowerCase() == s2.toLowerCase();
  285. end;
  286. function ParamCount: Longint;
  287. begin
  288. if Assigned(OnParamCount) then
  289. Result:=OnParamCount()
  290. else
  291. Result:=0;
  292. end;
  293. function ParamStr(Index: Longint): String;
  294. begin
  295. if Assigned(OnParamStr) then
  296. Result:=OnParamStr(Index)
  297. else if Index=0 then
  298. Result:='js'
  299. else
  300. Result:='';
  301. end;
  302. function Frac(const A: Double): Double; assembler;
  303. asm
  304. return A % 1;
  305. end;
  306. function Odd(const A: Integer): Boolean; assembler;
  307. asm
  308. return A&1 != 0;
  309. end;
  310. function Random(const Range: Integer): Integer; assembler;
  311. asm
  312. return Math.floor(Math.random()*Range);
  313. end;
  314. function Sqr(const A: Integer): Integer; assembler;
  315. asm
  316. return A*A;
  317. end;
  318. function Sqr(const A: Double): Double; assembler;
  319. asm
  320. return A*A;
  321. end;
  322. function Trunc(const A: Double): NativeInt; assembler;
  323. asm
  324. if (!Math.trunc) {
  325. Math.trunc = function(v) {
  326. v = +v;
  327. if (!isFinite(v)) return v;
  328. return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
  329. };
  330. }
  331. $mod.Trunc = Math.trunc;
  332. return Math.trunc(A);
  333. end;
  334. function Copy(const S: string; Index, Size: Integer): String; assembler;
  335. asm
  336. if (Index<1) Index = 1;
  337. return (Size>0) ? S.substring(Index-1,Index+Size-1) : "";
  338. end;
  339. function Copy(const S: string; Index: Integer): String; assembler;
  340. asm
  341. if (Index<1) Index = 1;
  342. return S.substr(Index-1);
  343. end;
  344. procedure Delete(var S: String; Index, Size: Integer);
  345. var
  346. h: String;
  347. begin
  348. if (Index<1) or (Index>length(S)) or (Size<=0) then exit;
  349. h:=S;
  350. S:=copy(h,1,Index-1)+copy(h,Index+Size);
  351. end;
  352. function Pos(const Search, InString: String): Integer; assembler;
  353. asm
  354. return InString.indexOf(Search)+1;
  355. end;
  356. function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
  357. asm
  358. return InString.indexOf(Search,StartAt-1)+1;
  359. end;
  360. procedure Insert(const Insertion: String; var Target: String; Index: Integer);
  361. var
  362. t: String;
  363. begin
  364. if Insertion='' then exit;
  365. t:=Target;
  366. if Index<1 then
  367. Target:=Insertion+t
  368. else if Index>length(t) then
  369. Target:=t+Insertion
  370. else
  371. Target:=copy(t,1,Index-1)+Insertion+copy(t,Index,length(t));
  372. end;
  373. type
  374. TJSArguments = class external name 'arguments'
  375. private
  376. FLength: NativeInt; external name 'length';
  377. function GetElements(Index: NativeInt): JSValue; external name '[]';
  378. procedure SetElements(Index: NativeInt; const AValue: JSValue); external name '[]';
  379. public
  380. property Length: NativeInt read FLength;
  381. property Elements[Index: NativeInt]: JSValue read GetElements write SetElements; default;
  382. end;
  383. var
  384. WriteBuf: String;
  385. JSArguments: TJSArguments; external name 'arguments';
  386. WriteCallBack : TConsoleHandler;
  387. Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
  388. begin
  389. Result:=WriteCallBack;
  390. WriteCallBack:=H;
  391. end;
  392. procedure Write;
  393. var
  394. i: Integer;
  395. begin
  396. for i:=0 to JSArguments.Length-1 do
  397. if Assigned(WriteCallBack) then
  398. WriteCallBack(JSArguments[i],False)
  399. else
  400. WriteBuf:=WriteBuf+String(JSArguments[i]);
  401. end;
  402. procedure Writeln;
  403. var
  404. i,l: Integer;
  405. s: String;
  406. begin
  407. L:=JSArguments.Length-1;
  408. if Assigned(WriteCallBack) then
  409. begin
  410. for i:=0 to L do
  411. WriteCallBack(JSArguments[i],I=L);
  412. end
  413. else
  414. begin
  415. s:=WriteBuf;
  416. for i:=0 to L do
  417. s:=s+String(JSArguments[i]);
  418. asm
  419. console.log(s);
  420. end;
  421. WriteBuf:='';
  422. end;
  423. end;
  424. function Int(const A: Double): double;
  425. begin
  426. // trunc contains fix for missing Math.trunc in IE
  427. Result:=Trunc(A);
  428. end;
  429. function Number(S: String): Double; external name 'Number';
  430. function valint(const S: String; MinVal, MaxVal: NativeInt; out Code: Integer): NativeInt;
  431. var
  432. x: double;
  433. begin
  434. x:=Number(S);
  435. if isNaN(x) then
  436. case copy(s,1,1) of
  437. '$': x:=Number('0x'+copy(S,2));
  438. '&': x:=Number('0o'+copy(S,2));
  439. '%': x:=Number('0b'+copy(S,2));
  440. else
  441. Code:=1;
  442. exit;
  443. end;
  444. if isNaN(x) or (X<>Int(X)) then
  445. Code:=1
  446. else if (x<MinVal) or (x>MaxVal) then
  447. Code:=2
  448. else
  449. begin
  450. Result:=Trunc(x);
  451. Code:=0;
  452. end;
  453. end;
  454. procedure val(const S: String; out NI : NativeInt; out Code: Integer);
  455. begin
  456. NI:=valint(S,low(NI),high(NI),Code);
  457. end;
  458. procedure val(const S: String; out NI: NativeUInt; out Code: Integer);
  459. var
  460. x : double;
  461. begin
  462. x:=Number(S);
  463. if isNaN(x) or (X<>Int(X)) or (X<0) then
  464. Code:=1
  465. else
  466. begin
  467. Code:=0;
  468. NI:=Trunc(x);
  469. end;
  470. end;
  471. procedure val(const S: String; out SI : ShortInt; out Code: Integer);
  472. begin
  473. SI:=valint(S,low(SI),high(SI),Code);
  474. end;
  475. procedure val(const S: String; out SI: smallint; out Code: Integer);
  476. begin
  477. SI:=valint(S,low(SI),high(SI),Code);
  478. end;
  479. procedure val(const S: String; out C: Cardinal; out Code: Integer);
  480. begin
  481. C:=valint(S,low(C),high(C),Code);
  482. end;
  483. procedure val(const S: String; out B: Byte; out Code: Integer);
  484. begin
  485. B:=valint(S,low(B),high(B),Code);
  486. end;
  487. procedure val(const S: String; out W: word; out Code: Integer);
  488. begin
  489. W:=valint(S,low(W),high(W),Code);
  490. end;
  491. procedure val(const S : String; out I : integer; out Code : Integer);
  492. begin
  493. I:=valint(S,low(I),high(I),Code);
  494. end;
  495. procedure val(const S : String; out d : double; out Code : Integer);
  496. Var
  497. x: double;
  498. begin
  499. x:=Number(S);
  500. if isNaN(x) then
  501. Code:=1
  502. else
  503. begin
  504. Code:=0;
  505. d:=x;
  506. end;
  507. end;
  508. procedure val(const S: String; out b: boolean; out Code: Integer);
  509. begin
  510. if SameText(S,'true') then
  511. begin
  512. Code:=0;
  513. b:=true;
  514. end
  515. else if SameText(S,'false') then
  516. begin
  517. Code:=0;
  518. b:=false;
  519. end
  520. else
  521. Code:=1;
  522. end;
  523. function upcase(c : char) : char; assembler;
  524. asm
  525. return c.toUpperCase();
  526. end;
  527. function StringOfChar(c: Char; l: NativeInt): String;
  528. var
  529. i: Integer;
  530. begin
  531. asm
  532. if ((l>0) && c.repeat) return c.repeat(l);
  533. end;
  534. Result:='';
  535. for i:=1 to l do Result:=Result+c;
  536. end;
  537. function Lo(i: word): byte;
  538. begin
  539. Result:=i and $ff;
  540. end;
  541. function Lo(i: smallint): byte;
  542. begin
  543. Result:=i and $ff;
  544. end;
  545. function Lo(i: longword): word;
  546. begin
  547. Result:=i and $ffff;
  548. end;
  549. function Lo(i: longint): word;
  550. begin
  551. Result:=i and $ffff;
  552. end;
  553. function Hi(i: word): byte;
  554. begin
  555. Result:=(i shr 8) and $ff;
  556. end;
  557. function Hi(i: smallint): byte;
  558. begin
  559. Result:=(i shr 8) and $ff;
  560. end;
  561. function Hi(i: longword): word;
  562. begin
  563. Result:=(i shr 16) and $ffff;
  564. end;
  565. function Hi(i: longint): word;
  566. begin
  567. Result:=(i shr 16) and $ffff;
  568. end;
  569. function Assigned(const V: JSValue): boolean; assembler;
  570. asm
  571. return (V!=undefined) && (V!=null) && (!rtl.isArray(V) || (V.length > 0));
  572. end;
  573. function StrictEqual(const A: JSValue; const B): boolean; assembler;
  574. asm
  575. return A === B;
  576. end;
  577. function StrictInequal(const A: JSValue; const B): boolean; assembler;
  578. asm
  579. return A !== B;
  580. end;
  581. { TContainedObject }
  582. function TContainedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  583. begin
  584. if GetInterface(iid,obj) then
  585. Result:=S_OK
  586. else
  587. Result:=Integer(E_NOINTERFACE);
  588. end;
  589. { TAggregatedObject }
  590. function TAggregatedObject.GetController: IUnknown;
  591. begin
  592. Result := IUnknown(fController);
  593. end;
  594. function TAggregatedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  595. begin
  596. Result := IUnknown(fController).QueryInterface(iid, obj);
  597. end;
  598. function TAggregatedObject._AddRef: Integer;
  599. begin
  600. Result := IUnknown(fController)._AddRef;
  601. end;
  602. function TAggregatedObject._Release: Integer;
  603. begin
  604. Result := IUnknown(fController)._Release;
  605. end;
  606. constructor TAggregatedObject.Create(const aController: IUnknown);
  607. begin
  608. inherited Create;
  609. { do not keep a counted reference to the controller! }
  610. fController := Pointer(aController);
  611. end;
  612. { TInterfacedObject }
  613. function TInterfacedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  614. begin
  615. if GetInterface(iid,obj) then
  616. Result:=S_OK
  617. else
  618. Result:=Integer(E_NOINTERFACE);
  619. end;
  620. function TInterfacedObject._AddRef: Integer;
  621. begin
  622. inc(fRefCount);
  623. Result:=fRefCount;
  624. end;
  625. function TInterfacedObject._Release: Integer;
  626. begin
  627. dec(fRefCount);
  628. Result:=fRefCount;
  629. if fRefCount=0 then
  630. Destroy;
  631. end;
  632. procedure TInterfacedObject.BeforeDestruction;
  633. begin
  634. if fRefCount<>0 then
  635. asm
  636. rtl.raiseE('EHeapMemoryError');
  637. end;
  638. end;
  639. { TObject }
  640. constructor TObject.Create;
  641. begin
  642. end;
  643. destructor TObject.Destroy;
  644. begin
  645. end;
  646. procedure TObject.Free;
  647. begin
  648. Destroy;
  649. end;
  650. class function TObject.ClassType: TClass; assembler;
  651. asm
  652. return this;
  653. end;
  654. class function TObject.ClassNameIs(const Name: string): boolean;
  655. begin
  656. Result:=SameText(Name,ClassName);
  657. end;
  658. class function TObject.InheritsFrom(aClass: TClass): boolean; assembler;
  659. asm
  660. return (aClass!=null) && ((this==aClass) || aClass.isPrototypeOf(this));
  661. end;
  662. procedure TObject.AfterConstruction;
  663. begin
  664. end;
  665. procedure TObject.BeforeDestruction;
  666. begin
  667. end;
  668. function TObject.GetInterface(const iid: TGuid; out obj): boolean;
  669. begin
  670. asm
  671. var i = iid.$intf;
  672. if (i){
  673. // iid is the private TGuid of an interface
  674. i = rtl.getIntfG(this,i.$guid,2);
  675. if (i){
  676. obj.set(i);
  677. return true;
  678. }
  679. }
  680. end;
  681. Result := GetInterfaceByStr(GUIDToString(iid),obj);
  682. end;
  683. function TObject.GetInterface(const iidstr: String; out obj): boolean;
  684. begin
  685. Result := GetInterfaceByStr(iidstr,obj);
  686. end;
  687. function TObject.GetInterfaceByStr(const iidstr: String; out obj): boolean;
  688. begin
  689. if not TJSObj(IObjectInstance)['$str'] then
  690. TJSObj(IObjectInstance)['$str']:=GUIDToString(IObjectInstance);
  691. if iidstr = TJSObj(IObjectInstance)['$str'] then
  692. begin
  693. obj:=Self;
  694. exit(true);
  695. end;
  696. asm
  697. var i = rtl.getIntfG(this,iidstr,2);
  698. obj.set(i);
  699. return i!==null;
  700. end;
  701. Result:=false;
  702. end;
  703. function TObject.GetInterfaceWeak(const iid: TGuid; out obj): boolean;
  704. begin
  705. Result:=GetInterface(iid,obj);
  706. asm
  707. if (Result){
  708. var o = obj.get();
  709. if (o.$kind==='com'){
  710. o._Release();
  711. }
  712. }
  713. end;
  714. end;
  715. function TObject.Equals(Obj: TObject): boolean;
  716. begin
  717. Result:=Obj=Self;
  718. end;
  719. function TObject.ToString: String;
  720. begin
  721. Result:=ClassName;
  722. end;
  723. initialization
  724. ExitCode:=0; // set it here, so that WPO does not remove it
  725. end.