@alloy-js/core 0.10.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 +28 -0
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +100 -19
- package/dist/src/code.js +1 -2
- package/dist/src/components/Block.js +2 -5
- package/dist/src/components/Declaration.js +2 -4
- package/dist/src/components/For.d.ts +2 -2
- package/dist/src/components/For.d.ts.map +1 -1
- package/dist/src/components/For.js +1 -2
- package/dist/src/components/Indent.js +2 -4
- package/dist/src/components/List.js +2 -5
- package/dist/src/components/MemberDeclaration.js +2 -4
- package/dist/src/components/MemberName.js +1 -2
- package/dist/src/components/MemberScope.js +2 -4
- package/dist/src/components/Name.js +1 -2
- package/dist/src/components/Output.js +2 -4
- package/dist/src/components/Prose.js +1 -2
- package/dist/src/components/ReferenceOrContent.d.ts +8 -0
- package/dist/src/components/ReferenceOrContent.d.ts.map +1 -0
- package/dist/src/components/ReferenceOrContent.js +11 -0
- package/dist/src/components/Scope.js +2 -4
- package/dist/src/components/Show.js +1 -2
- package/dist/src/components/SourceDirectory.js +2 -4
- package/dist/src/components/SourceFile.js +2 -5
- package/dist/src/components/StatementList.js +2 -4
- package/dist/src/components/Switch.d.ts +1 -1
- package/dist/src/components/Switch.d.ts.map +1 -1
- package/dist/src/components/Switch.js +1 -2
- package/dist/src/components/Wrap.js +2 -4
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +2 -2
- package/dist/src/components/stc/index.d.ts +1 -0
- package/dist/src/components/stc/index.d.ts.map +1 -1
- package/dist/src/components/stc/index.js +2 -2
- package/dist/src/components/stc/sti.js +1 -2
- package/dist/src/context/assignment.js +1 -2
- package/dist/src/context/binder.js +1 -2
- package/dist/src/context/declaration.js +1 -2
- package/dist/src/context/index.js +1 -2
- package/dist/src/context/member-declaration.js +1 -2
- package/dist/src/context/member-scope.js +1 -2
- package/dist/src/context/name-policy.js +1 -2
- package/dist/src/context/scope.js +1 -2
- package/dist/src/context/source-directory.js +1 -2
- package/dist/src/context/source-file.js +1 -2
- package/dist/src/context.js +1 -2
- package/dist/src/debug.js +13 -15
- package/dist/src/index.browser.js +1 -2
- package/dist/src/index.js +1 -2
- package/dist/src/jsx-runtime.d.ts +1 -1
- package/dist/src/jsx-runtime.d.ts.map +1 -1
- package/dist/src/jsx-runtime.js +10 -5
- package/dist/src/name-policy.js +1 -2
- package/dist/src/refkey.js +1 -2
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +6 -2
- 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/src/slot.js +1 -2
- package/dist/src/stc.js +1 -2
- package/dist/src/sti.js +1 -2
- package/dist/src/tap.js +1 -2
- package/dist/src/tsdoc-metadata.json +1 -1
- package/dist/src/utils.js +2 -4
- package/dist/src/write-output.browser.js +1 -2
- package/dist/src/write-output.js +1 -2
- package/dist/test/browser-build.test.js +85 -0
- package/dist/test/children.test.js +27 -0
- package/dist/test/components/block.test.js +45 -0
- package/dist/test/components/declaration.test.js +32 -0
- package/dist/test/components/list.test.js +86 -0
- package/dist/test/components/prose.test.js +25 -0
- package/dist/test/components/reference-or-content.test.d.ts +2 -0
- package/dist/test/components/reference-or-content.test.d.ts.map +1 -0
- package/dist/test/components/reference-or-content.test.js +149 -0
- package/dist/test/components/slot.test.js +134 -0
- package/dist/test/components/source-file.test.js +64 -0
- package/dist/test/components/wrap.test.js +35 -0
- package/dist/test/control-flow/for.test.js +219 -0
- package/dist/test/control-flow/match.test.js +67 -0
- package/dist/test/control-flow/show.test.js +29 -0
- package/dist/test/name-policy.test.js +19 -0
- package/dist/test/props-with-defaults.test.js +93 -0
- 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 +82 -0
- package/dist/test/reactivity/memo.test.js +16 -0
- package/dist/test/reactivity/ref-rendering.test.js +37 -0
- package/dist/test/reactivity/test.test.js +61 -0
- package/dist/test/reactivity/untrack.test.js +26 -0
- package/dist/test/refkey.test.js +25 -0
- package/dist/test/rendering/basic.test.js +96 -0
- package/dist/test/rendering/code.test.js +55 -0
- package/dist/test/rendering/formatting.test.js +402 -0
- package/dist/test/rendering/indent.test.js +90 -0
- package/dist/test/rendering/memoization.test.js +27 -0
- package/dist/test/rendering/refkeys.test.js +32 -0
- package/dist/test/split-props.test.js +77 -0
- package/dist/test/stc.test.js +34 -0
- package/dist/test/symbols.test.js +877 -0
- package/dist/test/utils.test.d.ts.map +1 -1
- package/dist/test/utils.test.js +223 -0
- package/dist/testing/extend-expect.js +1 -2
- package/dist/testing/index.js +1 -2
- package/dist/testing/render.js +1 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -22
- package/src/binder.ts +100 -17
- package/src/components/For.tsx +6 -6
- package/src/components/ReferenceOrContent.tsx +22 -0
- package/src/components/index.tsx +1 -0
- package/src/components/stc/index.ts +1 -0
- package/src/debug.ts +12 -13
- package/src/jsx-runtime.ts +24 -14
- package/src/render.ts +5 -0
- package/src/scheduler.ts +24 -0
- package/temp/api.json +216 -15
- package/test/components/declaration.test.tsx +2 -0
- package/test/components/list.test.tsx +0 -1
- package/test/components/reference-or-content.test.tsx +138 -0
- 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/babel.config.cjs +0 -4
- package/dist/src/binder.js.map +0 -1
- package/dist/src/code.js.map +0 -1
- package/dist/src/components/Block.js.map +0 -1
- package/dist/src/components/Declaration.js.map +0 -1
- package/dist/src/components/For.js.map +0 -1
- package/dist/src/components/Indent.js.map +0 -1
- package/dist/src/components/List.js.map +0 -1
- package/dist/src/components/MemberDeclaration.js.map +0 -1
- package/dist/src/components/MemberName.js.map +0 -1
- package/dist/src/components/MemberScope.js.map +0 -1
- package/dist/src/components/Name.js.map +0 -1
- package/dist/src/components/Output.js.map +0 -1
- package/dist/src/components/Prose.js.map +0 -1
- package/dist/src/components/Scope.js.map +0 -1
- package/dist/src/components/Show.js.map +0 -1
- package/dist/src/components/SourceDirectory.js.map +0 -1
- package/dist/src/components/SourceFile.js.map +0 -1
- package/dist/src/components/StatementList.js.map +0 -1
- package/dist/src/components/Switch.js.map +0 -1
- package/dist/src/components/Wrap.js.map +0 -1
- package/dist/src/components/index.js.map +0 -1
- package/dist/src/components/stc/index.js.map +0 -1
- package/dist/src/components/stc/sti.js.map +0 -1
- package/dist/src/context/assignment.js.map +0 -1
- package/dist/src/context/binder.js.map +0 -1
- package/dist/src/context/declaration.js.map +0 -1
- package/dist/src/context/index.js.map +0 -1
- package/dist/src/context/member-declaration.js.map +0 -1
- package/dist/src/context/member-scope.js.map +0 -1
- package/dist/src/context/name-policy.js.map +0 -1
- package/dist/src/context/scope.js.map +0 -1
- package/dist/src/context/source-directory.js.map +0 -1
- package/dist/src/context/source-file.js.map +0 -1
- package/dist/src/context.js.map +0 -1
- package/dist/src/debug.js.map +0 -1
- package/dist/src/index.browser.js.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/jsx-runtime.js.map +0 -1
- package/dist/src/name-policy.js.map +0 -1
- package/dist/src/refkey.js.map +0 -1
- package/dist/src/render.js.map +0 -1
- package/dist/src/slot.js.map +0 -1
- package/dist/src/stc.js.map +0 -1
- package/dist/src/sti.js.map +0 -1
- package/dist/src/tap.js.map +0 -1
- package/dist/src/utils.js.map +0 -1
- package/dist/src/write-output.browser.js.map +0 -1
- package/dist/src/write-output.js.map +0 -1
- package/dist/testing/extend-expect.js.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/testing/render.js.map +0 -1
- package/dist/testing/vitest.d.js.map +0 -1
package/src/binder.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computed,
|
|
3
|
-
effect,
|
|
4
3
|
reactive,
|
|
5
4
|
ref,
|
|
6
5
|
Ref,
|
|
@@ -10,8 +9,9 @@ import {
|
|
|
10
9
|
import { useBinder } from "./context/binder.js";
|
|
11
10
|
import { useMemberScope } from "./context/member-scope.js";
|
|
12
11
|
import { useScope } from "./context/scope.js";
|
|
13
|
-
import { memo, untrack } from "./jsx-runtime.js";
|
|
12
|
+
import { effect, memo, onCleanup, untrack } from "./jsx-runtime.js";
|
|
14
13
|
import { refkey, Refkey } from "./refkey.js";
|
|
14
|
+
import { queueJob, QueueJob } from "./scheduler.js";
|
|
15
15
|
export type Metadata = object;
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -464,6 +464,7 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
464
464
|
OutputScope,
|
|
465
465
|
Map<string, Ref<OutputScope | undefined>>
|
|
466
466
|
>();
|
|
467
|
+
const deconflictJobs = new Map<OutputScope, Map<string, QueueJob>>();
|
|
467
468
|
|
|
468
469
|
return binder;
|
|
469
470
|
|
|
@@ -622,26 +623,77 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
622
623
|
}
|
|
623
624
|
|
|
624
625
|
function instantiateSymbolInto(source: OutputSymbol, target: OutputSymbol) {
|
|
625
|
-
if (
|
|
626
|
-
|
|
626
|
+
if (target.staticMemberScope) {
|
|
627
|
+
return;
|
|
627
628
|
}
|
|
628
629
|
|
|
629
|
-
|
|
630
|
+
// Ensure static member scope exists
|
|
631
|
+
addStaticMembersToSymbol(target);
|
|
630
632
|
|
|
631
633
|
effect(() => {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
634
|
+
// copy instance members if it's an instance‐container
|
|
635
|
+
if (source.flags & OutputSymbolFlags.InstanceMemberContainer) {
|
|
636
|
+
copyMembers(
|
|
637
|
+
source.instanceMemberScope!.symbols,
|
|
638
|
+
target,
|
|
639
|
+
target.staticMemberScope!,
|
|
640
|
+
);
|
|
641
|
+
}
|
|
636
642
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
+
// copy static members if it's a static‐container
|
|
644
|
+
if (source.flags & OutputSymbolFlags.StaticMemberContainer) {
|
|
645
|
+
copyMembers(
|
|
646
|
+
source.staticMemberScope!.symbols,
|
|
647
|
+
target,
|
|
648
|
+
target.staticMemberScope!,
|
|
649
|
+
);
|
|
643
650
|
}
|
|
644
651
|
});
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Recursively copy `symbols` from `sourceSym` into `intoScope` of `targetSym`.
|
|
655
|
+
* Always marks each instantiation as StaticMember so lookups use dot notation (e.g. Parent.child)
|
|
656
|
+
* and preserves any StaticMemberContainer flag to auto create newSym.staticMemberScope.
|
|
657
|
+
*/
|
|
658
|
+
function copyMembers(
|
|
659
|
+
symbols: Set<OutputSymbol>,
|
|
660
|
+
targetSym: OutputSymbol,
|
|
661
|
+
intoScope: OutputScope,
|
|
662
|
+
) {
|
|
663
|
+
for (const srcSym of symbols) {
|
|
664
|
+
untrack(() => {
|
|
665
|
+
const wantKey = refkey(targetSym.refkeys[0], srcSym.refkeys[0]);
|
|
666
|
+
|
|
667
|
+
// create the new symbol. Preserve StaticMemberContainer if present
|
|
668
|
+
const newSym = createSymbol({
|
|
669
|
+
name: srcSym.name,
|
|
670
|
+
scope: intoScope,
|
|
671
|
+
refkey: wantKey,
|
|
672
|
+
flags: srcSym.flags | OutputSymbolFlags.StaticMember,
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
onCleanup(() => {
|
|
676
|
+
binder.deleteSymbol(newSym);
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
// if the source symbol itself was a container of static members,
|
|
680
|
+
// recurse into the newSym.staticMemberScope that createSymbol just gave us
|
|
681
|
+
if (
|
|
682
|
+
srcSym.staticMemberScope &&
|
|
683
|
+
srcSym.staticMemberScope.symbols.size > 0
|
|
684
|
+
) {
|
|
685
|
+
// ensure we have that scope
|
|
686
|
+
addStaticMembersToSymbol(newSym);
|
|
687
|
+
|
|
688
|
+
copyMembers(
|
|
689
|
+
srcSym.staticMemberScope.symbols,
|
|
690
|
+
newSym,
|
|
691
|
+
newSym.staticMemberScope!,
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
}
|
|
645
697
|
}
|
|
646
698
|
|
|
647
699
|
function addStaticMembersToSymbol(symbol: OutputSymbol) {
|
|
@@ -789,7 +841,7 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
789
841
|
function deconflict(symbol: OutputSymbol) {
|
|
790
842
|
const scope = symbol.scope;
|
|
791
843
|
const existingNames = [...scope.symbols].filter(
|
|
792
|
-
(sym) => sym.
|
|
844
|
+
(sym) => sym.name === symbol.name,
|
|
793
845
|
);
|
|
794
846
|
|
|
795
847
|
if (existingNames.length < 2) {
|
|
@@ -797,7 +849,13 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
797
849
|
}
|
|
798
850
|
|
|
799
851
|
if (options.nameConflictResolver) {
|
|
800
|
-
|
|
852
|
+
queueJob(
|
|
853
|
+
deconflictJobForScopeAndName(
|
|
854
|
+
scope,
|
|
855
|
+
symbol.name,
|
|
856
|
+
options.nameConflictResolver,
|
|
857
|
+
),
|
|
858
|
+
);
|
|
801
859
|
} else {
|
|
802
860
|
// default disambiguation is first-wins
|
|
803
861
|
for (let i = 1; i < existingNames.length; i++) {
|
|
@@ -806,6 +864,31 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
806
864
|
}
|
|
807
865
|
}
|
|
808
866
|
|
|
867
|
+
function deconflictJobForScopeAndName(
|
|
868
|
+
scope: OutputScope,
|
|
869
|
+
name: string,
|
|
870
|
+
handler: NameConflictResolver,
|
|
871
|
+
) {
|
|
872
|
+
if (!deconflictJobs.has(scope)) {
|
|
873
|
+
deconflictJobs.set(scope, new Map());
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
const jobs = deconflictJobs.get(scope)!;
|
|
877
|
+
if (jobs.has(name)) {
|
|
878
|
+
return jobs.get(name)!;
|
|
879
|
+
}
|
|
880
|
+
const job = () => {
|
|
881
|
+
const conflictedSymbols = [...scope.symbols].filter(
|
|
882
|
+
(sym) => sym.name === name,
|
|
883
|
+
);
|
|
884
|
+
handler(name, conflictedSymbols);
|
|
885
|
+
jobs.delete(name);
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
jobs.set(name, job);
|
|
889
|
+
return job;
|
|
890
|
+
}
|
|
891
|
+
|
|
809
892
|
function getSymbolForRefkey<TSymbol extends OutputSymbol>(
|
|
810
893
|
refkey: Refkey,
|
|
811
894
|
): Ref<TSymbol | undefined> {
|
package/src/components/For.tsx
CHANGED
|
@@ -4,9 +4,9 @@ import { baseListPropsToMapJoinArgs, mapJoin } from "../utils.js";
|
|
|
4
4
|
import { BaseListProps } from "./List.jsx";
|
|
5
5
|
|
|
6
6
|
export type ForCallbackArgs<T> =
|
|
7
|
-
|
|
7
|
+
number extends keyof T ? [value: T[number]]
|
|
8
|
+
: T extends Ref<infer U> ? ForCallbackArgs<U>
|
|
8
9
|
: T extends () => infer U ? ForCallbackArgs<U>
|
|
9
|
-
: T extends (infer U)[] ? [value: U]
|
|
10
10
|
: T extends Map<infer U, infer V> ? [key: U, value: V]
|
|
11
11
|
: T extends Set<infer U> ? [value: U]
|
|
12
12
|
: T extends IterableIterator<infer U> ? [value: U]
|
|
@@ -38,10 +38,10 @@ export interface ForProps<
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export type ForSupportedCollections =
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
| IterableIterator<
|
|
41
|
+
| readonly unknown[]
|
|
42
|
+
| ReadonlyMap<unknown, unknown>
|
|
43
|
+
| ReadonlySet<unknown>
|
|
44
|
+
| IterableIterator<unknown>;
|
|
45
45
|
/**
|
|
46
46
|
* The For component iterates over the provided array and invokes the child
|
|
47
47
|
* callback for each item. It can optionally be provided with a `joiner` which
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Children } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { computed } from "@vue/reactivity";
|
|
3
|
+
import { useContext } from "../context.js";
|
|
4
|
+
import { BinderContext } from "../context/binder.js";
|
|
5
|
+
import type { Refkey } from "../refkey.js";
|
|
6
|
+
|
|
7
|
+
export interface ReferenceOrContentProps {
|
|
8
|
+
readonly refkey: Refkey;
|
|
9
|
+
readonly children: Children;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function ReferenceOrContent(props: ReferenceOrContentProps) {
|
|
13
|
+
const binder = useContext(BinderContext);
|
|
14
|
+
if (!binder) {
|
|
15
|
+
throw new Error("Need binder context to create declarations");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const sym = binder.getSymbolForRefkey(props.refkey);
|
|
19
|
+
return computed(() =>
|
|
20
|
+
sym.value === undefined ? props.children : props.refkey,
|
|
21
|
+
);
|
|
22
|
+
}
|
package/src/components/index.tsx
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./MemberScope.jsx";
|
|
|
9
9
|
export * from "./Name.jsx";
|
|
10
10
|
export * from "./Output.js";
|
|
11
11
|
export * from "./Prose.jsx";
|
|
12
|
+
export * from "./ReferenceOrContent.jsx";
|
|
12
13
|
export * from "./Scope.js";
|
|
13
14
|
export * from "./Show.jsx";
|
|
14
15
|
export * from "./SourceDirectory.js";
|
|
@@ -19,5 +19,6 @@ export const SourceDirectory = stc(base.SourceDirectory);
|
|
|
19
19
|
export const SourceFile = stc(base.SourceFile);
|
|
20
20
|
export const Switch = stc(base.Switch);
|
|
21
21
|
export const Wrap = stc(base.Wrap);
|
|
22
|
+
export const ReferenceOrContent = stc(base.ReferenceOrContent);
|
|
22
23
|
|
|
23
24
|
export * from "./sti.js";
|
package/src/debug.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isReactive } from "@vue/reactivity";
|
|
2
|
-
import { Chalk } from "chalk";
|
|
3
2
|
import Table from "cli-table3";
|
|
3
|
+
import pc from "picocolors";
|
|
4
4
|
import { contextsByKey } from "./context.js";
|
|
5
5
|
import { Context, getContext } from "./jsx-runtime.js";
|
|
6
6
|
|
|
@@ -56,14 +56,14 @@ function debugStack() {
|
|
|
56
56
|
{ hAlign: "right", content: "props" },
|
|
57
57
|
props && Object.keys(props).length > 0 ?
|
|
58
58
|
dumpValue(props)
|
|
59
|
-
:
|
|
59
|
+
: pc.gray("(none)"),
|
|
60
60
|
]);
|
|
61
61
|
|
|
62
62
|
table.push([
|
|
63
63
|
{ hAlign: "right", content: "contexts" },
|
|
64
64
|
foundContexts.length > 0 ?
|
|
65
65
|
foundContexts.map((c) => printContext(c, true)).join("\n")
|
|
66
|
-
:
|
|
66
|
+
: pc.gray("(none)"),
|
|
67
67
|
]);
|
|
68
68
|
|
|
69
69
|
process.stdout.write(table.toString() + "\n\n");
|
|
@@ -119,39 +119,38 @@ declare global {
|
|
|
119
119
|
|
|
120
120
|
globalThis.debug = debug;
|
|
121
121
|
|
|
122
|
-
const chalk = new Chalk();
|
|
123
122
|
const style = {
|
|
124
123
|
value: {
|
|
125
124
|
primitive(value: string | number | boolean | null | undefined) {
|
|
126
125
|
switch (typeof value) {
|
|
127
126
|
case "string":
|
|
128
|
-
return
|
|
127
|
+
return pc.blue(`"${value}"`);
|
|
129
128
|
case "object":
|
|
130
129
|
case "undefined":
|
|
131
|
-
return
|
|
130
|
+
return pc.gray(String(value));
|
|
132
131
|
default:
|
|
133
|
-
return
|
|
132
|
+
return pc.blue(String(value));
|
|
134
133
|
}
|
|
135
134
|
},
|
|
136
135
|
symbol(value: symbol) {
|
|
137
|
-
return
|
|
136
|
+
return pc.gray(String(value));
|
|
138
137
|
},
|
|
139
138
|
},
|
|
140
139
|
context: {
|
|
141
140
|
name(name: string) {
|
|
142
|
-
return
|
|
141
|
+
return pc.bgBlack(` ${pc.white(name)} `);
|
|
143
142
|
},
|
|
144
143
|
},
|
|
145
144
|
component: {
|
|
146
145
|
name(name: string) {
|
|
147
|
-
return
|
|
146
|
+
return pc.bgBlue(` <${pc.white(name)}> `);
|
|
148
147
|
},
|
|
149
148
|
},
|
|
150
149
|
};
|
|
151
150
|
|
|
152
151
|
function reactiveTag(value: unknown) {
|
|
153
152
|
if (isReactive(value)) {
|
|
154
|
-
return " " +
|
|
153
|
+
return " " + pc.greenBright(`reactive`) + " ";
|
|
155
154
|
}
|
|
156
155
|
return "";
|
|
157
156
|
}
|
|
@@ -168,7 +167,7 @@ function dumpValue(value: unknown, level = 0) {
|
|
|
168
167
|
if (value === null) {
|
|
169
168
|
return style.value.primitive(null) + reactiveTag(value);
|
|
170
169
|
} else {
|
|
171
|
-
if (level > 0) return
|
|
170
|
+
if (level > 0) return pc.gray(`{ ... }` + reactiveTag(value));
|
|
172
171
|
|
|
173
172
|
const table = kvTable(" ");
|
|
174
173
|
|
|
@@ -179,7 +178,7 @@ function dumpValue(value: unknown, level = 0) {
|
|
|
179
178
|
return table.toString();
|
|
180
179
|
}
|
|
181
180
|
case "function":
|
|
182
|
-
return
|
|
181
|
+
return pc.gray("ƒ ()");
|
|
183
182
|
case "undefined":
|
|
184
183
|
return style.value.primitive(undefined);
|
|
185
184
|
}
|
package/src/jsx-runtime.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
isReactive,
|
|
6
6
|
pauseTracking,
|
|
7
7
|
proxyRefs,
|
|
8
|
+
ReactiveEffectRunner,
|
|
8
9
|
Ref,
|
|
9
10
|
resetTracking,
|
|
10
11
|
shallowRef,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
} from "@vue/reactivity";
|
|
15
16
|
import { Refkey } from "./refkey.js";
|
|
16
17
|
import { RenderedTextTree } from "./render.js";
|
|
18
|
+
import { scheduler } from "./scheduler.js";
|
|
17
19
|
|
|
18
20
|
if ((globalThis as any).ALLOY) {
|
|
19
21
|
throw new Error(
|
|
@@ -125,21 +127,29 @@ export function effect<T>(fn: (prev?: T) => T, current?: T) {
|
|
|
125
127
|
for (let k = 0, len = d.length; k < len; k++) d[k]();
|
|
126
128
|
|
|
127
129
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
128
|
-
final && stop(
|
|
130
|
+
final && stop(runner);
|
|
129
131
|
};
|
|
130
132
|
|
|
131
133
|
onCleanup(() => cleanupFn(true));
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
134
|
+
const runner: ReactiveEffectRunner<void> = vueEffect(
|
|
135
|
+
() => {
|
|
136
|
+
cleanupFn(false);
|
|
137
|
+
|
|
138
|
+
const oldContext = globalContext;
|
|
139
|
+
globalContext = context;
|
|
140
|
+
try {
|
|
141
|
+
current = fn(current);
|
|
142
|
+
} finally {
|
|
143
|
+
globalContext = oldContext;
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
scheduler: scheduler(() => runner),
|
|
148
|
+
},
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
// allow recursive effects (recursive option does nothing, possible bug)
|
|
152
|
+
(runner as any).effect.flags |= 1 << 5;
|
|
143
153
|
}
|
|
144
154
|
|
|
145
155
|
/**
|
|
@@ -462,9 +472,9 @@ export function createComponent<TProps extends Props = Props>(
|
|
|
462
472
|
export function taggedComponent<TProps = Props>(
|
|
463
473
|
tag: symbol,
|
|
464
474
|
component: Component<TProps>,
|
|
465
|
-
): Component<TProps> {
|
|
475
|
+
): Component<TProps> & Required<Pick<Component<TProps>, "tag">> {
|
|
466
476
|
component.tag = tag;
|
|
467
|
-
return component;
|
|
477
|
+
return component as any;
|
|
468
478
|
}
|
|
469
479
|
|
|
470
480
|
export const intrinsicElementKey = Symbol();
|
package/src/render.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
untrack,
|
|
23
23
|
} from "./jsx-runtime.js";
|
|
24
24
|
import { isRefkey } from "./refkey.js";
|
|
25
|
+
import { flushJobs } from "./scheduler.js";
|
|
25
26
|
const {
|
|
26
27
|
builders: {
|
|
27
28
|
align,
|
|
@@ -181,6 +182,7 @@ export function render(
|
|
|
181
182
|
options?: PrintTreeOptions,
|
|
182
183
|
): OutputDirectory {
|
|
183
184
|
const tree = renderTree(children);
|
|
185
|
+
flushJobs();
|
|
184
186
|
let rootDirectory: OutputDirectory | undefined = undefined;
|
|
185
187
|
|
|
186
188
|
// when passing Output, the first render tree child is the Output component.
|
|
@@ -559,6 +561,9 @@ export function printTree(tree: RenderedTextTree, options?: PrintTreeOptions) {
|
|
|
559
561
|
),
|
|
560
562
|
};
|
|
561
563
|
|
|
564
|
+
// make sure queue is empty
|
|
565
|
+
flushJobs();
|
|
566
|
+
|
|
562
567
|
const d = printTreeWorker(tree);
|
|
563
568
|
return doc.printer.printDocToString(d, options as doc.printer.Options)
|
|
564
569
|
.formatted;
|
package/src/scheduler.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ReactiveEffectRunner } from "@vue/reactivity";
|
|
2
|
+
|
|
3
|
+
export interface QueueJob {
|
|
4
|
+
(): any;
|
|
5
|
+
}
|
|
6
|
+
const queue = new Set<QueueJob>();
|
|
7
|
+
|
|
8
|
+
export function scheduler(jobGetter: () => ReactiveEffectRunner) {
|
|
9
|
+
return () => {
|
|
10
|
+
queueJob(jobGetter());
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function queueJob(job: QueueJob) {
|
|
14
|
+
// the set is serving an important purpose here in deduping the effects we run
|
|
15
|
+
// (which in effect coalesces multiple update effects together).
|
|
16
|
+
queue.add(job);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function flushJobs() {
|
|
20
|
+
for (const job of queue) {
|
|
21
|
+
queue.delete(job);
|
|
22
|
+
job();
|
|
23
|
+
}
|
|
24
|
+
}
|