system.pas 27 KB

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