system.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  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. Array of const support
  181. *****************************************************************************}
  182. const
  183. vtInteger = 0;
  184. vtBoolean = 1;
  185. //vtChar = 2; // Delphi/FPC: ansichar
  186. vtExtended = 3; // Note: double in pas2js, PExtended in Delphi/FPC
  187. //vtString = 4; // Delphi/FPC: PShortString
  188. vtPointer = 5;
  189. //vtPChar = 6;
  190. vtObject = 7;
  191. vtClass = 8;
  192. vtWideChar = 9;
  193. //vtPWideChar = 10;
  194. //vtAnsiString = 11;
  195. vtCurrency = 12; // Note: currency in pas2js, PCurrency in Delphi/FPC
  196. //vtVariant = 13;
  197. vtInterface = 14;
  198. //vtWideString = 15;
  199. //vtInt64 = 16;
  200. //vtQWord = 17;
  201. vtUnicodeString = 18;
  202. // only pas2js, not in Delphi/FPC:
  203. vtNativeInt = 19;
  204. vtJSValue = 20;
  205. type
  206. PVarRec = ^TVarRec;
  207. TVarRec = record
  208. VType: byte;
  209. VJSValue: JSValue;
  210. VInteger: LongInt external name 'VJSValue';
  211. VBoolean: Boolean external name 'VJSValue';
  212. VExtended: Double external name 'VJSValue';
  213. VPointer: Pointer external name 'VJSValue';
  214. VObject: TObject external name 'VJSValue';
  215. VClass: TClass external name 'VJSValue';
  216. VWideChar: WideChar external name 'VJSValue';
  217. VCurrency: Currency external name 'VJSValue';
  218. VInterface: Pointer external name 'VJSValue';
  219. VUnicodeString: UnicodeString external name 'VJSValue';
  220. VNativeInt: NativeInt external name 'VJSValue';
  221. end;
  222. TVarRecArray = array of TVarRec;
  223. function VarRecs: TVarRecArray; varargs;
  224. {*****************************************************************************
  225. Init / Exit / ExitProc
  226. *****************************************************************************}
  227. var
  228. ExitCode: Integer; external name 'rtl.exitcode';
  229. IsConsole: Boolean = {$IFDEF NodeJS}true{$ELSE}false{$ENDIF};
  230. FirstDotAtFileNameStartIsExtension : Boolean = False;
  231. type
  232. TOnParamCount = function: Longint;
  233. TOnParamStr = function(Index: Longint): String;
  234. var
  235. OnParamCount: TOnParamCount;
  236. OnParamStr: TOnParamStr;
  237. function ParamCount: Longint;
  238. function ParamStr(Index: Longint): String;
  239. {*****************************************************************************
  240. Math
  241. *****************************************************************************}
  242. const
  243. PI: Double; external name 'Math.PI';
  244. MathE: Double; external name 'Math.E'; // Euler's number
  245. MathLN10: Double; external name 'Math.LN10'; // ln(10)
  246. MathLN2: Double; external name 'Math.LN2'; // ln(2)
  247. MathLog10E: Double; external name 'Math.Log10E'; // log10(e)
  248. MathLog2E: Double; external name 'Math.LOG2E'; // log2(e)
  249. MathSQRT1_2: Double; external name 'Math.SQRT1_2'; // sqrt(0.5)
  250. MathSQRT2: Double; external name 'Math.SQRT2'; // sqrt(2)
  251. function Abs(const A: integer): integer; overload; external name 'Math.abs';
  252. function Abs(const A: NativeInt): integer; overload; external name 'Math.abs';
  253. function Abs(const A: Double): Double; overload; external name 'Math.abs';
  254. function ArcTan(const A, B: Double): Double; external name 'Math.atan';
  255. function Cos(const A: Double): Double; external name 'Math.cos';
  256. function Exp(const A: Double): Double; external name 'Math.exp';
  257. function Frac(const A: Double): Double; assembler;
  258. function Ln(const A: Double): Double; external name 'Math.log';
  259. function Odd(const A: Integer): Boolean; assembler;
  260. function Random(const Range: Integer): Integer; overload; assembler;
  261. function Random: Double; overload; external name 'Math.random';
  262. function Round(const A: Double): NativeInt; external name 'Math.round';
  263. function Sin(const A: Double): Double; external name 'Math.sin';
  264. function Sqr(const A: Integer): Integer; assembler; overload;
  265. function Sqr(const A: Double): Double; assembler; overload;
  266. function sqrt(const A: Double): Double; external name 'Math.sqrt';
  267. function Trunc(const A: Double): NativeInt;
  268. {*****************************************************************************
  269. String functions
  270. *****************************************************************************}
  271. const
  272. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
  273. function Int(const A: Double): double;
  274. function Copy(const S: string; Index, Size: Integer): String; assembler; overload;
  275. function Copy(const S: string; Index: Integer): String; assembler; overload;
  276. procedure Delete(var S: String; Index, Size: Integer); assembler; overload;
  277. function Pos(const Search, InString: String): Integer; assembler; overload;
  278. function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
  279. procedure Insert(const Insertion: String; var Target: String; Index: Integer); overload;
  280. function upcase(c : char) : char; assembler;
  281. function HexStr(Val: NativeInt; cnt: byte): string; external name 'rtl.hexStr'; overload;
  282. procedure val(const S: String; out NI : NativeInt; out Code: Integer); overload;
  283. procedure val(const S: String; out NI : NativeUInt; out Code: Integer); overload;
  284. procedure val(const S: String; out SI : ShortInt; out Code: Integer); overload;
  285. procedure val(const S: String; out B : Byte; out Code: Integer); overload;
  286. procedure val(const S: String; out SI : smallint; out Code: Integer); overload;
  287. procedure val(const S: String; out W : word; out Code : Integer); overload;
  288. procedure val(const S: String; out I : integer; out Code : Integer); overload;
  289. procedure val(const S: String; out C : Cardinal; out Code: Integer); overload;
  290. procedure val(const S: String; out d : double; out Code : Integer); overload;
  291. procedure val(const S: String; out b : boolean; out Code: Integer); overload;
  292. function StringOfChar(c: Char; l: NativeInt): String;
  293. {*****************************************************************************
  294. Other functions
  295. *****************************************************************************}
  296. procedure Write; varargs; // ToDo: should be compiler built-in function
  297. procedure Writeln; varargs; // ToDo: should be compiler built-in function
  298. Type
  299. TConsoleHandler = Procedure (S : JSValue; NewLine : Boolean);
  300. Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
  301. function Assigned(const V: JSValue): boolean; assembler; overload;
  302. function StrictEqual(const A: JSValue; const B): boolean; assembler;
  303. function StrictInequal(const A: JSValue; const B): boolean; assembler;
  304. implementation
  305. type
  306. { TJSObj - simple access to JS Object }
  307. TJSObj = class external name 'Object'
  308. private
  309. function GetProperties(Name: String): JSValue; external name '[]';
  310. procedure SetProperties(Name: String; const AValue: JSValue); external name '[]';
  311. public
  312. //constructor new;
  313. //function hasOwnProperty(prop: String): boolean;
  314. property Properties[Name: String]: JSValue read GetProperties write SetProperties; default;
  315. end;
  316. TJSArray = class external name 'Array'
  317. public
  318. //length: nativeint;
  319. //constructor new; overload;
  320. function push(aElement : JSValue) : NativeInt; varargs;
  321. end;
  322. TJSArguments = class external name 'arguments'
  323. private
  324. FLength: NativeInt; external name 'length';
  325. function GetElements(Index: NativeInt): JSValue; external name '[]';
  326. public
  327. property Length: NativeInt read FLength;
  328. property Elements[Index: NativeInt]: JSValue read GetElements; default;
  329. end;
  330. var
  331. JSArguments: TJSArguments; external name 'arguments';
  332. // function parseInt(s: String; Radix: NativeInt): NativeInt; external name 'parseInt'; // may result NaN
  333. function isNaN(i: JSValue): boolean; external name 'isNaN'; // may result NaN
  334. // needed by ClassNameIs, the real SameText is in SysUtils
  335. function SameText(const s1, s2: String): Boolean; assembler;
  336. asm
  337. return s1.toLowerCase() == s2.toLowerCase();
  338. end;
  339. function VarRecs: TVarRecArray;
  340. var
  341. i: nativeint;
  342. v: PVarRec;
  343. begin
  344. Result:=nil;
  345. while i<JSArguments.Length do
  346. begin
  347. new(v);
  348. v^.VType:=byte(JSArguments[i]);
  349. inc(i);
  350. v^.VJSValue:=JSArguments[i];
  351. inc(i);
  352. TJSArray(Result).push(v^);
  353. end;
  354. end;
  355. function ParamCount: Longint;
  356. begin
  357. if Assigned(OnParamCount) then
  358. Result:=OnParamCount()
  359. else
  360. Result:=0;
  361. end;
  362. function ParamStr(Index: Longint): String;
  363. begin
  364. if Assigned(OnParamStr) then
  365. Result:=OnParamStr(Index)
  366. else if Index=0 then
  367. Result:='js'
  368. else
  369. Result:='';
  370. end;
  371. function Frac(const A: Double): Double; assembler;
  372. asm
  373. return A % 1;
  374. end;
  375. function Odd(const A: Integer): Boolean; assembler;
  376. asm
  377. return A&1 != 0;
  378. end;
  379. function Random(const Range: Integer): Integer; assembler;
  380. asm
  381. return Math.floor(Math.random()*Range);
  382. end;
  383. function Sqr(const A: Integer): Integer; assembler;
  384. asm
  385. return A*A;
  386. end;
  387. function Sqr(const A: Double): Double; assembler;
  388. asm
  389. return A*A;
  390. end;
  391. function Trunc(const A: Double): NativeInt; assembler;
  392. asm
  393. if (!Math.trunc) {
  394. Math.trunc = function(v) {
  395. v = +v;
  396. if (!isFinite(v)) return v;
  397. return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
  398. };
  399. }
  400. $mod.Trunc = Math.trunc;
  401. return Math.trunc(A);
  402. end;
  403. function Copy(const S: string; Index, Size: Integer): String; assembler;
  404. asm
  405. if (Index<1) Index = 1;
  406. return (Size>0) ? S.substring(Index-1,Index+Size-1) : "";
  407. end;
  408. function Copy(const S: string; Index: Integer): String; assembler;
  409. asm
  410. if (Index<1) Index = 1;
  411. return S.substr(Index-1);
  412. end;
  413. procedure Delete(var S: String; Index, Size: Integer);
  414. var
  415. h: String;
  416. begin
  417. if (Index<1) or (Index>length(S)) or (Size<=0) then exit;
  418. h:=S;
  419. S:=copy(h,1,Index-1)+copy(h,Index+Size);
  420. end;
  421. function Pos(const Search, InString: String): Integer; assembler;
  422. asm
  423. return InString.indexOf(Search)+1;
  424. end;
  425. function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
  426. asm
  427. return InString.indexOf(Search,StartAt-1)+1;
  428. end;
  429. procedure Insert(const Insertion: String; var Target: String; Index: Integer);
  430. var
  431. t: String;
  432. begin
  433. if Insertion='' then exit;
  434. t:=Target;
  435. if Index<1 then
  436. Target:=Insertion+t
  437. else if Index>length(t) then
  438. Target:=t+Insertion
  439. else
  440. Target:=copy(t,1,Index-1)+Insertion+copy(t,Index,length(t));
  441. end;
  442. var
  443. WriteBuf: String;
  444. WriteCallBack : TConsoleHandler;
  445. Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
  446. begin
  447. Result:=WriteCallBack;
  448. WriteCallBack:=H;
  449. end;
  450. procedure Write;
  451. var
  452. i: Integer;
  453. begin
  454. for i:=0 to JSArguments.Length-1 do
  455. if Assigned(WriteCallBack) then
  456. WriteCallBack(JSArguments[i],False)
  457. else
  458. WriteBuf:=WriteBuf+String(JSArguments[i]);
  459. end;
  460. procedure Writeln;
  461. var
  462. i,l: Integer;
  463. s: String;
  464. begin
  465. L:=JSArguments.Length-1;
  466. if Assigned(WriteCallBack) then
  467. begin
  468. for i:=0 to L do
  469. WriteCallBack(JSArguments[i],I=L);
  470. end
  471. else
  472. begin
  473. s:=WriteBuf;
  474. for i:=0 to L do
  475. s:=s+String(JSArguments[i]);
  476. asm
  477. console.log(s);
  478. end;
  479. WriteBuf:='';
  480. end;
  481. end;
  482. function Int(const A: Double): double;
  483. begin
  484. // trunc contains fix for missing Math.trunc in IE
  485. Result:=Trunc(A);
  486. end;
  487. function Number(S: String): Double; external name 'Number';
  488. function valint(const S: String; MinVal, MaxVal: NativeInt; out Code: Integer): NativeInt;
  489. var
  490. x: double;
  491. begin
  492. x:=Number(S);
  493. if isNaN(x) then
  494. case copy(s,1,1) of
  495. '$': x:=Number('0x'+copy(S,2));
  496. '&': x:=Number('0o'+copy(S,2));
  497. '%': x:=Number('0b'+copy(S,2));
  498. else
  499. Code:=1;
  500. exit;
  501. end;
  502. if isNaN(x) or (X<>Int(X)) then
  503. Code:=1
  504. else if (x<MinVal) or (x>MaxVal) then
  505. Code:=2
  506. else
  507. begin
  508. Result:=Trunc(x);
  509. Code:=0;
  510. end;
  511. end;
  512. procedure val(const S: String; out NI : NativeInt; out Code: Integer);
  513. begin
  514. NI:=valint(S,low(NI),high(NI),Code);
  515. end;
  516. procedure val(const S: String; out NI: NativeUInt; out Code: Integer);
  517. var
  518. x : double;
  519. begin
  520. x:=Number(S);
  521. if isNaN(x) or (X<>Int(X)) or (X<0) then
  522. Code:=1
  523. else
  524. begin
  525. Code:=0;
  526. NI:=Trunc(x);
  527. end;
  528. end;
  529. procedure val(const S: String; out SI : ShortInt; out Code: Integer);
  530. begin
  531. SI:=valint(S,low(SI),high(SI),Code);
  532. end;
  533. procedure val(const S: String; out SI: smallint; out Code: Integer);
  534. begin
  535. SI:=valint(S,low(SI),high(SI),Code);
  536. end;
  537. procedure val(const S: String; out C: Cardinal; out Code: Integer);
  538. begin
  539. C:=valint(S,low(C),high(C),Code);
  540. end;
  541. procedure val(const S: String; out B: Byte; out Code: Integer);
  542. begin
  543. B:=valint(S,low(B),high(B),Code);
  544. end;
  545. procedure val(const S: String; out W: word; out Code: Integer);
  546. begin
  547. W:=valint(S,low(W),high(W),Code);
  548. end;
  549. procedure val(const S : String; out I : integer; out Code : Integer);
  550. begin
  551. I:=valint(S,low(I),high(I),Code);
  552. end;
  553. procedure val(const S : String; out d : double; out Code : Integer);
  554. Var
  555. x: double;
  556. begin
  557. x:=Number(S);
  558. if isNaN(x) then
  559. Code:=1
  560. else
  561. begin
  562. Code:=0;
  563. d:=x;
  564. end;
  565. end;
  566. procedure val(const S: String; out b: boolean; out Code: Integer);
  567. begin
  568. if SameText(S,'true') then
  569. begin
  570. Code:=0;
  571. b:=true;
  572. end
  573. else if SameText(S,'false') then
  574. begin
  575. Code:=0;
  576. b:=false;
  577. end
  578. else
  579. Code:=1;
  580. end;
  581. function upcase(c : char) : char; assembler;
  582. asm
  583. return c.toUpperCase();
  584. end;
  585. function StringOfChar(c: Char; l: NativeInt): String;
  586. var
  587. i: Integer;
  588. begin
  589. asm
  590. if ((l>0) && c.repeat) return c.repeat(l);
  591. end;
  592. Result:='';
  593. for i:=1 to l do Result:=Result+c;
  594. end;
  595. function Assigned(const V: JSValue): boolean; assembler;
  596. asm
  597. return (V!=undefined) && (V!=null) && (!rtl.isArray(V) || (V.length > 0));
  598. end;
  599. function StrictEqual(const A: JSValue; const B): boolean; assembler;
  600. asm
  601. return A === B;
  602. end;
  603. function StrictInequal(const A: JSValue; const B): boolean; assembler;
  604. asm
  605. return A !== B;
  606. end;
  607. { TContainedObject }
  608. function TContainedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  609. begin
  610. if GetInterface(iid,obj) then
  611. Result:=S_OK
  612. else
  613. Result:=Integer(E_NOINTERFACE);
  614. end;
  615. { TAggregatedObject }
  616. function TAggregatedObject.GetController: IUnknown;
  617. begin
  618. Result := IUnknown(fController);
  619. end;
  620. function TAggregatedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  621. begin
  622. Result := IUnknown(fController).QueryInterface(iid, obj);
  623. end;
  624. function TAggregatedObject._AddRef: Integer;
  625. begin
  626. Result := IUnknown(fController)._AddRef;
  627. end;
  628. function TAggregatedObject._Release: Integer;
  629. begin
  630. Result := IUnknown(fController)._Release;
  631. end;
  632. constructor TAggregatedObject.Create(const aController: IUnknown);
  633. begin
  634. inherited Create;
  635. { do not keep a counted reference to the controller! }
  636. fController := Pointer(aController);
  637. end;
  638. { TInterfacedObject }
  639. function TInterfacedObject.QueryInterface(const iid: TGuid; out obj): Integer;
  640. begin
  641. if GetInterface(iid,obj) then
  642. Result:=S_OK
  643. else
  644. Result:=Integer(E_NOINTERFACE);
  645. end;
  646. function TInterfacedObject._AddRef: Integer;
  647. begin
  648. inc(fRefCount);
  649. Result:=fRefCount;
  650. end;
  651. function TInterfacedObject._Release: Integer;
  652. begin
  653. dec(fRefCount);
  654. Result:=fRefCount;
  655. if fRefCount=0 then
  656. Destroy;
  657. end;
  658. procedure TInterfacedObject.BeforeDestruction;
  659. begin
  660. if fRefCount<>0 then
  661. asm
  662. rtl.raiseE('EHeapMemoryError');
  663. end;
  664. end;
  665. { TObject }
  666. constructor TObject.Create;
  667. begin
  668. end;
  669. destructor TObject.Destroy;
  670. begin
  671. end;
  672. procedure TObject.Free;
  673. begin
  674. Destroy;
  675. end;
  676. class function TObject.ClassType: TClass; assembler;
  677. asm
  678. return this;
  679. end;
  680. class function TObject.ClassNameIs(const Name: string): boolean;
  681. begin
  682. Result:=SameText(Name,ClassName);
  683. end;
  684. class function TObject.InheritsFrom(aClass: TClass): boolean; assembler;
  685. asm
  686. return (aClass!=null) && ((this==aClass) || aClass.isPrototypeOf(this));
  687. end;
  688. procedure TObject.AfterConstruction;
  689. begin
  690. end;
  691. procedure TObject.BeforeDestruction;
  692. begin
  693. end;
  694. function TObject.GetInterface(const iid: TGuid; out obj): boolean;
  695. begin
  696. asm
  697. var i = iid.$intf;
  698. if (i){
  699. // iid is the private TGuid of an interface
  700. i = rtl.getIntfG(this,i.$guid,2);
  701. if (i){
  702. obj.set(i);
  703. return true;
  704. }
  705. }
  706. end;
  707. Result := GetInterfaceByStr(GUIDToString(iid),obj);
  708. end;
  709. function TObject.GetInterface(const iidstr: String; out obj): boolean;
  710. begin
  711. Result := GetInterfaceByStr(iidstr,obj);
  712. end;
  713. function TObject.GetInterfaceByStr(const iidstr: String; out obj): boolean;
  714. begin
  715. if not TJSObj(IObjectInstance)['$str'] then
  716. TJSObj(IObjectInstance)['$str']:=GUIDToString(IObjectInstance);
  717. if iidstr = TJSObj(IObjectInstance)['$str'] then
  718. begin
  719. obj:=Self;
  720. exit(true);
  721. end;
  722. asm
  723. var i = rtl.getIntfG(this,iidstr,2);
  724. obj.set(i);
  725. return i!==null;
  726. end;
  727. Result:=false;
  728. end;
  729. function TObject.GetInterfaceWeak(const iid: TGuid; out obj): boolean;
  730. begin
  731. Result:=GetInterface(iid,obj);
  732. asm
  733. if (Result){
  734. var o = obj.get();
  735. if (o.$kind==='com'){
  736. o._Release();
  737. }
  738. }
  739. end;
  740. end;
  741. function TObject.Equals(Obj: TObject): boolean;
  742. begin
  743. Result:=Obj=Self;
  744. end;
  745. function TObject.ToString: String;
  746. begin
  747. Result:=ClassName;
  748. end;
  749. initialization
  750. ExitCode:=0; // set it here, so that WPO does not remove it
  751. end.