system.pas 28 KB

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