12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091 |
- {
- This file is part of the Pas2JS run time library.
- Copyright (c) 2018 by Mattias Gaertner
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit System;
- {$mode objfpc}
- {$modeswitch externalclass}
- interface
- {$IFDEF NodeJS}
- var
- LineEnding: string = #10;
- sLineBreak: string = #10;
- {$ELSE}
- const
- LineEnding = #10;
- sLineBreak = LineEnding;
- {$ENDIF}
- Var
- PathDelim : Char = '/';
- AllowDirectorySeparators : Set of Char = ['/'];
- AllowDriveSeparators : Set of Char = [':'];
- ExtensionSeparator : Char = '.';
- const
- MaxSmallint = 32767;
- MinSmallint = -32768;
- MaxShortInt = 127;
- MinShortInt = -128;
- MaxByte = $FF;
- MaxWord = $FFFF;
- MaxLongint = $7fffffff;
- MaxCardinal = LongWord($ffffffff);
- Maxint = MaxLongint;
- IsMultiThread = false;
- {*****************************************************************************
- Base types
- *****************************************************************************}
- type
- Int8 = ShortInt;
- UInt8 = Byte;
- Int16 = SmallInt;
- UInt16 = Word;
- Int32 = Longint;
- UInt32 = LongWord;
- Integer = LongInt;
- Cardinal = LongWord;
- DWord = LongWord;
- SizeInt = NativeInt;
- SizeUInt = NativeUInt;
- PtrInt = NativeInt;
- PtrUInt = NativeUInt;
- ValSInt = NativeInt;
- ValUInt = NativeUInt;
- CodePointer = Pointer;
- ValReal = Double;
- Real = type Double;
- Extended = type Double;
- TDateTime = type double;
- TTime = type TDateTime;
- TDate = type TDateTime;
- Int64 = type NativeInt unimplemented; // only 53 bits at runtime
- UInt64 = type NativeUInt unimplemented; // only 52 bits at runtime
- QWord = type NativeUInt unimplemented; // only 52 bits at runtime
- Single = type Double unimplemented;
- Comp = type NativeInt unimplemented;
- NativeLargeInt = NativeInt;
- NativeLargeUInt = NativeUInt;
- UnicodeString = type String;
- WideString = type String;
- WideChar = char;
- UnicodeChar = char;
- TDynArrayIndex = NativeInt;
- TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR);
- TCompareOption = ({coLingIgnoreCase, coLingIgnoreDiacritic, }coIgnoreCase{,
- coIgnoreKanaType, coIgnoreNonSpace, coIgnoreSymbols, coIgnoreWidth,
- coLingCasing, coDigitAsNumbers, coStringSort});
- TCompareOptions = set of TCompareOption;
- {*****************************************************************************
- TObject, TClass, IUnknown, IInterface, TInterfacedObject
- *****************************************************************************}
- type
- TGuid = record
- D1: DWord;
- D2: word;
- D3: word;
- D4: array[0..7] of byte;
- end;
- TGUIDString = type string;
- PMethod = ^TMethod;
- TMethod = record
- Code : CodePointer;
- Data : Pointer;
- end;
- TClass = class of TObject;
- { TObject }
- {$DispatchField Msg} // enable checking message methods for record field name "Msg"
- {$DispatchStrField MsgStr}
- TObject = class
- private
- class var FClassName: String; external name '$classname';
- class var FClassParent: TClass; external name '$ancestor';
- class var FUnitName: String; external name '$module.$name';
- public
- constructor Create;
- destructor Destroy; virtual;
- // Free is using compiler magic.
- // Reasons:
- // 1. In JS calling obj.Free when obj=nil would crash.
- // 2. In JS freeing memory requires to set all references to nil.
- // Therefore any obj.free call is replaced by the compiler with some rtl magic.
- procedure Free;
- class function ClassType: TClass; assembler;
- class property ClassName: String read FClassName;
- class function ClassNameIs(const Name: string): boolean;
- class property ClassParent: TClass read FClassParent;
- class function InheritsFrom(aClass: TClass): boolean; assembler;
- class property UnitName: String read FUnitName;
- Class function MethodName(aCode : Pointer) : String;
- Class function MethodAddress(aName : String) : Pointer;
- Class Function FieldAddress(aName : String) : Pointer;
- Class Function ClassInfo : Pointer;
- procedure AfterConstruction; virtual;
- procedure BeforeDestruction; virtual;
- // message handling routines
- procedure Dispatch(var aMessage); virtual;
- procedure DispatchStr(var aMessage); virtual;
- procedure DefaultHandler(var aMessage); virtual;
- procedure DefaultHandlerStr(var aMessage); virtual;
- function GetInterface(const iid: TGuid; out obj): boolean;
- function GetInterface(const iidstr: String; out obj): boolean; inline;
- function GetInterfaceByStr(const iidstr: String; out obj): boolean;
- function GetInterfaceWeak(const iid: TGuid; out obj): boolean; // equal to GetInterface but the interface returned is not referenced
- function Equals(Obj: TObject): boolean; virtual;
- function ToString: String; virtual;
- end;
- { TCustomAttribute - base class of all user defined attributes. }
- TCustomAttribute = class
- end;
- TCustomAttributeArray = array of TCustomAttribute;
- const
- { IInterface }
- S_OK = 0;
- S_FALSE = 1;
- E_NOINTERFACE = -2147467262; // FPC: longint($80004002)
- E_UNEXPECTED = -2147418113; // FPC: longint($8000FFFF)
- E_NOTIMPL = -2147467263; // FPC: longint($80004001)
- type
- {$Interfaces COM}
- IUnknown = interface
- ['{00000000-0000-0000-C000-000000000046}']
- function QueryInterface(const iid: TGuid; out obj): Integer;
- function _AddRef: Integer;
- function _Release: Integer;
- end;
- IInterface = IUnknown;
- {$M+}
- IInvokable = interface(IInterface)
- end;
- {$M-}
- { Enumerator support }
- IEnumerator = interface(IInterface)
- function GetCurrent: TObject;
- function MoveNext: Boolean;
- procedure Reset;
- property Current: TObject read GetCurrent;
- end;
- IEnumerable = interface(IInterface)
- function GetEnumerator: IEnumerator;
- end;
- { TInterfacedObject }
- TInterfacedObject = class(TObject,IUnknown)
- protected
- fRefCount: Integer;
- { implement methods of IUnknown }
- function QueryInterface(const iid: TGuid; out obj): Integer; virtual;
- function _AddRef: Integer; virtual;
- function _Release: Integer; virtual;
- public
- procedure BeforeDestruction; override;
- property RefCount: Integer read fRefCount;
- end;
- TInterfacedClass = class of TInterfacedObject;
- { TAggregatedObject - sub or satellite object using same interface as controller }
- TAggregatedObject = class(TObject)
- private
- fController: Pointer;
- function GetController: IUnknown;
- protected
- { implement methods of IUnknown }
- function QueryInterface(const iid: TGuid; out obj): Integer; virtual;
- function _AddRef: Integer; virtual;
- function _Release: Integer; virtual;
- public
- constructor Create(const aController: IUnknown); reintroduce;
- property Controller: IUnknown read GetController;
- end;
- { TContainedObject }
- TContainedObject = class(TAggregatedObject,IInterface)
- protected
- function QueryInterface(const iid: TGuid; out obj): Integer; override;
- end;
- const
- { for safe as operator support }
- IObjectInstance: TGuid = '{D91C9AF4-3C93-420F-A303-BF5BA82BFD23}';
- function GUIDToString(const GUID: TGUID): string; external name 'rtl.guidrToStr';
- {*****************************************************************************
- Array of const support
- *****************************************************************************}
- const
- vtInteger = 0;
- vtBoolean = 1;
- //vtChar = 2; // Delphi/FPC: ansichar
- vtExtended = 3; // Note: double in pas2js, PExtended in Delphi/FPC
- //vtString = 4; // Delphi/FPC: PShortString
- vtPointer = 5;
- //vtPChar = 6;
- vtObject = 7;
- vtClass = 8;
- vtWideChar = 9;
- //vtPWideChar = 10;
- //vtAnsiString = 11;
- vtCurrency = 12; // Note: currency in pas2js, PCurrency in Delphi/FPC
- //vtVariant = 13;
- vtInterface = 14;
- //vtWideString = 15;
- //vtInt64 = 16;
- //vtQWord = 17;
- vtUnicodeString = 18;
- // only pas2js, not in Delphi/FPC:
- vtNativeInt = 19;
- vtJSValue = 20;
- type
- PVarRec = ^TVarRec;
- TVarRec = record
- VType: byte;
- VJSValue: JSValue;
- VInteger: LongInt external name 'VJSValue';
- VBoolean: Boolean external name 'VJSValue';
- VExtended: Double external name 'VJSValue';
- VPointer: Pointer external name 'VJSValue';
- VObject: TObject external name 'VJSValue';
- VClass: TClass external name 'VJSValue';
- VWideChar: WideChar external name 'VJSValue';
- VCurrency: Currency external name 'VJSValue';
- VInterface: Pointer external name 'VJSValue';
- VUnicodeString: UnicodeString external name 'VJSValue';
- VNativeInt: NativeInt external name 'VJSValue';
- end;
- TVarRecArray = array of TVarRec;
- function VarRecs: TVarRecArray; varargs;
- {*****************************************************************************
- Init / Exit / ExitProc
- *****************************************************************************}
- var
- ExitCode: Integer; external name 'rtl.exitcode';
- IsConsole: Boolean = {$IFDEF NodeJS}true{$ELSE}false{$ENDIF};
- FirstDotAtFileNameStartIsExtension : Boolean = False;
- type
- TOnParamCount = function: Longint;
- TOnParamStr = function(Index: Longint): String;
- var
- OnParamCount: TOnParamCount;
- OnParamStr: TOnParamStr;
- function ParamCount: Longint;
- function ParamStr(Index: Longint): String;
- {*****************************************************************************
- Math
- *****************************************************************************}
- const
- PI: Double; external name 'Math.PI';
- MathE: Double; external name 'Math.E'; // Euler's number
- MathLN10: Double; external name 'Math.LN10'; // ln(10)
- MathLN2: Double; external name 'Math.LN2'; // ln(2)
- MathLog10E: Double; external name 'Math.Log10E'; // log10(e)
- MathLog2E: Double; external name 'Math.LOG2E'; // log2(e)
- MathSQRT1_2: Double; external name 'Math.SQRT1_2'; // sqrt(0.5)
- MathSQRT2: Double; external name 'Math.SQRT2'; // sqrt(2)
- function Abs(const A: integer): integer; overload; external name 'Math.abs';
- function Abs(const A: NativeInt): integer; overload; external name 'Math.abs';
- function Abs(const A: Double): Double; overload; external name 'Math.abs';
- function ArcTan(const A: Double): Double; external name 'Math.atan';
- function ArcTan2(const A,B: Double): Double; external name 'Math.atan2';
- function Cos(const A: Double): Double; external name 'Math.cos';
- function Exp(const A: Double): Double; external name 'Math.exp';
- function Frac(const A: Double): Double; assembler;
- function Ln(const A: Double): Double; external name 'Math.log';
- function Odd(const A: Integer): Boolean; assembler;
- function Random(const Range: Integer): Integer; overload; assembler;
- function Random: Double; overload; external name 'Math.random';
- function Round(const A: Double): NativeInt; external name 'Math.round';
- function Sin(const A: Double): Double; external name 'Math.sin';
- function Sqr(const A: Integer): Integer; assembler; overload;
- function Sqr(const A: Double): Double; assembler; overload;
- function sqrt(const A: Double): Double; external name 'Math.sqrt';
- function Trunc(const A: Double): NativeInt;
- {*****************************************************************************
- String functions
- *****************************************************************************}
- const
- DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
- function Int(const A: Double): double;
- function Copy(const S: string; Index, Size: Integer): String; assembler; overload;
- function Copy(const S: string; Index: Integer): String; assembler; overload;
- procedure Delete(var S: String; Index, Size: Integer); assembler; overload;
- function Pos(const Search, InString: String): Integer; assembler; overload;
- function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
- procedure Insert(const Insertion: String; var Target: String; Index: Integer); overload;
- function upcase(c : char) : char; assembler;
- function HexStr(Val: NativeInt; cnt: byte): string; external name 'rtl.hexStr'; overload;
- function binstr(val : NativeUInt; cnt : byte) : string;
- procedure val(const S: String; out NI : NativeInt; out Code: Integer); overload;
- procedure val(const S: String; out NI : NativeUInt; out Code: Integer); overload;
- procedure val(const S: String; out SI : ShortInt; out Code: Integer); overload;
- procedure val(const S: String; out B : Byte; out Code: Integer); overload;
- procedure val(const S: String; out SI : smallint; out Code: Integer); overload;
- procedure val(const S: String; out W : word; out Code : Integer); overload;
- procedure val(const S: String; out I : integer; out Code : Integer); overload;
- procedure val(const S: String; out C : Cardinal; out Code: Integer); overload;
- procedure val(const S: String; out d : double; out Code : Integer); overload;
- procedure val(const S: String; out b : boolean; out Code: Integer); overload;
- function StringOfChar(c: Char; l: NativeInt): String;
- {*****************************************************************************
- Other functions
- *****************************************************************************}
- procedure Write; varargs; // ToDo: should be compiler built-in function
- procedure Writeln; varargs; // ToDo: should be compiler built-in function
- Type
- TConsoleHandler = Procedure (S : JSValue; NewLine : Boolean);
- Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
- function Assigned(const V: JSValue): boolean; assembler; overload;
- function StrictEqual(const A: JSValue; const B): boolean; assembler;
- function StrictInequal(const A: JSValue; const B): boolean; assembler;
- implementation
- type
- { TJSObj - simple access to JS Object }
- TJSObj = class external name 'Object'
- private
- function GetProperties(Name: String): JSValue; external name '[]';
- procedure SetProperties(Name: String; const AValue: JSValue); external name '[]';
- public
- //constructor new;
- //function hasOwnProperty(prop: String): boolean;
- property Properties[Name: String]: JSValue read GetProperties write SetProperties; default;
- end;
- TJSArray = class external name 'Array'
- public
- //length: nativeint;
- //constructor new; overload;
- function push(aElement : JSValue) : NativeInt; varargs;
- end;
- TJSArguments = class external name 'arguments'
- private
- FLength: NativeInt; external name 'length';
- function GetElements(Index: NativeInt): JSValue; external name '[]';
- public
- property Length: NativeInt read FLength;
- property Elements[Index: NativeInt]: JSValue read GetElements; default;
- end;
- var
- JSArguments: TJSArguments; external name 'arguments';
- function isNumber(const v: JSValue): boolean; external name 'rtl.isNumber';
- function isObject(const v: JSValue): boolean; external name 'rtl.isObject'; // true if not null and a JS Object
- function isString(const v: JSValue): boolean; external name 'rtl.isString';
- function isNaN(i: JSValue): boolean; external name 'isNaN'; // may result NaN
- // needed by ClassNameIs, the real SameText is in SysUtils
- function SameText(const s1, s2: String): Boolean; assembler;
- asm
- return s1.toLowerCase() == s2.toLowerCase();
- end;
- function VarRecs: TVarRecArray;
- var
- i: nativeint;
- v: PVarRec;
- begin
- Result:=nil;
- while i<JSArguments.Length do
- begin
- new(v);
- v^.VType:=byte(JSArguments[i]);
- inc(i);
- v^.VJSValue:=JSArguments[i];
- inc(i);
- TJSArray(Result).push(v^);
- end;
- end;
- function ParamCount: Longint;
- begin
- if Assigned(OnParamCount) then
- Result:=OnParamCount()
- else
- Result:=0;
- end;
- function ParamStr(Index: Longint): String;
- begin
- if Assigned(OnParamStr) then
- Result:=OnParamStr(Index)
- else if Index=0 then
- Result:='js'
- else
- Result:='';
- end;
- function Frac(const A: Double): Double; assembler;
- asm
- return A % 1;
- end;
- function Odd(const A: Integer): Boolean; assembler;
- asm
- return A&1 != 0;
- end;
- function Random(const Range: Integer): Integer; assembler;
- asm
- return Math.floor(Math.random()*Range);
- end;
- function Sqr(const A: Integer): Integer; assembler;
- asm
- return A*A;
- end;
- function Sqr(const A: Double): Double; assembler;
- asm
- return A*A;
- end;
- function Trunc(const A: Double): NativeInt; assembler;
- asm
- if (!Math.trunc) {
- Math.trunc = function(v) {
- v = +v;
- if (!isFinite(v)) return v;
- return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
- };
- }
- $mod.Trunc = Math.trunc;
- return Math.trunc(A);
- end;
- function Copy(const S: string; Index, Size: Integer): String; assembler;
- asm
- if (Index<1) Index = 1;
- return (Size>0) ? S.substring(Index-1,Index+Size-1) : "";
- end;
- function Copy(const S: string; Index: Integer): String; assembler;
- asm
- if (Index<1) Index = 1;
- return S.substr(Index-1);
- end;
- procedure Delete(var S: String; Index, Size: Integer);
- var
- h: String;
- begin
- if (Index<1) or (Index>length(S)) or (Size<=0) then exit;
- h:=S;
- S:=copy(h,1,Index-1)+copy(h,Index+Size);
- end;
- function Pos(const Search, InString: String): Integer; assembler;
- asm
- return InString.indexOf(Search)+1;
- end;
- function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
- asm
- return InString.indexOf(Search,StartAt-1)+1;
- end;
- procedure Insert(const Insertion: String; var Target: String; Index: Integer);
- var
- t: String;
- begin
- if Insertion='' then exit;
- t:=Target;
- if Index<1 then
- Target:=Insertion+t
- else if Index>length(t) then
- Target:=t+Insertion
- else
- Target:=copy(t,1,Index-1)+Insertion+copy(t,Index,length(t));
- end;
- var
- WriteBuf: String;
- WriteCallBack : TConsoleHandler;
- Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
- begin
- Result:=WriteCallBack;
- WriteCallBack:=H;
- end;
- procedure Write;
- var
- i: Integer;
- begin
- for i:=0 to JSArguments.Length-1 do
- if Assigned(WriteCallBack) then
- WriteCallBack(JSArguments[i],False)
- else
- WriteBuf:=WriteBuf+String(JSArguments[i]);
- end;
- procedure Writeln;
- var
- i,l: Integer;
- s: String;
- begin
- L:=JSArguments.Length-1;
- if Assigned(WriteCallBack) then
- begin
- for i:=0 to L do
- WriteCallBack(JSArguments[i],I=L);
- end
- else
- begin
- s:=WriteBuf;
- for i:=0 to L do
- s:=s+String(JSArguments[i]);
- asm
- console.log(s);
- end;
- WriteBuf:='';
- end;
- end;
- function Int(const A: Double): double;
- begin
- // trunc contains fix for missing Math.trunc in IE
- Result:=Trunc(A);
- end;
- function Number(S: String): Double; external name 'Number';
- function valint(const S: String; MinVal, MaxVal: NativeInt; out Code: Integer): NativeInt;
- var
- x: double;
- begin
- x:=Number(S);
- if isNaN(x) then
- case copy(s,1,1) of
- '$': x:=Number('0x'+copy(S,2));
- '&': x:=Number('0o'+copy(S,2));
- '%': x:=Number('0b'+copy(S,2));
- else
- Code:=1;
- exit;
- end;
- if isNaN(x) or (X<>Int(X)) then
- Code:=1
- else if (x<MinVal) or (x>MaxVal) then
- Code:=2
- else
- begin
- Result:=Trunc(x);
- Code:=0;
- end;
- end;
- procedure val(const S: String; out NI : NativeInt; out Code: Integer);
- begin
- NI:=valint(S,low(NI),high(NI),Code);
- end;
- procedure val(const S: String; out NI: NativeUInt; out Code: Integer);
- var
- x : double;
- begin
- x:=Number(S);
- if isNaN(x) or (X<>Int(X)) or (X<0) then
- Code:=1
- else
- begin
- Code:=0;
- NI:=Trunc(x);
- end;
- end;
- procedure val(const S: String; out SI : ShortInt; out Code: Integer);
- begin
- SI:=valint(S,low(SI),high(SI),Code);
- end;
- procedure val(const S: String; out SI: smallint; out Code: Integer);
- begin
- SI:=valint(S,low(SI),high(SI),Code);
- end;
- procedure val(const S: String; out C: Cardinal; out Code: Integer);
- begin
- C:=valint(S,low(C),high(C),Code);
- end;
- procedure val(const S: String; out B: Byte; out Code: Integer);
- begin
- B:=valint(S,low(B),high(B),Code);
- end;
- procedure val(const S: String; out W: word; out Code: Integer);
- begin
- W:=valint(S,low(W),high(W),Code);
- end;
- procedure val(const S : String; out I : integer; out Code : Integer);
- begin
- I:=valint(S,low(I),high(I),Code);
- end;
- procedure val(const S : String; out d : double; out Code : Integer);
- Var
- x: double;
- begin
- x:=Number(S);
- if isNaN(x) then
- Code:=1
- else
- begin
- Code:=0;
- d:=x;
- end;
- end;
- procedure val(const S: String; out b: boolean; out Code: Integer);
- begin
- if SameText(S,'true') then
- begin
- Code:=0;
- b:=true;
- end
- else if SameText(S,'false') then
- begin
- Code:=0;
- b:=false;
- end
- else
- Code:=1;
- end;
- function binstr(val : NativeUInt;cnt : byte) : string;
- var
- i : Integer;
- begin
- SetLength(Result,cnt);
- for i:=cnt downto 1 do
- begin
- Result[i]:=char(48+val and 1);
- val:=val shr 1;
- end;
- end;
- function upcase(c : char) : char; assembler;
- asm
- return c.toUpperCase();
- end;
- function StringOfChar(c: Char; l: NativeInt): String;
- var
- i: Integer;
- begin
- asm
- if ((l>0) && c.repeat) return c.repeat(l);
- end;
- Result:='';
- for i:=1 to l do Result:=Result+c;
- end;
- function Assigned(const V: JSValue): boolean; assembler;
- asm
- return (V!=undefined) && (V!=null) && (!rtl.isArray(V) || (V.length > 0));
- end;
- function StrictEqual(const A: JSValue; const B): boolean; assembler;
- asm
- return A === B;
- end;
- function StrictInequal(const A: JSValue; const B): boolean; assembler;
- asm
- return A !== B;
- end;
- { TContainedObject }
- function TContainedObject.QueryInterface(const iid: TGuid; out obj): Integer;
- begin
- if GetInterface(iid,obj) then
- Result:=S_OK
- else
- Result:=Integer(E_NOINTERFACE);
- end;
- { TAggregatedObject }
- function TAggregatedObject.GetController: IUnknown;
- begin
- Result := IUnknown(fController);
- end;
- function TAggregatedObject.QueryInterface(const iid: TGuid; out obj): Integer;
- begin
- Result := IUnknown(fController).QueryInterface(iid, obj);
- end;
- function TAggregatedObject._AddRef: Integer;
- begin
- Result := IUnknown(fController)._AddRef;
- end;
- function TAggregatedObject._Release: Integer;
- begin
- Result := IUnknown(fController)._Release;
- end;
- constructor TAggregatedObject.Create(const aController: IUnknown);
- begin
- inherited Create;
- { do not keep a counted reference to the controller! }
- fController := Pointer(aController);
- end;
- { TInterfacedObject }
- function TInterfacedObject.QueryInterface(const iid: TGuid; out obj): Integer;
- begin
- if GetInterface(iid,obj) then
- Result:=S_OK
- else
- Result:=Integer(E_NOINTERFACE);
- end;
- function TInterfacedObject._AddRef: Integer;
- begin
- inc(fRefCount);
- Result:=fRefCount;
- end;
- function TInterfacedObject._Release: Integer;
- begin
- dec(fRefCount);
- Result:=fRefCount;
- if fRefCount=0 then
- Destroy;
- end;
- procedure TInterfacedObject.BeforeDestruction;
- begin
- if fRefCount<>0 then
- asm
- rtl.raiseE('EHeapMemoryError');
- end;
- end;
- { TObject }
- constructor TObject.Create;
- begin
- end;
- destructor TObject.Destroy;
- begin
- end;
- procedure TObject.Free;
- begin
- Destroy;
- end;
- class function TObject.ClassType: TClass; assembler;
- asm
- return this;
- end;
- class function TObject.ClassNameIs(const Name: string): boolean;
- begin
- Result:=SameText(Name,ClassName);
- end;
- class function TObject.InheritsFrom(aClass: TClass): boolean; assembler;
- asm
- return (aClass!=null) && ((this==aClass) || aClass.isPrototypeOf(this));
- end;
- Class function TObject.MethodName(aCode : Pointer) : String;
- begin
- Result:='';
- if aCode=Nil then
- exit;
- asm
- if (typeof(aCode)!=='function') return "";
- var i = 0;
- var TI = this.$rtti;
- if (rtl.isObject(aCode.scope)){
- // callback
- if (typeof aCode.fn === "string") return aCode.fn;
- aCode = aCode.fn;
- }
- // Not a callback, check rtti
- while ((Result === "") && (TI != null)) {
- i = 0;
- while ((Result === "") && (i < TI.methods.length)) {
- if (this[TI.getMethod(i).name] === aCode)
- Result=TI.getMethod(i).name;
- i += 1;
- };
- if (Result === "") TI = TI.ancestor;
- };
- return Result;
- end;
- end;
- Class function TObject.MethodAddress(aName : String) : Pointer;
- // We must do this in asm, because the typinfo unit is not available.
- begin
- Result:=Nil;
- if AName='' then
- exit;
- asm
- var i = 0;
- var TI = this.$rtti;
- var N = "";
- var MN = "";
- N = aName.toLowerCase();
- while ((MN === "") && (TI != null)) {
- i = 0;
- while ((MN === "") && (i < TI.methods.length)) {
- if (TI.getMethod(i).name.toLowerCase() === N) MN = TI.getMethod(i).name;
- i += 1;
- };
- if (MN === "") TI = TI.ancestor;
- };
- if (MN !== "") Result = this[MN];
- return Result;
- end;
- end;
- class function TObject.FieldAddress(aName: String): Pointer;
- begin
- Result:=Nil;
- if aName='' then exit;
- asm
- var aClass = null;
- var i = 0;
- var ClassTI = null;
- var myName = aName.toLowerCase();
- var MemberTI = null;
- aClass = this.$class;
- while (aClass !== null) {
- ClassTI = aClass.$rtti;
- for (var $l1 = 0, $end2 = ClassTI.fields.length - 1; $l1 <= $end2; $l1++) {
- i = $l1;
- MemberTI = ClassTI.getField(i);
- if (MemberTI.name.toLowerCase() === myName) {
- return MemberTI;
- };
- };
- aClass = aClass.$ancestor ? aClass.$ancestor : null;
- };
- end;
- end;
- Class Function TObject.ClassInfo : Pointer;
- begin
- // This works different from FPC/Delphi.
- // We get the actual type info.
- Result:=TypeInfo(Self);
- end;
- procedure TObject.AfterConstruction;
- begin
- end;
- procedure TObject.BeforeDestruction;
- begin
- end;
- procedure TObject.Dispatch(var aMessage);
- // aMessage is a record with an integer field 'Msg'
- var
- aClass: TClass;
- Msg: TJSObj absolute aMessage;
- Id: jsvalue;
- begin
- if not isObject(Msg) then exit;
- Id:=Msg['Msg'];
- if not isNumber(Id) then exit;
- aClass:=ClassType;
- while aClass<>nil do
- begin
- asm
- var Handlers = aClass.$msgint;
- if (rtl.isObject(Handlers) && Handlers.hasOwnProperty(Id)){
- this[Handlers[Id]](aMessage);
- return;
- }
- end;
- aClass:=aClass.ClassParent;
- end;
- DefaultHandler(aMessage);
- end;
- procedure TObject.DispatchStr(var aMessage);
- // aMessage is a record with a string field 'MsgStr'
- var
- aClass: TClass;
- Msg: TJSObj absolute aMessage;
- Id: jsvalue;
- begin
- if not isObject(Msg) then exit;
- Id:=Msg['MsgStr'];
- if not isString(Id) then exit;
- aClass:=ClassType;
- while (aClass<>Nil) do
- begin
- asm
- var Handlers = aClass.$msgstr;
- if (rtl.isObject(Handlers) && Handlers.hasOwnProperty(Id)){
- this[Handlers[Id]](aMessage);
- return;
- }
- end;
- aClass:=aClass.ClassParent;
- end;
- DefaultHandlerStr(aMessage);
- end;
- procedure TObject.DefaultHandler(var aMessage);
- begin
- if jsvalue(TMethod(aMessage)) then ;
- end;
- procedure TObject.DefaultHandlerStr(var aMessage);
- begin
- if jsvalue(TMethod(aMessage)) then ;
- end;
- function TObject.GetInterface(const iid: TGuid; out obj): boolean;
- begin
- asm
- var i = iid.$intf;
- if (i){
- // iid is the private TGuid of an interface
- i = rtl.getIntfG(this,i.$guid,2);
- if (i){
- obj.set(i);
- return true;
- }
- }
- end;
- Result := GetInterfaceByStr(GUIDToString(iid),obj);
- end;
- function TObject.GetInterface(const iidstr: String; out obj): boolean;
- begin
- Result := GetInterfaceByStr(iidstr,obj);
- end;
- function TObject.GetInterfaceByStr(const iidstr: String; out obj): boolean;
- begin
- if not TJSObj(IObjectInstance)['$str'] then
- TJSObj(IObjectInstance)['$str']:=GUIDToString(IObjectInstance);
- if iidstr = TJSObj(IObjectInstance)['$str'] then
- begin
- obj:=Self;
- exit(true);
- end;
- asm
- var i = rtl.getIntfG(this,iidstr,2);
- obj.set(i);
- return i!==null;
- end;
- Result:=false;
- end;
- function TObject.GetInterfaceWeak(const iid: TGuid; out obj): boolean;
- begin
- Result:=GetInterface(iid,obj);
- asm
- if (Result){
- var o = obj.get();
- if (o.$kind==='com'){
- o._Release();
- }
- }
- end;
- end;
- function TObject.Equals(Obj: TObject): boolean;
- begin
- Result:=Obj=Self;
- end;
- function TObject.ToString: String;
- begin
- Result:=ClassName;
- end;
- initialization
- ExitCode:=0; // set it here, so that WPO does not remove it
- end.
|