@live-codes/pascal-wasm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +501 -0
- package/README.md +278 -0
- package/THIRD-PARTY-NOTICES.md +48 -0
- package/assets/pas2js.wasm +0 -0
- package/assets/rtl/Rtl.BrowserLoadHelper.pas +179 -0
- package/assets/rtl/browserconsole.pas +190 -0
- package/assets/rtl/classes.pas +11371 -0
- package/assets/rtl/js.pas +2211 -0
- package/assets/rtl/manifest.json +19 -0
- package/assets/rtl/math.pas +903 -0
- package/assets/rtl/p2jsres.pp +334 -0
- package/assets/rtl/rtl.js +1563 -0
- package/assets/rtl/rtlconsts.pas +97 -0
- package/assets/rtl/simplelinkedlist.pas +152 -0
- package/assets/rtl/system.pas +1166 -0
- package/assets/rtl/sysutils.pas +8959 -0
- package/assets/rtl/types.pas +2296 -0
- package/assets/rtl/typinfo.pas +1680 -0
- package/assets/rtl/web.pas +3586 -0
- package/assets/rtl/weborworker.pas +2101 -0
- package/dist/pascal-wasm.iife.min.js +6 -0
- package/dist/pascal-wasm.iife.min.js.map +7 -0
- package/package.json +54 -0
- package/src/assets.js +119 -0
- package/src/compiler.js +142 -0
- package/src/config.js +24 -0
- package/src/iife.js +27 -0
- package/src/index.js +130 -0
- package/src/vendor/browser_wasi_shim/debug.js +1 -0
- package/src/vendor/browser_wasi_shim/fd.js +1 -0
- package/src/vendor/browser_wasi_shim/fs_mem.js +1 -0
- package/src/vendor/browser_wasi_shim/fs_opfs.js +1 -0
- package/src/vendor/browser_wasi_shim/index.js +1 -0
- package/src/vendor/browser_wasi_shim/strace.js +1 -0
- package/src/vendor/browser_wasi_shim/wasi.js +1 -0
- package/src/vendor/browser_wasi_shim/wasi_defs.js +1 -0
- package/types/index.d.ts +89 -0
|
@@ -0,0 +1,1166 @@
|
|
|
1
|
+
{
|
|
2
|
+
This file is part of the Pas2JS run time library.
|
|
3
|
+
Copyright (c) 2018 by Mattias Gaertner
|
|
4
|
+
|
|
5
|
+
See the file COPYING.FPC, included in this distribution,
|
|
6
|
+
for details about the copyright.
|
|
7
|
+
|
|
8
|
+
This program is distributed in the hope that it will be useful,
|
|
9
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
11
|
+
|
|
12
|
+
**********************************************************************}
|
|
13
|
+
unit System;
|
|
14
|
+
|
|
15
|
+
{$mode objfpc}
|
|
16
|
+
{$modeswitch externalclass}
|
|
17
|
+
|
|
18
|
+
interface
|
|
19
|
+
|
|
20
|
+
{$IFDEF NodeJS}
|
|
21
|
+
var
|
|
22
|
+
LineEnding: string = #10;
|
|
23
|
+
sLineBreak: string = #10;
|
|
24
|
+
{$ELSE}
|
|
25
|
+
const
|
|
26
|
+
LineEnding = #10;
|
|
27
|
+
sLineBreak = LineEnding;
|
|
28
|
+
{$ENDIF}
|
|
29
|
+
|
|
30
|
+
Var
|
|
31
|
+
PathDelim : Char = '/';
|
|
32
|
+
AllowDirectorySeparators : Set of Char = ['/'];
|
|
33
|
+
AllowDriveSeparators : Set of Char = [':'];
|
|
34
|
+
ExtensionSeparator : Char = '.';
|
|
35
|
+
|
|
36
|
+
const
|
|
37
|
+
MaxSmallint = 32767;
|
|
38
|
+
MinSmallint = -32768;
|
|
39
|
+
MaxShortInt = 127;
|
|
40
|
+
MinShortInt = -128;
|
|
41
|
+
MaxByte = $FF;
|
|
42
|
+
MaxWord = $FFFF;
|
|
43
|
+
MaxLongint = $7fffffff;
|
|
44
|
+
MaxCardinal = LongWord($ffffffff);
|
|
45
|
+
|
|
46
|
+
Maxint = MaxLongint;
|
|
47
|
+
IsMultiThread = false;
|
|
48
|
+
|
|
49
|
+
{*****************************************************************************
|
|
50
|
+
Base types
|
|
51
|
+
*****************************************************************************}
|
|
52
|
+
type
|
|
53
|
+
HRESULT = Longint; // For Delphi compatibility
|
|
54
|
+
Int8 = ShortInt;
|
|
55
|
+
UInt8 = Byte;
|
|
56
|
+
Int16 = SmallInt;
|
|
57
|
+
UInt16 = Word;
|
|
58
|
+
Int32 = Longint;
|
|
59
|
+
UInt32 = LongWord;
|
|
60
|
+
|
|
61
|
+
Integer = LongInt;
|
|
62
|
+
Cardinal = LongWord;
|
|
63
|
+
DWord = LongWord;
|
|
64
|
+
SizeInt = NativeInt;
|
|
65
|
+
SizeUInt = NativeUInt;
|
|
66
|
+
PtrInt = NativeInt;
|
|
67
|
+
PtrUInt = NativeUInt;
|
|
68
|
+
ValSInt = NativeInt;
|
|
69
|
+
ValUInt = NativeUInt;
|
|
70
|
+
CodePointer = Pointer;
|
|
71
|
+
ValReal = Double;
|
|
72
|
+
Real = type Double;
|
|
73
|
+
Extended = type Double;
|
|
74
|
+
|
|
75
|
+
TDateTime = type double;
|
|
76
|
+
TTime = type TDateTime;
|
|
77
|
+
TDate = type TDateTime;
|
|
78
|
+
|
|
79
|
+
Int64 = type NativeInt unimplemented; // only 53 bits at runtime
|
|
80
|
+
UInt64 = type NativeUInt unimplemented; // only 52 bits at runtime
|
|
81
|
+
QWord = type NativeUInt unimplemented; // only 52 bits at runtime
|
|
82
|
+
Single = type Double unimplemented;
|
|
83
|
+
Comp = type NativeInt unimplemented;
|
|
84
|
+
NativeLargeInt = NativeInt;
|
|
85
|
+
NativeLargeUInt = NativeUInt;
|
|
86
|
+
|
|
87
|
+
UnicodeChar = Char;
|
|
88
|
+
UnicodeString = type String;
|
|
89
|
+
WideString = type String;
|
|
90
|
+
WideChar = Char;
|
|
91
|
+
|
|
92
|
+
TDynArrayIndex = NativeInt;
|
|
93
|
+
TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR);
|
|
94
|
+
|
|
95
|
+
TCompareOption = ({coLingIgnoreCase, coLingIgnoreDiacritic, }coIgnoreCase{,
|
|
96
|
+
coIgnoreKanaType, coIgnoreNonSpace, coIgnoreSymbols, coIgnoreWidth,
|
|
97
|
+
coLingCasing, coDigitAsNumbers, coStringSort});
|
|
98
|
+
TCompareOptions = set of TCompareOption;
|
|
99
|
+
|
|
100
|
+
generic TArray<T> = array of T;
|
|
101
|
+
|
|
102
|
+
{*****************************************************************************
|
|
103
|
+
TObject, TClass, IUnknown, IInterface, TInterfacedObject
|
|
104
|
+
*****************************************************************************}
|
|
105
|
+
|
|
106
|
+
type
|
|
107
|
+
TGuid = record
|
|
108
|
+
D1: DWord;
|
|
109
|
+
D2: word;
|
|
110
|
+
D3: word;
|
|
111
|
+
D4: array[0..7] of byte;
|
|
112
|
+
end;
|
|
113
|
+
TGUIDString = type string;
|
|
114
|
+
|
|
115
|
+
TMethod = record
|
|
116
|
+
Code : CodePointer;
|
|
117
|
+
Data : Pointer;
|
|
118
|
+
end;
|
|
119
|
+
|
|
120
|
+
PMethod = ^TMethod;
|
|
121
|
+
|
|
122
|
+
TClass = class of TObject;
|
|
123
|
+
|
|
124
|
+
{ TObject }
|
|
125
|
+
{$IFDEF ENABLE_DELPHI_RTTI}
|
|
126
|
+
{$RTTI INHERIT
|
|
127
|
+
METHODS([vcPublic, vcPublished])
|
|
128
|
+
FIELDS([vcPrivate,vcProtected, vcPublic,vcPublished])
|
|
129
|
+
PROPERTIES([vcPublic, vcPublished])
|
|
130
|
+
}
|
|
131
|
+
{$ENDIF}
|
|
132
|
+
|
|
133
|
+
{$DispatchField Msg} // enable checking message methods for record field name "Msg"
|
|
134
|
+
{$DispatchStrField MsgStr}
|
|
135
|
+
TObject = class
|
|
136
|
+
private
|
|
137
|
+
class var FClassName: String; external name '$classname';
|
|
138
|
+
class var FClassParent: TClass; external name '$ancestor';
|
|
139
|
+
class var FUnitName: String; external name '$module.$name';
|
|
140
|
+
public
|
|
141
|
+
constructor Create;
|
|
142
|
+
destructor Destroy; virtual;
|
|
143
|
+
|
|
144
|
+
// Free is using compiler magic.
|
|
145
|
+
// Reasons:
|
|
146
|
+
// 1. In JS calling obj.Free when obj=nil would crash.
|
|
147
|
+
// 2. In JS freeing memory requires to set all references to nil.
|
|
148
|
+
// Therefore any obj.free call is replaced by the compiler with some rtl magic.
|
|
149
|
+
procedure Free;
|
|
150
|
+
|
|
151
|
+
class function ClassType: TClass; assembler;
|
|
152
|
+
class property ClassName: String read FClassName;
|
|
153
|
+
class function ClassNameIs(const Name: string): boolean;
|
|
154
|
+
class property ClassParent: TClass read FClassParent;
|
|
155
|
+
class function InheritsFrom(aClass: TClass): boolean; assembler;
|
|
156
|
+
class property UnitName: String read FUnitName;
|
|
157
|
+
Class function MethodName(aCode : Pointer) : String;
|
|
158
|
+
Class function MethodAddress(aName : String) : Pointer;
|
|
159
|
+
Class Function FieldAddress(aName : String) : Pointer;
|
|
160
|
+
Class Function ClassInfo : Pointer;
|
|
161
|
+
class function QualifiedClassName: String;
|
|
162
|
+
|
|
163
|
+
procedure AfterConstruction; virtual;
|
|
164
|
+
procedure BeforeDestruction; virtual;
|
|
165
|
+
|
|
166
|
+
// message handling routines
|
|
167
|
+
procedure Dispatch(var aMessage); virtual;
|
|
168
|
+
procedure DispatchStr(var aMessage); virtual;
|
|
169
|
+
procedure DefaultHandler(var aMessage); virtual;
|
|
170
|
+
procedure DefaultHandlerStr(var aMessage); virtual;
|
|
171
|
+
|
|
172
|
+
function GetInterface(const iid: TGuid; out obj): boolean;
|
|
173
|
+
function GetInterface(const iidstr: String; out obj): boolean; inline;
|
|
174
|
+
function GetInterfaceByStr(const iidstr: String; out obj): boolean;
|
|
175
|
+
function GetInterfaceWeak(const iid: TGuid; out obj): boolean; // equal to GetInterface but the interface returned is not referenced
|
|
176
|
+
|
|
177
|
+
function Equals(Obj: TObject): boolean; virtual;
|
|
178
|
+
function ToString: String; virtual;
|
|
179
|
+
end;
|
|
180
|
+
|
|
181
|
+
{ TCustomAttribute - base class of all user defined attributes. }
|
|
182
|
+
|
|
183
|
+
TCustomAttribute = class
|
|
184
|
+
end;
|
|
185
|
+
TCustomAttributeClass = class of TCustomAttribute;
|
|
186
|
+
TCustomAttributeArray = array of TCustomAttribute;
|
|
187
|
+
|
|
188
|
+
const
|
|
189
|
+
{ IInterface }
|
|
190
|
+
S_OK = 0;
|
|
191
|
+
S_FALSE = 1;
|
|
192
|
+
E_NOINTERFACE = -2147467262; // FPC: longint($80004002)
|
|
193
|
+
E_UNEXPECTED = -2147418113; // FPC: longint($8000FFFF)
|
|
194
|
+
E_NOTIMPL = -2147467263; // FPC: longint($80004001)
|
|
195
|
+
|
|
196
|
+
type
|
|
197
|
+
{$Interfaces COM}
|
|
198
|
+
IUnknown = interface
|
|
199
|
+
['{00000000-0000-0000-C000-000000000046}']
|
|
200
|
+
function QueryInterface(const iid: TGuid; out obj): Integer;
|
|
201
|
+
function _AddRef: Integer;
|
|
202
|
+
function _Release: Integer;
|
|
203
|
+
end;
|
|
204
|
+
IInterface = IUnknown;
|
|
205
|
+
|
|
206
|
+
{$M+}
|
|
207
|
+
IInvokable = interface(IInterface)
|
|
208
|
+
end;
|
|
209
|
+
{$M-}
|
|
210
|
+
|
|
211
|
+
{ Enumerator support }
|
|
212
|
+
IEnumerator = interface(IInterface)
|
|
213
|
+
function GetCurrent: TObject;
|
|
214
|
+
function MoveNext: Boolean;
|
|
215
|
+
procedure Reset;
|
|
216
|
+
property Current: TObject read GetCurrent;
|
|
217
|
+
end;
|
|
218
|
+
|
|
219
|
+
IEnumerable = interface(IInterface)
|
|
220
|
+
function GetEnumerator: IEnumerator;
|
|
221
|
+
end;
|
|
222
|
+
|
|
223
|
+
{ TInterfacedObject }
|
|
224
|
+
|
|
225
|
+
TInterfacedObject = class(TObject,IUnknown)
|
|
226
|
+
protected
|
|
227
|
+
fRefCount: Integer;
|
|
228
|
+
{ implement methods of IUnknown }
|
|
229
|
+
function QueryInterface(const iid: TGuid; out obj): Integer; virtual;
|
|
230
|
+
function _AddRef: Integer; virtual;
|
|
231
|
+
function _Release: Integer; virtual;
|
|
232
|
+
public
|
|
233
|
+
procedure BeforeDestruction; override;
|
|
234
|
+
property RefCount: Integer read fRefCount;
|
|
235
|
+
end;
|
|
236
|
+
TInterfacedClass = class of TInterfacedObject;
|
|
237
|
+
|
|
238
|
+
{ TAggregatedObject - sub or satellite object using same interface as controller }
|
|
239
|
+
|
|
240
|
+
TAggregatedObject = class(TObject)
|
|
241
|
+
private
|
|
242
|
+
fController: Pointer;
|
|
243
|
+
function GetController: IUnknown;
|
|
244
|
+
protected
|
|
245
|
+
{ implement methods of IUnknown }
|
|
246
|
+
function QueryInterface(const iid: TGuid; out obj): Integer; virtual;
|
|
247
|
+
function _AddRef: Integer; virtual;
|
|
248
|
+
function _Release: Integer; virtual;
|
|
249
|
+
public
|
|
250
|
+
constructor Create(const aController: IUnknown); reintroduce;
|
|
251
|
+
property Controller: IUnknown read GetController;
|
|
252
|
+
end;
|
|
253
|
+
|
|
254
|
+
{ TContainedObject }
|
|
255
|
+
|
|
256
|
+
TContainedObject = class(TAggregatedObject,IInterface)
|
|
257
|
+
protected
|
|
258
|
+
function QueryInterface(const iid: TGuid; out obj): Integer; override;
|
|
259
|
+
end;
|
|
260
|
+
|
|
261
|
+
const
|
|
262
|
+
{ for safe as operator support }
|
|
263
|
+
IObjectInstance: TGuid = '{D91C9AF4-3C93-420F-A303-BF5BA82BFD23}';
|
|
264
|
+
|
|
265
|
+
function GUIDToString(const GUID: TGUID): string; external name 'rtl.guidrToStr';
|
|
266
|
+
|
|
267
|
+
{*****************************************************************************
|
|
268
|
+
RTTI support
|
|
269
|
+
*****************************************************************************}
|
|
270
|
+
type
|
|
271
|
+
// if you change the following enumeration type in any way
|
|
272
|
+
// you also have to change the rtl.js in an appropriate way !
|
|
273
|
+
TTypeKind = (
|
|
274
|
+
tkUnknown, // 0
|
|
275
|
+
tkInteger, // 1
|
|
276
|
+
tkChar, // 2 in Delphi/FPC tkWChar, tkUChar
|
|
277
|
+
tkString, // 3 in Delphi/FPC tkSString, tkWString or tkUString
|
|
278
|
+
tkEnumeration, // 4
|
|
279
|
+
tkSet, // 5
|
|
280
|
+
tkDouble, // 6
|
|
281
|
+
tkBool, // 7
|
|
282
|
+
tkProcVar, // 8 function or procedure
|
|
283
|
+
tkMethod, // 9 proc var of object
|
|
284
|
+
tkArray, // 10 static array
|
|
285
|
+
tkDynArray, // 11
|
|
286
|
+
tkRecord, // 12
|
|
287
|
+
tkClass, // 13
|
|
288
|
+
tkClassRef, // 14
|
|
289
|
+
tkPointer, // 15
|
|
290
|
+
tkJSValue, // 16
|
|
291
|
+
tkRefToProcVar, // 17 variable of procedure type
|
|
292
|
+
tkInterface, // 18
|
|
293
|
+
//tkObject,
|
|
294
|
+
//tkSString,tkLString,tkAString,tkWString,
|
|
295
|
+
//tkVariant,
|
|
296
|
+
//tkWChar,
|
|
297
|
+
//tkInt64,
|
|
298
|
+
//tkQWord,
|
|
299
|
+
//tkInterfaceRaw,
|
|
300
|
+
//tkUString,tkUChar,
|
|
301
|
+
tkHelper, // 19
|
|
302
|
+
//tkFile,
|
|
303
|
+
tkExtClass // 20
|
|
304
|
+
);
|
|
305
|
+
TTypeKinds = set of TTypeKind;
|
|
306
|
+
|
|
307
|
+
const
|
|
308
|
+
tkFloat = tkDouble; // for compatibility with Delphi/FPC
|
|
309
|
+
tkProcedure = tkProcVar; // for compatibility with Delphi
|
|
310
|
+
tkAny = [Low(TTypeKind)..High(TTypeKind)];
|
|
311
|
+
tkMethods = [tkMethod];
|
|
312
|
+
tkProperties = tkAny-tkMethods-[tkUnknown];
|
|
313
|
+
|
|
314
|
+
{*****************************************************************************
|
|
315
|
+
Array of const support
|
|
316
|
+
*****************************************************************************}
|
|
317
|
+
|
|
318
|
+
const
|
|
319
|
+
vtInteger = 0;
|
|
320
|
+
vtBoolean = 1;
|
|
321
|
+
//vtChar = 2; // Delphi/FPC: ansichar
|
|
322
|
+
vtExtended = 3; // Note: double in pas2js, PExtended in Delphi/FPC
|
|
323
|
+
//vtString = 4; // Delphi/FPC: PShortString
|
|
324
|
+
vtPointer = 5;
|
|
325
|
+
//vtPChar = 6;
|
|
326
|
+
vtObject = 7;
|
|
327
|
+
vtClass = 8;
|
|
328
|
+
vtWideChar = 9;
|
|
329
|
+
//vtPWideChar = 10;
|
|
330
|
+
//vtAnsiString = 11;
|
|
331
|
+
vtCurrency = 12; // Note: currency in pas2js, PCurrency in Delphi/FPC
|
|
332
|
+
//vtVariant = 13;
|
|
333
|
+
vtInterface = 14;
|
|
334
|
+
//vtWideString = 15;
|
|
335
|
+
//vtInt64 = 16;
|
|
336
|
+
//vtQWord = 17;
|
|
337
|
+
vtUnicodeString = 18;
|
|
338
|
+
// only pas2js, not in Delphi/FPC:
|
|
339
|
+
vtNativeInt = 19;
|
|
340
|
+
vtJSValue = 20;
|
|
341
|
+
|
|
342
|
+
type
|
|
343
|
+
PVarRec = ^TVarRec;
|
|
344
|
+
TVarRec = record
|
|
345
|
+
VType: byte;
|
|
346
|
+
VJSValue: JSValue;
|
|
347
|
+
VInteger: LongInt external name 'VJSValue';
|
|
348
|
+
VBoolean: Boolean external name 'VJSValue';
|
|
349
|
+
VExtended: Double external name 'VJSValue';
|
|
350
|
+
VPointer: Pointer external name 'VJSValue';
|
|
351
|
+
VObject: TObject external name 'VJSValue';
|
|
352
|
+
VClass: TClass external name 'VJSValue';
|
|
353
|
+
VWideChar: WideChar external name 'VJSValue';
|
|
354
|
+
VCurrency: Currency external name 'VJSValue';
|
|
355
|
+
VInterface: Pointer external name 'VJSValue';
|
|
356
|
+
VUnicodeString: UnicodeString external name 'VJSValue';
|
|
357
|
+
VNativeInt: NativeInt external name 'VJSValue';
|
|
358
|
+
end;
|
|
359
|
+
TVarRecArray = array of TVarRec;
|
|
360
|
+
|
|
361
|
+
function VarRecs: TVarRecArray; varargs;
|
|
362
|
+
|
|
363
|
+
{*****************************************************************************
|
|
364
|
+
Init / Exit / ExitProc
|
|
365
|
+
*****************************************************************************}
|
|
366
|
+
var
|
|
367
|
+
ExitCode: Integer; external name 'rtl.exitcode';
|
|
368
|
+
IsConsole: Boolean = {$IFDEF NodeJS}true{$ELSE}false{$ENDIF};
|
|
369
|
+
FirstDotAtFileNameStartIsExtension : Boolean = False;
|
|
370
|
+
|
|
371
|
+
type
|
|
372
|
+
TOnParamCount = function: Longint;
|
|
373
|
+
TOnParamStr = function(Index: Longint): String;
|
|
374
|
+
var
|
|
375
|
+
OnParamCount: TOnParamCount;
|
|
376
|
+
OnParamStr: TOnParamStr;
|
|
377
|
+
|
|
378
|
+
function ParamCount: Longint;
|
|
379
|
+
function ParamStr(Index: Longint): String;
|
|
380
|
+
|
|
381
|
+
{*****************************************************************************
|
|
382
|
+
Math
|
|
383
|
+
*****************************************************************************}
|
|
384
|
+
const
|
|
385
|
+
PI: Double; external name 'Math.PI';
|
|
386
|
+
MathE: Double; external name 'Math.E'; // Euler's number
|
|
387
|
+
MathLN10: Double; external name 'Math.LN10'; // ln(10)
|
|
388
|
+
MathLN2: Double; external name 'Math.LN2'; // ln(2)
|
|
389
|
+
MathLog10E: Double; external name 'Math.LOG10E'; // log10(e)
|
|
390
|
+
MathLog2E: Double; external name 'Math.LOG2E'; // log2(e)
|
|
391
|
+
MathSQRT1_2: Double; external name 'Math.SQRT1_2'; // sqrt(0.5)
|
|
392
|
+
MathSQRT2: Double; external name 'Math.SQRT2'; // sqrt(2)
|
|
393
|
+
|
|
394
|
+
function Abs(const A: integer): integer; overload; external name 'Math.abs';
|
|
395
|
+
function Abs(const A: NativeInt): integer; overload; external name 'Math.abs';
|
|
396
|
+
function Abs(const A: Double): Double; overload; external name 'Math.abs';
|
|
397
|
+
function ArcTan(const A: Double): Double; external name 'Math.atan';
|
|
398
|
+
function ArcTan2(const A,B: Double): Double; external name 'Math.atan2';
|
|
399
|
+
function Cos(const A: Double): Double; external name 'Math.cos';
|
|
400
|
+
function Exp(const A: Double): Double; external name 'Math.exp';
|
|
401
|
+
function Frac(const A: Double): Double; assembler;
|
|
402
|
+
function Ln(const A: Double): Double; external name 'Math.log';
|
|
403
|
+
function Odd(const A: Integer): Boolean; assembler;
|
|
404
|
+
function Random(const Range: Integer): Integer; overload; assembler;
|
|
405
|
+
function Random: Double; overload; external name 'Math.random';
|
|
406
|
+
function Round(const A: Double): NativeInt; external name 'Math.round';
|
|
407
|
+
function Sin(const A: Double): Double; external name 'Math.sin';
|
|
408
|
+
function Sqr(const A: Integer): Integer; assembler; overload;
|
|
409
|
+
function Sqr(const A: Double): Double; assembler; overload;
|
|
410
|
+
function sqrt(const A: Double): Double; external name 'Math.sqrt';
|
|
411
|
+
function Trunc(const A: Double): NativeInt;
|
|
412
|
+
|
|
413
|
+
{*****************************************************************************
|
|
414
|
+
String functions
|
|
415
|
+
*****************************************************************************}
|
|
416
|
+
const
|
|
417
|
+
DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
|
|
418
|
+
|
|
419
|
+
function Int(const A: Double): double;
|
|
420
|
+
function Copy(const S: string; Index, Size: Integer): String; assembler; overload;
|
|
421
|
+
function Copy(const S: string; Index: Integer): String; assembler; overload;
|
|
422
|
+
procedure Delete(var S: String; Index, Size: Integer); overload;
|
|
423
|
+
function Pos(const Search, InString: String): Integer; assembler; overload;
|
|
424
|
+
function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
|
|
425
|
+
procedure Insert(const Insertion: String; var Target: String; Index: Integer); overload;
|
|
426
|
+
function upcase(c : char) : char; assembler;
|
|
427
|
+
function HexStr(Val: NativeInt; cnt: byte): string; external name 'rtl.hexStr'; overload;
|
|
428
|
+
function binstr(val : NativeUInt; cnt : byte) : string;
|
|
429
|
+
|
|
430
|
+
procedure val(const S: String; out NI : NativeInt; out Code: Integer); overload;
|
|
431
|
+
procedure val(const S: String; out NI : NativeUInt; out Code: Integer); overload;
|
|
432
|
+
procedure val(const S: String; out SI : ShortInt; out Code: Integer); overload;
|
|
433
|
+
procedure val(const S: String; out B : Byte; out Code: Integer); overload;
|
|
434
|
+
procedure val(const S: String; out SI : smallint; out Code: Integer); overload;
|
|
435
|
+
procedure val(const S: String; out W : word; out Code : Integer); overload;
|
|
436
|
+
procedure val(const S: String; out I : integer; out Code : Integer); overload;
|
|
437
|
+
procedure val(const S: String; out C : Cardinal; out Code: Integer); overload;
|
|
438
|
+
procedure val(const S: String; out d : double; out Code : Integer); overload;
|
|
439
|
+
procedure val(const S: String; out b : boolean; out Code: Integer); overload;
|
|
440
|
+
function StringOfChar(c: Char; l: NativeInt): String;
|
|
441
|
+
|
|
442
|
+
{*****************************************************************************
|
|
443
|
+
Other functions
|
|
444
|
+
*****************************************************************************}
|
|
445
|
+
procedure Write; varargs; // ToDo: should be compiler built-in function
|
|
446
|
+
procedure Writeln; varargs; // ToDo: should be compiler built-in function
|
|
447
|
+
|
|
448
|
+
Type
|
|
449
|
+
TConsoleHandler = Reference to Procedure (S : JSValue; NewLine : Boolean);
|
|
450
|
+
Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
|
|
451
|
+
|
|
452
|
+
function Assigned(const V: JSValue): boolean; assembler; overload;
|
|
453
|
+
function StrictEqual(const A: JSValue; const B): boolean; assembler;
|
|
454
|
+
function StrictInequal(const A: JSValue; const B): boolean; assembler;
|
|
455
|
+
|
|
456
|
+
implementation
|
|
457
|
+
|
|
458
|
+
type
|
|
459
|
+
|
|
460
|
+
{ TJSObj - simple access to JS Object }
|
|
461
|
+
|
|
462
|
+
TJSObj = class external name 'Object'
|
|
463
|
+
private
|
|
464
|
+
function GetProperties(Name: String): JSValue; external name '[]';
|
|
465
|
+
procedure SetProperties(Name: String; const AValue: JSValue); external name '[]';
|
|
466
|
+
public
|
|
467
|
+
//constructor new;
|
|
468
|
+
//function hasOwnProperty(prop: String): boolean;
|
|
469
|
+
property Properties[Name: String]: JSValue read GetProperties write SetProperties; default;
|
|
470
|
+
end;
|
|
471
|
+
|
|
472
|
+
TJSArray = class external name 'Array'
|
|
473
|
+
public
|
|
474
|
+
//length: nativeint;
|
|
475
|
+
//constructor new; overload;
|
|
476
|
+
function push(aElement : JSValue) : NativeInt; varargs;
|
|
477
|
+
end;
|
|
478
|
+
|
|
479
|
+
TJSArguments = class external name 'arguments'
|
|
480
|
+
private
|
|
481
|
+
FLength: NativeInt; external name 'length';
|
|
482
|
+
function GetElements(Index: NativeInt): JSValue; external name '[]';
|
|
483
|
+
public
|
|
484
|
+
property Length: NativeInt read FLength;
|
|
485
|
+
property Elements[Index: NativeInt]: JSValue read GetElements; default;
|
|
486
|
+
end;
|
|
487
|
+
var
|
|
488
|
+
JSArguments: TJSArguments; external name 'arguments';
|
|
489
|
+
|
|
490
|
+
function isNumber(const v: JSValue): boolean; external name 'rtl.isNumber';
|
|
491
|
+
function isObject(const v: JSValue): boolean; external name 'rtl.isObject'; // true if not null and a JS Object
|
|
492
|
+
function isString(const v: JSValue): boolean; external name 'rtl.isString';
|
|
493
|
+
function isNaN(i: JSValue): boolean; external name 'isNaN'; // may result NaN
|
|
494
|
+
|
|
495
|
+
// needed by ClassNameIs, the real SameText is in SysUtils
|
|
496
|
+
function SameText(const s1, s2: String): Boolean; assembler;
|
|
497
|
+
asm
|
|
498
|
+
return s1.toLowerCase() == s2.toLowerCase();
|
|
499
|
+
end;
|
|
500
|
+
|
|
501
|
+
function VarRecs: TVarRecArray;
|
|
502
|
+
var
|
|
503
|
+
i: nativeint;
|
|
504
|
+
v: PVarRec;
|
|
505
|
+
begin
|
|
506
|
+
Result:=nil;
|
|
507
|
+
while i<JSArguments.Length do
|
|
508
|
+
begin
|
|
509
|
+
new(v);
|
|
510
|
+
v^.VType:=byte(JSArguments[i]);
|
|
511
|
+
inc(i);
|
|
512
|
+
v^.VJSValue:=JSArguments[i];
|
|
513
|
+
inc(i);
|
|
514
|
+
TJSArray(Result).push(v^);
|
|
515
|
+
end;
|
|
516
|
+
end;
|
|
517
|
+
|
|
518
|
+
function ParamCount: Longint;
|
|
519
|
+
begin
|
|
520
|
+
if Assigned(OnParamCount) then
|
|
521
|
+
Result:=OnParamCount()
|
|
522
|
+
else
|
|
523
|
+
Result:=0;
|
|
524
|
+
end;
|
|
525
|
+
|
|
526
|
+
function ParamStr(Index: Longint): String;
|
|
527
|
+
begin
|
|
528
|
+
if Assigned(OnParamStr) then
|
|
529
|
+
Result:=OnParamStr(Index)
|
|
530
|
+
else if Index=0 then
|
|
531
|
+
Result:='js'
|
|
532
|
+
else
|
|
533
|
+
Result:='';
|
|
534
|
+
end;
|
|
535
|
+
|
|
536
|
+
function Frac(const A: Double): Double; assembler;
|
|
537
|
+
asm
|
|
538
|
+
return A % 1;
|
|
539
|
+
end;
|
|
540
|
+
|
|
541
|
+
function Odd(const A: Integer): Boolean; assembler;
|
|
542
|
+
asm
|
|
543
|
+
return A&1 != 0;
|
|
544
|
+
end;
|
|
545
|
+
|
|
546
|
+
function Random(const Range: Integer): Integer; assembler;
|
|
547
|
+
asm
|
|
548
|
+
return Math.floor(Math.random()*Range);
|
|
549
|
+
end;
|
|
550
|
+
|
|
551
|
+
function Sqr(const A: Integer): Integer; assembler;
|
|
552
|
+
asm
|
|
553
|
+
return A*A;
|
|
554
|
+
end;
|
|
555
|
+
|
|
556
|
+
function Sqr(const A: Double): Double; assembler;
|
|
557
|
+
asm
|
|
558
|
+
return A*A;
|
|
559
|
+
end;
|
|
560
|
+
|
|
561
|
+
function Trunc(const A: Double): NativeInt; assembler;
|
|
562
|
+
asm
|
|
563
|
+
if (!Math.trunc) {
|
|
564
|
+
Math.trunc = function(v) {
|
|
565
|
+
v = +v;
|
|
566
|
+
if (!isFinite(v)) return v;
|
|
567
|
+
return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
$mod.Trunc = Math.trunc;
|
|
571
|
+
return Math.trunc(A);
|
|
572
|
+
end;
|
|
573
|
+
|
|
574
|
+
function Copy(const S: string; Index, Size: Integer): String; assembler;
|
|
575
|
+
asm
|
|
576
|
+
if (Index<1) Index = 1;
|
|
577
|
+
return (Size>0) ? S.substring(Index-1,Index+Size-1) : "";
|
|
578
|
+
end;
|
|
579
|
+
|
|
580
|
+
function Copy(const S: string; Index: Integer): String; assembler;
|
|
581
|
+
asm
|
|
582
|
+
if (Index<1) Index = 1;
|
|
583
|
+
return S.substr(Index-1);
|
|
584
|
+
end;
|
|
585
|
+
|
|
586
|
+
procedure Delete(var S: String; Index, Size: Integer);
|
|
587
|
+
var
|
|
588
|
+
h: String;
|
|
589
|
+
begin
|
|
590
|
+
if (Index<1) or (Index>length(S)) or (Size<=0) then exit;
|
|
591
|
+
h:=S;
|
|
592
|
+
S:=copy(h,1,Index-1)+copy(h,Index+Size);
|
|
593
|
+
end;
|
|
594
|
+
|
|
595
|
+
function Pos(const Search, InString: String): Integer; assembler;
|
|
596
|
+
asm
|
|
597
|
+
return InString.indexOf(Search)+1;
|
|
598
|
+
end;
|
|
599
|
+
|
|
600
|
+
function Pos(const Search, InString: String; StartAt : Integer): Integer; assembler; overload;
|
|
601
|
+
asm
|
|
602
|
+
return InString.indexOf(Search,StartAt-1)+1;
|
|
603
|
+
end;
|
|
604
|
+
|
|
605
|
+
procedure Insert(const Insertion: String; var Target: String; Index: Integer);
|
|
606
|
+
var
|
|
607
|
+
t: String;
|
|
608
|
+
begin
|
|
609
|
+
if Insertion='' then exit;
|
|
610
|
+
t:=Target;
|
|
611
|
+
if Index<1 then
|
|
612
|
+
Target:=Insertion+t
|
|
613
|
+
else if Index>length(t) then
|
|
614
|
+
Target:=t+Insertion
|
|
615
|
+
else
|
|
616
|
+
Target:=copy(t,1,Index-1)+Insertion+copy(t,Index,length(t));
|
|
617
|
+
end;
|
|
618
|
+
|
|
619
|
+
var
|
|
620
|
+
WriteBuf: String;
|
|
621
|
+
WriteCallBack : TConsoleHandler;
|
|
622
|
+
|
|
623
|
+
Function SetWriteCallBack(H : TConsoleHandler) : TConsoleHandler;
|
|
624
|
+
|
|
625
|
+
begin
|
|
626
|
+
Result:=WriteCallBack;
|
|
627
|
+
WriteCallBack:=H;
|
|
628
|
+
end;
|
|
629
|
+
|
|
630
|
+
procedure Write;
|
|
631
|
+
var
|
|
632
|
+
i: Integer;
|
|
633
|
+
begin
|
|
634
|
+
for i:=0 to JSArguments.Length-1 do
|
|
635
|
+
if Assigned(WriteCallBack) then
|
|
636
|
+
WriteCallBack(JSArguments[i],False)
|
|
637
|
+
else
|
|
638
|
+
WriteBuf:=WriteBuf+String(JSArguments[i]);
|
|
639
|
+
end;
|
|
640
|
+
|
|
641
|
+
procedure Writeln;
|
|
642
|
+
|
|
643
|
+
var
|
|
644
|
+
i,l: Integer;
|
|
645
|
+
s: String;
|
|
646
|
+
|
|
647
|
+
begin
|
|
648
|
+
L:=JSArguments.Length-1;
|
|
649
|
+
if Assigned(WriteCallBack) then
|
|
650
|
+
begin
|
|
651
|
+
for i:=0 to L do
|
|
652
|
+
WriteCallBack(JSArguments[i],I=L);
|
|
653
|
+
end
|
|
654
|
+
else
|
|
655
|
+
begin
|
|
656
|
+
s:=WriteBuf;
|
|
657
|
+
for i:=0 to L do
|
|
658
|
+
s:=s+String(JSArguments[i]);
|
|
659
|
+
asm
|
|
660
|
+
console.log(s);
|
|
661
|
+
end;
|
|
662
|
+
WriteBuf:='';
|
|
663
|
+
end;
|
|
664
|
+
end;
|
|
665
|
+
|
|
666
|
+
function Int(const A: Double): double;
|
|
667
|
+
|
|
668
|
+
begin
|
|
669
|
+
// trunc contains fix for missing Math.trunc in IE
|
|
670
|
+
Result:=Trunc(A);
|
|
671
|
+
end;
|
|
672
|
+
|
|
673
|
+
function Number(S: String): Double; external name 'Number';
|
|
674
|
+
|
|
675
|
+
function valint(const S: String; MinVal, MaxVal: NativeInt; out Code: Integer): NativeInt;
|
|
676
|
+
var
|
|
677
|
+
x: double;
|
|
678
|
+
begin
|
|
679
|
+
if S='' then
|
|
680
|
+
begin
|
|
681
|
+
code:=1;
|
|
682
|
+
exit;
|
|
683
|
+
end;
|
|
684
|
+
x:=Number(S);
|
|
685
|
+
if isNaN(x) then
|
|
686
|
+
case copy(s,1,1) of
|
|
687
|
+
'$': x:=Number('0x'+copy(S,2));
|
|
688
|
+
'&': x:=Number('0o'+copy(S,2));
|
|
689
|
+
'%': x:=Number('0b'+copy(S,2));
|
|
690
|
+
else
|
|
691
|
+
Code:=1;
|
|
692
|
+
exit;
|
|
693
|
+
end;
|
|
694
|
+
if isNaN(x) or (X<>Int(X)) then
|
|
695
|
+
Code:=1
|
|
696
|
+
else if (x<MinVal) or (x>MaxVal) then
|
|
697
|
+
Code:=2
|
|
698
|
+
else
|
|
699
|
+
begin
|
|
700
|
+
Result:=Trunc(x);
|
|
701
|
+
Code:=0;
|
|
702
|
+
end;
|
|
703
|
+
end;
|
|
704
|
+
|
|
705
|
+
procedure val(const S: String; out NI : NativeInt; out Code: Integer);
|
|
706
|
+
begin
|
|
707
|
+
NI:=valint(S,low(NI),high(NI),Code);
|
|
708
|
+
end;
|
|
709
|
+
|
|
710
|
+
procedure val(const S: String; out NI: NativeUInt; out Code: Integer);
|
|
711
|
+
var
|
|
712
|
+
x : double;
|
|
713
|
+
begin
|
|
714
|
+
if S='' then
|
|
715
|
+
begin
|
|
716
|
+
code:=1;
|
|
717
|
+
exit;
|
|
718
|
+
end;
|
|
719
|
+
x:=Number(S);
|
|
720
|
+
if isNaN(x) or (X<>Int(X)) or (X<0) then
|
|
721
|
+
Code:=1
|
|
722
|
+
else
|
|
723
|
+
begin
|
|
724
|
+
Code:=0;
|
|
725
|
+
NI:=Trunc(x);
|
|
726
|
+
end;
|
|
727
|
+
end;
|
|
728
|
+
|
|
729
|
+
procedure val(const S: String; out SI : ShortInt; out Code: Integer);
|
|
730
|
+
begin
|
|
731
|
+
SI:=valint(S,low(SI),high(SI),Code);
|
|
732
|
+
end;
|
|
733
|
+
|
|
734
|
+
procedure val(const S: String; out SI: smallint; out Code: Integer);
|
|
735
|
+
begin
|
|
736
|
+
SI:=valint(S,low(SI),high(SI),Code);
|
|
737
|
+
end;
|
|
738
|
+
|
|
739
|
+
procedure val(const S: String; out C: Cardinal; out Code: Integer);
|
|
740
|
+
begin
|
|
741
|
+
C:=valint(S,low(C),high(C),Code);
|
|
742
|
+
end;
|
|
743
|
+
|
|
744
|
+
procedure val(const S: String; out B: Byte; out Code: Integer);
|
|
745
|
+
begin
|
|
746
|
+
B:=valint(S,low(B),high(B),Code);
|
|
747
|
+
end;
|
|
748
|
+
|
|
749
|
+
procedure val(const S: String; out W: word; out Code: Integer);
|
|
750
|
+
begin
|
|
751
|
+
W:=valint(S,low(W),high(W),Code);
|
|
752
|
+
end;
|
|
753
|
+
|
|
754
|
+
procedure val(const S : String; out I : integer; out Code : Integer);
|
|
755
|
+
begin
|
|
756
|
+
I:=valint(S,low(I),high(I),Code);
|
|
757
|
+
end;
|
|
758
|
+
|
|
759
|
+
procedure val(const S : String; out d : double; out Code : Integer);
|
|
760
|
+
Var
|
|
761
|
+
x: double;
|
|
762
|
+
begin
|
|
763
|
+
if S='' then
|
|
764
|
+
begin
|
|
765
|
+
code:=1;
|
|
766
|
+
exit;
|
|
767
|
+
end;
|
|
768
|
+
x:=Number(S);
|
|
769
|
+
if isNaN(x) then
|
|
770
|
+
Code:=1
|
|
771
|
+
else
|
|
772
|
+
begin
|
|
773
|
+
Code:=0;
|
|
774
|
+
d:=x;
|
|
775
|
+
end;
|
|
776
|
+
end;
|
|
777
|
+
|
|
778
|
+
procedure val(const S: String; out b: boolean; out Code: Integer);
|
|
779
|
+
begin
|
|
780
|
+
if SameText(S,'true') then
|
|
781
|
+
begin
|
|
782
|
+
Code:=0;
|
|
783
|
+
b:=true;
|
|
784
|
+
end
|
|
785
|
+
else if SameText(S,'false') then
|
|
786
|
+
begin
|
|
787
|
+
Code:=0;
|
|
788
|
+
b:=false;
|
|
789
|
+
end
|
|
790
|
+
else
|
|
791
|
+
Code:=1;
|
|
792
|
+
end;
|
|
793
|
+
|
|
794
|
+
function binstr(val : NativeUInt;cnt : byte) : string;
|
|
795
|
+
var
|
|
796
|
+
i : Integer;
|
|
797
|
+
begin
|
|
798
|
+
SetLength(Result,cnt);
|
|
799
|
+
for i:=cnt downto 1 do
|
|
800
|
+
begin
|
|
801
|
+
Result[i]:=char(48+val and 1);
|
|
802
|
+
val:=val shr 1;
|
|
803
|
+
end;
|
|
804
|
+
end;
|
|
805
|
+
|
|
806
|
+
function upcase(c : char) : char; assembler;
|
|
807
|
+
asm
|
|
808
|
+
return c.toUpperCase();
|
|
809
|
+
end;
|
|
810
|
+
|
|
811
|
+
function StringOfChar(c: Char; l: NativeInt): String;
|
|
812
|
+
var
|
|
813
|
+
i: Integer;
|
|
814
|
+
begin
|
|
815
|
+
asm
|
|
816
|
+
if ((l>0) && c.repeat) return c.repeat(l);
|
|
817
|
+
end;
|
|
818
|
+
Result:='';
|
|
819
|
+
for i:=1 to l do Result:=Result+c;
|
|
820
|
+
end;
|
|
821
|
+
|
|
822
|
+
function Assigned(const V: JSValue): boolean; assembler;
|
|
823
|
+
asm
|
|
824
|
+
return (V!=undefined) && (V!=null) && (!rtl.isArray(V) || (V.length > 0));
|
|
825
|
+
end;
|
|
826
|
+
|
|
827
|
+
function StrictEqual(const A: JSValue; const B): boolean; assembler;
|
|
828
|
+
asm
|
|
829
|
+
return A === B;
|
|
830
|
+
end;
|
|
831
|
+
|
|
832
|
+
function StrictInequal(const A: JSValue; const B): boolean; assembler;
|
|
833
|
+
asm
|
|
834
|
+
return A !== B;
|
|
835
|
+
end;
|
|
836
|
+
|
|
837
|
+
{ TContainedObject }
|
|
838
|
+
|
|
839
|
+
function TContainedObject.QueryInterface(const iid: TGuid; out obj): Integer;
|
|
840
|
+
begin
|
|
841
|
+
if GetInterface(iid,obj) then
|
|
842
|
+
Result:=S_OK
|
|
843
|
+
else
|
|
844
|
+
Result:=Integer(E_NOINTERFACE);
|
|
845
|
+
end;
|
|
846
|
+
|
|
847
|
+
{ TAggregatedObject }
|
|
848
|
+
|
|
849
|
+
function TAggregatedObject.GetController: IUnknown;
|
|
850
|
+
begin
|
|
851
|
+
Result := IUnknown(fController);
|
|
852
|
+
end;
|
|
853
|
+
|
|
854
|
+
function TAggregatedObject.QueryInterface(const iid: TGuid; out obj): Integer;
|
|
855
|
+
begin
|
|
856
|
+
Result := IUnknown(fController).QueryInterface(iid, obj);
|
|
857
|
+
end;
|
|
858
|
+
|
|
859
|
+
function TAggregatedObject._AddRef: Integer;
|
|
860
|
+
begin
|
|
861
|
+
Result := IUnknown(fController)._AddRef;
|
|
862
|
+
end;
|
|
863
|
+
|
|
864
|
+
function TAggregatedObject._Release: Integer;
|
|
865
|
+
begin
|
|
866
|
+
Result := IUnknown(fController)._Release;
|
|
867
|
+
end;
|
|
868
|
+
|
|
869
|
+
constructor TAggregatedObject.Create(const aController: IUnknown);
|
|
870
|
+
begin
|
|
871
|
+
inherited Create;
|
|
872
|
+
{ do not keep a counted reference to the controller! }
|
|
873
|
+
fController := Pointer(aController);
|
|
874
|
+
end;
|
|
875
|
+
|
|
876
|
+
{ TInterfacedObject }
|
|
877
|
+
|
|
878
|
+
function TInterfacedObject.QueryInterface(const iid: TGuid; out obj): Integer;
|
|
879
|
+
begin
|
|
880
|
+
if GetInterface(iid,obj) then
|
|
881
|
+
Result:=S_OK
|
|
882
|
+
else
|
|
883
|
+
Result:=Integer(E_NOINTERFACE);
|
|
884
|
+
end;
|
|
885
|
+
|
|
886
|
+
function TInterfacedObject._AddRef: Integer;
|
|
887
|
+
begin
|
|
888
|
+
inc(fRefCount);
|
|
889
|
+
Result:=fRefCount;
|
|
890
|
+
end;
|
|
891
|
+
|
|
892
|
+
function TInterfacedObject._Release: Integer;
|
|
893
|
+
begin
|
|
894
|
+
dec(fRefCount);
|
|
895
|
+
Result:=fRefCount;
|
|
896
|
+
if fRefCount=0 then
|
|
897
|
+
Destroy;
|
|
898
|
+
end;
|
|
899
|
+
|
|
900
|
+
procedure TInterfacedObject.BeforeDestruction;
|
|
901
|
+
begin
|
|
902
|
+
if fRefCount<>0 then
|
|
903
|
+
asm
|
|
904
|
+
rtl.raiseE('EHeapMemoryError');
|
|
905
|
+
end;
|
|
906
|
+
end;
|
|
907
|
+
|
|
908
|
+
{ TObject }
|
|
909
|
+
|
|
910
|
+
constructor TObject.Create;
|
|
911
|
+
begin
|
|
912
|
+
|
|
913
|
+
end;
|
|
914
|
+
|
|
915
|
+
destructor TObject.Destroy;
|
|
916
|
+
begin
|
|
917
|
+
|
|
918
|
+
end;
|
|
919
|
+
|
|
920
|
+
procedure TObject.Free;
|
|
921
|
+
begin
|
|
922
|
+
Destroy;
|
|
923
|
+
end;
|
|
924
|
+
|
|
925
|
+
class function TObject.ClassType: TClass; assembler;
|
|
926
|
+
asm
|
|
927
|
+
return this;
|
|
928
|
+
end;
|
|
929
|
+
|
|
930
|
+
class function TObject.ClassNameIs(const Name: string): boolean;
|
|
931
|
+
begin
|
|
932
|
+
Result:=SameText(Name,ClassName);
|
|
933
|
+
end;
|
|
934
|
+
|
|
935
|
+
class function TObject.InheritsFrom(aClass: TClass): boolean; assembler;
|
|
936
|
+
asm
|
|
937
|
+
return (aClass!=null) && ((this==aClass) || aClass.isPrototypeOf(this));
|
|
938
|
+
end;
|
|
939
|
+
|
|
940
|
+
Class function TObject.MethodName(aCode : Pointer) : String;
|
|
941
|
+
|
|
942
|
+
begin
|
|
943
|
+
Result:='';
|
|
944
|
+
if aCode=Nil then
|
|
945
|
+
exit;
|
|
946
|
+
asm
|
|
947
|
+
if (typeof(aCode)!=='function') return "";
|
|
948
|
+
var i = 0;
|
|
949
|
+
var TI = this.$rtti;
|
|
950
|
+
if (rtl.isObject(aCode.scope)){
|
|
951
|
+
// callback
|
|
952
|
+
if (typeof aCode.fn === "string") return aCode.fn;
|
|
953
|
+
aCode = aCode.fn;
|
|
954
|
+
}
|
|
955
|
+
// Not a callback, check rtti
|
|
956
|
+
while ((Result === "") && (TI != null)) {
|
|
957
|
+
i = 0;
|
|
958
|
+
while ((Result === "") && (i < TI.methods.length)) {
|
|
959
|
+
if (this[TI.getMethod(i).name] === aCode)
|
|
960
|
+
Result=TI.getMethod(i).name;
|
|
961
|
+
i += 1;
|
|
962
|
+
};
|
|
963
|
+
if (Result === "") TI = TI.ancestor;
|
|
964
|
+
};
|
|
965
|
+
// return Result;
|
|
966
|
+
end;
|
|
967
|
+
end;
|
|
968
|
+
|
|
969
|
+
Class function TObject.MethodAddress(aName : String) : Pointer;
|
|
970
|
+
|
|
971
|
+
// We must do this in asm, because the typinfo unit is not available.
|
|
972
|
+
begin
|
|
973
|
+
Result:=Nil;
|
|
974
|
+
if AName='' then
|
|
975
|
+
exit;
|
|
976
|
+
asm
|
|
977
|
+
var i = 0;
|
|
978
|
+
var TI = this.$rtti;
|
|
979
|
+
var N = "";
|
|
980
|
+
var MN = "";
|
|
981
|
+
N = aName.toLowerCase();
|
|
982
|
+
while ((MN === "") && (TI != null)) {
|
|
983
|
+
i = 0;
|
|
984
|
+
while ((MN === "") && (i < TI.methods.length)) {
|
|
985
|
+
if (TI.getMethod(i).name.toLowerCase() === N) MN = TI.getMethod(i).name;
|
|
986
|
+
i += 1;
|
|
987
|
+
};
|
|
988
|
+
if (MN === "") TI = TI.ancestor;
|
|
989
|
+
};
|
|
990
|
+
if (MN !== "") Result = this[MN];
|
|
991
|
+
// return Result;
|
|
992
|
+
end;
|
|
993
|
+
end;
|
|
994
|
+
|
|
995
|
+
class function TObject.FieldAddress(aName: String): Pointer;
|
|
996
|
+
|
|
997
|
+
begin
|
|
998
|
+
Result:=Nil;
|
|
999
|
+
if aName='' then exit;
|
|
1000
|
+
asm
|
|
1001
|
+
var aClass = this.$class;
|
|
1002
|
+
var ClassTI = null;
|
|
1003
|
+
var myName = aName.toLowerCase();
|
|
1004
|
+
var MemberTI = null;
|
|
1005
|
+
while (aClass !== null) {
|
|
1006
|
+
ClassTI = aClass.$rtti;
|
|
1007
|
+
for (var i = 0, $end2 = ClassTI.fields.length - 1; i <= $end2; i++) {
|
|
1008
|
+
MemberTI = ClassTI.getField(i);
|
|
1009
|
+
if (MemberTI.name.toLowerCase() === myName) {
|
|
1010
|
+
return MemberTI;
|
|
1011
|
+
};
|
|
1012
|
+
};
|
|
1013
|
+
aClass = aClass.$ancestor ? aClass.$ancestor : null;
|
|
1014
|
+
};
|
|
1015
|
+
end;
|
|
1016
|
+
end;
|
|
1017
|
+
|
|
1018
|
+
Class Function TObject.ClassInfo : Pointer;
|
|
1019
|
+
|
|
1020
|
+
begin
|
|
1021
|
+
// This works different from FPC/Delphi.
|
|
1022
|
+
// We get the actual type info.
|
|
1023
|
+
Result:=TypeInfo(Self);
|
|
1024
|
+
end;
|
|
1025
|
+
|
|
1026
|
+
procedure TObject.AfterConstruction;
|
|
1027
|
+
begin
|
|
1028
|
+
|
|
1029
|
+
end;
|
|
1030
|
+
|
|
1031
|
+
procedure TObject.BeforeDestruction;
|
|
1032
|
+
begin
|
|
1033
|
+
|
|
1034
|
+
end;
|
|
1035
|
+
|
|
1036
|
+
procedure TObject.Dispatch(var aMessage);
|
|
1037
|
+
// aMessage is a record with an integer field 'Msg'
|
|
1038
|
+
var
|
|
1039
|
+
aClass: TClass;
|
|
1040
|
+
Msg: TJSObj absolute aMessage;
|
|
1041
|
+
Id: jsvalue;
|
|
1042
|
+
begin
|
|
1043
|
+
if not isObject(Msg) then exit;
|
|
1044
|
+
Id:=Msg['Msg'];
|
|
1045
|
+
if not isNumber(Id) then exit;
|
|
1046
|
+
aClass:=ClassType;
|
|
1047
|
+
while aClass<>nil do
|
|
1048
|
+
begin
|
|
1049
|
+
asm
|
|
1050
|
+
var Handlers = aClass.$msgint;
|
|
1051
|
+
if (rtl.isObject(Handlers) && Handlers.hasOwnProperty(Id)){
|
|
1052
|
+
this[Handlers[Id]](aMessage);
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
end;
|
|
1056
|
+
aClass:=aClass.ClassParent;
|
|
1057
|
+
end;
|
|
1058
|
+
DefaultHandler(aMessage);
|
|
1059
|
+
end;
|
|
1060
|
+
|
|
1061
|
+
procedure TObject.DispatchStr(var aMessage);
|
|
1062
|
+
// aMessage is a record with a string field 'MsgStr'
|
|
1063
|
+
var
|
|
1064
|
+
aClass: TClass;
|
|
1065
|
+
Msg: TJSObj absolute aMessage;
|
|
1066
|
+
Id: jsvalue;
|
|
1067
|
+
begin
|
|
1068
|
+
if not isObject(Msg) then exit;
|
|
1069
|
+
Id:=Msg['MsgStr'];
|
|
1070
|
+
if not isString(Id) then exit;
|
|
1071
|
+
aClass:=ClassType;
|
|
1072
|
+
while (aClass<>Nil) do
|
|
1073
|
+
begin
|
|
1074
|
+
asm
|
|
1075
|
+
var Handlers = aClass.$msgstr;
|
|
1076
|
+
if (rtl.isObject(Handlers) && Handlers.hasOwnProperty(Id)){
|
|
1077
|
+
this[Handlers[Id]](aMessage);
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
end;
|
|
1081
|
+
aClass:=aClass.ClassParent;
|
|
1082
|
+
end;
|
|
1083
|
+
DefaultHandlerStr(aMessage);
|
|
1084
|
+
end;
|
|
1085
|
+
|
|
1086
|
+
procedure TObject.DefaultHandler(var aMessage);
|
|
1087
|
+
begin
|
|
1088
|
+
if jsvalue(TMethod(aMessage)) then ;
|
|
1089
|
+
end;
|
|
1090
|
+
|
|
1091
|
+
procedure TObject.DefaultHandlerStr(var aMessage);
|
|
1092
|
+
begin
|
|
1093
|
+
if jsvalue(TMethod(aMessage)) then ;
|
|
1094
|
+
end;
|
|
1095
|
+
|
|
1096
|
+
function TObject.GetInterface(const iid: TGuid; out obj): boolean;
|
|
1097
|
+
begin
|
|
1098
|
+
asm
|
|
1099
|
+
var i = iid.$intf;
|
|
1100
|
+
if (i){
|
|
1101
|
+
// iid is the private TGuid of an interface
|
|
1102
|
+
i = rtl.getIntfG(this,i.$guid,2);
|
|
1103
|
+
if (i){
|
|
1104
|
+
obj.set(i);
|
|
1105
|
+
return true;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
end;
|
|
1109
|
+
Result := GetInterfaceByStr(GUIDToString(iid),obj);
|
|
1110
|
+
end;
|
|
1111
|
+
|
|
1112
|
+
function TObject.GetInterface(const iidstr: String; out obj): boolean;
|
|
1113
|
+
begin
|
|
1114
|
+
Result := GetInterfaceByStr(iidstr,obj);
|
|
1115
|
+
end;
|
|
1116
|
+
|
|
1117
|
+
function TObject.GetInterfaceByStr(const iidstr: String; out obj): boolean;
|
|
1118
|
+
begin
|
|
1119
|
+
Result:=false;
|
|
1120
|
+
if not TJSObj(IObjectInstance)['$str'] then
|
|
1121
|
+
TJSObj(IObjectInstance)['$str']:=GUIDToString(IObjectInstance);
|
|
1122
|
+
if iidstr = TJSObj(IObjectInstance)['$str'] then
|
|
1123
|
+
begin
|
|
1124
|
+
obj:=Self;
|
|
1125
|
+
exit(true);
|
|
1126
|
+
end;
|
|
1127
|
+
asm
|
|
1128
|
+
var i = rtl.getIntfG(this,iidstr,2);
|
|
1129
|
+
obj.set(i);
|
|
1130
|
+
Result=(i!==null);
|
|
1131
|
+
end;
|
|
1132
|
+
end;
|
|
1133
|
+
|
|
1134
|
+
function TObject.GetInterfaceWeak(const iid: TGuid; out obj): boolean;
|
|
1135
|
+
begin
|
|
1136
|
+
Result:=GetInterface(iid,obj);
|
|
1137
|
+
asm
|
|
1138
|
+
if (Result){
|
|
1139
|
+
var o = obj.get();
|
|
1140
|
+
if (o.$kind==='com'){
|
|
1141
|
+
o._Release();
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
end;
|
|
1145
|
+
end;
|
|
1146
|
+
|
|
1147
|
+
function TObject.Equals(Obj: TObject): boolean;
|
|
1148
|
+
begin
|
|
1149
|
+
Result:=Obj=Self;
|
|
1150
|
+
end;
|
|
1151
|
+
|
|
1152
|
+
function TObject.ToString: String;
|
|
1153
|
+
begin
|
|
1154
|
+
Result:=ClassName;
|
|
1155
|
+
end;
|
|
1156
|
+
|
|
1157
|
+
class function TObject.QualifiedClassName: String;
|
|
1158
|
+
begin
|
|
1159
|
+
Result := UnitName + '.' + ClassName;
|
|
1160
|
+
end;
|
|
1161
|
+
|
|
1162
|
+
initialization
|
|
1163
|
+
ExitCode:=0; // set it here, so that WPO does not remove it
|
|
1164
|
+
|
|
1165
|
+
end.
|
|
1166
|
+
|