system.pas 23 KB

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