system.pas 25 KB

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