forked from synopse/mORMot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SynSMAPI.pas
4897 lines (4165 loc) · 214 KB
/
SynSMAPI.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/// SpiderMonkey *.h header port to Delphi
// - this unit is a part of the freeware Synopse mORMot framework,
// licensed under a MPL/GPL/LGPL tri-license; version 1.18
unit SynSMAPI;
{
This file is part of Synopse framework.
Synopse framework. Copyright (C) 2017 Arnaud Bouchez
Synopse Informatique - https://synopse.info
Scripting support for mORMot Copyright (C) 2017 Pavel Mashlyakovsky
pavel.mash at gmail.com
Some ideas taken from
http://code.google.com/p/delphi-javascript
http://delphi.mozdev.org/javascript_bridge/
*** BEGIN LICENSE BLOCK *****
Version: MPL 1.1/GPL 2.0/LGPL 2.1
The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the License.
The Initial Developer of the Original Code is
Pavel Mashlyakovsky.
Portions created by the Initial Developer are Copyright (C) 2017
the Initial Developer. All Rights Reserved.
Contributor(s):
- Arnaud Bouchez
- Vadim Orel
Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****
---------------------------------------------------------------------------
Download the SpiderMonkey library at https://synopse.info/files/synsm.7z !
---------------------------------------------------------------------------
Version 1.18
- initial release. Use SpiderMonkey 24
https://developer.mozilla.org/en-US/docs/SpiderMonkey/24
and Modify jsapi.h for possibility import from Delphi
and jsapi.cpp for possibility use JS_NumberValue
- add JSString.ToJSVal method
- change JS_ARGV macro result type to PjsvalVector
- add debugger support functions
road map:
write Tjsval - object (record) wraper for jsval with methods Is* To* As*
migrate to IonMonkey
compile mozjs without nspr
enable ctypes? for byte array work #ifdef JS_HAS_CTYPES JS_InitCTypesClass
}
{$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64 OWNNORMTOUPPER
{$I SynSM.inc} //define JS_THREADSAFE WITHASSERT
interface
uses
{$ifdef MSWINDOWS}
Windows,
{$endif}
Variants,
SynCommons;
const
{$ifdef MSWINDOWS}
{$ifdef CPU64}
SpiderMonkeyLib = 'mozjs64.dll';
{$else}
SpiderMonkeyLib = 'mozjs-24.dll';
NSPRLib = 'libnspr4.dll';
{$endif}
{$endif}
{$ifdef LINUX} // for Kylix/FPC (not tested yet)
SpiderMonkeyLib = 'mozjs.so';
{$endif}
type
{$ifndef UNICODE}
/// 8 bit signed integer type for C APIs
int8 = ShortInt;
/// 8 bit unsigned integer type for C APIs
uint8 = Byte;
/// 16 bit signed integer type for C APIs
int16 = Smallint;
/// 16 bit unsigned integer type for C APIs
uint16 = Word;
/// 32 bit signed integer type for C APIs
int32 = Integer;
/// 32 bit unsigned integer type for C APIs
uint32 = Cardinal;
{$endif}
/// define SpiderMonkey dedicated text buffer type
// - in SM 1.8.5 exist mode JS_CSringAreUTF8, so it is possibe to use our
// RawUTF8 strings (in all cases internaly in SM it will be converted to
// Unicode - so need to test if SynCommons conversion faster or not -
// - but in SM 1.8.8 JS_CSringAreUTF8 removed, and all API may have to
// switch to jschar ( = Word/WideChar ) ?
PCChar = PAnsiChar;
/// 8 bit signed integer type for SMAPI
JSInt8 = ShortInt;
/// 16 bit signed integer type for SMAPI
JSInt16 = SmallInt;
/// 32 bit signed integer type for SMAPI
JSInt32 = Integer;
/// 8 bit unsigned integer type for SMAPI
JSUint8 = Byte;
/// 16 bit unsigned integer type for SMAPI
JSUint16 = Word;
/// 32 bit unsigned integer type for SMAPI
JSUInt32 = LongWord;
/// 64 bit signed integer type for SMAPI
JSInt64 = Int64;
/// 64 bit unsigned integer type for SMAPI
JSUInt64 = QWord;
{$ifndef FPC}
/// variable type used to store a buffer size (in bytes) for SMAPI
size_t = PtrUInt;
{$endif}
/// jschar is the type of JavaScript "characters", the 16 bits elements
// that make up JavaScript strings (maybe not truly valid UTF-16)
// - It is a 16-bit unsigned integer type
// - As required by the ECMAScript standard, ECMA 262-3 §4.3.16, JavaScript
// strings are arbitrary sequences of 16-bit values
// - A string may contain unmatched surrogates, which are not valid UTF-16
// - It may also contain zeroes (0)
// - so we did not define it as WideChar, but as abstract Word element
jschar = Word;
/// pointer to a sequence of JavaScript "characters", i.e. some 16 bits
// elements that make up JavaScript strings (maybe not truly valid UTF-16)
// - As required by the ECMAScript standard, ECMA 262-3 §4.3.16, JavaScript
// strings are arbitrary sequences of 16-bit values
// - A string may contain unmatched surrogates, which are not valid UTF-16
// - It may also contain zeroes (0)
Pjschar = ^jschar;
/// pointer to a pointer of JavaScript "characters"
// - is mostly used for arrays of JavaScript strings
PPjschar = ^Pjschar;
/// jsdouble is the internal type of numbers, i.e. floating-point values
// - jsdouble is obsolete since JavaScript 1.8.7+ - instead we must use C double
// so let's do it for future now
// - in all cases see JSFloat64 - NSPR's floating point type is always 64 bits.
jsdouble = Double;
/// Pointer to JSScript structure defined if jsscript.h
// - we do not directly use of this structure, so we define just a pointer
PJSScript = type Pointer;
/// type appropriate for most signed integer variables for SMAPI
// - They are guaranteed to be at least 16 bits, though various architectures
// may define them to be wider (e.g., 32 or even 64 bits). These types are
// never valid for fields of a structure.
JSIntn = PtrInt;
/// type appropriate for most unsigned integer variables for SMAPI
// - They are guaranteed to be at least 16 bits, though various architectures
// may define them to be wider (e.g., 32 or even 64 bits). These types are
// never valid for fields of a structure.
JSUintn = PtrUInt;
/// type appropriate for most flag set variables
// - They are guaranteed to be at least 16 bits, though various architectures
// may define them to be wider (e.g., 32 or even 64 bits). These types are
// never valid for fields of a structure.
uintn = PtrUInt;
/// pointer to a flag set variable
puintN = ^uintn;
/// internal type of numbers, i.e. floating-point values for SMAPI
// - NSPR's floating point type is always 64 bits.
JSFloat64 = Double;
/// a type for representing the size of objects for SMAPI
JSSize = size_t;
/// type for pointer arithmetic difference
// - Variables of this type are suitable for storing a pointer or pointer sutraction
ptrdiff_t = PtrInt;
/// type for pointer arithmetic difference for SMAPI
// - Variables of this type are suitable for storing a pointer or pointer sutraction
JSPtrdiff = ptrdiff_t;
/// ordinal type used for pointer arithmetic
// - Variables of this type are suitable for storing a pointer or pointer sutraction
JSUIntPtr = PtrUInt;
/// pointer on an ordinal type used for pointer arithmetic
PJSuintptr = ^JSuintptr;
/// ordinal type used for pointer arithmetic
// - Variables of this type are suitable for storing a pointer or pointer sutraction
JSUptrdiff = JSUintPtr ;
/// boolean type for variables and parameter types for SMAPI
// - Use JS_FALSE and JS_TRUE constants for clarity of target type in assignments
JSBool = JSIntn;
/// pointer to boolean type for variables and parameter types for SMAPI
PJSBool = ^JSBool;
const
/// boolean TRUE value for variables and parameter types for SMAPI
JS_TRUE = JSBool(1);
/// boolean FALSE value for variables and parameter types for SMAPI
JS_FALSE = JSBool(0);
/// packed boolean type for variables and parameter types for SMAPI
// - use JSPackedBool within structs where bitfields are not desireable
// but minimum and consistent overhead matters.
type
JSPackedBool = JSUint8;
/// a JSWord is a signed integer that is the same size as a pointer
JSWord = PtrInt;
/// a JSWord is an unsigned integer that is the same size as a pointer
JSUword = PtrUInt;
{ jsbuiltins.h conversion - "object" types }
/// available options for JS Objects
TJSOption = (
jsoExtraWarning, jsoWError, jsoVarObjFix, jsoPrivateIsNSISupports, jsoCompileNGo,
jsoUnused5, jsoUnused6, jsoUnused7, jsoDontReportUncaught, jsoUnused9,
jsoUnused10, jsoUnused11, jsoNoScriptRVal, jsoUnrootedGlobal,
jsoBaseLine, jsoPcCount, jsoTypeInference, jsoStrictMode, jsoIon, jsoAsmJS);
/// set of available options for JS Objects
TJSOptions = set of TJSOption;
/// available options for JS Objects Properties
TJSPropertyAttr = (
jspEnumerate, jspReadOnly, jspPermanent, jspUnused, jspGetter,
jspSetter, jspShared, jspIndex, sjpShortID);
/// set of available options for JS Objects Properties
TJSPropertyAttrs = set of TJSPropertyAttr;
/// pointer to a JS Runtime instance
PJSRuntime = ^JSRuntime;
/// pointer to a JS String instance
PJSString = ^JSString;
/// pointer to a JS Object instance
PJSObject = ^JSObject;
/// map a generic JavaScript value internal representation
// - a variable of type jsval can hold exactly the same values as a JavaScript
// var or property: string, number, object, boolean, null, or undefined
// (including Arrays, functions, and Errors are all objects)
// - jsval is a variant type whose exact representation varies by architecture.
// - you should never use this value internals, but pjsval and its TSMValue
// wrapper, as defined in SynSM.pas unit, for a given TSMEngine execution
// context - see
// https://developer.mozilla.org/en-US/docs/SpiderMonkey/JSAPI_Reference/JSval
jsval = type QWord;
/// pointer to a jsval JavaScript value
pjsval = ^jsval;
/// an abstract array of jsval JavaScript values
TjsvalVector = array[0..(MaxInt div sizeof(jsval))-1] of jsval;
/// map an array of jsval JavaScript values
PjsvalVector = ^TjsvalVector;
/// used to store a JavaScript version
JSVersion = Integer;
/// JavaScript execution context
// - this object does not store anything, but just provide some helper methods
// to access a PPJSContext value via JS_*Context*(..) API functions
JSContext = object
private
function GetVersion: JSVersion;
// JS_SetVersion is not supported now Use CompartmentOptions in JS_NewGlobalObject
function GetPrivate: Pointer;
{$ifdef HASINLINE}inline;{$endif}
procedure SetPrivate(const Value: Pointer);
{$ifdef FIXBUGXE3}
public
{$endif}
function GetOptions: TJSOptions;
procedure SetOptions(const Value: TJSOptions);
public
/// wrapper to JS_DestroyContext(@self)
procedure Destroy;
/// wrapper to JS_GetRuntime(@self)
function Runtime: PJSRuntime;
/// wrapper to JS_InitStandardClasses(@self,global)
function InitStandardClasses(global: PJSObject): boolean;
{$ifndef FIXBUGXE3}
/// wrapper to JS_GetOptions()/JS_SetOptions()
// - due to a XE3 bug, you should use the GetOptions/SetOptions methods
// instead of this property, under this compiler revision
property Options: TJSOptions read GetOptions write SetOptions;
{$endif}
/// wrapper to JS_GetVersion()/JS_SetVersion()
property Version: JSVersion read GetVersion;
/// wrapper to JS_GetVersion() and string conversion
function VersionToString: RawUTF8;
/// wrapper to JS_GetContextPrivate()/JS_SetContextPrivate()
property PrivateData: Pointer read GetPrivate write SetPrivate;
public
/// create a new JavaScript string instance from a given UTF-8 text
function NewJSString(const Value: RawUTF8): PJSString; overload;
/// create a new JavaScript string instance from a given UTF-16 text
function NewJSString(const Value: SynUnicode): PJSString; overload;
/// create a new JavaScript string instance from a given UTF-16 text buffer
function NewJSString(TextWide: PWideChar; TextLen: integer): PJSString; overload;
/// create a new JavaScript string instance from a given Ansi text buffer
// - will use the specified Ansi code page for the conversion
// - if CodePage is 0, will use the CurrentAnsiCodePage value
function NewJSString(TextAnsi: PAnsiChar; TextLen, CodePage: integer): PJSString; overload;
end;
/// pointer to JavaScript execution context
// - allows convenient access of JSContext wrapper methods
PJSContext = ^JSContext;
/// pointer to a pointer of JavaScript execution context
PPJSContext = ^PJSContext;
/// JavaScript execution runtime
// - this object does not store anything, but just provide some helper methods
// to access a PJSRuntime value via JS_*Runtime*(..) API functions
JSRuntime = object
private
function GetPrivate: Pointer;
procedure SetPrivate(const Value: Pointer);
public
/// wrapper to JS_LockRuntime(@self)
procedure Lock;
/// wrapper to JS_UnLockRuntime(@self)
procedure Unlock;
/// wrapper to JS_DestroyRuntime(@self)
procedure Destroy;
/// wrapper to JS_GetRuntimePrivate()/JS_SetRuntimePrivate()
property PrivateData: Pointer read GetPrivate write SetPrivate;
end;
/// points to a JavaScript execution compartment
// - allows convenient access of JSCompartment wrapper methods
PJSCompartment = ^JSCompartment;
/// JavaScript execution compartment
// - this object does not store anything, but just provide some helper methods
// to access a PJSRuntime value via JS_*Runtime*(..) API functions
JSCompartment = object
private
fcx: PJSContext;
public
/// initialize and enter a JavaScript execution compartment
function EnterCompartment(cx: PJSContext; target: PJSObject): PJSCompartment;
/// leave a JavaScript execution compartment
procedure Destroy;
end;
/// JavaScript string instance
// - this object does not store anything, but just provide some helper methods
// to access a PPJSString value via JS_*String*(..) API functions
// - use function JSContext.NewJSString() to create a new instance for a given
// execution context
// - to understand string in SpiderMonkey good point is comments in vm\String.h
// in short this is C structure:
// $struct Data
// $ {
// $ size_t lengthAndFlags; /* JSString */
// $ union {
// $ const jschar *chars; /* JSLinearString */
// $ JSString *left; /* JSRope */
// $ } u1;
// $ union {
// $ jschar inlineStorage[NUM_INLINE_CHARS]; /* JS(Inline|Short)String */
// $ struct {
// $ union {
// $ JSLinearString *base; /* JSDependentString */
// $ JSString *right; /* JSRope */
// $ size_t capacity; /* JSFlatString (extensible) */
// $ size_t externalType; /* JSExternalString */
// $ } u2;
// $ union {
// $ JSString *parent; /* JSRope (temporary) */
// $ void *externalClosure; /* JSExternalString */
// $ size_t reserved; /* may use for bug 615290 */
// $ } u3;
// $ } s;
// $ };
// $ } d;
// but in API there is no need to use this structure, only pointer to it, and
// high-level access to the SpiderMonkey API via this JSString wrapper
JSString = object
public
/// get the UTF-8 text corresponding to this string, for a given
// runtime execution context
function ToUTF8(cx: PJSContext): RawUTF8; overload;
/// get the UTF-8 text corresponding to this string, for a given
// runtime execution context
// - slightly faster overloaded method (avoid string assignment)
procedure ToUTF8(cx: PJSContext; var result: RawUTF8); overload;
/// Add UTF-8 text corresponding to this string to writer,
// without escaping
procedure ToUTF8(cx: PJSContext; W: TTextWriter); overload;
/// get the UTF-16 text corresponding to this string, for a given
// runtime execution context
function ToSynUnicode(cx: PJSContext): SynUnicode;
/// get the UTF-16 text corresponding to this string, for a given
// runtime execution context
function ToWideString(cx: PJSContext): WideString;
/// get the UTF-16 text corresponding to this string as a variant,
// for a given runtime execution context
// - will store a SynUnicode value into the variant instance
procedure ToVariant(cx: PJSContext; var Value: Variant);
/// get the Delphi string text corresponding to this string, for a given
// runtime execution context
function ToString(cx: PJSContext): string;
/// get the text encoded as a UTF-8 JSON string
procedure ToJSONString(cx: PJSContext; W: TTextWriter);
/// get a jsval corresponding to this string
function ToJSVal: jsval;
end;
/// pointer to a pointer of JavaScript string
PPJSString = ^PJSString;
/// JSObject is the type of JavaScript objects in the JSAPI
// - this object does not store anything, but just provide some helper methods
// to access a PJSObject value via low-level API functions
JSObject = object
public
/// get a jsval corresponding to this object
function ToJSValue: jsval; {$ifdef HASINLINE}inline;{$endif}
end;
/// pointer to a pointer of JavaScript object
PPJSObject = ^PJSObject;
/// abstract pointer to a JavaScript function
PJSFunction = type Pointer;
/// jsid is a generic identifier for any JavaScript object property of method
// - a jsid is an identifier for a property or method of an object which is
// either a 31-bit signed integer, internal string or object. If XML is
// enabled, there is an additional singleton jsid value; see
// JS_DEFAULT_XML_NAMESPACE_ID below. Finally, there is an additional jsid
// value, JSID_VOID, which does not occur in JS scripts but may be used to
// indicate the absence of a valid jsid.
jsid = size_t;
/// pointer to a JavaScript object property of method identifier
pjsid = ^jsid;
/// abstract array to JavaScript object property of method identifiers
// - set to -2 instead of -1 to allow JSIdArray record compilation
TjsidVector = array[0..(MaxInt div sizeof(jsid))-2] of jsid;
/// map an array to JavaScript object property of method identifiers
PjsidVector = ^TjsidVector;
{ jspubtd.h conversion - public types }
const
/// Run-time version enumeration corresponding to 1.0
JSVERSION_1_0 = 100;
/// Run-time version enumeration corresponding to 1.1
JSVERSION_1_1 = 110;
/// Run-time version enumeration corresponding to 1.2
JSVERSION_1_2 = 120;
/// Run-time version enumeration corresponding to 1.3
JSVERSION_1_3 = 130;
/// Run-time version enumeration corresponding to 1.4
JSVERSION_1_4 = 140;
/// Run-time version enumeration corresponding to ECMA standard 3, i.e. 1.4.8
JSVERSION_ECMA_3 = 148;
/// Run-time version enumeration corresponding to 1.5
JSVERSION_1_5 = 150;
/// Run-time version enumeration corresponding to 1.6
JSVERSION_1_6 = 160;
/// Run-time version enumeration corresponding to 1.7
JSVERSION_1_7 = 170;
/// Run-time version enumeration corresponding to 1.8
JSVERSION_1_8 = 180;
/// Run-time version enumeration corresponding to ECMA standard 5, i.e. 1.8.5
JSVERSION_ECMA_5 = 185;
/// Run-time version enumeration corresponding to default version
JSVERSION_DEFAULT = 0;
/// Run-time version enumeration corresponding to an identified version
JSVERSION_UNKNOWN = -1;
/// Run-time version enumeration corresponding to the latest available
// - that is, ECMA standard 5, i.e. 1.8.5
JSVERSION_LATEST = JSVERSION_ECMA_5;
type
/// Result of typeof operator enumeration
JSType = (
JSTYPE_VOID, { undefined }
JSTYPE_OBJECT, { object }
JSTYPE_FUNCTION, { function }
JSTYPE_STRING, { string }
JSTYPE_NUMBER, { number }
JSTYPE_BOOLEAN, { boolean }
JSTYPE_NULL, { null }
// JSTYPE_XML is not supported now
JSTYPE_LIMIT
);
/// js_CheckAccess mode enumeration
JSAccessMode = (
JSACC_PROTO = 0, { XXXbe redundant w.r.t. id }
{
* enum value #1 formerly called JSACC_PARENT,
* gap preserved for ABI compatibility.
}
{
* enum value #2 formerly called JSACC_IMPORT,
* gap preserved for ABI compatibility.
}
JSACC_WATCH = 3, { a watchpoint on object foo for id 'bar' }
JSACC_READ = 4, { a "get" of foo.bar }
JSACC_WRITE = 8, { a "set" of foo.bar = baz }
JSACC_LIMIT = 9
);
/// This enum type is used to control the behavior of a JSObject property
// iterator function that has type JSNewEnumerate.
// - JSENUMERATE_INIT
// A new, opaque iterator state should be allocated and stored in *statep.
// (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
// The number of properties that will be enumerated should be returned as
// an integer jsval in *idp, if idp is non-null, and provided the number of
// enumerable properties is known. If idp is non-null and the number of
// enumerable properties can't be computed in advance, *idp should be set
// to JSVAL_ZERO.
// - JSENUMERATE_INIT_ALL
// Used identically to JSENUMERATE_INIT, but exposes all properties of the
// object regardless of enumerability.
// - JSENUMERATE_NEXT
// A previously allocated opaque iterator state is passed in via statep.
// Return the next jsid in the iteration using *idp. The opaque iterator
// state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
// if there are no properties left to enumerate.
// - JSENUMERATE_DESTROY
// Destroy the opaque iterator state previously allocated in *statep by a
// call to this function when enum_op was JSENUMERATE_INIT or
// JSENUMERATE_INIT_ALL.
JSIterateOp = (
//* Create new iterator state over enumerable properties. */
JSENUMERATE_INIT,
//* Create new iterator state over all properties. */
JSENUMERATE_INIT_ALL,
//* Iterate once. */
JSENUMERATE_NEXT,
//* Destroy iterator state. */
JSENUMERATE_DESTROY
);
// JSClass (and js::ObjectOps where appropriate) function pointer typedefs
/// JSClass method prototype to add, or get a property named by id in obj
// - note the jsid id type -- id may be a string (Unicode property identifier)
// or an int (element index)
// - the vp out parameter, on success, is the new property value after
// an add or get. After a successful delete, *vp is JSVAL_FALSE iff
// obj[id] can't be deleted (because it's permanent)
JSPropertyOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid;
vp: pjsval): JSBool; cdecl;
/// JSClass method prototype to delete a property named by id in obj
// - note the jsid id type -- id may be a string (Unicode property identifier)
// or an int (element index)
// - the *succeeded out parameter, on success, is the JSVAL_TRUE. *succeeded is
// JSVAL_FALSE if obj[id] can't be deleted (because it's permanent)
JSDeletePropertyOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid;
succeeded: PJSBool):JSBool; cdecl;
/// JSClass method prototype to set a property named by id in obj, treating
// the assignment as strict mode code if strict is true
// - note the jsid id type -- id may be a string (Unicode property identifier)
// or an int (element index)
// - the vp out parameter, on success, is the new property value after the set
JSStrictPropertyOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid;
strict: JSBool; vp: pjsval): JSBool; cdecl;
/// function prototype used for callbacks that enumerate the properties of
// a JSObject
// - The behavior depends on the value of enum_op
// -The return value is used to indicate success, with a value of JS_FALSE
// indicating failure.
JSNewEnumerateOp = function(cx: PJSContext; var obj: PJSObject; enum_op: JSIterateOp;
statep: pjsval; idp: pjsid): JSBool; cdecl;
/// The old-style JSClass.enumerate op should define all lazy properties not
// yet reflected in obj.
JSEnumerateOp = function(cx: PJSContext; var obj: PJSObject): JSBool; cdecl;
/// function prototype used to resolve a lazy property named by id in obj
// by defining it directly in obj
// - Lazy properties are those reflected from some peer native property space
// (e.g., the DOM attributes for a given node reflected as obj) on demand.
// - JS looks for a property in an object, and if not found, tries to resolve
// the given id. If resolve succeeds, the engine looks again in case resolve
// defined obj[id]. If no such property exists directly in obj, the process
// is repeated with obj's prototype, etc.
// - NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
JSResolveOp = function(cx: PJSContext; var obj: PJSObject;
var id: jsid): JSBool; cdecl;
/// function prototype used to resolve a lazy property named by id in obj
// by defining it directly in obj
// - Like JSResolveOp, but flags provide contextual information as follows:
// ! JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id
// ! JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
// ! JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence
// ! JSRESOLVE_DECLARING var, const, or function prolog declaration opcode
// ! JSRESOLVE_CLASSNAME class name used when constructing
// - The *objp out parameter, on success, should be null to indicate that id
// was not resolved; and non-null, referring to obj or one of its prototypes,
// if id was resolved.
// - This hook instead of JSResolveOp is called via the JSClass.resolve member
// if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
// - Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further
// extends this hook by passing in the starting object on the prototype chain
// via *objp. Thus a resolve hook implementation may define the property id
// being resolved in the object in which the id was first sought, rather than
// in a prototype object whose class led to the resolve hook being called.
// - When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
// null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no
// JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
// This is not good practice, but enough existing hook implementations count
// on it that we can't break compatibility by passing the starting object in
// *objp without a new JSClass flag.
JSNewResolveOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid; flags: uintN;
var objp: PPJSObject): JSBool; cdecl;
// Convert obj to the given type, returning true with the resulting value in
// vp on success, and returning false on error or exception.
JSConvertOp = function(cx: PJSContext; var obj: PJSObject; typ: JSType;
vp: pjsval): JSBool; cdecl;
/// callback used to delegate typeof to an object so it can cloak a
// primitive or another object
JSTypeOfOp = function(cx: PJSContext; var obj: PJSObject): JSType; cdecl;
/// Finalize obj, which the garbage collector has determined to be unreachable
// from other live objects or from GC roots. Obviously, finalizers must never
// store a reference to obj.
JSFinalizeOp = procedure(cx: PJSContext; obj: PJSObject); cdecl;
/// callback used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer
// to extend and reduce the set of string types finalized by the GC.
JSStringFinalizeOp = procedure(cx: PJSContext; var obj: PJSString); cdecl;
/// JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
// returning false on error/exception, true on success with obj[id]'s last-got
// value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id
// is either a string or an int jsval.
JSCheckAccessOp = function(cx: PJSContext; var obj: PJSObject; var id: jsid;
mode: JSAccessMode; vp: Pjsval): JSBool; cdecl;
/// state value as expected by JSXDRObjectOp() prototype
PJSXDRState = type Pointer;
/// Encode or decode an object, given an XDR state record representing external data
JSXDRObjectOp = function(xdr: PJSXDRState; var objp: PJSObject): JSBool; cdecl;
/// callback used to check whether v is an instance of obj or not
// - Return false on error or exception, true on success with JS_TRUE in bp
// if v is an instance of obj, JS_FALSE in bp otherwise.
JSHasInstanceOp = function(cx: PJSContext; obj: PJSObject; const v: Pjsval;
var bp: JSBool): JSBool; cdecl;
// here we miss trace and debug-only function defenition
/// callback typedef for native functions called by the JS VM
// - cx is the execution context
// - argc is the number of supplied arguments
// - vp[0] is the callee - see JS_CALLEE()
// - vp[1] is the object instance - see JS_THIS()
// - vp[2]..vp[argc+1] are the supplied arguments - see JS_ARGV_PTR()
JSNative = function(cx: PJSContext; argc: uintN; vp: Pjsval): JSBool; cdecl;
/// callback used for trace operation of a given class
// - enumerate all traceable things reachable from obj's private data structure.
// - For each such thing, a trace implementation must call one of the
// JS_Call*Tracer variants on the thing.
// - JSTraceOp implementation can assume that no other threads mutates object
// state. It must not change state of the object or corresponding native
// structures. The only exception for this rule is the case when the embedding
// needs a tight integration with GC. In that case the embedding can check if
// the traversal is a part of the marking phase through calling
// JS_IsGCMarkingTracer and apply a special code like emptying caches or
// marking its native structures.
JSTraceOp = procedure(cx: PJSContext; argc: uintN; vp: Pjsval); cdecl;
/// a JavaScript tracer instance
PJSTracer = Pointer;
/// flag used for JSContextCallback() argument
// - JSCONTEXT_NEW: JS_NewContext successfully created a new JSContext
// instance. The callback can initialize the instance as
// required. If the callback returns false, the instance
// will be destroyed and JS_NewContext returns null. In
// this case the callback is not called again.
// - JSCONTEXT_DESTROY: One of JS_DestroyContext* methods is called. The
// callback may perform its own cleanup and must always
// return true.
// - Any other value: For future compatibility the callback must do nothing
// and return true in this case.
JSContextOp = (
JSCONTEXT_NEW,
JSCONTEXT_DESTROY
);
/// callback prototype for a given runtime context
// - the possible values for contextOp when the runtime calls the callback
// are defined by JSContextOp
JSContextCallback = function(cx: PJSContext; contextOp: uintN): JSBool; cdecl;
/// flag used for callback for a given runtime context garbage collection
JSGCStatus = (
JSGC_BEGIN,
JSGC_END
);
/// callback prototype for a given runtime context garbage collection
JSGCCallback = function(cx: PJSContext; status: JSGCStatus): JSBool; cdecl;
/// generic operaiton callback prototype for a given runtime context
JSOperationCallback = function(cx: PJSContext): JSBool; cdecl;
/// Security protocol
PJSPrincipals = Pointer;
/// internal structure used to report JavaScript errors
JSErrorReport = record
/// source file name, URL, etc., or null
filename: PCChar;
/// see 'originPrincipals' comment above
originPrincipals: PJSPrincipals;
/// source line number
lineno: uintN;
/// offending source line without final #13
linebuf: PCChar;
/// pointer to error token in linebuf
tokenptr: PCChar;
/// unicode (original) line buffer
uclinebuf: Pjschar;
/// unicode (original) token pointer
uctokenptr: Pjschar;
/// error/warning, etc.
flags: uintN;
/// the error number, e.g. see js.msg
errorNumber: uintN;
/// the (default) error message
ucmessage: Pjschar;
/// arguments for the error message
messageArgs: PPjschar;
/// One of the JSExnType constants
exnType: int16;
/// zero-based column index in line
column: uintN;
end;
/// map an internal structure used to report JavaScript errors
PJSErrorReport = ^JSErrorReport;
/// callback prototype for reporting error for a given runtime context
JSErrorReporter = procedure(cx: PJSContext; _message: PCChar; report: PJSErrorReport); cdecl;
/// Possible exception types
// -These types are part of a JSErrorFormatString structure
// - They define which error to throw in case of a runtime error
// - JSEXN_NONE marks an unthrowable error
JSExnType = (
JSEXN_NONE = -1,
JSEXN_ERR,
JSEXN_INTERNALERR,
JSEXN_EVALERR,
JSEXN_RANGEERR,
JSEXN_REFERENCEERR,
JSEXN_SYNTAXERR,
JSEXN_TYPEERR,
JSEXN_URIERR,
JSEXN_LIMIT
);
/// used by JSErrorCallback() callback
JSErrorFormatString = record
/// The error format string (UTF-8 if js_CStringsAreUTF8)
format: PCChar;
/// The number of arguments to expand in the formatted error message
argCount: uint16;
/// One of the JSExnType constants above
exnType: int16;
end;
/// pointer used by JSErrorCallback() callback
PJSErrorFormatString = ^JSErrorFormatString;
/// callback prototype for returning an execution error
JSErrorCallback = function(userRef: Pointer; const locale: PCChar;
const errorNumber: uintN): PJSErrorFormatString; cdecl;
// here we miss *Principals* functions - we do not use it for now
{ jsval.h conversion - extended types }
const
{$ifdef CPU64}
JSVAL_TAG_SHIFT = 47;
{$define JS_BITS_PER_WORD_IS64}
{$else}
{$define JS_BITS_PER_WORD_IS32}
{$endif}
{$ifdef CPU64}
JS_BYTES_PER_DOUBLE = 8;
JS_BYTES_PER_WORD = 8;
JS_BITS_PER_WORD_LOG2 = 6;
JS_ALIGN_OF_POINTER = 8;
{$else}
JS_BYTES_PER_DOUBLE = 8;
JS_BYTES_PER_WORD = 4;
JS_BITS_PER_WORD_LOG2 = 5;
JS_ALIGN_OF_POINTER = 4;
{$endif}
// JSValueType
type
JSValueType = Byte;
const
JSVAL_TYPE_DOUBLE = Byte($00);
JSVAL_TYPE_INT32 = Byte($01);
JSVAL_TYPE_UNDEFINED= Byte($02);
JSVAL_TYPE_BOOLEAN = Byte($03);
JSVAL_TYPE_MAGIC = Byte($04);
JSVAL_TYPE_STRING = Byte($05);
JSVAL_TYPE_NULL = Byte($06);
JSVAL_TYPE_OBJECT = Byte($07);
//JSValueTag
{$IFDEF CPU32}
type
JSValueTag = Cardinal;
const
JSVAL_TAG_CLEAR = Cardinal($FFFFFF80);
JSVAL_TAG_INT32 = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_INT32);
JSVAL_TAG_UNDEFINED = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_UNDEFINED);
JSVAL_TAG_STRING = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_STRING);
JSVAL_TAG_BOOLEAN = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_BOOLEAN);
JSVAL_TAG_MAGIC = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_MAGIC);
JSVAL_TAG_NULL = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_NULL);
JSVAL_TAG_OBJECT = Cardinal(JSVAL_TAG_CLEAR or JSVAL_TYPE_OBJECT);
{$ELSE} //CPU64
type
JSValueTag = Cardinal;
const
JSVAL_TAG_MAX_DOUBLE= Cardinal($0001FFF0);
JSVAL_TAG_INT32 = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_INT32);
JSVAL_TAG_UNDEFINED = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_UNDEFINED);
JSVAL_TAG_STRING = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_STRING);
JSVAL_TAG_BOOLEAN = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_BOOLEAN);
JSVAL_TAG_MAGIC = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_MAGIC);
JSVAL_TAG_NULL = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_NULL);
JSVAL_TAG_OBJECT = Cardinal(JSVAL_TAG_MAX_DOUBLE or JSVAL_TYPE_OBJECT);
type
JSValueShiftedTag = QWord;
const
JSVAL_SHIFTED_TAG_MAX_DOUBLE = (QWord(JSVAL_TAG_MAX_DOUBLE) shl JSVAL_TAG_SHIFT) or $FFFFFFFF;
JSVAL_SHIFTED_TAG_INT32 = QWord(JSVAL_TAG_INT32) shl JSVAL_TAG_SHIFT;
JSVAL_SHIFTED_TAG_UNDEFINED = QWord(JSVAL_TAG_UNDEFINED) shl JSVAL_TAG_SHIFT;
JSVAL_SHIFTED_TAG_STRING = QWord(JSVAL_TAG_STRING) shl JSVAL_TAG_SHIFT;
JSVAL_SHIFTED_TAG_BOOLEAN = QWord(JSVAL_TAG_BOOLEAN) shl JSVAL_TAG_SHIFT;
JSVAL_SHIFTED_TAG_MAGIC = QWord(JSVAL_TAG_MAGIC) shl JSVAL_TAG_SHIFT;
JSVAL_SHIFTED_TAG_NULL = QWord(JSVAL_TAG_NULL) shl JSVAL_TAG_SHIFT;
JSVAL_SHIFTED_TAG_OBJECT = QWord(JSVAL_TAG_OBJECT) shl JSVAL_TAG_SHIFT;
{$ENDIF}
JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET = JSVAL_TYPE_NULL;
JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET = JSVAL_TYPE_OBJECT;
JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET = JSVAL_TYPE_INT32;
JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET = JSVAL_TYPE_MAGIC;
{$ifdef CPU32}
//#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET = JSVAL_TAG_NULL;
JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET = JSVAL_TAG_OBJECT;
JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET = JSVAL_TAG_INT32;
JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET = JSVAL_TAG_STRING;
{$else} // CPU64
JSVAL_PAYLOAD_MASK : QWord = $00007FFFFFFFFFFF;
JSVAL_TAG_MASK : QWord = $FFFF800000000000;
JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET = JSVAL_SHIFTED_TAG_NULL;
JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET = JSVAL_SHIFTED_TAG_OBJECT;
JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET = JSVAL_SHIFTED_TAG_UNDEFINED;
JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET = JSVAL_SHIFTED_TAG_STRING;
{$endif}
type
JSWhyMagic = (
JS_ELEMENTS_HOLE, // a hole in a native object's elements
JS_NATIVE_ENUMERATE, // indicates that a custom enumerate hook forwarded
// to JS_EnumerateState, which really means the object can be
// enumerated like a native object.
JS_NO_ITER_VALUE, // there is not a pending iterator value
JS_GENERATOR_CLOSING, // exception value thrown when closing a generator
JS_NO_CONSTANT, // compiler sentinel value
JS_THIS_POISON, // used in debug builds to catch tracing errors
JS_ARG_POISON, // used in debug builds to catch tracing errors
JS_SERIALIZE_NO_NODE, // an empty subnode in the AST serializer
JS_LAZY_ARGUMENTS, // lazy arguments value on the stack
JS_OPTIMIZED_ARGUMENTS, // optimized-away 'arguments' value
JS_IS_CONSTRUCTING, // magic value passed to natives to indicate construction
JS_OVERWRITTEN_CALLEE, // arguments.callee has been overwritten
JS_FORWARD_TO_CALL_OBJECT, // args object element stored in call object
JS_BLOCK_NEEDS_CLONE, // value of static block object slot
JS_HASH_KEY_EMPTY, // see class js::HashableValue
JS_ION_ERROR, // error while running Ion code
JS_ION_BAILOUT, // status code to signal EnterIon will OSR into Interpret
JS_GENERIC_MAGIC // for local use
);
// here must be jsval_layout struct defenition and *_IMPL functions
// but it moved to implementation part of unit, because used only internaly
//#if JS_BITS_PER_WORD == 32
//#define BUILD_JSVAL(tag, payload) ((((uint64)(uint32)(tag)) << 32) | (uint32)(payload))
//#elif JS_BITS_PER_WORD == 64
//#define BUILD_JSVAL(tag, payload) ((((uint64)(uint32)(tag)) << JSVAL_TAG_SHIFT) | (payload))
{ jsapi.h conversion - main SpiderMonkey unit }
const
CPU_SHIFT = {$ifdef CPU32}32{$else}JSVAL_TAG_SHIFT{$endif};
JSVAL_NULL : QWord = QWord((QWord(JSVAL_TAG_NULL) shl CPU_SHIFT) or 0);
JSVAL_ZERO : QWord = QWord((QWord(JSVAL_TAG_INT32) shl CPU_SHIFT) or 0);
JSVAL_ONE : QWord = QWord((QWord(JSVAL_TAG_INT32) shl CPU_SHIFT) or 1);
JSVAL_FALSE : QWord = QWord((QWord(JSVAL_TAG_BOOLEAN) shl CPU_SHIFT) or JS_FALSE);
JSVAL_TRUE : QWord = QWord((QWord(JSVAL_TAG_BOOLEAN) shl CPU_SHIFT) or JS_TRUE);
JSVAL_VOID : QWord = QWord((QWord(JSVAL_TAG_UNDEFINED) shl CPU_SHIFT) or 0);
type
jsint = JSInt32;
jsuint = JSUInt32;
//#define JSVAL_BITS(v) ((v).asBits)
//#define JSVAL_FROM_LAYOUT(l) (l)
//#define IMPL_TO_JSVAL(v) (v)
//#define JSID_BITS(id) ((id).asBits)
/// check if a jsval is NULL
function JSVAL_IS_NULL(const v: jsval): Boolean;
{$ifdef HASINLINE}inline;{$endif}
/// check if jsval is VOID
function JSVAL_IS_VOID(const v: jsval): Boolean;
{$ifdef HASINLINE}inline;{$endif}
/// check if jsval is a 32 bit integer
function JSVAL_IS_INT(const v: jsval): Boolean;
{$ifdef HASINLINE}inline;{$endif}
/// convert a jsval into a 32 bit integer
// - there is no check that jsval is really a 32 bit integer: caller shall
// ensure this is the case (by using
function JSVAL_TO_INT(const v: jsval): jsint;
{$ifndef WITHASSERT}{$ifdef HASINLINE}inline;{$endif}{$endif}
const
JSVAL_INT_BITS = 32;
JSVAL_INT_MIN = jsint($80000000);
JSVAL_INT_MAX = jsint($7fffffff);
function INT_TO_JSVAL(i: int32): jsval;
{$ifdef HASINLINE}inline;{$endif}
function JSVAL_IS_DOUBLE(const v: jsval): Boolean;
{$ifdef HASINLINE}inline;{$endif}