-
Notifications
You must be signed in to change notification settings - Fork 21
/
Duktape.pas
2263 lines (1879 loc) · 68 KB
/
Duktape.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
unit Duktape;
{$INCLUDE 'Grijjy.inc'}
{$MINENUMSIZE 4}
interface
uses
System.SysUtils,
Duktape.Api;
const
DT_VARARGS = DUK_VARARGS;
type
{ Type for (fatal) error generated by the Duktape library. }
EdtError = class(Exception);
type
{ Internal Duktape strings are UTF8 strings. }
DuktapeString = UTF8String;
type
TdtThreadState = record
{$REGION 'Internal Declarations'}
public
_Data: array [0..SizeOf(TDukThreadState) - 1] of Byte;
{$ENDREGION 'Internal Declarations'}
end;
type
TdtMemoryFunctions = TDukMemoryFunctions;
TdtTimeComponents = TDukTimeComponents;
TdtFunctionListEntry = TDukFunctionListEntry;
TdtNumberListEntry = TDukNumberListEntry;
PdtFunctionListEntry = PDukFunctionListEntry;
PdtNumberListEntry = PDukNumberListEntry;
type
TdtErrCode = (
None = DUK_ERR_NONE,
Error = DUK_ERR_ERROR,
EvalError = DUK_ERR_EVAL_ERROR,
RangeError = DUK_ERR_RANGE_ERROR,
ReferenceError = DUK_ERR_REFERENCE_ERROR,
SyntaxError = DUK_ERR_SYNTAX_ERROR,
TypeError = DUK_ERR_TYPE_ERROR,
UriError = DUK_ERR_URI_ERROR);
type
{ Result for functions implemented in Delphi }
TdtResult = (
{ The Delphi function left a return value on the stack. }
HasResult = 1,
{ The Delphi function did not leave a return value (it behaved like a
procedure) }
NoResult = 0,
{ Generic error }
Error = DUK_RET_ERROR,
{ Evaluation error }
EvalError = DUK_RET_EVAL_ERROR,
{ Range error }
RangeError = DUK_RET_RANGE_ERROR,
{ Reference error }
ReferenceError = DUK_RET_REFERENCE_ERROR,
{ Syntax error }
SyntaxError = DUK_RET_SYNTAX_ERROR,
{ Type error }
TypeError = DUK_RET_TYPE_ERROR,
{ URI error }
UriError = DUK_RET_URI_ERROR);
type
TdtGCFlag = (Compact = 0);
TdtGCFlags = set of TdtGCFlag;
type
TdtBufferType = (
ArrayBuffer = DUK_BUFOBJ_ARRAYBUFFER,
NodeJSBuffer = DUK_BUFOBJ_NODEJS_BUFFER,
DataView = DUK_BUFOBJ_DATAVIEW,
Int8Array = DUK_BUFOBJ_INT8ARRAY,
UInt8Array = DUK_BUFOBJ_UINT8ARRAY,
UInt8ClampedArray = DUK_BUFOBJ_UINT8CLAMPEDARRAY,
Int16Array = DUK_BUFOBJ_INT16ARRAY,
UInt16Array = DUK_BUFOBJ_UINT16ARRAY,
Int32Array = DUK_BUFOBJ_INT32ARRAY,
UInt32Array = DUK_BUFOBJ_UINT32ARRAY,
Float32Array = DUK_BUFOBJ_FLOAT32ARRAY,
Float64Array = DUK_BUFOBJ_FLOAT64ARRAY);
type
TdtType = (
None = DUK_TYPE_NONE,
Undefined = DUK_TYPE_UNDEFINED,
Null = DUK_TYPE_NULL,
Boolean = DUK_TYPE_BOOLEAN,
Number = DUK_TYPE_NUMBER,
Str = DUK_TYPE_STRING,
Obj = DUK_TYPE_OBJECT,
Buffer = DUK_TYPE_BUFFER,
Pointer = DUK_TYPE_POINTER,
LightFunc = DUK_TYPE_LIGHTFUNC);
TdtTypes = set of TdtType;
type
TdtHint = (
None = DUK_HINT_NONE,
Str = DUK_HINT_STRING,
Number = DUK_HINT_NUMBER);
type
TgtDefPropFlag = (
Writable = 0,
Enumerable = 1,
Configurable = 2,
HaveWritable = 3,
HaveEnumerable = 4,
HaveConfigurable = 5,
HaveValue = 6,
HaveGetter = 7,
HaveSetter = 8,
Force = 9);
TgtDefPropFlags = set of TgtDefPropFlag;
type
TdtEnumFlag = (
IncludeNonEnumerable = 0,
IncludeHidden = 1,
IncludeSymbols = 2,
ExcludeStrings = 3,
OwnPropertiesOnly = 4,
ArrayIndicesOnly = 5,
SortArrayIndices = 6,
NoProxyBehavior = 7);
TdtEnumFlags = set of TdtEnumFlag;
type
TdtCompileFlag = (
Eval = 3,
Func = 4,
Strict = 5,
Shebang = 6,
Safe = 7,
NoResult = 8,
NoSource = 9,
StrLen = 10,
NoFilename = 11,
FuncExpr = 12);
TdtCompileFlags = set of TdtCompileFlag;
type
TdtDecodeCharCallback = procedure(const AUserData: Pointer;
const ACodePoint: Integer); cdecl;
TdtMapCharCallback = function(const AUserData: Pointer;
const ACodePoint: Integer): Integer; cdecl;
type
{ Medium-level Duktape class. }
TDuktape = record
{$REGION 'Internal Declarations'}
private
FContext: PDukContext;
private
class function DelphiAlloc(AUserData: Pointer; ASize: TDukSize): Pointer; cdecl; static;
class function DelphiRealloc(AUserData: Pointer; APtr: Pointer; ASize: TDukSize): Pointer; cdecl; static;
class procedure DelphiFree(AUserData: Pointer; APtr: Pointer); cdecl; static;
class procedure FatalHandler(AUserData: Pointer; const AMsg: MarshaledAString); cdecl; static;
{$ENDREGION 'Internal Declarations'}
public
(*** Context management ***)
{ Creates a new Duktape context and heap.
Parameters:
AUseDelphiMemoryManager: whether to use Delphi's memory manager.
When False (default), the system memory manager is used. Set to True
to have Delphi manage all memory (de)allocations for Duktape. That is
useful if you want to check for memory leaks using the
ReportMemoryLeaksOnShutdown global variable. }
class function Create(const AUseDelphiMemoryManager: Boolean = False): TDuktape; static;
{ Destroys the Duktape context and heap. }
procedure Free;
function Suspend: TdtThreadState;
procedure Resume(const AState: TdtThreadState);
public
(*** Memory management
Raw functions have no side effects (cannot trigger GC). ***)
function AllocRaw(const ASize: NativeInt): Pointer;
procedure FreeRaw(const APtr: Pointer);
function ReallocRaw(const APtr: Pointer; const ASize: NativeInt): Pointer;
function AllocMem(const ASize: NativeInt): Pointer;
procedure FreeMem(const APtr: Pointer);
function ReallocMem(const APtr: Pointer; const ASize: NativeInt): Pointer;
function GetMemoryManagementFunctions: TdtMemoryFunctions;
procedure GarbageCollect(const AFlags: TdtGCFlags = []);
public
(*** Error handling ***)
procedure Throw;
procedure Fatal(const AErrMsg: DuktapeString);
procedure Error(const AErrCode: TdtErrCode; const AErrMsg: DuktapeString);
procedure GenericError(const AErrMsg: DuktapeString);
procedure EvalError(const AErrMsg: DuktapeString);
procedure RangeError(const AErrMsg: DuktapeString);
procedure ReferenceError(const AErrMsg: DuktapeString);
procedure SyntaxError(const AErrMsg: DuktapeString);
procedure TypeError(const AErrMsg: DuktapeString);
procedure UriError(const AErrMsg: DuktapeString);
public
(*** Other state related functions ***)
function IsStrictCall: Boolean;
function IsConstructorCall: Boolean;
public
(*** Stack management ***)
function NormalizeIndex(const AIndex: Integer): Integer;
function RequireNormalizeIndex(const AIndex: Integer): Integer;
function IsValidIndex(const AIndex: Integer): Boolean;
procedure RequireValidIndex(const AIndex: Integer);
{ Get current stack top (>= 0), indicating the number of values currently on
the value stack (of the current activation). }
function GetTop: Integer;
procedure SetTop(const AIndex: Integer);
function GetTopIndex: Integer;
function RequireTopIndex: Integer;
function CheckStack(const AExtra: Integer): Boolean;
procedure RequireStack(const AExtra: Integer);
function CheckStackTop(const ATop: Integer): Boolean;
procedure RequireStackTop(const ATop: Integer);
public
(*** Stack manipulation (other than push/pop) ***)
procedure Swap(const AIndex1, AIndex2: Integer);
procedure SwapTop(const AIndex: Integer);
procedure Dup(const AFromIndex: Integer);
procedure DupTop;
{ Insert a value at AToIndex with a value popped from the stack top. The
previous value at AToIndex and any values above it are moved up the
stack by a step. If AToIndex is an invalid index, throws an error.
Negative indices are evaluated prior to popping the value at the stack
top. }
procedure Insert(const AToIndex: Integer);
procedure Replace(const AToIndex: Integer);
procedure Copy(const AFromIndex, AToIndex: Integer);
procedure Remove(const AIndex: Integer);
procedure XMoveTop(const AToContext: TDuktape; const ACount: Integer);
procedure XCopyTop(const AToContext: TDuktape; const ACount: Integer);
public
(*** Push operations
Push functions return the absolute (relative to bottom of frame)
position of the pushed value for convenience.
Note: Dup is technically a push. ***)
procedure PushUndefined;
procedure PushNull;
procedure PushBoolean(const AValue: Boolean);
procedure PushTrue;
procedure PushFalse;
procedure PushNumber(const AValue: Double);
procedure PushNan;
procedure PushInt(const AValue: Integer);
procedure PushUInt(const AValue: Cardinal);
{ Push a string to the stack. The string may contain arbitrary data,
including internal NUL characters. A pointer to the interned string data
is returned. If the operation fails, throws an error.
The returned pointer can be dereferenced and a NUL terminator character is
guaranteed. }
function PushString(const AString: DuktapeString): MarshaledAString;
procedure PushPointer(const AValue: Pointer);
procedure PushThis;
procedure PushCurrentFunction;
procedure PushCurrentThread;
procedure PushGlobalObject;
procedure PushHeapStash;
procedure PushGlobalStash;
procedure PushThreadStash(const ATargetContext: TDuktape);
function PushObject: Integer;
function PushBareObject: Integer;
function PushArray: Integer;
function PushThread: Integer;
function PushThreadNewGlobalEnv: Integer;
function PushProxy(const AFlags: Cardinal): Integer;
function PushErrorObject(const AErrCode: TdtErrcode; const AErrMsg: DuktapeString): Integer;
function PushBuffer(const ASize: NativeInt; const AIsDynamic: Boolean): Pointer;
function PushFixedBuffer(const ASize: NativeInt): Pointer;
function PushDynamicBuffer(const ASize: NativeInt): Pointer;
function PushExternalBuffer: Pointer;
procedure PushBufferObject(const ABufferIndex: Integer;
const AByteOffset, AByteLength: NativeInt; const AType: TdtBufferType);
function PushHeapPtr(const APtr: Pointer): Integer;
public
(*** Pop operations ***)
procedure Pop; overload;
procedure Pop(const ACount: Integer); overload;
procedure Pop2;
procedure Pop3;
public
(*** Type checks
IsNone, which would indicate whether index it outside of stack,
is not needed; IsValidIndex gives the same information. ***)
function GetType(const AIndex: Integer): TdtType;
function CheckType(const AIndex: Integer; const AType: TdtType): Boolean;
function GetTypes(const AIndex: Integer): TdtTypes;
function CheckTypes(const AIndex: Integer; const ATypes: TdtTypes): Boolean;
function IsUndefined(const AIndex: Integer): Boolean;
function IsNull(const AIndex: Integer): Boolean;
function IsNullOrUndefined(const AIndex: Integer): Boolean;
function IsBoolean(const AIndex: Integer): Boolean;
function IsNumber(const AIndex: Integer): Boolean;
function IsNan(const AIndex: Integer): Boolean;
function IsString(const AIndex: Integer): Boolean;
function IsObject(const AIndex: Integer): Boolean;
function IsBuffer(const AIndex: Integer): Boolean;
function IsBufferData(const AIndex: Integer): Boolean;
function IsPointer(const AIndex: Integer): Boolean;
function IsLightFunc(const AIndex: Integer): Boolean;
function IsSymbol(const AIndex: Integer): Boolean;
function IsArray(const AIndex: Integer): Boolean;
function IsFunction(const AIndex: Integer): Boolean;
function IsDelphiFunction(const AIndex: Integer): Boolean;
function IsEcmaScriptFunction(const AIndex: Integer): Boolean;
function IsBoundFunction(const AIndex: Integer): Boolean;
function IsThread(const AIndex: Integer): Boolean;
function IsCallable(const AIndex: Integer): Boolean;
function IsConstructable(const AIndex: Integer): Boolean;
function IsDynamicBuffer(const AIndex: Integer): Boolean;
function IsFixedBuffer(const AIndex: Integer): Boolean;
function IsExternalBuffer(const AIndex: Integer): Boolean;
function IsPrimitive(const AIndex: Integer): Boolean;
function IsObjectCoercible(const AIndex: Integer): Boolean;
function GetErrorCode(const AIndex: Integer): TdtErrcode;
function IsError(const AIndex: Integer): Boolean;
function IsEvalError(const AIndex: Integer): Boolean;
function IsRangeError(const AIndex: Integer): Boolean;
function IsReferenceError(const AIndex: Integer): Boolean;
function IsSyntaxError(const AIndex: Integer): Boolean;
function IsTypeError(const AIndex: Integer): Boolean;
function IsUriError(const AIndex: Integer): Boolean;
public
(*** Get operations: no coercion, returns default value for invalid
indices and invalid value types.
GetUndefined and GetNull would be pointless and are not included. ***)
function GetBoolean(const AIndex: Integer): Boolean; overload;
function GetBoolean(const AIndex: Integer; const ADefault: Boolean): Boolean; overload;
function GetNumber(const AIndex: Integer): Double; overload;
function GetNumber(const AIndex: Integer; const ADefault: Double): Double; overload;
function GetInt(const AIndex: Integer): Integer; overload;
function GetInt(const AIndex: Integer; const ADefault: Integer): Integer; overload;
function GetUInt(const AIndex: Integer): Cardinal; overload;
function GetUInt(const AIndex: Integer; const ADefault: Cardinal): Cardinal; overload;
function GetString(const AIndex: Integer): DuktapeString; overload;
function GetString(const AIndex: Integer; const ADefault: DuktapeString): DuktapeString; overload;
function GetBuffer(const AIndex: Integer; out ASize: NativeInt): Pointer; overload;
function GetBuffer(const AIndex: Integer; out ASize: NativeInt;
const ADefault: Pointer; const ADefaultSize: NativeInt): Pointer; overload;
function GetBufferData(const AIndex: Integer; out ASize: NativeInt): Pointer; overload;
function GetBufferData(const AIndex: Integer; out ASize: NativeInt;
const ADefault: Pointer; const ADefaultSize: NativeInt): Pointer; overload;
function GetPointer(const AIndex: Integer): Pointer; overload;
function GetPointer(const AIndex: Integer; const ADefault: Pointer): Pointer; overload;
function GetContext(const AIndex: Integer): TDuktape; overload;
function GetContext(const AIndex: Integer; const ADefault: TDuktape): TDuktape; overload;
function GetHeapPtr(const AIndex: Integer): Pointer; overload;
function GetHeapPtr(const AIndex: Integer; const ADefault: Pointer): Pointer; overload;
public
(*** Opt operations: like require operations but with an explicit default
value when value is undefined or index is invalid, null and
non-matching types cause a TypeError. ***)
function OptBoolean(const AIndex: Integer; const ADefault: Boolean): Boolean;
function OptNumber(const AIndex: Integer; const ADefault: Double): Double;
function OptInt(const AIndex: Integer; const ADefault: Integer): Integer;
function OptUInt(const AIndex: Integer; const ADefault: Cardinal): Cardinal;
function OptString(const AIndex: Integer; const ADefault: DuktapeString): DuktapeString;
function OptBuffer(const AIndex: Integer; out ASize: NativeInt;
const ADefault: Pointer; const ADefaultSize: NativeInt): Pointer;
function OptBufferData(const AIndex: Integer; out ASize: NativeInt;
const ADefault: Pointer; const ADefaultSize: NativeInt): Pointer;
function OptPointer(const AIndex: Integer; const ADefault: Pointer): Pointer;
function OptContext(const AIndex: Integer; const ADefault: TDuktape): TDuktape;
function OptHeapPtr(const AIndex: Integer; const ADefault: Pointer): Pointer;
public
(*** Require operations: no coercion, throw error if index or type
is incorrect. No defaulting. ***)
procedure RequireTypes(const AIndex: Integer; const ATypes: TdtTypes);
procedure RequireUndefined(const AIndex: Integer);
procedure RequireNull(const AIndex: Integer);
function RequireBoolean(const AIndex: Integer): Boolean;
function RequireNumber(const AIndex: Integer): Double;
function RequireInt(const AIndex: Integer): Integer;
function RequireUInt(const AIndex: Integer): Cardinal;
function RequireString(const AIndex: Integer): DuktapeString;
procedure RequireObject(const AIndex: Integer);
function RequireBuffer(const AIndex: Integer; out ASize: NativeInt): Pointer;
function RequireBufferData(const AIndex: Integer; out ASize: NativeInt): Pointer;
function RequirePointer(const AIndex: Integer): Pointer;
function RequireContext(const AIndex: Integer): TDuktape;
procedure RequireFunction(const AIndex: Integer);
procedure RequireCallable(const AIndex: Integer);
function RequireHeapPtr(const AIndex: Integer): Pointer;
procedure RequireObjectCoercible(const AIndex: Integer);
public
(*** Coercion operations: in-place coercion, return coerced value where
applicable. If AIndex is invalid, throw error. Some coercions may
throw an expected error (e.g. from a ToString or ValueOf call)
or an internal error (e.g. from out of memory). ***)
procedure ToUndefined(const AIndex: Integer);
procedure ToNull(const AIndex: Integer);
function ToBoolean(const AIndex: Integer): Boolean;
function ToNumber(const AIndex: Integer): Double;
function ToInt(const AIndex: Integer): Integer;
function ToUInt(const AIndex: Integer): Cardinal;
function ToInt32(const AIndex: Integer): Integer;
function ToUInt32(const AIndex: Integer): Cardinal;
function ToUInt16(const AIndex: Integer): UInt16;
function ToString(const AIndex: Integer): DuktapeString;
function ToPointer(const AIndex: Integer): Pointer;
procedure ToObject(const AIndex: Integer);
procedure ToPrimitive(const AIndex: Integer; const AHint: TdtHint);
function ToBuffer(const AIndex: Integer; out ASize: NativeInt): Pointer;
function ToFixedBuffer(const AIndex: Integer; out ASize: NativeInt): Pointer;
function ToDynamicBuffer(const AIndex: Integer; out ASize: NativeInt): Pointer;
{ Like ToString but if the initial string coercion fails, the error value is
coerced to a string. If that also fails, a fixed error string is returned.
The caller can safely use this function to coerce a value to a string,
which is useful in Delphi code to print out a return value safely. The
only uncaught errors possible are out-of-memory and other internal errors
which trigger fatal error handling anyway. }
function SafeToString(const AIndex: Integer): DuktapeString;
public
(*** Value length ***)
function GetLength(const AIndex: Integer): NativeInt;
procedure SetLength(const AIndex: Integer; const ALength: NativeInt);
public
(*** Misc conversion **)
function Base64Encode(const AIndex: Integer): DuktapeString;
procedure Base64Decode(const AIndex: Integer);
function HexEncode(const AIndex: Integer): DuktapeString;
procedure HexDecode(const AIndex: Integer);
function JsonEncode(const AIndex: Integer): DuktapeString;
procedure JsonDecode(const AIndex: Integer);
function BufferToString(const AIndex: Integer): DuktapeString;
public
(*** Buffer ***)
function Resize_buffer(const AIndex: Integer; const ANewSize: NativeInt): Pointer;
function StealBuffer(const AIndex: Integer; out ASize: NativeInt): Pointer;
procedure ConfigBuffer(const AIndex: Integer; const APtr: Pointer; const ALen: NativeInt);
public
(*** Property access
The basic function assumes key is on stack. The String variant takes
a string as a property name, while the Index variant takes an array
index as a property name (e.g. 123 is equivalent to the key "123"). ***)
function GetProp(const AObjIndex: Integer): Boolean; overload;
function GetProp(const AObjIndex: Integer; const AKey: DuktapeString): Boolean; overload;
function GetProp(const AObjIndex, AArrIndex: Integer): Boolean; overload;
function GetProp(const AObjIndex: Integer; const APtr: Pointer): Boolean; overload;
function PutProp(const AObjIndex: Integer): Boolean; overload;
function PutProp(const AObjIndex: Integer; const AKey: DuktapeString): Boolean; overload;
function PutProp(const AObjIndex, AArrIndex: Integer): Boolean; overload;
function PutProp(const AObjIndex: Integer; const APtr: Pointer): Boolean; overload;
function DelProp(const AObjIndex: Integer): Boolean; overload;
function DelProp(const AObjIndex: Integer; const AKey: DuktapeString): Boolean; overload;
function DelProp(const AObjIndex, AArrIndex: Integer): Boolean; overload;
function DelProp(const AObjIndex: Integer; const APtr: Pointer): Boolean; overload;
function HasProp(const AObjIndex: Integer): Boolean; overload;
function HasProp(const AObjIndex: Integer; const AKey: DuktapeString): Boolean; overload;
function HasProp(const AObjIndex, AArrIndex: Integer): Boolean; overload;
function HasProp(const AObjIndex: Integer; const APtr: Pointer): Boolean; overload;
procedure GetPropDesc(const AObjIndex: Integer);
procedure DefProp(const AObjIndex: Integer; const AFlags: TgtDefPropFlags);
function GetGlobalString(const AKey: DuktapeString): Boolean;
{ Put property named AKey to the global object. Return value behaves
similarly to PutProp. This is a convenience function which does the
equivalent of:
<source>
Duktape.PushGlobalObject;
Duktape.Insert(-2);
Result := Duktape.PutPropString(-2, AKey);
Duktape.Pop;
</source> }
function PutGlobalString(const AKey: DuktapeString): Boolean;
public
(*** Inspection ***)
procedure InspectValue(const AIndex: Integer);
procedure InspectCallstackEntry(const ALevel: Integer);
public
(*** Object prototype ***)
procedure GetPrototype(const AIndex: Integer);
procedure SetPrototype(const AIndex: Integer);
public
(*** Object finalizer ***)
procedure GetFinalizer(const AIndex: Integer);
procedure SetFinalizer(const AIndex: Integer);
public
(*** Global object ***)
procedure SetGlobalObject;
public
(*** Duktape/Delphi function magic value ***)
function GetMagic(const AIndex: Integer): Integer;
procedure SetMagic(const AIndex: Integer; const AMagic: Integer);
function GetCurrentMagic: Integer;
public
(*** Module helpers: put multiple function or constant properties ***)
procedure PutFunctionList(const AObjIndex: Integer;
const AFunctions: PdtFunctionListEntry);
procedure PutNumberList(const AObjIndex: Integer;
const ANumbers: PdtNumberListEntry);
public
(*** Object operations ***)
procedure Compact(const AObjIndex: Integer);
procedure Enum(const AObjIndex: Integer; const AFlags: TdtEnumFlags);
function Next(const AEnumIndex: Integer; const AGetValue: Boolean): Boolean;
procedure Seal(const AObjIndex: Integer);
procedure Freeze(const AObjIndex: Integer);
public
(*** String manipulation ***)
procedure Concat(const ACount: Integer);
{ Join zero or more values into a result string with a separator between
each value. The separator and the input values are automatically coerced
with ToString.
This primitive minimizes the number of intermediate string interning
operations and is better than joining strings manually. }
procedure Join(const ACount: Integer);
procedure DecodeString(const AIndex: Integer;
const ACallback: TdtDecodeCharCallback; const AUserData: Pointer);
procedure MapString(const AIndex: Integer;
const ACallback: TdtMapCharCallback; const AUserData: Pointer);
procedure SubString(const AIndex: Integer; const AStartCharOffset,
AEndCharOffset: NativeInt);
function CharCodeAt(const AIndex: Integer; const ACharOffset: NativeInt): Integer;
public
(*** Ecmascript operators ***)
function Equals(const AIndex1, AIndex2: Integer): Boolean;
function StrictEquals(const AIndex1, AIndex2: Integer): Boolean;
function SameValue(const AIndex1, AIndex2: Integer): Boolean;
function InstanceOf(const AIndex1, AIndex2: Integer): Boolean;
public
(*** Function (method) calls ***)
procedure Call(const ANumArgs: Integer);
procedure CallMethod(const ANumArgs: Integer);
procedure CallProp(const AObjIndex, ANumArgs: Integer);
function ProtectedCall(const ANumArgs: Integer): Integer;
function ProtectedCallMethod(const ANumArgs: Integer): Integer;
function ProtectedCallProp(const AObjIndex, ANumArgs: Integer): Integer;
procedure New(const ANumArgs: Integer);
function ProtectedNew(const ANumArgs: Integer): Integer;
public
(*** Compilation and evaluation ***)
function Eval: Integer; overload;
function Eval(const ASource: DuktapeString): Integer; overload;
function EvalNoResult: Integer; overload;
function EvalNoResult(const ASource: DuktapeString): Integer; overload;
function ProtectedEval: Integer; overload;
function ProtectedEval(const ASource: DuktapeString): Integer; overload;
function ProtectedEvalNoResult: Integer; overload;
function ProtectedEvalNoResult(const ASource: DuktapeString): Integer; overload;
function Compile(const AFlags: TdtCompileFlags): Integer; overload;
function Compile(const AFlags: TdtCompileFlags; const ASource: DuktapeString): Integer; overload;
function CompileFilename(const AFlags: TdtCompileFlags; const ASource: DuktapeString): Integer;
function ProtectedCompile(const AFlags: TdtCompileFlags): Integer; overload;
function ProtectedCompile(const AFlags: TdtCompileFlags; const ASource: DuktapeString): Integer; overload;
function ProtectedCompileFilename(const AFlags: TdtCompileFlags; const ASource: DuktapeString): Integer;
public
(*** Bytecode load/dump ***)
procedure DumpFunction;
procedure LoadFunction;
public
(*** Debugging ***)
procedure PushContextDump;
public
(*** Debugger (debug protocol) ***)
procedure DebuggerDetach;
procedure DebuggerCooperate;
function DebuggerNotify(const ANumValues: Integer): Boolean;
procedure DebuggerPause;
public
(*** Time handling ***)
function GetNow: Double;
function TimeToComponents(const ATimeVal: Double): TdtTimeComponents;
function ComponentsToTime(const AComponents: TdtTimeComponents): Double;
public
(*** Low level context handle ***)
property Context: PDukContext read FContext;
end;
type
{ Function signature for Delphi functions that can be called from JavaScript. }
TdtDelphiFunction = function(const ADuktape: TDuktape): TdtResult; cdecl;
TdtSafeCallFunction = function(const ADuktape: TDuktape;
const AUserData: Pointer): TdtResult; cdecl;
TdtDebugReadCallback = function(const AUserData: Pointer;
const ABuffer: MarshaledAString; const ALength: NativeInt): NativeInt; cdecl;
TdtDebugWriteCallback = function(const AUserData: Pointer;
const ABuffer: MarshaledAString; const Aength: NativeInt): NativeInt; cdecl;
TdtDebugPeekCallback = function(const AUserData: Pointer): NativeInt; cdecl;
TdtDebugReadFlushCallback = procedure(const AUserData: Pointer); cdecl;
TdtDebugWriteFlushCallback = procedure(const AUserData: Pointer); cdecl;
TdtDebugRequestCallback = function(const ADuktape: TDuktape;
const AUserData: Pointer; const ANumValues: Integer): Integer; cdecl;
TdtDebugDetachedCallback = procedure(const ADuktape: TDuktape;
const AUserData: Pointer); cdecl;
type
TDuktapeHelper = record helper for TDuktape
public
(*** Push operations ***)
{ Push a new function object, associated with a Delphi function, to the
stack. The function object is an Ecmascript function object; when called,
AFunc will be called using the Duktape/C function interface. Returns
non-negative index (relative to stack bottom) of the pushed function.
The ANumArgs argument controls how the value stack looks like when AFunc
is entered:
If ANumArgs is >= 0, it indicates the exact number of arguments the
function expects to see; extra arguments are discarded and missing
arguments are filled in with undefined values. Upon entry to the function,
value stack top will always match nargs.
If ANumArgs is set to DT_VARARGS, the value stack will contain actual
(variable) call arguments and the function needs to check actual argument
count with GetTop.
The function created will be callable both as a normal function (AFunc())
and as a constructor (new AFunc()). You can differentiate between the two
call styles using IsConstructorCall. Although the function can be used as
a constructor, it doesn't have an automatic prototype property like
Ecmascript functions.
@bold(Note): If you intend to use the pushed function as a constructor,
you should usually create a prototype object and set the prototype
property of the function manually. }
function PushDelphiFunction(const AFunc: TdtDelphiFunction;
const ANumArgs: Integer): Integer;
function PushDelphiLightFunction(const AFunc: TdtDelphiFunction;
const ANumArgs, ALength, AMagic: Integer): Integer;
public
(*** Get operations ***)
function GetDelphiFunction(const AIndex: Integer): TdtDelphiFunction; overload;
function GetDelphiFunction(const AIndex: Integer; const ADefault: TdtDelphiFunction): TdtDelphiFunction; overload;
public
(*** Opt operations ***)
function OptDelphiFunction(const AIndex: Integer; const ADefault: TdtDelphiFunction): TdtDelphiFunction;
public
(*** Require operations ***)
function RequireDelphiFunction(const AIndex: Integer): TdtDelphiFunction;
public
(*** Function (method) calls ***)
function SafeCall(const AFunc: TdtSafeCallFunction; const AUserData: Pointer;
const ANumArgs, ANumReturns: Integer): Integer;
public
(*** Debugger (debug protocol) ***)
procedure DebuggerAttach(
const AReadCallback: TdtDebugReadCallback;
const AWriteCallback: TdtDebugWriteCallback;
const APeekCallback: TdtDebugPeekCallback;
const AReadFlushCallback: TdtDebugReadFlushCallback;
const AWriteFlushCallback: TdtDebugWriteFlushCallback;
const ARequestCallback: TdtDebugRequestCallback;
const ADetachedCallback: TdtDebugDetachedCallback;
const AUserData: Pointer);
end;
implementation
{ TDuktape }
function TDuktape.AllocMem(const ASize: NativeInt): Pointer;
begin
Result := duk_alloc(FContext, ASize);
end;
function TDuktape.AllocRaw(const ASize: NativeInt): Pointer;
begin
Result := duk_alloc_raw(FContext, ASize);
end;
procedure TDuktape.Base64Decode(const AIndex: Integer);
begin
duk_base64_decode(FContext, AIndex);
end;
function TDuktape.Base64Encode(const AIndex: Integer): DuktapeString;
begin
Result := DuktapeString(duk_base64_encode(FContext, AIndex));
end;
function TDuktape.BufferToString(const AIndex: Integer): DuktapeString;
begin
Result := DuktapeString(duk_buffer_to_string(FContext, AIndex));
end;
procedure TDuktape.Call(const ANumArgs: Integer);
begin
duk_call(FContext, ANumArgs);
end;
procedure TDuktape.CallMethod(const ANumArgs: Integer);
begin
duk_call_method(FContext, ANumArgs);
end;
procedure TDuktape.CallProp(const AObjIndex, ANumArgs: Integer);
begin
duk_call_prop(FContext, AObjIndex, ANumArgs);
end;
function TDuktape.CharCodeAt(const AIndex: Integer;
const ACharOffset: NativeInt): Integer;
begin
Result := duk_char_code_at(FContext, AIndex, ACharOffset);
end;
function TDuktape.CheckStack(const AExtra: Integer): Boolean;
begin
Result := (duk_check_stack(FContext, AExtra) <> 0);
end;
function TDuktape.CheckStackTop(const ATop: Integer): Boolean;
begin
Result := (duk_check_stack_top(FContext, ATop) <> 0);
end;
function TDuktape.CheckType(const AIndex: Integer;
const AType: TdtType): Boolean;
begin
Result := (duk_check_type(FContext, AIndex, Ord(AType)) <> 0);
end;
function TDuktape.CheckTypes(const AIndex: Integer;
const ATypes: TdtTypes): Boolean;
begin
Result := (duk_check_type_mask(FContext, AIndex, Word(ATypes)) <> 0);
end;
procedure TDuktape.Compact(const AObjIndex: Integer);
begin
duk_compact(FContext, AObjIndex);
end;
function TDuktape.Compile(const AFlags: TdtCompileFlags): Integer;
begin
Result := duk_compile(FContext, Word(AFlags));
end;
function TDuktape.Compile(const AFlags: TdtCompileFlags;
const ASource: DuktapeString): Integer;
begin
Result := duk_compile_lstring(FContext, Word(AFlags),
MarshaledAString(ASource), Length(ASource));
end;
function TDuktape.CompileFilename(const AFlags: TdtCompileFlags;
const ASource: DuktapeString): Integer;
begin
Result := duk_compile_lstring_filename(FContext, Word(AFlags),
MarshaledAString(ASource), Length(ASource));
end;
function TDuktape.ComponentsToTime(
const AComponents: TdtTimeComponents): Double;
begin
Result := duk_components_to_time(FContext, @AComponents);
end;
procedure TDuktape.Concat(const ACount: Integer);
begin
duk_concat(FContext, ACount);
end;
procedure TDuktape.ConfigBuffer(const AIndex: Integer; const APtr: Pointer;
const ALen: NativeInt);
begin
duk_config_buffer(FContext, AIndex, APtr, ALen);
end;
procedure TDuktape.Copy(const AFromIndex, AToIndex: Integer);
begin
duk_copy(FContext, AFromIndex, AToIndex);
end;
class function TDuktape.Create(const AUseDelphiMemoryManager: Boolean): TDuktape;
begin
if (AUseDelphiMemoryManager) then
Result.FContext := duk_create_heap(DelphiAlloc, DelphiRealloc, DelphiFree, nil, FatalHandler)
else
Result.FContext := duk_create_heap(nil, nil, nil, nil, FatalHandler);
if (Result.FContext = nil) then
raise EdtError.Create('Unable to create Duktape heap and context');
end;
procedure TDuktape.DebuggerCooperate;
begin
duk_debugger_cooperate(FContext);
end;
procedure TDuktape.DebuggerDetach;
begin
duk_debugger_detach(FContext);
end;
function TDuktape.DebuggerNotify(const ANumValues: Integer): Boolean;
begin
Result := (duk_debugger_notify(FContext, ANumValues) <> 0);
end;
procedure TDuktape.DebuggerPause;
begin
duk_debugger_pause(FContext);
end;
procedure TDuktape.DecodeString(const AIndex: Integer;
const ACallback: TdtDecodeCharCallback; const AUserData: Pointer);
begin
duk_decode_string(FContext, AIndex, TDukDecodeCharFunction(ACallback), AUserData);
end;
procedure TDuktape.DefProp(const AObjIndex: Integer;
const AFlags: TgtDefPropFlags);
begin
duk_def_prop(FContext, AObjIndex, Word(AFlags));
end;
class function TDuktape.DelphiAlloc(AUserData: Pointer;
ASize: TDukSize): Pointer;
begin
GetMem(Result, ASize);
end;
class procedure TDuktape.DelphiFree(AUserData, APtr: Pointer);
begin
System.FreeMem(APtr);
end;
class function TDuktape.DelphiRealloc(AUserData, APtr: Pointer;
ASize: TDukSize): Pointer;
begin
Result := APtr;
System.ReallocMem(Result, ASize);
end;
function TDuktape.DelProp(const AObjIndex: Integer): Boolean;
begin
Result := (duk_del_prop(FContext, AObjIndex) <> 0);
end;
function TDuktape.DelProp(const AObjIndex, AArrIndex: Integer): Boolean;
begin
Result := (duk_del_prop_index(FContext, AObjIndex, AArrIndex) <> 0);
end;
function TDuktape.DelProp(const AObjIndex: Integer;
const AKey: DuktapeString): Boolean;
begin
Result := (duk_del_prop_string(FContext, AObjIndex, MarshaledAString(AKey)) <> 0);
end;
function TDuktape.DelProp(const AObjIndex: Integer;
const APtr: Pointer): Boolean;
begin
Result := (duk_del_prop_heapptr(FContext, AObjIndex, APtr) <> 0);
end;
procedure TDuktape.DumpFunction;
begin
duk_dump_function(FContext);
end;
procedure TDuktape.Dup(const AFromIndex: Integer);
begin
duk_dup(FContext, AFromIndex);
end;
procedure TDuktape.DupTop;
begin
duk_dup_top(FContext);
end;
procedure TDuktape.Enum(const AObjIndex: Integer; const AFlags: TdtEnumFlags);
begin
duk_enum(FContext, AObjIndex, Byte(AFlags));
end;
function TDuktape.Equals(const AIndex1, AIndex2: Integer): Boolean;
begin
Result := (duk_equals(FContext, AIndex1, AIndex2) <> 0);
end;
procedure TDuktape.Error(const AErrCode: TdtErrCode;
const AErrMsg: DuktapeString);
begin
duk_error(FContext, Ord(AErrCode), MarshaledAString(AErrMsg));
end;
function TDuktape.Eval: Integer;
begin
Result := duk_eval(FContext);
end;
function TDuktape.Eval(const ASource: DuktapeString): Integer;
begin
Result := duk_eval_lstring(FContext, MarshaledAString(ASource), Length(ASource));
end;
procedure TDuktape.EvalError(const AErrMsg: DuktapeString);
begin
duk_eval_error(FContext, MarshaledAString(AErrMsg));
end;
function TDuktape.EvalNoResult(const ASource: DuktapeString): Integer;
begin
Result := duk_eval_lstring_noresult(FContext, MarshaledAString(ASource), Length(ASource));
end;
function TDuktape.EvalNoResult: Integer;
begin
Result := duk_eval_noresult(FContext);
end;
procedure TDuktape.Fatal(const AErrMsg: DuktapeString);
begin
duk_fatal(FContext, MarshaledAString(AErrMsg));
end;
class procedure TDuktape.FatalHandler(AUserData: Pointer;
const AMsg: MarshaledAString);
begin
raise EdtError.Create(String(AMsg));
end;
procedure TDuktape.Free;
begin
if (FContext <> nil) then
duk_destroy_heap(FContext);
end;
procedure TDuktape.FreeMem(const APtr: Pointer);
begin