@as-pect/assembly 6.0.0 → 7.0.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/README.md +34 -34
- package/assembly/index.ts +24 -24
- package/assembly/internal/Actual.ts +20 -20
- package/assembly/internal/Expectation.ts +544 -481
- package/assembly/internal/Expected.ts +55 -55
- package/assembly/internal/Reflect.ts +698 -662
- package/assembly/internal/ReflectedValueType.ts +17 -17
- package/assembly/internal/Test.ts +81 -81
- package/assembly/internal/assert.ts +3 -3
- package/assembly/internal/call.ts +3 -3
- package/assembly/internal/comparison/toIncludeComparison.ts +67 -62
- package/assembly/internal/comparison/toIncludeEqualComparison.ts +91 -78
- package/assembly/internal/log.ts +19 -18
- package/assembly/internal/noOp.ts +3 -2
- package/package.json +17 -10
- package/types/as-pect.d.ts +733 -733
- package/types/as-pect.portable.d.ts +389 -389
- package/types/env.d.ts +1 -1
|
@@ -1,662 +1,698 @@
|
|
|
1
|
-
import { ArrayBufferView } from "arraybuffer";
|
|
2
|
-
import { Set } from "set";
|
|
3
|
-
import { assert } from "./assert";
|
|
4
|
-
import { ReflectedValueType } from "./ReflectedValueType";
|
|
5
|
-
import { OBJECT, OBJECT_OVERHEAD } from "rt/common";
|
|
6
|
-
|
|
7
|
-
function pairSeen(a1: usize, a2: usize, b1: usize, b2: usize): bool {
|
|
8
|
-
return bool(
|
|
9
|
-
(i32(a1 == b1) & i32(a2 == b2)) | (i32(a1 == b2) & i32(a2 == b1)),
|
|
10
|
-
);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// @ts-ignore: Decorators *are* valid here!
|
|
14
|
-
@external("__aspect", "attachStackTraceToReflectedValue")
|
|
15
|
-
declare function attachStackTraceToReflectedValue(id: i32): void;
|
|
16
|
-
|
|
17
|
-
// @ts-ignore: linked function decorator
|
|
18
|
-
@external("__aspect", "createReflectedValue")
|
|
19
|
-
declare function createReflectedValue(
|
|
20
|
-
isNull: bool,
|
|
21
|
-
hasKeys: bool,
|
|
22
|
-
nullable: bool,
|
|
23
|
-
offset: i32,
|
|
24
|
-
pointer: usize,
|
|
25
|
-
signed: bool,
|
|
26
|
-
size: i32,
|
|
27
|
-
reflectedTypeValue: ReflectedValueType,
|
|
28
|
-
typeId: i32,
|
|
29
|
-
typeName: string,
|
|
30
|
-
value: usize,
|
|
31
|
-
hasValues: bool,
|
|
32
|
-
isManaged: bool,
|
|
33
|
-
): i32;
|
|
34
|
-
|
|
35
|
-
// @ts-ignore: linked function decorator
|
|
36
|
-
@external("__aspect", "createReflectedNumber")
|
|
37
|
-
declare function createReflectedNumber(
|
|
38
|
-
signed: bool,
|
|
39
|
-
size: i32,
|
|
40
|
-
reflectedTypeValue: ReflectedValueType,
|
|
41
|
-
typeName: string,
|
|
42
|
-
value: f64,
|
|
43
|
-
): i32;
|
|
44
|
-
|
|
45
|
-
// @ts-ignore: linked function decorator
|
|
46
|
-
@external("__aspect", "createReflectedLong")
|
|
47
|
-
declare function createReflectedLong(
|
|
48
|
-
signed: bool,
|
|
49
|
-
size: i32,
|
|
50
|
-
reflectedTypeValue: ReflectedValueType,
|
|
51
|
-
typeName: string,
|
|
52
|
-
lowValue: i32,
|
|
53
|
-
highValue: i32,
|
|
54
|
-
): i32;
|
|
55
|
-
|
|
56
|
-
// @ts-ignore: external declaration
|
|
57
|
-
@external("__aspect", "pushReflectedObjectValue")
|
|
58
|
-
@global
|
|
59
|
-
declare function __aspectPushReflectedObjectValue(
|
|
60
|
-
parentID: i32,
|
|
61
|
-
value: i32,
|
|
62
|
-
): void;
|
|
63
|
-
|
|
64
|
-
// @ts-ignore: external declaration
|
|
65
|
-
@external("__aspect", "pushReflectedObjectKey")
|
|
66
|
-
@global
|
|
67
|
-
declare function __aspectPushReflectedObjectKey(
|
|
68
|
-
parentID: i32,
|
|
69
|
-
value: i32,
|
|
70
|
-
): void;
|
|
71
|
-
|
|
72
|
-
@inline function sizeOf(ptr: usize): i32 {
|
|
73
|
-
return changetype<OBJECT>(ptr - OBJECT_OVERHEAD).rtSize;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
@global
|
|
77
|
-
// @ts-ignore: global decorator is allowed here
|
|
78
|
-
export class Reflect {
|
|
79
|
-
public static toReflectedValue<T>(
|
|
80
|
-
value: T,
|
|
81
|
-
seen: Map<usize, i32> = new Map<usize, i32>(),
|
|
82
|
-
): i32 {
|
|
83
|
-
// if T is a reference
|
|
84
|
-
if (isReference<T>()) {
|
|
85
|
-
// if the value is null, create a Null reflected value
|
|
86
|
-
if (changetype<usize>(value) == 0) {
|
|
87
|
-
return createReflectedValue(
|
|
88
|
-
true,
|
|
89
|
-
false,
|
|
90
|
-
isNullable<T>(),
|
|
91
|
-
0,
|
|
92
|
-
0,
|
|
93
|
-
false,
|
|
94
|
-
sizeof<T>(),
|
|
95
|
-
isFunction<T>()
|
|
96
|
-
? ReflectedValueType.Function
|
|
97
|
-
: ReflectedValueType.Class,
|
|
98
|
-
isManaged<T>() ? idof<T>() : 0,
|
|
99
|
-
isFunction<T>() ? "Function" : nameof<T>(),
|
|
100
|
-
0,
|
|
101
|
-
false,
|
|
102
|
-
isManaged<T>(),
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// check the cache for anything that isn't a function
|
|
107
|
-
if (!isFunction<T>()) {
|
|
108
|
-
if (seen.has(changetype<usize>(value))) {
|
|
109
|
-
return seen.get(changetype<usize>(value));
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// @ts-ignore: __aspectReflectAs() can potentially be implemented
|
|
114
|
-
if (isDefined(value.__aspectReflectAs())) {
|
|
115
|
-
// @ts-ignore: typesafe call to __aspectReflectAs()
|
|
116
|
-
let displayValue = value.__aspectReflectAs();
|
|
117
|
-
if (
|
|
118
|
-
!
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
false,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
true,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
let
|
|
160
|
-
|
|
161
|
-
false,
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
false,
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
true,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
let
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
let
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
true,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
let
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
let
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
let
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
false,
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
let
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
false,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
);
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
false,
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
let
|
|
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
|
-
} else {
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
} else {
|
|
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
|
-
|
|
1
|
+
import { ArrayBufferView } from "arraybuffer";
|
|
2
|
+
import { Set } from "set";
|
|
3
|
+
import { assert } from "./assert";
|
|
4
|
+
import { ReflectedValueType } from "./ReflectedValueType";
|
|
5
|
+
import { OBJECT, OBJECT_OVERHEAD } from "rt/common";
|
|
6
|
+
|
|
7
|
+
function pairSeen(a1: usize, a2: usize, b1: usize, b2: usize): bool {
|
|
8
|
+
return bool(
|
|
9
|
+
(i32(a1 == b1) & i32(a2 == b2)) | (i32(a1 == b2) & i32(a2 == b1)),
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// @ts-ignore: Decorators *are* valid here!
|
|
14
|
+
@external("__aspect", "attachStackTraceToReflectedValue")
|
|
15
|
+
declare function attachStackTraceToReflectedValue(id: i32): void;
|
|
16
|
+
|
|
17
|
+
// @ts-ignore: linked function decorator
|
|
18
|
+
@external("__aspect", "createReflectedValue")
|
|
19
|
+
declare function createReflectedValue(
|
|
20
|
+
isNull: bool,
|
|
21
|
+
hasKeys: bool,
|
|
22
|
+
nullable: bool,
|
|
23
|
+
offset: i32,
|
|
24
|
+
pointer: usize,
|
|
25
|
+
signed: bool,
|
|
26
|
+
size: i32,
|
|
27
|
+
reflectedTypeValue: ReflectedValueType,
|
|
28
|
+
typeId: i32,
|
|
29
|
+
typeName: string,
|
|
30
|
+
value: usize,
|
|
31
|
+
hasValues: bool,
|
|
32
|
+
isManaged: bool,
|
|
33
|
+
): i32;
|
|
34
|
+
|
|
35
|
+
// @ts-ignore: linked function decorator
|
|
36
|
+
@external("__aspect", "createReflectedNumber")
|
|
37
|
+
declare function createReflectedNumber(
|
|
38
|
+
signed: bool,
|
|
39
|
+
size: i32,
|
|
40
|
+
reflectedTypeValue: ReflectedValueType,
|
|
41
|
+
typeName: string,
|
|
42
|
+
value: f64,
|
|
43
|
+
): i32;
|
|
44
|
+
|
|
45
|
+
// @ts-ignore: linked function decorator
|
|
46
|
+
@external("__aspect", "createReflectedLong")
|
|
47
|
+
declare function createReflectedLong(
|
|
48
|
+
signed: bool,
|
|
49
|
+
size: i32,
|
|
50
|
+
reflectedTypeValue: ReflectedValueType,
|
|
51
|
+
typeName: string,
|
|
52
|
+
lowValue: i32,
|
|
53
|
+
highValue: i32,
|
|
54
|
+
): i32;
|
|
55
|
+
|
|
56
|
+
// @ts-ignore: external declaration
|
|
57
|
+
@external("__aspect", "pushReflectedObjectValue")
|
|
58
|
+
@global
|
|
59
|
+
declare function __aspectPushReflectedObjectValue(
|
|
60
|
+
parentID: i32,
|
|
61
|
+
value: i32,
|
|
62
|
+
): void;
|
|
63
|
+
|
|
64
|
+
// @ts-ignore: external declaration
|
|
65
|
+
@external("__aspect", "pushReflectedObjectKey")
|
|
66
|
+
@global
|
|
67
|
+
declare function __aspectPushReflectedObjectKey(
|
|
68
|
+
parentID: i32,
|
|
69
|
+
value: i32,
|
|
70
|
+
): void;
|
|
71
|
+
|
|
72
|
+
@inline function sizeOf(ptr: usize): i32 {
|
|
73
|
+
return changetype<OBJECT>(ptr - OBJECT_OVERHEAD).rtSize;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@global
|
|
77
|
+
// @ts-ignore: global decorator is allowed here
|
|
78
|
+
export class Reflect {
|
|
79
|
+
public static toReflectedValue<T>(
|
|
80
|
+
value: T,
|
|
81
|
+
seen: Map<usize, i32> = new Map<usize, i32>(),
|
|
82
|
+
): i32 {
|
|
83
|
+
// if T is a reference
|
|
84
|
+
if (isReference<T>()) {
|
|
85
|
+
// if the value is null, create a Null reflected value
|
|
86
|
+
if (changetype<usize>(value) == 0) {
|
|
87
|
+
return createReflectedValue(
|
|
88
|
+
true,
|
|
89
|
+
false,
|
|
90
|
+
isNullable<T>(),
|
|
91
|
+
0,
|
|
92
|
+
0,
|
|
93
|
+
false,
|
|
94
|
+
sizeof<T>(),
|
|
95
|
+
isFunction<T>()
|
|
96
|
+
? ReflectedValueType.Function
|
|
97
|
+
: ReflectedValueType.Class,
|
|
98
|
+
isManaged<T>() ? idof<T>() : 0,
|
|
99
|
+
isFunction<T>() ? "Function" : nameof<T>(),
|
|
100
|
+
0,
|
|
101
|
+
false,
|
|
102
|
+
isManaged<T>(),
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// check the cache for anything that isn't a function
|
|
107
|
+
if (!isFunction<T>()) {
|
|
108
|
+
if (seen.has(changetype<usize>(value))) {
|
|
109
|
+
return seen.get(changetype<usize>(value));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// @ts-ignore: __aspectReflectAs() can potentially be implemented
|
|
114
|
+
if (isDefined(value.__aspectReflectAs())) {
|
|
115
|
+
// @ts-ignore: typesafe call to __aspectReflectAs()
|
|
116
|
+
let displayValue = value.__aspectReflectAs();
|
|
117
|
+
if (!isInteger(displayValue)) {
|
|
118
|
+
if (!isFloat(displayValue)) {
|
|
119
|
+
// @as-covers: ignore compile time check
|
|
120
|
+
if (!isManaged(displayValue)) {
|
|
121
|
+
ERROR(
|
|
122
|
+
"__aspectReflectAs() function should return a managed type or a number",
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return Reflect.toReflectedValue(displayValue, seen);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (value instanceof ArrayBuffer) {
|
|
131
|
+
let reflectedValue = createReflectedValue(
|
|
132
|
+
false,
|
|
133
|
+
false,
|
|
134
|
+
isNullable<T>(),
|
|
135
|
+
value.byteLength,
|
|
136
|
+
changetype<usize>(value),
|
|
137
|
+
false,
|
|
138
|
+
value.byteLength,
|
|
139
|
+
ReflectedValueType.ArrayBuffer,
|
|
140
|
+
idof<T>(),
|
|
141
|
+
nameof<T>(),
|
|
142
|
+
0,
|
|
143
|
+
true,
|
|
144
|
+
true,
|
|
145
|
+
);
|
|
146
|
+
seen.set(changetype<usize>(value), reflectedValue);
|
|
147
|
+
let length = value.byteLength;
|
|
148
|
+
for (let i = 0; i < length; i++) {
|
|
149
|
+
__aspectPushReflectedObjectValue(
|
|
150
|
+
reflectedValue,
|
|
151
|
+
Reflect.toReflectedValue(
|
|
152
|
+
load<u8>(changetype<usize>(value) + <usize>i),
|
|
153
|
+
seen,
|
|
154
|
+
),
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
return reflectedValue;
|
|
158
|
+
} else if (isFunction<T>()) {
|
|
159
|
+
let func = value;
|
|
160
|
+
let reflectedValue = createReflectedValue(
|
|
161
|
+
false,
|
|
162
|
+
false,
|
|
163
|
+
isNullable<T>(),
|
|
164
|
+
0,
|
|
165
|
+
// @ts-ignore has field
|
|
166
|
+
func.index,
|
|
167
|
+
false,
|
|
168
|
+
0,
|
|
169
|
+
ReflectedValueType.Function,
|
|
170
|
+
0,
|
|
171
|
+
"Function",
|
|
172
|
+
// @ts-ignore has field
|
|
173
|
+
func.index,
|
|
174
|
+
false,
|
|
175
|
+
isManaged<T>(),
|
|
176
|
+
);
|
|
177
|
+
return reflectedValue;
|
|
178
|
+
} else if (value instanceof Set) {
|
|
179
|
+
// create a Set reflected value
|
|
180
|
+
let reflectedObject = createReflectedValue(
|
|
181
|
+
false,
|
|
182
|
+
false, // sets don't have keys
|
|
183
|
+
isNullable<T>(),
|
|
184
|
+
0,
|
|
185
|
+
changetype<usize>(value),
|
|
186
|
+
false,
|
|
187
|
+
value.size,
|
|
188
|
+
ReflectedValueType.Set,
|
|
189
|
+
idof<T>(),
|
|
190
|
+
nameof<T>(),
|
|
191
|
+
0,
|
|
192
|
+
true, // sets have values
|
|
193
|
+
true,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// cache this value
|
|
197
|
+
seen.set(changetype<usize>(value), reflectedObject);
|
|
198
|
+
|
|
199
|
+
// loop over each item and push it to the Set
|
|
200
|
+
let values = value.values();
|
|
201
|
+
let length = values.length;
|
|
202
|
+
for (let i = 0; i < length; i++) {
|
|
203
|
+
let value = unchecked(values[i]);
|
|
204
|
+
let reflectedValueID = Reflect.toReflectedValue(value, seen);
|
|
205
|
+
__aspectPushReflectedObjectValue(reflectedObject, reflectedValueID);
|
|
206
|
+
}
|
|
207
|
+
} else if (value instanceof Map) {
|
|
208
|
+
// create a Set reflected object
|
|
209
|
+
let reflectedValue = createReflectedValue(
|
|
210
|
+
false,
|
|
211
|
+
true, // maps have keys
|
|
212
|
+
isNullable<T>(),
|
|
213
|
+
0,
|
|
214
|
+
changetype<usize>(value),
|
|
215
|
+
false,
|
|
216
|
+
value.size,
|
|
217
|
+
ReflectedValueType.Map,
|
|
218
|
+
idof<T>(),
|
|
219
|
+
nameof<T>(),
|
|
220
|
+
0,
|
|
221
|
+
true, // maps have values
|
|
222
|
+
true,
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
// cache this value
|
|
226
|
+
seen.set(changetype<usize>(value), reflectedValue);
|
|
227
|
+
|
|
228
|
+
// loop over each key and push the key value pair to the reflected Map
|
|
229
|
+
let keys = value.keys();
|
|
230
|
+
let length = keys.length;
|
|
231
|
+
for (let i = 0; i < length; i++) {
|
|
232
|
+
let mapKey = unchecked(keys[i]);
|
|
233
|
+
let reflectedKeyID = Reflect.toReflectedValue(mapKey, seen);
|
|
234
|
+
__aspectPushReflectedObjectKey(reflectedValue, reflectedKeyID);
|
|
235
|
+
|
|
236
|
+
let mapValue = value.get(mapKey);
|
|
237
|
+
let reflectedValueID = Reflect.toReflectedValue(mapValue, seen);
|
|
238
|
+
__aspectPushReflectedObjectValue(reflectedValue, reflectedValueID);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return reflectedValue;
|
|
242
|
+
} else if (value instanceof ArrayBufferView) {
|
|
243
|
+
// @ts-ignore: has field
|
|
244
|
+
let length = value.length;
|
|
245
|
+
|
|
246
|
+
// create an arraylike reflected value
|
|
247
|
+
let reflectedValue = createReflectedValue(
|
|
248
|
+
false,
|
|
249
|
+
false, // arrays don't have keys
|
|
250
|
+
isNullable<T>(),
|
|
251
|
+
0,
|
|
252
|
+
changetype<usize>(value),
|
|
253
|
+
false,
|
|
254
|
+
length,
|
|
255
|
+
ReflectedValueType.TypedArray,
|
|
256
|
+
idof<T>(),
|
|
257
|
+
nameof<T>(),
|
|
258
|
+
0,
|
|
259
|
+
true, // maps have values
|
|
260
|
+
isManaged<T>(),
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
// cache this value
|
|
264
|
+
seen.set(changetype<usize>(value), reflectedValue);
|
|
265
|
+
|
|
266
|
+
// loop over each value and push it to the reflected value
|
|
267
|
+
for (let i = 0; i < length; i++) {
|
|
268
|
+
// @ts-ignore index signature is garunteed at this point
|
|
269
|
+
let arrayValue = unchecked(value[i]);
|
|
270
|
+
let reflectedArrayValueID = Reflect.toReflectedValue(
|
|
271
|
+
arrayValue,
|
|
272
|
+
seen,
|
|
273
|
+
);
|
|
274
|
+
__aspectPushReflectedObjectValue(
|
|
275
|
+
reflectedValue,
|
|
276
|
+
reflectedArrayValueID,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return reflectedValue;
|
|
281
|
+
} else if (value instanceof String) {
|
|
282
|
+
let reflectedStringID = createReflectedValue(
|
|
283
|
+
false,
|
|
284
|
+
false,
|
|
285
|
+
isNullable<T>(),
|
|
286
|
+
0,
|
|
287
|
+
changetype<usize>(value),
|
|
288
|
+
false,
|
|
289
|
+
value.length,
|
|
290
|
+
ReflectedValueType.String,
|
|
291
|
+
idof<T>(),
|
|
292
|
+
nameof<T>(),
|
|
293
|
+
changetype<usize>(value),
|
|
294
|
+
false,
|
|
295
|
+
true,
|
|
296
|
+
);
|
|
297
|
+
seen.set(changetype<usize>(value), reflectedStringID);
|
|
298
|
+
return reflectedStringID;
|
|
299
|
+
} else if (isArrayLike<T>()) {
|
|
300
|
+
// @ts-ignore: arraylike has length property
|
|
301
|
+
let length = <i32>value.length;
|
|
302
|
+
|
|
303
|
+
// create an arraylike reflected value
|
|
304
|
+
let reflectedValue = createReflectedValue(
|
|
305
|
+
false,
|
|
306
|
+
false, // arrays don't have keys
|
|
307
|
+
isNullable<T>(),
|
|
308
|
+
0,
|
|
309
|
+
changetype<usize>(value),
|
|
310
|
+
false,
|
|
311
|
+
length,
|
|
312
|
+
ReflectedValueType.Array,
|
|
313
|
+
isManaged<T>() ? idof<T>() : 0,
|
|
314
|
+
nameof<T>(),
|
|
315
|
+
0,
|
|
316
|
+
true, // maps have values
|
|
317
|
+
isManaged<T>(),
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
// cache this value
|
|
321
|
+
seen.set(changetype<usize>(value), reflectedValue);
|
|
322
|
+
|
|
323
|
+
// loop over each array item and push it to the reflected value
|
|
324
|
+
for (let i = 0; i < length; i++) {
|
|
325
|
+
// @ts-ignore: index signature in arraylike
|
|
326
|
+
let arrayValue = unchecked(value[i]);
|
|
327
|
+
let reflectedArrayValueID = Reflect.toReflectedValue(
|
|
328
|
+
arrayValue,
|
|
329
|
+
seen,
|
|
330
|
+
);
|
|
331
|
+
__aspectPushReflectedObjectValue(
|
|
332
|
+
reflectedValue,
|
|
333
|
+
reflectedArrayValueID,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
return reflectedValue;
|
|
337
|
+
} else {
|
|
338
|
+
// generic class
|
|
339
|
+
let reflectedObjectID = createReflectedValue(
|
|
340
|
+
false,
|
|
341
|
+
true, // classes have keys
|
|
342
|
+
isNullable<T>(),
|
|
343
|
+
offsetof<T>(),
|
|
344
|
+
changetype<usize>(value),
|
|
345
|
+
false,
|
|
346
|
+
sizeOf(changetype<usize>(value)),
|
|
347
|
+
ReflectedValueType.Class,
|
|
348
|
+
isManaged<T>() ? idof<T>() : 0,
|
|
349
|
+
nameof<T>(),
|
|
350
|
+
0,
|
|
351
|
+
true, // classes have values
|
|
352
|
+
isManaged<T>(),
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
// cache this object
|
|
356
|
+
seen.set(changetype<usize>(value), reflectedObjectID);
|
|
357
|
+
|
|
358
|
+
// @ts-ignore: __aspectAddReflectedValueKeyValuePairs is auto-generated by the transform
|
|
359
|
+
value.__aspectAddReflectedValueKeyValuePairs(
|
|
360
|
+
reflectedObjectID,
|
|
361
|
+
seen,
|
|
362
|
+
[] as StaticArray<i64>,
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
return reflectedObjectID;
|
|
366
|
+
}
|
|
367
|
+
} else if (alignof<T>() === 3) {
|
|
368
|
+
if (isInteger<T>()) {
|
|
369
|
+
// u64, i64, isize, or usize (when targeting 64 bit WebAssembly)
|
|
370
|
+
// @ts-ignore: value is a number
|
|
371
|
+
let reflectedValue = createReflectedLong(
|
|
372
|
+
isSigned<T>(),
|
|
373
|
+
sizeof<T>(),
|
|
374
|
+
ReflectedValueType.Integer,
|
|
375
|
+
nameof<T>(),
|
|
376
|
+
// @ts-ignore: value is a 64 bit number
|
|
377
|
+
<i32>(value & 0xffffffff),
|
|
378
|
+
// @ts-ignore: value is a 64 bit number
|
|
379
|
+
<i32>(value >>> 32),
|
|
380
|
+
);
|
|
381
|
+
return reflectedValue;
|
|
382
|
+
}
|
|
383
|
+
// float64
|
|
384
|
+
let reflectedValue = createReflectedNumber(
|
|
385
|
+
isSigned<T>(),
|
|
386
|
+
sizeof<T>(),
|
|
387
|
+
ReflectedValueType.Float,
|
|
388
|
+
nameof<T>(),
|
|
389
|
+
// @ts-ignore: type is bool, i32, f64, or f32
|
|
390
|
+
<f64>value,
|
|
391
|
+
);
|
|
392
|
+
return reflectedValue;
|
|
393
|
+
} else {
|
|
394
|
+
// boolean, i32, u32, f32, isize, usize (when targeting 32 bit WebAssembly), or numbers with less bits
|
|
395
|
+
let reflectedValue = createReflectedNumber(
|
|
396
|
+
isSigned<T>(),
|
|
397
|
+
sizeof<T>(),
|
|
398
|
+
isBoolean<T>()
|
|
399
|
+
? ReflectedValueType.Boolean
|
|
400
|
+
: isInteger<T>()
|
|
401
|
+
? ReflectedValueType.Integer
|
|
402
|
+
: ReflectedValueType.Float,
|
|
403
|
+
nameof<T>(),
|
|
404
|
+
// @ts-ignore: type is bool, i32, f64, or f32
|
|
405
|
+
<f64>value,
|
|
406
|
+
);
|
|
407
|
+
return reflectedValue;
|
|
408
|
+
}
|
|
409
|
+
return 0;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
public static equals<T>(
|
|
413
|
+
left: T,
|
|
414
|
+
right: T,
|
|
415
|
+
stack: usize[] = [],
|
|
416
|
+
cache: usize[] = [],
|
|
417
|
+
): i32 {
|
|
418
|
+
// use `==` operator to work with operator overloads and strings
|
|
419
|
+
if (isReference(left)) {
|
|
420
|
+
if (changetype<usize>(left) == changetype<usize>(right)) return Reflect.SUCCESSFUL_MATCH;
|
|
421
|
+
if (isNullable(left)) {
|
|
422
|
+
if(
|
|
423
|
+
i32(changetype<usize>(left) == 0) ^ i32(changetype<usize>(right) == 0)
|
|
424
|
+
) {
|
|
425
|
+
return Reflect.FAILED_MATCH;
|
|
426
|
+
}
|
|
427
|
+
// @ts-expect-error: operator overload check
|
|
428
|
+
if (left! == right!) return Reflect.SUCCESSFUL_MATCH;
|
|
429
|
+
} else {
|
|
430
|
+
if (left == right) return Reflect.SUCCESSFUL_MATCH;
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
if (left == right) return Reflect.SUCCESSFUL_MATCH; // works immutably for string comparison
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// floats should equal each other
|
|
437
|
+
if (isFloat<T>()) {
|
|
438
|
+
if (i32(isNaN(left)) & i32(isNaN(right))) return Reflect.SUCCESSFUL_MATCH;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (isReference<T>()) {
|
|
442
|
+
// T can always be null if it's a reference, emit a runtime check for it regardless of type
|
|
443
|
+
if (
|
|
444
|
+
i32(changetype<usize>(left) == 0) ^ i32(changetype<usize>(right) == 0)
|
|
445
|
+
) {
|
|
446
|
+
return Reflect.FAILED_MATCH;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// check every reference that isn't a function reference
|
|
451
|
+
if (isReference<T>()) {
|
|
452
|
+
if (!isFunction<T>()) {
|
|
453
|
+
if (isNullable<T>()) {
|
|
454
|
+
return referencesEqual(left!, right!, stack, cache);
|
|
455
|
+
} else {
|
|
456
|
+
return referencesEqual(left, right, stack, cache);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
// value type, and strict equality cannot be asserted
|
|
461
|
+
return Reflect.FAILED_MATCH;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
public static attachStackTrace(id: i32): void {
|
|
465
|
+
attachStackTraceToReflectedValue(id);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function referencesEqual<T>(
|
|
470
|
+
left: T,
|
|
471
|
+
right: T,
|
|
472
|
+
stack: usize[],
|
|
473
|
+
cache: usize[],
|
|
474
|
+
): i32 {
|
|
475
|
+
let a = changetype<usize>(left);
|
|
476
|
+
let b = changetype<usize>(right);
|
|
477
|
+
|
|
478
|
+
let cacheLength = cache.length;
|
|
479
|
+
// must be EVEN or there's a big problem
|
|
480
|
+
assert(i32((cacheLength & 0x00000001) == 0), "cacheLength should be even");
|
|
481
|
+
|
|
482
|
+
// short circuit for strings
|
|
483
|
+
if (left instanceof String) {
|
|
484
|
+
return Reflect.FAILED_MATCH;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// check the cache for matched pairs
|
|
488
|
+
for (let i = 0; i < cacheLength; i += 2) {
|
|
489
|
+
if (pairSeen(a, b, unchecked(cache[i]), unchecked(cache[i + 1])))
|
|
490
|
+
return Reflect.SUCCESSFUL_MATCH;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// short circuit because this pair might already be resolving
|
|
494
|
+
let length = stack.length;
|
|
495
|
+
for (let i = 0; i < length; i += 2) {
|
|
496
|
+
if (pairSeen(a, b, unchecked(stack[i]), unchecked(stack[i + 1])))
|
|
497
|
+
return Reflect.DEFER_MATCH;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// once we've determined we need to check the references for their values, arraybuffers
|
|
501
|
+
// require a memory compare
|
|
502
|
+
if (left instanceof ArrayBuffer) {
|
|
503
|
+
// @ts-ignore: typesafe access to byteLength property because T is ArrayBuffer
|
|
504
|
+
if (left.byteLength != right.byteLength) return Reflect.FAILED_MATCH;
|
|
505
|
+
let result = memory.compare(a, b, left.byteLength);
|
|
506
|
+
if (result == 0) {
|
|
507
|
+
cache.push(a);
|
|
508
|
+
cache.push(b);
|
|
509
|
+
return Reflect.SUCCESSFUL_MATCH;
|
|
510
|
+
} else return Reflect.FAILED_MATCH;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// @ts-ignore: valid index signature check
|
|
514
|
+
if (isDefined(left[0])) {
|
|
515
|
+
// test for safe indexof usage
|
|
516
|
+
// set match
|
|
517
|
+
if (left instanceof Set) {
|
|
518
|
+
// @ts-ignore: size is a valid property of Set
|
|
519
|
+
if (left.size != right.size) return Reflect.FAILED_MATCH;
|
|
520
|
+
stack.push(a);
|
|
521
|
+
stack.push(b);
|
|
522
|
+
// @ts-ignore: values() is a valid function of Set
|
|
523
|
+
let leftValues = left.values();
|
|
524
|
+
// @ts-ignore: values() is a valid function of Set
|
|
525
|
+
let rightValues = right.values();
|
|
526
|
+
let length = leftValues.length;
|
|
527
|
+
let leftoverLength = length;
|
|
528
|
+
for (let i = 0; i < length; i++) {
|
|
529
|
+
let leftItem = unchecked(leftValues[i]);
|
|
530
|
+
let continueOuter = false;
|
|
531
|
+
for (let j = 0; j < leftoverLength; j++) {
|
|
532
|
+
let rightItem = unchecked(rightValues[j]);
|
|
533
|
+
if (
|
|
534
|
+
Reflect.equals(leftItem, rightItem, stack, cache) !=
|
|
535
|
+
Reflect.FAILED_MATCH
|
|
536
|
+
) {
|
|
537
|
+
rightValues.splice(j, 1);
|
|
538
|
+
leftoverLength--;
|
|
539
|
+
continueOuter = true;
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
if (continueOuter) continue;
|
|
544
|
+
|
|
545
|
+
stack.pop();
|
|
546
|
+
stack.pop();
|
|
547
|
+
return Reflect.FAILED_MATCH;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
cache.push(a);
|
|
551
|
+
cache.push(b);
|
|
552
|
+
|
|
553
|
+
stack.pop();
|
|
554
|
+
stack.pop();
|
|
555
|
+
return Reflect.SUCCESSFUL_MATCH;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
if (left instanceof Map) {
|
|
559
|
+
// @ts-ignore: size is a valid property of Map
|
|
560
|
+
if (left.size != right.size) return Reflect.FAILED_MATCH;
|
|
561
|
+
stack.push(a);
|
|
562
|
+
stack.push(b);
|
|
563
|
+
|
|
564
|
+
// collect all the keys and loop over each one
|
|
565
|
+
let leftKeys = left.keys();
|
|
566
|
+
// @ts-ignore: keys() is a valid function of Map
|
|
567
|
+
let rightKeys = right.keys();
|
|
568
|
+
|
|
569
|
+
// @ts-ignore: length is a valid property of Array
|
|
570
|
+
let keyLength = leftKeys.length;
|
|
571
|
+
let leftoverKeyLength = keyLength;
|
|
572
|
+
|
|
573
|
+
// assume we match and determine if the match was a failure
|
|
574
|
+
let result = Reflect.SUCCESSFUL_MATCH;
|
|
575
|
+
|
|
576
|
+
// for each key
|
|
577
|
+
for (let i = 0; i < keyLength; i++) {
|
|
578
|
+
let leftKey = unchecked(leftKeys[i]);
|
|
579
|
+
// assume won't find it
|
|
580
|
+
let found = false;
|
|
581
|
+
|
|
582
|
+
// find a matching key
|
|
583
|
+
for (let j = 0; j < leftoverKeyLength; j++) {
|
|
584
|
+
let rightKey = unchecked(rightKeys[j]);
|
|
585
|
+
|
|
586
|
+
// if the keys match, or are still being resolved
|
|
587
|
+
if (
|
|
588
|
+
Reflect.equals(leftKey, rightKey, stack, cache) !=
|
|
589
|
+
Reflect.FAILED_MATCH
|
|
590
|
+
) {
|
|
591
|
+
// the key potentially matches, obtain the values associated with the keys
|
|
592
|
+
let leftValue = left.get(leftKey);
|
|
593
|
+
// @ts-ignore: get() is a valid function of Map
|
|
594
|
+
let rightValue = right.get(rightKey);
|
|
595
|
+
|
|
596
|
+
// if the values match, or are still being resolved
|
|
597
|
+
if (
|
|
598
|
+
Reflect.equals(leftValue, rightValue, stack, cache) !=
|
|
599
|
+
Reflect.FAILED_MATCH
|
|
600
|
+
) {
|
|
601
|
+
leftoverKeyLength--;
|
|
602
|
+
rightKeys.splice(j, 1); // remove this key from the list
|
|
603
|
+
found = true;
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// if there was no match for this key value pair, the result is Failed
|
|
610
|
+
if (!found) {
|
|
611
|
+
result = Reflect.FAILED_MATCH;
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// if every key matched, result is still equal to `Reflect.MATCH`
|
|
617
|
+
if (result == Reflect.SUCCESSFUL_MATCH) {
|
|
618
|
+
cache.push(a);
|
|
619
|
+
cache.push(b);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
stack.pop();
|
|
623
|
+
stack.pop();
|
|
624
|
+
return result;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// compile time array values should be compared over a for loop
|
|
628
|
+
// @ts-ignore: typesafe access to length
|
|
629
|
+
if (isDefined(left.length)) {
|
|
630
|
+
// @ts-ignore: typesafe access to length
|
|
631
|
+
let aLength = left.length;
|
|
632
|
+
// @ts-ignore: typesafe access to length
|
|
633
|
+
let bLength = right.length;
|
|
634
|
+
|
|
635
|
+
// assert the lengths are good
|
|
636
|
+
if (aLength != bLength) return Reflect.FAILED_MATCH;
|
|
637
|
+
|
|
638
|
+
// check each item
|
|
639
|
+
for (let i = 0; i < aLength; i++) {
|
|
640
|
+
let result = Reflect.equals(
|
|
641
|
+
// @ts-ignore: typesafe and runtime check safe array access
|
|
642
|
+
unchecked(left[i]),
|
|
643
|
+
// @ts-ignore: typesafe and runtime check safe array access
|
|
644
|
+
unchecked(right[i]),
|
|
645
|
+
stack,
|
|
646
|
+
cache,
|
|
647
|
+
);
|
|
648
|
+
if (result == Reflect.FAILED_MATCH) return Reflect.FAILED_MATCH;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// cache this result
|
|
652
|
+
cache.push(a);
|
|
653
|
+
cache.push(b);
|
|
654
|
+
|
|
655
|
+
return Reflect.SUCCESSFUL_MATCH;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// todo: handle Set<keyof<T>> and Map<keyof<T>, valueof<T>>
|
|
660
|
+
|
|
661
|
+
// we are trying to resolve this pair, push it to the stack
|
|
662
|
+
stack.push(a);
|
|
663
|
+
stack.push(b);
|
|
664
|
+
|
|
665
|
+
let result = false;
|
|
666
|
+
if (isNullable(left)) {
|
|
667
|
+
// @ts-ignore: __aspectStrictEquals is defined at this point
|
|
668
|
+
result = left!.__aspectStrictEquals(
|
|
669
|
+
right,
|
|
670
|
+
stack,
|
|
671
|
+
cache,
|
|
672
|
+
[] as StaticArray<i64>,
|
|
673
|
+
);
|
|
674
|
+
} else {
|
|
675
|
+
// @ts-ignore: __aspectStrictEquals is defined at this point
|
|
676
|
+
result = left.__aspectStrictEquals(
|
|
677
|
+
right,
|
|
678
|
+
stack,
|
|
679
|
+
cache,
|
|
680
|
+
[] as StaticArray<i64>,
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
if (result) {
|
|
685
|
+
cache.push(a);
|
|
686
|
+
cache.push(b);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
stack.pop();
|
|
690
|
+
stack.pop();
|
|
691
|
+
return select(Reflect.SUCCESSFUL_MATCH, Reflect.FAILED_MATCH, result);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
export namespace Reflect {
|
|
695
|
+
export const FAILED_MATCH = 0;
|
|
696
|
+
export const SUCCESSFUL_MATCH = 1;
|
|
697
|
+
export const DEFER_MATCH = 2;
|
|
698
|
+
}
|