@alloy-js/core 0.11.0 → 0.13.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 +22 -0
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +79 -22
- 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 +391 -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 +3 -3
- package/src/binder.ts +116 -22
- 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 +401 -13
- package/test/utils.test.tsx +2 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
import { createOutputBinder, OutputScopeFlags, OutputSymbolFlags } from "../src/binder.js";
|
|
3
3
|
import { refkey } from "../src/refkey.js";
|
|
4
|
+
import { flushJobs } from "../src/scheduler.js";
|
|
4
5
|
it("works", () => {
|
|
5
6
|
const binder = createOutputBinder();
|
|
6
7
|
const scope = binder.createScope({
|
|
@@ -12,8 +13,10 @@ it("works", () => {
|
|
|
12
13
|
name: "sym",
|
|
13
14
|
scope
|
|
14
15
|
});
|
|
16
|
+
flushJobs();
|
|
15
17
|
expect([...scope.getSymbolNames()]).toEqual(["sym"]);
|
|
16
18
|
symbol.name = "bar";
|
|
19
|
+
flushJobs();
|
|
17
20
|
expect([...scope.getSymbolNames()]).toEqual(["bar"]);
|
|
18
21
|
});
|
|
19
22
|
it("resolves symbol conflicts", () => {
|
|
@@ -31,7 +34,14 @@ it("resolves symbol conflicts", () => {
|
|
|
31
34
|
name: "sym",
|
|
32
35
|
scope
|
|
33
36
|
});
|
|
37
|
+
const s3 = binder.createSymbol({
|
|
38
|
+
name: "sym",
|
|
39
|
+
scope
|
|
40
|
+
});
|
|
41
|
+
flushJobs();
|
|
42
|
+
expect(_s1.name).toEqual("sym");
|
|
34
43
|
expect(s2.name).toEqual("sym_2");
|
|
44
|
+
expect(s3.name).toEqual("sym_3");
|
|
35
45
|
});
|
|
36
46
|
function createScopeTree(binder, tree) {
|
|
37
47
|
const createdItems = {
|
|
@@ -242,8 +252,25 @@ describe("instance members", () => {
|
|
|
242
252
|
});
|
|
243
253
|
});
|
|
244
254
|
describe("instantiating members", () => {
|
|
245
|
-
it("instantiates
|
|
255
|
+
it("instantiates instance members", () => {
|
|
246
256
|
const binder = createOutputBinder();
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* The following structure would match code like this:
|
|
260
|
+
* ```ts
|
|
261
|
+
* // A class with instance members
|
|
262
|
+
* class Source {
|
|
263
|
+
* instance() {
|
|
264
|
+
* print("instance");
|
|
265
|
+
* }
|
|
266
|
+
* }
|
|
267
|
+
*
|
|
268
|
+
* // Instantiates into t
|
|
269
|
+
* var t = new Source();
|
|
270
|
+
*
|
|
271
|
+
* t.instance();
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
247
274
|
const {
|
|
248
275
|
symbols: {
|
|
249
276
|
rootSymbol,
|
|
@@ -257,7 +284,7 @@ describe("instantiating members", () => {
|
|
|
257
284
|
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
258
285
|
instanceMembers: {
|
|
259
286
|
instance: {
|
|
260
|
-
flags: OutputSymbolFlags.
|
|
287
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
261
288
|
}
|
|
262
289
|
}
|
|
263
290
|
},
|
|
@@ -266,12 +293,89 @@ describe("instantiating members", () => {
|
|
|
266
293
|
}
|
|
267
294
|
});
|
|
268
295
|
binder.instantiateSymbolInto(rootSymbol, instantiation);
|
|
269
|
-
expect(instantiation.flags & OutputSymbolFlags.
|
|
270
|
-
expect(instantiation.
|
|
296
|
+
expect(instantiation.flags & OutputSymbolFlags.StaticMemberContainer).toBeTruthy();
|
|
297
|
+
expect(instantiation.staticMemberScope).toBeDefined();
|
|
271
298
|
const expectedRefkey = refkey(instantiation.refkeys[0], instance.refkeys[0]);
|
|
272
|
-
expect(instantiation.
|
|
299
|
+
expect(instantiation.staticMemberScope.symbolsByRefkey.get(expectedRefkey)).toBeDefined();
|
|
300
|
+
});
|
|
301
|
+
it("doesn't duplicate symbols", () => {
|
|
302
|
+
const binder = createOutputBinder();
|
|
303
|
+
const {
|
|
304
|
+
symbols: {
|
|
305
|
+
rootSymbol,
|
|
306
|
+
instantiation
|
|
307
|
+
}
|
|
308
|
+
} = createScopeTree(binder, {
|
|
309
|
+
rootScope: {
|
|
310
|
+
symbols: {
|
|
311
|
+
rootSymbol: {
|
|
312
|
+
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
313
|
+
instanceMembers: {
|
|
314
|
+
instance: {
|
|
315
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
instantiation: {}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
binder.instantiateSymbolInto(rootSymbol, instantiation);
|
|
324
|
+
flushJobs();
|
|
325
|
+
expect(instantiation.staticMemberScope.symbols.size).toBe(1);
|
|
326
|
+
const lateKey = refkey();
|
|
327
|
+
// now add a brand‐new static member to source
|
|
328
|
+
binder.createSymbol({
|
|
329
|
+
name: "lateChild",
|
|
330
|
+
scope: rootSymbol.instanceMemberScope,
|
|
331
|
+
refkey: lateKey,
|
|
332
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
333
|
+
});
|
|
334
|
+
flushJobs();
|
|
335
|
+
expect(rootSymbol.instanceMemberScope.symbols.size).toBe(2);
|
|
336
|
+
expect(instantiation.staticMemberScope.symbols.size).toBe(2);
|
|
337
|
+
});
|
|
338
|
+
it("should remove members in instance when source deleted them", () => {
|
|
339
|
+
const binder = createOutputBinder();
|
|
340
|
+
const {
|
|
341
|
+
symbols: {
|
|
342
|
+
rootSymbol,
|
|
343
|
+
instantiation
|
|
344
|
+
}
|
|
345
|
+
} = createScopeTree(binder, {
|
|
346
|
+
rootScope: {
|
|
347
|
+
symbols: {
|
|
348
|
+
rootSymbol: {
|
|
349
|
+
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
350
|
+
instanceMembers: {
|
|
351
|
+
instance: {
|
|
352
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
instantiation: {}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
binder.instantiateSymbolInto(rootSymbol, instantiation);
|
|
361
|
+
expect(instantiation.staticMemberScope.symbols.size).toBe(1);
|
|
362
|
+
const lateKey = refkey();
|
|
363
|
+
// now add a brand‐new static member to source
|
|
364
|
+
binder.createSymbol({
|
|
365
|
+
name: "lateChild",
|
|
366
|
+
scope: rootSymbol.instanceMemberScope,
|
|
367
|
+
refkey: lateKey,
|
|
368
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
369
|
+
});
|
|
370
|
+
flushJobs();
|
|
371
|
+
expect(rootSymbol.instanceMemberScope.symbols.size).toBe(2);
|
|
372
|
+
expect(instantiation.staticMemberScope.symbols.size).toBe(2);
|
|
373
|
+
binder.deleteSymbol(rootSymbol.instanceMemberScope.symbols.values().next().value);
|
|
374
|
+
flushJobs();
|
|
375
|
+
expect(rootSymbol.instanceMemberScope.symbols.size).toBe(1);
|
|
376
|
+
expect(instantiation.staticMemberScope.symbols.size).toBe(1);
|
|
273
377
|
});
|
|
274
|
-
it("instantiates
|
|
378
|
+
it("instantiates instance members added after the instantiation", () => {
|
|
275
379
|
const binder = createOutputBinder();
|
|
276
380
|
const {
|
|
277
381
|
symbols: {
|
|
@@ -286,7 +390,7 @@ describe("instantiating members", () => {
|
|
|
286
390
|
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
287
391
|
instanceMembers: {
|
|
288
392
|
instance: {
|
|
289
|
-
flags: OutputSymbolFlags.
|
|
393
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
290
394
|
}
|
|
291
395
|
}
|
|
292
396
|
},
|
|
@@ -295,10 +399,11 @@ describe("instantiating members", () => {
|
|
|
295
399
|
}
|
|
296
400
|
});
|
|
297
401
|
binder.instantiateSymbolInto(rootSymbol, instantiation);
|
|
298
|
-
|
|
299
|
-
expect(instantiation.
|
|
402
|
+
flushJobs();
|
|
403
|
+
expect(instantiation.flags & OutputSymbolFlags.StaticMemberContainer).toBeTruthy();
|
|
404
|
+
expect(instantiation.staticMemberScope).toBeDefined();
|
|
300
405
|
const expectedRefkey = refkey(instantiation.refkeys[0], instance.refkeys[0]);
|
|
301
|
-
expect(instantiation.
|
|
406
|
+
expect(instantiation.staticMemberScope.symbolsByRefkey.get(expectedRefkey)).toBeDefined();
|
|
302
407
|
const newInstanceMemberRefkey = refkey();
|
|
303
408
|
binder.createSymbol({
|
|
304
409
|
name: "newInstanceMember",
|
|
@@ -307,7 +412,279 @@ describe("instantiating members", () => {
|
|
|
307
412
|
flags: OutputSymbolFlags.InstanceMember
|
|
308
413
|
});
|
|
309
414
|
const newExpectedRefkey = refkey(instantiation.refkeys[0], newInstanceMemberRefkey);
|
|
310
|
-
|
|
415
|
+
flushJobs();
|
|
416
|
+
expect(instantiation.staticMemberScope.symbolsByRefkey.get(newExpectedRefkey)).toBeDefined();
|
|
417
|
+
});
|
|
418
|
+
it("instantiates static symbols for a static container source", () => {
|
|
419
|
+
const binder = createOutputBinder();
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* The following structure would match code like this:
|
|
423
|
+
* ```ts
|
|
424
|
+
* // A class with instance members
|
|
425
|
+
* class Source {
|
|
426
|
+
* static child() {
|
|
427
|
+
* print("child");
|
|
428
|
+
* }
|
|
429
|
+
* }
|
|
430
|
+
*
|
|
431
|
+
*
|
|
432
|
+
* var printChild = Source.child;
|
|
433
|
+
*
|
|
434
|
+
* printChild();
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
const {
|
|
438
|
+
symbols: {
|
|
439
|
+
source,
|
|
440
|
+
child,
|
|
441
|
+
target
|
|
442
|
+
}
|
|
443
|
+
} = createScopeTree(binder, {
|
|
444
|
+
root: {
|
|
445
|
+
symbols: {
|
|
446
|
+
source: {
|
|
447
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
448
|
+
staticMembers: {
|
|
449
|
+
child: {
|
|
450
|
+
flags: OutputSymbolFlags.StaticMember
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
target: {}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
binder.instantiateSymbolInto(source, target);
|
|
459
|
+
|
|
460
|
+
// target must now be a StaticMemberContainer too
|
|
461
|
+
expect(target.flags & OutputSymbolFlags.StaticMemberContainer).toBeTruthy();
|
|
462
|
+
expect(target.staticMemberScope).toBeDefined();
|
|
463
|
+
const expectedKey = refkey(target.refkeys[0], child.refkeys[0]);
|
|
464
|
+
expect(target.staticMemberScope.symbolsByRefkey.get(expectedKey)).toBeDefined();
|
|
465
|
+
});
|
|
466
|
+
it("instantiates static symbols added after instantiation", () => {
|
|
467
|
+
const binder = createOutputBinder();
|
|
468
|
+
const lateKey = refkey();
|
|
469
|
+
const {
|
|
470
|
+
symbols: {
|
|
471
|
+
source,
|
|
472
|
+
target
|
|
473
|
+
}
|
|
474
|
+
} = createScopeTree(binder, {
|
|
475
|
+
root: {
|
|
476
|
+
symbols: {
|
|
477
|
+
source: {
|
|
478
|
+
flags: OutputSymbolFlags.StaticMemberContainer
|
|
479
|
+
},
|
|
480
|
+
target: {}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
// hook up instantiation
|
|
486
|
+
binder.instantiateSymbolInto(source, target);
|
|
487
|
+
|
|
488
|
+
// now add a brand‐new static member to source
|
|
489
|
+
const late = binder.createSymbol({
|
|
490
|
+
name: "lateChild",
|
|
491
|
+
scope: source.staticMemberScope,
|
|
492
|
+
refkey: lateKey,
|
|
493
|
+
flags: OutputSymbolFlags.StaticMember
|
|
494
|
+
});
|
|
495
|
+
flushJobs();
|
|
496
|
+
|
|
497
|
+
// it should *automatically* show up on target.staticMemberScope
|
|
498
|
+
const expectedKey = refkey(target.refkeys[0], late.refkeys[0]);
|
|
499
|
+
expect(target.staticMemberScope.symbolsByRefkey.get(expectedKey)).toBeDefined();
|
|
500
|
+
});
|
|
501
|
+
it("recursively instantiates nested static members", () => {
|
|
502
|
+
const binder = createOutputBinder();
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* The following structure would match code like this:
|
|
506
|
+
* ```ts
|
|
507
|
+
* class Source {
|
|
508
|
+
* static Level1 = class {
|
|
509
|
+
* static level2() { print("deep"); }
|
|
510
|
+
* }
|
|
511
|
+
* }
|
|
512
|
+
*
|
|
513
|
+
* var target = Source;
|
|
514
|
+
*
|
|
515
|
+
* target.Level1.level2()
|
|
516
|
+
* ```
|
|
517
|
+
*/
|
|
518
|
+
const {
|
|
519
|
+
symbols: {
|
|
520
|
+
source,
|
|
521
|
+
level1,
|
|
522
|
+
level2,
|
|
523
|
+
target
|
|
524
|
+
}
|
|
525
|
+
} = createScopeTree(binder, {
|
|
526
|
+
root: {
|
|
527
|
+
symbols: {
|
|
528
|
+
source: {
|
|
529
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
530
|
+
staticMembers: {
|
|
531
|
+
level1: {
|
|
532
|
+
flags: OutputSymbolFlags.StaticMember | OutputSymbolFlags.StaticMemberContainer,
|
|
533
|
+
staticMembers: {
|
|
534
|
+
level2: {
|
|
535
|
+
flags: OutputSymbolFlags.StaticMember
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
},
|
|
541
|
+
target: {}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
binder.instantiateSymbolInto(source, target);
|
|
546
|
+
|
|
547
|
+
// level1 should appear under target.staticMemberScope
|
|
548
|
+
const key1 = refkey(target.refkeys[0], level1.refkeys[0]);
|
|
549
|
+
const instantiated1 = target.staticMemberScope.symbolsByRefkey.get(key1);
|
|
550
|
+
expect(instantiated1.name).toBe(level1.name);
|
|
551
|
+
|
|
552
|
+
// and level2 should appear under the *child* staticMemberScope of that instantiated level1
|
|
553
|
+
const childScope = instantiated1.staticMemberScope;
|
|
554
|
+
const key2 = refkey(instantiated1.refkeys[0], level2.refkeys[0]);
|
|
555
|
+
expect(childScope.symbolsByRefkey.get(key2)).toBeDefined();
|
|
556
|
+
});
|
|
557
|
+
it("copies both instance *and* static members when source has both flags", () => {
|
|
558
|
+
const binder = createOutputBinder();
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* ```ts
|
|
562
|
+
* class Source {
|
|
563
|
+
* instance() { print("inst"); }
|
|
564
|
+
* static s1() { print("static"); }
|
|
565
|
+
* }
|
|
566
|
+
*
|
|
567
|
+
* let t = new Source()
|
|
568
|
+
* t.instance()
|
|
569
|
+
* t.s1()
|
|
570
|
+
* ```
|
|
571
|
+
*/
|
|
572
|
+
const {
|
|
573
|
+
symbols: {
|
|
574
|
+
source,
|
|
575
|
+
inst
|
|
576
|
+
}
|
|
577
|
+
} = createScopeTree(binder, {
|
|
578
|
+
root: {
|
|
579
|
+
symbols: {
|
|
580
|
+
source: {
|
|
581
|
+
flags: OutputSymbolFlags.InstanceMemberContainer | OutputSymbolFlags.StaticMemberContainer,
|
|
582
|
+
instanceMembers: {
|
|
583
|
+
i1: {
|
|
584
|
+
flags: OutputSymbolFlags.InstanceMember
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
staticMembers: {
|
|
588
|
+
s1: {
|
|
589
|
+
flags: OutputSymbolFlags.StaticMember
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
inst: {}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
binder.instantiateSymbolInto(source, inst);
|
|
598
|
+
expect(inst.staticMemberScope).toBeDefined();
|
|
599
|
+
expect([...inst.staticMemberScope.symbols].some(s => s.name === "i1")).toBe(true);
|
|
600
|
+
|
|
601
|
+
// static side
|
|
602
|
+
const symbols = [...source.staticMemberScope.symbols];
|
|
603
|
+
expect(inst.staticMemberScope).toBeDefined();
|
|
604
|
+
const sKey = refkey(inst.refkeys[0], symbols[0].refkeys[0]);
|
|
605
|
+
expect(inst.staticMemberScope.symbolsByRefkey.has(sKey)).toBe(true);
|
|
606
|
+
});
|
|
607
|
+
it("is idempotent, calling twice does not duplicate", () => {
|
|
608
|
+
const binder = createOutputBinder();
|
|
609
|
+
const {
|
|
610
|
+
symbols: {
|
|
611
|
+
source,
|
|
612
|
+
target
|
|
613
|
+
}
|
|
614
|
+
} = createScopeTree(binder, {
|
|
615
|
+
root: {
|
|
616
|
+
symbols: {
|
|
617
|
+
source: {
|
|
618
|
+
flags: OutputSymbolFlags.StaticMemberContainer,
|
|
619
|
+
staticMembers: {
|
|
620
|
+
a: {
|
|
621
|
+
flags: OutputSymbolFlags.StaticMember
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
target: {}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
binder.instantiateSymbolInto(source, target);
|
|
630
|
+
flushJobs();
|
|
631
|
+
const initialCount = target.staticMemberScope.symbols.size;
|
|
632
|
+
binder.instantiateSymbolInto(source, target);
|
|
633
|
+
flushJobs();
|
|
634
|
+
expect(target.staticMemberScope.symbols.size).toBe(initialCount);
|
|
635
|
+
});
|
|
636
|
+
it("instantiates static children of instance members under the instance scope", () => {
|
|
637
|
+
const binder = createOutputBinder();
|
|
638
|
+
/**
|
|
639
|
+
* ```ts
|
|
640
|
+
* class Source {
|
|
641
|
+
* instM = class {
|
|
642
|
+
* static deep() { print("deep"); }
|
|
643
|
+
* }
|
|
644
|
+
* }
|
|
645
|
+
*
|
|
646
|
+
* var t = new Source();
|
|
647
|
+
* t.instM.deep();
|
|
648
|
+
* ```
|
|
649
|
+
*/
|
|
650
|
+
const {
|
|
651
|
+
symbols: {
|
|
652
|
+
source,
|
|
653
|
+
deep,
|
|
654
|
+
target
|
|
655
|
+
}
|
|
656
|
+
} = createScopeTree(binder, {
|
|
657
|
+
root: {
|
|
658
|
+
symbols: {
|
|
659
|
+
source: {
|
|
660
|
+
flags: OutputSymbolFlags.InstanceMemberContainer,
|
|
661
|
+
instanceMembers: {
|
|
662
|
+
instM: {
|
|
663
|
+
flags: OutputSymbolFlags.InstanceMember | OutputSymbolFlags.StaticMemberContainer,
|
|
664
|
+
staticMembers: {
|
|
665
|
+
deep: {
|
|
666
|
+
flags: OutputSymbolFlags.StaticMember
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
},
|
|
672
|
+
target: {}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
binder.instantiateSymbolInto(source, target);
|
|
677
|
+
|
|
678
|
+
// Find the instantiated copy of instM under target.instanceMemberScope
|
|
679
|
+
const instMSym = [...target.staticMemberScope.symbols].find(s => s.name === "instM");
|
|
680
|
+
|
|
681
|
+
// instMSym should have gotten its own staticMemberScope via the StaticMemberContainer flag
|
|
682
|
+
expect(instMSym.staticMemberScope).toBeDefined();
|
|
683
|
+
|
|
684
|
+
// compute the expected key for the deep child:
|
|
685
|
+
// (<target>, <instM>) then (on that) (<deep original>)
|
|
686
|
+
const expectedDeepKey = refkey(instMSym.refkeys[0], deep.refkeys[0]);
|
|
687
|
+
expect(instMSym.staticMemberScope.symbolsByRefkey.has(expectedDeepKey)).toBe(true);
|
|
311
688
|
});
|
|
312
689
|
});
|
|
313
690
|
describe("symbol name resolution", () => {
|
|
@@ -439,6 +816,7 @@ describe("refkey resolution", () => {
|
|
|
439
816
|
});
|
|
440
817
|
expect(resolvedSym.value).toBe(undefined);
|
|
441
818
|
sym.refkeys[0] = key;
|
|
819
|
+
flushJobs();
|
|
442
820
|
expect(resolvedSym.value?.targetDeclaration).toBe(sym);
|
|
443
821
|
});
|
|
444
822
|
});
|
|
@@ -453,8 +831,10 @@ describe("Deleting symbols", () => {
|
|
|
453
831
|
});
|
|
454
832
|
expect(resolvedSym.value).toBe(undefined);
|
|
455
833
|
sym.refkeys[0] = key;
|
|
834
|
+
flushJobs();
|
|
456
835
|
expect(resolvedSym.value?.targetDeclaration).toBe(sym);
|
|
457
836
|
binder.deleteSymbol(sym);
|
|
837
|
+
flushJobs();
|
|
458
838
|
expect(resolvedSym.value).toBe(undefined);
|
|
459
839
|
});
|
|
460
840
|
it("removes from parent scopes", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../test/utils.test.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../test/utils.test.tsx"],"names":[],"mappings":"AAMA,OAAO,6BAA6B,CAAC"}
|
package/dist/test/utils.test.js
CHANGED
|
@@ -2,6 +2,7 @@ import { memo as _$memo, createComponent as _$createComponent } from "@alloy-js/
|
|
|
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
|
describe("mapJoin", () => {
|
|
@@ -66,6 +67,7 @@ describe("mapJoin", () => {
|
|
|
66
67
|
expect(callCount).toBe(2);
|
|
67
68
|
arr.value.push(3);
|
|
68
69
|
triggerRef(arr);
|
|
70
|
+
flushJobs();
|
|
69
71
|
expect(callCount).toBe(3);
|
|
70
72
|
});
|
|
71
73
|
it("can map a joiner", () => {
|