@alloy-js/core 0.11.0 → 0.12.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/CHANGELOG.md +15 -0
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +67 -17
- package/dist/src/components/For.d.ts +1 -1
- package/dist/src/components/For.d.ts.map +1 -1
- package/dist/src/jsx-runtime.d.ts.map +1 -1
- package/dist/src/jsx-runtime.js +9 -3
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +5 -0
- package/dist/src/scheduler.d.ts +8 -0
- package/dist/src/scheduler.d.ts.map +1 -0
- package/dist/src/scheduler.js +17 -0
- package/dist/test/components/declaration.test.js +2 -0
- package/dist/test/control-flow/for.test.js +36 -2
- package/dist/test/reactivity/circular-reactives.test.d.ts +2 -0
- package/dist/test/reactivity/circular-reactives.test.d.ts.map +1 -0
- package/dist/test/reactivity/circular-reactives.test.js +31 -0
- package/dist/test/reactivity/cleanup.test.js +5 -0
- package/dist/test/reactivity/untrack.test.js +3 -0
- package/dist/test/rendering/memoization.test.js +2 -0
- package/dist/test/symbols.test.js +384 -11
- package/dist/test/utils.test.d.ts.map +1 -1
- package/dist/test/utils.test.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/binder.ts +100 -17
- package/src/components/For.tsx +4 -4
- package/src/jsx-runtime.ts +22 -12
- package/src/render.ts +5 -0
- package/src/scheduler.ts +24 -0
- package/temp/api.json +8 -8
- package/test/components/declaration.test.tsx +2 -0
- package/test/components/list.test.tsx +0 -1
- package/test/control-flow/for.test.tsx +34 -4
- package/test/reactivity/circular-reactives.test.tsx +32 -0
- package/test/reactivity/cleanup.test.tsx +5 -0
- package/test/reactivity/untrack.test.ts +3 -0
- package/test/rendering/memoization.test.tsx +2 -0
- package/test/symbols.test.ts +392 -13
- package/test/utils.test.tsx +2 -0
package/test/symbols.test.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
OutputSymbolFlags,
|
|
9
9
|
} from "../src/binder.js";
|
|
10
10
|
import { Refkey, refkey } from "../src/refkey.js";
|
|
11
|
+
import { flushJobs } from "../src/scheduler.js";
|
|
11
12
|
|
|
12
13
|
it("works", () => {
|
|
13
14
|
const binder = createOutputBinder();
|
|
@@ -22,10 +23,11 @@ it("works", () => {
|
|
|
22
23
|
scope,
|
|
23
24
|
});
|
|
24
25
|
|
|
26
|
+
flushJobs();
|
|
25
27
|
expect([...scope.getSymbolNames()]).toEqual(["sym"]);
|
|
26
28
|
|
|
27
29
|
symbol.name = "bar";
|
|
28
|
-
|
|
30
|
+
flushJobs();
|
|
29
31
|
expect([...scope.getSymbolNames()]).toEqual(["bar"]);
|
|
30
32
|
});
|
|
31
33
|
|
|
@@ -299,8 +301,25 @@ describe("instance members", () => {
|
|
|
299
301
|
});
|
|
300
302
|
|
|
301
303
|
describe("instantiating members", () => {
|
|
302
|
-
it("instantiates
|
|
304
|
+
it("instantiates instance members", () => {
|
|
303
305
|
const binder = createOutputBinder();
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* The following structure would match code like this:
|
|
309
|
+
* ```ts
|
|
310
|
+
* // A class with instance members
|
|
311
|
+
* class Source {
|
|
312
|
+
* instance() {
|
|
313
|
+
* print("instance");
|
|
314
|
+
* }
|
|
315
|
+
* }
|
|
316
|
+
*
|
|
317
|
+
* // Instantiates into t
|
|
318
|
+
* var t = new Source();
|
|
319
|
+
*
|
|
320
|
+
* t.instance();
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
304
323
|
const {
|
|
305
324
|
symbols: { rootSymbol, instance, instantiation },
|
|
306
325
|
} = createScopeTree(binder, {
|
|
@@ -310,7 +329,7 @@ describe("instantiating members", () => {
|
|
|
310
329
|
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
311
330
|
instanceMembers: {
|
|
312
331
|
instance: {
|
|
313
|
-
flags: OutputSymbolFlags.
|
|
332
|
+
flags: OutputSymbolFlags.InstanceMember,
|
|
314
333
|
},
|
|
315
334
|
},
|
|
316
335
|
},
|
|
@@ -321,20 +340,107 @@ describe("instantiating members", () => {
|
|
|
321
340
|
|
|
322
341
|
binder.instantiateSymbolInto(rootSymbol, instantiation);
|
|
323
342
|
expect(
|
|
324
|
-
instantiation.flags & OutputSymbolFlags.
|
|
343
|
+
instantiation.flags & OutputSymbolFlags.StaticMemberContainer,
|
|
325
344
|
).toBeTruthy();
|
|
326
|
-
expect(instantiation.
|
|
345
|
+
expect(instantiation.staticMemberScope).toBeDefined();
|
|
327
346
|
const expectedRefkey = refkey(
|
|
328
347
|
instantiation.refkeys[0],
|
|
329
348
|
instance.refkeys[0],
|
|
330
349
|
);
|
|
331
350
|
expect(
|
|
332
|
-
instantiation.
|
|
351
|
+
instantiation.staticMemberScope!.symbolsByRefkey.get(expectedRefkey),
|
|
333
352
|
).toBeDefined();
|
|
334
353
|
});
|
|
335
354
|
|
|
336
|
-
it("
|
|
355
|
+
it("doesn't duplicate symbols", () => {
|
|
356
|
+
const binder = createOutputBinder();
|
|
357
|
+
|
|
358
|
+
const {
|
|
359
|
+
symbols: { rootSymbol, instantiation },
|
|
360
|
+
} = createScopeTree(binder, {
|
|
361
|
+
rootScope: {
|
|
362
|
+
symbols: {
|
|
363
|
+
rootSymbol: {
|
|
364
|
+
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
365
|
+
instanceMembers: {
|
|
366
|
+
instance: {
|
|
367
|
+
flags: OutputSymbolFlags.InstanceMember,
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
instantiation: {},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
binder.instantiateSymbolInto(rootSymbol, instantiation);
|
|
377
|
+
flushJobs();
|
|
378
|
+
expect(instantiation.staticMemberScope!.symbols.size).toBe(1);
|
|
379
|
+
|
|
380
|
+
const lateKey = refkey();
|
|
381
|
+
// now add a brand‐new static member to source
|
|
382
|
+
binder.createSymbol({
|
|
383
|
+
name: "lateChild",
|
|
384
|
+
scope: rootSymbol.instanceMemberScope!,
|
|
385
|
+
refkey: lateKey,
|
|
386
|
+
flags: OutputSymbolFlags.InstanceMember,
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
flushJobs();
|
|
390
|
+
|
|
391
|
+
expect(rootSymbol.instanceMemberScope!.symbols.size).toBe(2);
|
|
392
|
+
expect(instantiation.staticMemberScope!.symbols.size).toBe(2);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it("should remove members in instance when source deleted them", () => {
|
|
396
|
+
const binder = createOutputBinder();
|
|
397
|
+
|
|
398
|
+
const {
|
|
399
|
+
symbols: { rootSymbol, instantiation },
|
|
400
|
+
} = createScopeTree(binder, {
|
|
401
|
+
rootScope: {
|
|
402
|
+
symbols: {
|
|
403
|
+
rootSymbol: {
|
|
404
|
+
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
405
|
+
instanceMembers: {
|
|
406
|
+
instance: {
|
|
407
|
+
flags: OutputSymbolFlags.InstanceMember,
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
instantiation: {},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
binder.instantiateSymbolInto(rootSymbol, instantiation);
|
|
417
|
+
expect(instantiation.staticMemberScope!.symbols.size).toBe(1);
|
|
418
|
+
|
|
419
|
+
const lateKey = refkey();
|
|
420
|
+
// now add a brand‐new static member to source
|
|
421
|
+
binder.createSymbol({
|
|
422
|
+
name: "lateChild",
|
|
423
|
+
scope: rootSymbol.instanceMemberScope!,
|
|
424
|
+
refkey: lateKey,
|
|
425
|
+
flags: OutputSymbolFlags.InstanceMember,
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
flushJobs();
|
|
429
|
+
|
|
430
|
+
expect(rootSymbol.instanceMemberScope!.symbols.size).toBe(2);
|
|
431
|
+
expect(instantiation.staticMemberScope!.symbols.size).toBe(2);
|
|
432
|
+
|
|
433
|
+
binder.deleteSymbol(
|
|
434
|
+
rootSymbol.instanceMemberScope!.symbols.values().next().value!,
|
|
435
|
+
);
|
|
436
|
+
flushJobs();
|
|
437
|
+
expect(rootSymbol.instanceMemberScope!.symbols.size).toBe(1);
|
|
438
|
+
expect(instantiation.staticMemberScope!.symbols.size).toBe(1);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it("instantiates instance members added after the instantiation", () => {
|
|
337
442
|
const binder = createOutputBinder();
|
|
443
|
+
|
|
338
444
|
const {
|
|
339
445
|
symbols: { rootSymbol, instance, instantiation },
|
|
340
446
|
} = createScopeTree(binder, {
|
|
@@ -344,7 +450,7 @@ describe("instantiating members", () => {
|
|
|
344
450
|
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
345
451
|
instanceMembers: {
|
|
346
452
|
instance: {
|
|
347
|
-
flags: OutputSymbolFlags.
|
|
453
|
+
flags: OutputSymbolFlags.InstanceMember,
|
|
348
454
|
},
|
|
349
455
|
},
|
|
350
456
|
},
|
|
@@ -354,16 +460,17 @@ describe("instantiating members", () => {
|
|
|
354
460
|
});
|
|
355
461
|
|
|
356
462
|
binder.instantiateSymbolInto(rootSymbol, instantiation);
|
|
463
|
+
flushJobs();
|
|
357
464
|
expect(
|
|
358
|
-
instantiation.flags & OutputSymbolFlags.
|
|
465
|
+
instantiation.flags & OutputSymbolFlags.StaticMemberContainer,
|
|
359
466
|
).toBeTruthy();
|
|
360
|
-
expect(instantiation.
|
|
467
|
+
expect(instantiation.staticMemberScope).toBeDefined();
|
|
361
468
|
const expectedRefkey = refkey(
|
|
362
469
|
instantiation.refkeys[0],
|
|
363
470
|
instance.refkeys[0],
|
|
364
471
|
);
|
|
365
472
|
expect(
|
|
366
|
-
instantiation.
|
|
473
|
+
instantiation.staticMemberScope!.symbolsByRefkey.get(expectedRefkey),
|
|
367
474
|
).toBeDefined();
|
|
368
475
|
|
|
369
476
|
const newInstanceMemberRefkey = refkey();
|
|
@@ -377,10 +484,280 @@ describe("instantiating members", () => {
|
|
|
377
484
|
instantiation.refkeys[0],
|
|
378
485
|
newInstanceMemberRefkey,
|
|
379
486
|
);
|
|
487
|
+
flushJobs();
|
|
488
|
+
expect(
|
|
489
|
+
instantiation.staticMemberScope!.symbolsByRefkey.get(newExpectedRefkey),
|
|
490
|
+
).toBeDefined();
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it("instantiates static symbols for a static container source", () => {
|
|
494
|
+
const binder = createOutputBinder();
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* The following structure would match code like this:
|
|
498
|
+
* ```ts
|
|
499
|
+
* // A class with instance members
|
|
500
|
+
* class Source {
|
|
501
|
+
* static child() {
|
|
502
|
+
* print("child");
|
|
503
|
+
* }
|
|
504
|
+
* }
|
|
505
|
+
*
|
|
506
|
+
*
|
|
507
|
+
* var printChild = Source.child;
|
|
508
|
+
*
|
|
509
|
+
* printChild();
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
const {
|
|
513
|
+
symbols: { source, child, target },
|
|
514
|
+
} = createScopeTree(binder, {
|
|
515
|
+
root: {
|
|
516
|
+
symbols: {
|
|
517
|
+
source: {
|
|
518
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
519
|
+
staticMembers: {
|
|
520
|
+
child: { flags: OutputSymbolFlags.StaticMember },
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
target: {},
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
binder.instantiateSymbolInto(source, target);
|
|
529
|
+
|
|
530
|
+
// target must now be a StaticMemberContainer too
|
|
531
|
+
expect(target.flags & OutputSymbolFlags.StaticMemberContainer).toBeTruthy();
|
|
532
|
+
expect(target.staticMemberScope).toBeDefined();
|
|
533
|
+
|
|
534
|
+
const expectedKey = refkey(target.refkeys[0], child.refkeys[0]);
|
|
380
535
|
expect(
|
|
381
|
-
|
|
536
|
+
target.staticMemberScope!.symbolsByRefkey.get(expectedKey),
|
|
382
537
|
).toBeDefined();
|
|
383
538
|
});
|
|
539
|
+
|
|
540
|
+
it("instantiates static symbols added after instantiation", () => {
|
|
541
|
+
const binder = createOutputBinder();
|
|
542
|
+
const lateKey = refkey();
|
|
543
|
+
|
|
544
|
+
const {
|
|
545
|
+
symbols: { source, target },
|
|
546
|
+
} = createScopeTree(binder, {
|
|
547
|
+
root: {
|
|
548
|
+
symbols: {
|
|
549
|
+
source: {
|
|
550
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
551
|
+
},
|
|
552
|
+
target: {},
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
// hook up instantiation
|
|
558
|
+
binder.instantiateSymbolInto(source, target);
|
|
559
|
+
|
|
560
|
+
// now add a brand‐new static member to source
|
|
561
|
+
const late = binder.createSymbol({
|
|
562
|
+
name: "lateChild",
|
|
563
|
+
scope: source.staticMemberScope!,
|
|
564
|
+
refkey: lateKey,
|
|
565
|
+
flags: OutputSymbolFlags.StaticMember,
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
flushJobs();
|
|
569
|
+
|
|
570
|
+
// it should *automatically* show up on target.staticMemberScope
|
|
571
|
+
const expectedKey = refkey(target.refkeys[0], late.refkeys[0]);
|
|
572
|
+
expect(
|
|
573
|
+
target.staticMemberScope!.symbolsByRefkey.get(expectedKey),
|
|
574
|
+
).toBeDefined();
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
it("recursively instantiates nested static members", () => {
|
|
578
|
+
const binder = createOutputBinder();
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* The following structure would match code like this:
|
|
582
|
+
* ```ts
|
|
583
|
+
* class Source {
|
|
584
|
+
* static Level1 = class {
|
|
585
|
+
* static level2() { print("deep"); }
|
|
586
|
+
* }
|
|
587
|
+
* }
|
|
588
|
+
*
|
|
589
|
+
* var target = Source;
|
|
590
|
+
*
|
|
591
|
+
* target.Level1.level2()
|
|
592
|
+
* ```
|
|
593
|
+
*/
|
|
594
|
+
const {
|
|
595
|
+
symbols: { source, level1, level2, target },
|
|
596
|
+
} = createScopeTree(binder, {
|
|
597
|
+
root: {
|
|
598
|
+
symbols: {
|
|
599
|
+
source: {
|
|
600
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
601
|
+
staticMembers: {
|
|
602
|
+
level1: {
|
|
603
|
+
flags:
|
|
604
|
+
OutputSymbolFlags.StaticMember |
|
|
605
|
+
OutputSymbolFlags.StaticMemberContainer,
|
|
606
|
+
staticMembers: {
|
|
607
|
+
level2: { flags: OutputSymbolFlags.StaticMember },
|
|
608
|
+
},
|
|
609
|
+
},
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
target: {},
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
binder.instantiateSymbolInto(source, target);
|
|
618
|
+
|
|
619
|
+
// level1 should appear under target.staticMemberScope
|
|
620
|
+
const key1 = refkey(target.refkeys[0], level1.refkeys[0]);
|
|
621
|
+
const instantiated1 = target.staticMemberScope!.symbolsByRefkey.get(key1)!;
|
|
622
|
+
expect(instantiated1.name).toBe(level1.name);
|
|
623
|
+
|
|
624
|
+
// and level2 should appear under the *child* staticMemberScope of that instantiated level1
|
|
625
|
+
const childScope = instantiated1.staticMemberScope!;
|
|
626
|
+
const key2 = refkey(instantiated1.refkeys[0], level2.refkeys[0]);
|
|
627
|
+
expect(childScope.symbolsByRefkey.get(key2)).toBeDefined();
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it("copies both instance *and* static members when source has both flags", () => {
|
|
631
|
+
const binder = createOutputBinder();
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* ```ts
|
|
635
|
+
* class Source {
|
|
636
|
+
* instance() { print("inst"); }
|
|
637
|
+
* static s1() { print("static"); }
|
|
638
|
+
* }
|
|
639
|
+
*
|
|
640
|
+
* let t = new Source()
|
|
641
|
+
* t.instance()
|
|
642
|
+
* t.s1()
|
|
643
|
+
* ```
|
|
644
|
+
*/
|
|
645
|
+
const {
|
|
646
|
+
symbols: { source, inst },
|
|
647
|
+
} = createScopeTree(binder, {
|
|
648
|
+
root: {
|
|
649
|
+
symbols: {
|
|
650
|
+
source: {
|
|
651
|
+
flags:
|
|
652
|
+
OutputSymbolFlags.InstanceMemberContainer |
|
|
653
|
+
OutputSymbolFlags.StaticMemberContainer,
|
|
654
|
+
instanceMembers: {
|
|
655
|
+
i1: { flags: OutputSymbolFlags.InstanceMember },
|
|
656
|
+
},
|
|
657
|
+
staticMembers: {
|
|
658
|
+
s1: { flags: OutputSymbolFlags.StaticMember },
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
inst: {},
|
|
662
|
+
},
|
|
663
|
+
},
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
binder.instantiateSymbolInto(source, inst);
|
|
667
|
+
|
|
668
|
+
expect(inst.staticMemberScope).toBeDefined();
|
|
669
|
+
expect(
|
|
670
|
+
[...inst.staticMemberScope!.symbols].some((s) => s.name === "i1"),
|
|
671
|
+
).toBe(true);
|
|
672
|
+
|
|
673
|
+
// static side
|
|
674
|
+
const symbols = [...source.staticMemberScope!.symbols];
|
|
675
|
+
expect(inst.staticMemberScope).toBeDefined();
|
|
676
|
+
const sKey = refkey(inst.refkeys[0], symbols[0].refkeys[0]);
|
|
677
|
+
expect(inst.staticMemberScope!.symbolsByRefkey.has(sKey)).toBe(true);
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
it("is idempotent, calling twice does not duplicate", () => {
|
|
681
|
+
const binder = createOutputBinder();
|
|
682
|
+
const {
|
|
683
|
+
symbols: { source, target },
|
|
684
|
+
} = createScopeTree(binder, {
|
|
685
|
+
root: {
|
|
686
|
+
symbols: {
|
|
687
|
+
source: {
|
|
688
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
689
|
+
staticMembers: {
|
|
690
|
+
a: { flags: OutputSymbolFlags.StaticMember },
|
|
691
|
+
},
|
|
692
|
+
},
|
|
693
|
+
target: {},
|
|
694
|
+
},
|
|
695
|
+
},
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
binder.instantiateSymbolInto(source, target);
|
|
699
|
+
flushJobs();
|
|
700
|
+
const initialCount = target.staticMemberScope!.symbols.size;
|
|
701
|
+
binder.instantiateSymbolInto(source, target);
|
|
702
|
+
flushJobs();
|
|
703
|
+
expect(target.staticMemberScope!.symbols.size).toBe(initialCount);
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
it("instantiates static children of instance members under the instance scope", () => {
|
|
707
|
+
const binder = createOutputBinder();
|
|
708
|
+
/**
|
|
709
|
+
* ```ts
|
|
710
|
+
* class Source {
|
|
711
|
+
* instM = class {
|
|
712
|
+
* static deep() { print("deep"); }
|
|
713
|
+
* }
|
|
714
|
+
* }
|
|
715
|
+
*
|
|
716
|
+
* var t = new Source();
|
|
717
|
+
* t.instM.deep();
|
|
718
|
+
* ```
|
|
719
|
+
*/
|
|
720
|
+
const {
|
|
721
|
+
symbols: { source, deep, target },
|
|
722
|
+
} = createScopeTree(binder, {
|
|
723
|
+
root: {
|
|
724
|
+
symbols: {
|
|
725
|
+
source: {
|
|
726
|
+
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
727
|
+
instanceMembers: {
|
|
728
|
+
instM: {
|
|
729
|
+
flags:
|
|
730
|
+
OutputSymbolFlags.InstanceMember |
|
|
731
|
+
OutputSymbolFlags.StaticMemberContainer,
|
|
732
|
+
staticMembers: {
|
|
733
|
+
deep: { flags: OutputSymbolFlags.StaticMember },
|
|
734
|
+
},
|
|
735
|
+
},
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
target: {},
|
|
739
|
+
},
|
|
740
|
+
},
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
binder.instantiateSymbolInto(source, target);
|
|
744
|
+
|
|
745
|
+
// Find the instantiated copy of instM under target.instanceMemberScope
|
|
746
|
+
const instMSym = [...target.staticMemberScope!.symbols].find(
|
|
747
|
+
(s) => s.name === "instM",
|
|
748
|
+
)!;
|
|
749
|
+
|
|
750
|
+
// instMSym should have gotten its own staticMemberScope via the StaticMemberContainer flag
|
|
751
|
+
expect(instMSym.staticMemberScope).toBeDefined();
|
|
752
|
+
|
|
753
|
+
// compute the expected key for the deep child:
|
|
754
|
+
// (<target>, <instM>) then (on that) (<deep original>)
|
|
755
|
+
const expectedDeepKey = refkey(instMSym.refkeys[0], deep.refkeys[0]);
|
|
756
|
+
|
|
757
|
+
expect(
|
|
758
|
+
instMSym.staticMemberScope!.symbolsByRefkey.has(expectedDeepKey),
|
|
759
|
+
).toBe(true);
|
|
760
|
+
});
|
|
384
761
|
});
|
|
385
762
|
|
|
386
763
|
describe("symbol name resolution", () => {
|
|
@@ -540,6 +917,7 @@ describe("refkey resolution", () => {
|
|
|
540
917
|
expect(resolvedSym.value).toBe(undefined);
|
|
541
918
|
|
|
542
919
|
sym.refkeys[0] = key;
|
|
920
|
+
flushJobs();
|
|
543
921
|
expect(resolvedSym.value?.targetDeclaration).toBe(sym);
|
|
544
922
|
});
|
|
545
923
|
});
|
|
@@ -563,10 +941,11 @@ describe("Deleting symbols", () => {
|
|
|
563
941
|
expect(resolvedSym.value).toBe(undefined);
|
|
564
942
|
|
|
565
943
|
sym.refkeys[0] = key;
|
|
944
|
+
flushJobs();
|
|
566
945
|
expect(resolvedSym.value?.targetDeclaration).toBe(sym);
|
|
567
946
|
|
|
568
947
|
binder.deleteSymbol(sym);
|
|
569
|
-
|
|
948
|
+
flushJobs();
|
|
570
949
|
expect(resolvedSym.value).toBe(undefined);
|
|
571
950
|
});
|
|
572
951
|
|
package/test/utils.test.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { Children } from "@alloy-js/core/jsx-runtime";
|
|
|
2
2
|
import { computed, ref, triggerRef } from "@vue/reactivity";
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
4
|
import { renderTree } from "../src/render.js";
|
|
5
|
+
import { flushJobs } from "../src/scheduler.js";
|
|
5
6
|
import { children, join, mapJoin } from "../src/utils.js";
|
|
6
7
|
import "../testing/extend-expect.js";
|
|
7
8
|
|
|
@@ -93,6 +94,7 @@ describe("mapJoin", () => {
|
|
|
93
94
|
expect(callCount).toBe(2);
|
|
94
95
|
arr.value.push(3);
|
|
95
96
|
triggerRef(arr);
|
|
97
|
+
flushJobs();
|
|
96
98
|
expect(callCount).toBe(3);
|
|
97
99
|
});
|
|
98
100
|
it("can map a joiner", () => {
|