@alloy-js/core 0.23.0-dev.1 → 0.23.0-dev.11
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 +0 -22
- package/dist/devtools/index.html +80 -0
- package/dist/src/binder.d.ts +2 -0
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +60 -12
- package/dist/src/binder.js.map +1 -1
- package/dist/src/components/AccessExpression.d.ts +78 -0
- package/dist/src/components/AccessExpression.d.ts.map +1 -0
- package/dist/src/components/AccessExpression.js +218 -0
- package/dist/src/components/AccessExpression.js.map +1 -0
- package/dist/src/components/AccessExpression.test.d.ts +2 -0
- package/dist/src/components/AccessExpression.test.d.ts.map +1 -0
- package/dist/src/components/AccessExpression.test.js +137 -0
- package/dist/src/components/AccessExpression.test.js.map +1 -0
- package/dist/src/components/AppendFile.d.ts.map +1 -1
- package/dist/src/components/AppendFile.js +14 -3
- package/dist/src/components/AppendFile.js.map +1 -1
- package/dist/src/components/Block.js +1 -1
- package/dist/src/components/Block.js.map +1 -1
- package/dist/src/components/Declaration.d.ts.map +1 -1
- package/dist/src/components/Declaration.js +2 -1
- package/dist/src/components/Declaration.js.map +1 -1
- package/dist/src/components/For.d.ts.map +1 -1
- package/dist/src/components/For.js +1 -1
- package/dist/src/components/For.js.map +1 -1
- package/dist/src/components/List.d.ts.map +1 -1
- package/dist/src/components/List.js +1 -1
- package/dist/src/components/List.js.map +1 -1
- package/dist/src/components/Prose.js +2 -2
- package/dist/src/components/Prose.js.map +1 -1
- package/dist/src/components/Scope.d.ts.map +1 -1
- package/dist/src/components/Scope.js +6 -1
- package/dist/src/components/Scope.js.map +1 -1
- package/dist/src/components/SourceDirectory.d.ts.map +1 -1
- package/dist/src/components/SourceDirectory.js +1 -2
- package/dist/src/components/SourceDirectory.js.map +1 -1
- package/dist/src/components/Switch.d.ts.map +1 -1
- package/dist/src/components/Switch.js +1 -1
- package/dist/src/components/Switch.js.map +1 -1
- package/dist/src/components/TemplateFile.d.ts.map +1 -1
- package/dist/src/components/TemplateFile.js +18 -3
- package/dist/src/components/TemplateFile.js.map +1 -1
- 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 +1 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/content-slot.d.ts.map +1 -1
- package/dist/src/content-slot.js +7 -6
- package/dist/src/content-slot.js.map +1 -1
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.js +10 -3
- package/dist/src/context.js.map +1 -1
- package/dist/src/debug/cli.d.ts +6 -0
- package/dist/src/debug/cli.d.ts.map +1 -0
- package/dist/src/{debug.js → debug/cli.js} +79 -82
- package/dist/src/debug/cli.js.map +1 -0
- package/dist/src/debug/diagnostics.test.d.ts +2 -0
- package/dist/src/debug/diagnostics.test.d.ts.map +1 -0
- package/dist/src/debug/diagnostics.test.js +46 -0
- package/dist/src/debug/diagnostics.test.js.map +1 -0
- package/dist/src/debug/effects.d.ts +81 -0
- package/dist/src/debug/effects.d.ts.map +1 -0
- package/dist/src/debug/effects.js +358 -0
- package/dist/src/debug/effects.js.map +1 -0
- package/dist/src/debug/effects.test.d.ts +2 -0
- package/dist/src/debug/effects.test.d.ts.map +1 -0
- package/dist/src/debug/effects.test.js +256 -0
- package/dist/src/debug/effects.test.js.map +1 -0
- package/dist/src/debug/files.d.ts +14 -0
- package/dist/src/debug/files.d.ts.map +1 -0
- package/dist/src/debug/files.js +29 -0
- package/dist/src/debug/files.js.map +1 -0
- package/dist/src/debug/files.test.d.ts +2 -0
- package/dist/src/debug/files.test.d.ts.map +1 -0
- package/dist/src/debug/files.test.js +66 -0
- package/dist/src/debug/files.test.js.map +1 -0
- package/dist/src/debug/index.d.ts +63 -0
- package/dist/src/debug/index.d.ts.map +1 -0
- package/dist/src/debug/index.js +71 -0
- package/dist/src/debug/index.js.map +1 -0
- package/dist/src/debug/message-format.test.d.ts +2 -0
- package/dist/src/debug/message-format.test.d.ts.map +1 -0
- package/dist/src/debug/message-format.test.js +700 -0
- package/dist/src/debug/message-format.test.js.map +1 -0
- package/dist/src/debug/render-tree-orphans.test.d.ts +2 -0
- package/dist/src/debug/render-tree-orphans.test.d.ts.map +1 -0
- package/dist/src/debug/render-tree-orphans.test.js +297 -0
- package/dist/src/debug/render-tree-orphans.test.js.map +1 -0
- package/dist/src/debug/render.d.ts +57 -0
- package/dist/src/debug/render.d.ts.map +1 -0
- package/dist/src/debug/render.js +472 -0
- package/dist/src/debug/render.js.map +1 -0
- package/dist/src/debug/render.test.d.ts +2 -0
- package/dist/src/debug/render.test.d.ts.map +1 -0
- package/dist/src/debug/render.test.js +291 -0
- package/dist/src/debug/render.test.js.map +1 -0
- package/dist/src/debug/serialize.d.ts +9 -0
- package/dist/src/debug/serialize.d.ts.map +1 -0
- package/dist/src/debug/serialize.js +70 -0
- package/dist/src/debug/serialize.js.map +1 -0
- package/dist/src/debug/symbols.d.ts +16 -0
- package/dist/src/debug/symbols.d.ts.map +1 -0
- package/dist/src/debug/symbols.js +196 -0
- package/dist/src/debug/symbols.js.map +1 -0
- package/dist/src/debug/symbols.test.d.ts +2 -0
- package/dist/src/debug/symbols.test.d.ts.map +1 -0
- package/dist/src/debug/symbols.test.js +93 -0
- package/dist/src/debug/symbols.test.js.map +1 -0
- package/dist/src/debug/trace-writer.d.ts +55 -0
- package/dist/src/debug/trace-writer.d.ts.map +1 -0
- package/dist/src/debug/trace-writer.js +658 -0
- package/dist/src/debug/trace-writer.js.map +1 -0
- package/dist/src/debug/trace.d.ts +342 -0
- package/dist/src/debug/trace.d.ts.map +1 -0
- package/dist/src/debug/trace.js +446 -0
- package/dist/src/debug/trace.js.map +1 -0
- package/dist/src/devtools/devtools-protocol.d.ts +389 -0
- package/dist/src/devtools/devtools-protocol.d.ts.map +1 -0
- package/dist/src/devtools/devtools-protocol.js +2 -0
- package/dist/src/devtools/devtools-protocol.js.map +1 -0
- package/dist/src/devtools/devtools-server.browser.d.ts +23 -0
- package/dist/src/devtools/devtools-server.browser.d.ts.map +1 -0
- package/dist/src/devtools/devtools-server.browser.js +33 -0
- package/dist/src/devtools/devtools-server.browser.js.map +1 -0
- package/dist/src/devtools/devtools-server.d.ts +66 -0
- package/dist/src/devtools/devtools-server.d.ts.map +1 -0
- package/dist/src/devtools/devtools-server.js +444 -0
- package/dist/src/devtools/devtools-server.js.map +1 -0
- package/dist/src/devtools/devtools-transport.d.ts +23 -0
- package/dist/src/devtools/devtools-transport.d.ts.map +1 -0
- package/dist/src/devtools/devtools-transport.js +114 -0
- package/dist/src/devtools/devtools-transport.js.map +1 -0
- package/dist/src/devtools-entry.browser.d.ts +4 -0
- package/dist/src/devtools-entry.browser.d.ts.map +1 -0
- package/dist/src/devtools-entry.browser.js +2 -0
- package/dist/src/devtools-entry.browser.js.map +1 -0
- package/dist/src/devtools-entry.d.ts +4 -0
- package/dist/src/devtools-entry.d.ts.map +1 -0
- package/dist/src/devtools-entry.js +2 -0
- package/dist/src/devtools-entry.js.map +1 -0
- package/dist/src/diagnostics.d.ts +34 -0
- package/dist/src/diagnostics.d.ts.map +1 -0
- package/dist/src/diagnostics.js +89 -0
- package/dist/src/diagnostics.js.map +1 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/print-hook.d.ts +14 -0
- package/dist/src/print-hook.d.ts.map +1 -0
- package/dist/src/print-hook.js +10 -0
- package/dist/src/print-hook.js.map +1 -0
- package/dist/src/reactive-union-set.d.ts.map +1 -1
- package/dist/src/reactive-union-set.js +28 -3
- package/dist/src/reactive-union-set.js.map +1 -1
- package/dist/src/reactivity.d.ts +60 -7
- package/dist/src/reactivity.d.ts.map +1 -1
- package/dist/src/reactivity.js +308 -39
- package/dist/src/reactivity.js.map +1 -1
- package/dist/src/render-stack.d.ts +18 -1
- package/dist/src/render-stack.d.ts.map +1 -1
- package/dist/src/render-stack.js +61 -1
- package/dist/src/render-stack.js.map +1 -1
- package/dist/src/render.d.ts +8 -15
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +424 -109
- package/dist/src/render.js.map +1 -1
- package/dist/src/resource.d.ts.map +1 -1
- package/dist/src/resource.js +5 -0
- package/dist/src/resource.js.map +1 -1
- package/dist/src/scheduler.d.ts +13 -0
- package/dist/src/scheduler.d.ts.map +1 -1
- package/dist/src/scheduler.js +150 -13
- package/dist/src/scheduler.js.map +1 -1
- package/dist/src/symbols/basic-symbol.d.ts.map +1 -1
- package/dist/src/symbols/basic-symbol.js +6 -1
- package/dist/src/symbols/basic-symbol.js.map +1 -1
- package/dist/src/symbols/decl.d.ts.map +1 -1
- package/dist/src/symbols/decl.js +5 -1
- package/dist/src/symbols/decl.js.map +1 -1
- package/dist/src/symbols/output-scope.d.ts +2 -1
- package/dist/src/symbols/output-scope.d.ts.map +1 -1
- package/dist/src/symbols/output-scope.js +13 -8
- package/dist/src/symbols/output-scope.js.map +1 -1
- package/dist/src/symbols/output-symbol.d.ts +1 -0
- package/dist/src/symbols/output-symbol.d.ts.map +1 -1
- package/dist/src/symbols/output-symbol.js +25 -8
- package/dist/src/symbols/output-symbol.js.map +1 -1
- package/dist/src/symbols/symbol-flow.d.ts.map +1 -1
- package/dist/src/symbols/symbol-flow.js +24 -8
- package/dist/src/symbols/symbol-flow.js.map +1 -1
- package/dist/src/symbols/symbol-slot.d.ts.map +1 -1
- package/dist/src/symbols/symbol-slot.js +15 -0
- package/dist/src/symbols/symbol-slot.js.map +1 -1
- package/dist/src/symbols/symbol-slot.test.d.ts +2 -0
- package/dist/src/symbols/symbol-slot.test.d.ts.map +1 -0
- package/dist/src/symbols/symbol-slot.test.js +35 -0
- package/dist/src/symbols/symbol-slot.test.js.map +1 -0
- package/dist/src/symbols/symbol-table.d.ts.map +1 -1
- package/dist/src/symbols/symbol-table.js +6 -5
- package/dist/src/symbols/symbol-table.js.map +1 -1
- package/dist/src/trace.d.ts +2 -0
- package/dist/src/trace.d.ts.map +1 -0
- package/dist/src/trace.js +2 -0
- package/dist/src/trace.js.map +1 -0
- package/dist/src/tracer.d.ts +2 -228
- package/dist/src/tracer.d.ts.map +1 -1
- package/dist/src/tracer.js +5 -298
- package/dist/src/tracer.js.map +1 -1
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +17 -9
- package/dist/src/utils.js.map +1 -1
- package/dist/test/components/append-file.test.d.ts.map +1 -1
- package/dist/test/components/append-file.test.js +18 -10
- package/dist/test/components/append-file.test.js.map +1 -1
- package/dist/test/components/template-file.test.d.ts.map +1 -1
- package/dist/test/components/template-file.test.js +6 -4
- package/dist/test/components/template-file.test.js.map +1 -1
- package/dist/test/lazy-isempty.test.d.ts +2 -0
- package/dist/test/lazy-isempty.test.d.ts.map +1 -0
- package/dist/test/lazy-isempty.test.js +89 -0
- package/dist/test/lazy-isempty.test.js.map +1 -0
- package/dist/test/reactive-union-set-disposers.test.d.ts +2 -0
- package/dist/test/reactive-union-set-disposers.test.d.ts.map +1 -0
- package/dist/test/reactive-union-set-disposers.test.js +98 -0
- package/dist/test/reactive-union-set-disposers.test.js.map +1 -0
- package/dist/test/reactivity/shallow-reactive.test.d.ts +2 -0
- package/dist/test/reactivity/shallow-reactive.test.d.ts.map +1 -0
- package/dist/test/reactivity/shallow-reactive.test.js +52 -0
- package/dist/test/reactivity/shallow-reactive.test.js.map +1 -0
- package/dist/test/rendering/basic.test.js +3 -0
- package/dist/test/rendering/basic.test.js.map +1 -1
- package/dist/test/rendering/print-render-stack.test.d.ts.map +1 -1
- package/dist/test/rendering/print-render-stack.test.js +91 -98
- package/dist/test/rendering/print-render-stack.test.js.map +1 -1
- package/dist/test/scheduler-extended.test.d.ts +2 -0
- package/dist/test/scheduler-extended.test.d.ts.map +1 -0
- package/dist/test/scheduler-extended.test.js +96 -0
- package/dist/test/scheduler-extended.test.js.map +1 -0
- package/dist/test/scheduler.test.d.ts +2 -0
- package/dist/test/scheduler.test.d.ts.map +1 -0
- package/dist/test/scheduler.test.js +46 -0
- package/dist/test/scheduler.test.js.map +1 -0
- package/dist/testing/create-test-wrapper.d.ts +1 -1
- package/dist/testing/create-test-wrapper.d.ts.map +1 -1
- package/dist/testing/create-test-wrapper.js +1 -1
- package/dist/testing/create-test-wrapper.js.map +1 -1
- package/dist/testing/devtools-utils.d.ts +35 -0
- package/dist/testing/devtools-utils.d.ts.map +1 -0
- package/dist/testing/devtools-utils.js +162 -0
- package/dist/testing/devtools-utils.js.map +1 -0
- package/dist/testing/extend-expect.d.ts.map +1 -1
- package/dist/testing/extend-expect.js +63 -1
- package/dist/testing/extend-expect.js.map +1 -1
- package/dist/testing/render.d.ts +2 -2
- package/dist/testing/render.d.ts.map +1 -1
- package/dist/testing/render.js +2 -2
- package/dist/testing/render.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +21 -7
- package/scripts/copy-devtools-ui.mjs +26 -0
- package/src/binder.ts +117 -53
- package/src/components/AccessExpression.test.tsx +132 -0
- package/src/components/AccessExpression.tsx +344 -0
- package/src/components/AppendFile.tsx +14 -9
- package/src/components/Block.tsx +1 -1
- package/src/components/Declaration.tsx +2 -1
- package/src/components/For.tsx +14 -10
- package/src/components/List.tsx +7 -4
- package/src/components/Prose.tsx +1 -1
- package/src/components/Scope.tsx +6 -1
- package/src/components/SourceDirectory.tsx +1 -2
- package/src/components/Switch.tsx +11 -7
- package/src/components/TemplateFile.tsx +18 -9
- package/src/components/index.tsx +1 -0
- package/src/content-slot.tsx +7 -7
- package/src/context.ts +17 -6
- package/src/{debug.ts → debug/cli.ts} +114 -125
- package/src/debug/diagnostics.test.tsx +56 -0
- package/src/debug/effects.test.tsx +301 -0
- package/src/debug/effects.ts +531 -0
- package/src/debug/files.test.tsx +76 -0
- package/src/debug/files.ts +40 -0
- package/src/debug/index.ts +132 -0
- package/src/debug/message-format.test.tsx +759 -0
- package/src/debug/render-tree-orphans.test.tsx +344 -0
- package/src/debug/render.test.tsx +357 -0
- package/src/debug/render.ts +698 -0
- package/src/debug/serialize.ts +85 -0
- package/src/debug/symbols.test.tsx +105 -0
- package/src/debug/symbols.ts +322 -0
- package/src/debug/trace-writer.ts +969 -0
- package/src/debug/trace.ts +309 -0
- package/src/devtools/devtools-protocol.ts +497 -0
- package/src/devtools/devtools-server.browser.ts +62 -0
- package/src/devtools/devtools-server.ts +468 -0
- package/src/devtools/devtools-transport.ts +154 -0
- package/src/devtools-entry.browser.ts +48 -0
- package/src/devtools-entry.ts +48 -0
- package/src/diagnostics.ts +150 -0
- package/src/index.ts +2 -7
- package/src/print-hook.ts +22 -0
- package/src/reactive-union-set.ts +85 -44
- package/src/reactivity.ts +396 -58
- package/src/render-stack.ts +73 -1
- package/src/render.ts +544 -161
- package/src/resource.ts +28 -19
- package/src/scheduler.ts +209 -14
- package/src/symbols/basic-symbol.ts +6 -1
- package/src/symbols/decl.ts +5 -1
- package/src/symbols/output-scope.ts +21 -13
- package/src/symbols/output-symbol.ts +34 -14
- package/src/symbols/symbol-flow.ts +76 -39
- package/src/symbols/symbol-slot.test.tsx +41 -0
- package/src/symbols/symbol-slot.tsx +47 -20
- package/src/symbols/symbol-table.ts +6 -10
- package/src/trace.ts +1 -0
- package/src/tracer.ts +13 -242
- package/src/utils.tsx +31 -21
- package/temp/api.json +5700 -3015
- package/test/components/append-file.test.tsx +36 -29
- package/test/components/template-file.test.tsx +11 -11
- package/test/lazy-isempty.test.tsx +106 -0
- package/test/reactive-union-set-disposers.test.tsx +112 -0
- package/test/reactivity/shallow-reactive.test.tsx +56 -0
- package/test/rendering/basic.test.tsx +4 -0
- package/test/rendering/print-render-stack.test.tsx +52 -43
- package/test/scheduler-extended.test.tsx +122 -0
- package/test/scheduler.test.tsx +50 -0
- package/testing/create-test-wrapper.tsx +1 -1
- package/testing/devtools-utils.ts +245 -0
- package/testing/extend-expect.ts +89 -0
- package/testing/render.ts +2 -2
- package/testing/vitest.d.ts +9 -0
- package/dist/src/debug.d.ts +0 -14
- package/dist/src/debug.d.ts.map +0 -1
- package/dist/src/debug.js.map +0 -1
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Children,
|
|
3
|
+
childrenArray,
|
|
4
|
+
ComponentCreator,
|
|
5
|
+
ComponentDefinition,
|
|
6
|
+
computed,
|
|
7
|
+
isComponentCreator,
|
|
8
|
+
OutputSymbol,
|
|
9
|
+
Refkeyable,
|
|
10
|
+
symbolForRefkey,
|
|
11
|
+
takeSymbols,
|
|
12
|
+
} from "../index.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Base props that all language-specific Part components must include.
|
|
16
|
+
* Language packages extend this with additional props.
|
|
17
|
+
*/
|
|
18
|
+
export interface BasePartProps {
|
|
19
|
+
refkey?: Refkeyable;
|
|
20
|
+
symbol?: OutputSymbol;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for creating a language-specific access expression component.
|
|
25
|
+
*
|
|
26
|
+
* @typeParam TPartProps - The Part component's props type (extends BasePartProps)
|
|
27
|
+
* @typeParam TPart - The descriptor type that formatPart receives
|
|
28
|
+
*/
|
|
29
|
+
export interface AccessExpressionConfig<
|
|
30
|
+
TPartProps extends BasePartProps,
|
|
31
|
+
TPart,
|
|
32
|
+
> {
|
|
33
|
+
/**
|
|
34
|
+
* Convert Part props + resolved symbol into a plain descriptor object.
|
|
35
|
+
* Called once per Part during children processing. The returned descriptor
|
|
36
|
+
* is wrapped in a computed + getter delegation for reactive optimization.
|
|
37
|
+
*/
|
|
38
|
+
createDescriptor(
|
|
39
|
+
props: TPartProps,
|
|
40
|
+
symbol: OutputSymbol | undefined,
|
|
41
|
+
first: boolean,
|
|
42
|
+
): TPart;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Extract the base content from the first part (the leftmost identifier).
|
|
46
|
+
*/
|
|
47
|
+
getBase(part: TPart): Children;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Format a non-first part given its descriptor and the previous part.
|
|
51
|
+
* Returns JSX children for that segment (e.g., `.foo`, `?.bar`, `[idx]`, `(args)`).
|
|
52
|
+
* `inCallChain` is true when rendering inside a chunked call chain.
|
|
53
|
+
*/
|
|
54
|
+
formatPart(part: TPart, prevPart: TPart, inCallChain: boolean): Children;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Identify which parts are function calls, for call chain detection.
|
|
58
|
+
* When provided, the factory uses the chunked call chain algorithm
|
|
59
|
+
* (line breaks after each call group) when more than one call is detected.
|
|
60
|
+
* When omitted, the expression is always formatted linearly.
|
|
61
|
+
*/
|
|
62
|
+
isCallPart?(part: TPart): boolean;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Additional check for whether call chain formatting should be used.
|
|
66
|
+
* Called only when `isCallPart` is provided and more than one call is detected.
|
|
67
|
+
* Return false to force linear formatting (e.g., TypeScript disables call
|
|
68
|
+
* chains when any part has `await`).
|
|
69
|
+
* Defaults to `() => true`.
|
|
70
|
+
*/
|
|
71
|
+
canUseCallChains?(parts: TPart[]): boolean;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Post-process the accumulated expression after each part in linear
|
|
75
|
+
* (non-call-chain) mode. Use this for language-specific wrapping like
|
|
76
|
+
* TypeScript's `await` which wraps the entire expression so far.
|
|
77
|
+
* Defaults to identity (returns expression unchanged).
|
|
78
|
+
*/
|
|
79
|
+
wrapPartResult?(
|
|
80
|
+
expression: Children,
|
|
81
|
+
part: TPart,
|
|
82
|
+
index: number,
|
|
83
|
+
isLast: boolean,
|
|
84
|
+
): Children;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create a language-specific access/member expression component pair.
|
|
89
|
+
*
|
|
90
|
+
* Returns `{ Expression, Part }` where:
|
|
91
|
+
* - `Expression` is the main component that collects Part children and renders the chain
|
|
92
|
+
* - `Part` is a no-op component whose props are consumed by Expression
|
|
93
|
+
*
|
|
94
|
+
* The factory handles:
|
|
95
|
+
* - Children collection and Part filtering
|
|
96
|
+
* - Symbol resolution (refkey → symbol via binder, single computed per part)
|
|
97
|
+
* - Reactive optimization (getter delegation over single computed per part)
|
|
98
|
+
* - Flattening nested Expression instances
|
|
99
|
+
* - `takeSymbols()` to prevent symbol leakage
|
|
100
|
+
* - Call chain detection and chunked formatting algorithm
|
|
101
|
+
*/
|
|
102
|
+
export function createAccessExpression<
|
|
103
|
+
TPartProps extends BasePartProps,
|
|
104
|
+
TPart extends Record<string, unknown>,
|
|
105
|
+
>(config: AccessExpressionConfig<TPartProps, TPart>) {
|
|
106
|
+
// Additional component references to match during flattening.
|
|
107
|
+
// Used when the wrapper function (e.g. MemberExpression) differs
|
|
108
|
+
// from the inner Expression function.
|
|
109
|
+
const outerComponents: ComponentDefinition<any>[] = [];
|
|
110
|
+
|
|
111
|
+
function Expression(props: { children: Children }): Children {
|
|
112
|
+
const children = flattenExpression(childrenArray(() => props.children));
|
|
113
|
+
const parts = collectParts(children);
|
|
114
|
+
takeSymbols();
|
|
115
|
+
|
|
116
|
+
if (parts.length === 0) {
|
|
117
|
+
return <></>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const { isCallPart, canUseCallChains } = config;
|
|
121
|
+
|
|
122
|
+
if (!isCallPart) {
|
|
123
|
+
return formatLinear(config, parts);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const isCallChain = computed(() => {
|
|
127
|
+
if (canUseCallChains && !canUseCallChains(parts)) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
let callCount = 0;
|
|
131
|
+
for (const part of parts) {
|
|
132
|
+
if (isCallPart(part)) callCount++;
|
|
133
|
+
}
|
|
134
|
+
return callCount > 1;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return () => {
|
|
138
|
+
return isCallChain.value ?
|
|
139
|
+
formatCallChain(config, parts)
|
|
140
|
+
: formatLinear(config, parts);
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function Part(_props: TPartProps) {
|
|
145
|
+
// No-op — props are consumed by the parent Expression component.
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function isExpressionComponent(child: unknown): boolean {
|
|
149
|
+
if (isComponentCreator(child, Expression)) return true;
|
|
150
|
+
for (const comp of outerComponents) {
|
|
151
|
+
if (isComponentCreator(child, comp as any)) return true;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function flattenExpression(children: Children[]): Children[] {
|
|
157
|
+
const flattened: Children[] = [];
|
|
158
|
+
for (const child of children) {
|
|
159
|
+
if (isExpressionComponent(child)) {
|
|
160
|
+
flattened.push(
|
|
161
|
+
...flattenExpression(
|
|
162
|
+
childrenArray(() => (child as ComponentCreator).props.children),
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
} else {
|
|
166
|
+
flattened.push(child);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return flattened;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function collectParts(children: Children[]): TPart[] {
|
|
173
|
+
const parts: TPart[] = [];
|
|
174
|
+
for (const child of children) {
|
|
175
|
+
if (!isComponentCreator(child, Part)) continue;
|
|
176
|
+
const partProps = child.props as TPartProps;
|
|
177
|
+
const first = parts.length === 0;
|
|
178
|
+
|
|
179
|
+
const symbolSource = computed(() => {
|
|
180
|
+
if (partProps.refkey) {
|
|
181
|
+
return symbolForRefkey(partProps.refkey).value;
|
|
182
|
+
} else if (partProps.symbol) {
|
|
183
|
+
return partProps.symbol;
|
|
184
|
+
}
|
|
185
|
+
return undefined;
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const desc = computed(() =>
|
|
189
|
+
config.createDescriptor(partProps, symbolSource.value, first),
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
// Create getter-delegation object for reactive optimization.
|
|
193
|
+
// Property access on this object tracks the single `desc` computed.
|
|
194
|
+
const keys = Object.keys(
|
|
195
|
+
config.createDescriptor(partProps, undefined, first),
|
|
196
|
+
);
|
|
197
|
+
const proxy: Record<string, unknown> = {};
|
|
198
|
+
for (const key of keys) {
|
|
199
|
+
Object.defineProperty(proxy, key, {
|
|
200
|
+
get() {
|
|
201
|
+
return (desc.value as Record<string, unknown>)[key];
|
|
202
|
+
},
|
|
203
|
+
enumerable: true,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
parts.push(proxy as TPart);
|
|
208
|
+
}
|
|
209
|
+
return parts;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Register an outer wrapper component for flattening support.
|
|
214
|
+
* Call this after creating the wrapper function:
|
|
215
|
+
* `registerOuterComponent(MemberExpression);`
|
|
216
|
+
*/
|
|
217
|
+
function registerOuterComponent(component: ComponentDefinition<any>) {
|
|
218
|
+
outerComponents.push(component);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return { Expression, Part, registerOuterComponent };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Format parts linearly (no call chain grouping).
|
|
226
|
+
*/
|
|
227
|
+
function formatLinear<TPartProps extends BasePartProps, TPart>(
|
|
228
|
+
config: AccessExpressionConfig<TPartProps, TPart>,
|
|
229
|
+
parts: TPart[],
|
|
230
|
+
): Children {
|
|
231
|
+
return computed(() => {
|
|
232
|
+
let expression: Children = [];
|
|
233
|
+
|
|
234
|
+
for (let i = 0; i < parts.length; i++) {
|
|
235
|
+
const part = parts[i];
|
|
236
|
+
|
|
237
|
+
if (i === 0) {
|
|
238
|
+
(expression as Children[]).push(config.getBase(part));
|
|
239
|
+
} else {
|
|
240
|
+
const prevPart = parts[i - 1];
|
|
241
|
+
const partExpr = config.formatPart(part, prevPart, false);
|
|
242
|
+
|
|
243
|
+
if (Array.isArray(expression)) {
|
|
244
|
+
expression.push(partExpr);
|
|
245
|
+
} else {
|
|
246
|
+
expression = (
|
|
247
|
+
<>
|
|
248
|
+
{expression}
|
|
249
|
+
{partExpr}
|
|
250
|
+
</>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (config.wrapPartResult) {
|
|
256
|
+
expression = config.wrapPartResult(
|
|
257
|
+
expression,
|
|
258
|
+
part,
|
|
259
|
+
i,
|
|
260
|
+
i === parts.length - 1,
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return expression;
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Format parts as a call chain with indented line breaks at call boundaries.
|
|
271
|
+
*/
|
|
272
|
+
function formatCallChain<TPartProps extends BasePartProps, TPart>(
|
|
273
|
+
config: AccessExpressionConfig<TPartProps, TPart>,
|
|
274
|
+
parts: TPart[],
|
|
275
|
+
): Children {
|
|
276
|
+
return computed(() => {
|
|
277
|
+
const expression: Children[] = [];
|
|
278
|
+
const chunks: TPart[][] = [];
|
|
279
|
+
let pi = 0;
|
|
280
|
+
|
|
281
|
+
function pushPart() {
|
|
282
|
+
chunks.at(-1)!.push(parts[pi]);
|
|
283
|
+
pi++;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function pushChunk() {
|
|
287
|
+
chunks.push([]);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// First chunk: take parts up to and including the first call
|
|
291
|
+
pushChunk();
|
|
292
|
+
while (
|
|
293
|
+
pi < parts.length &&
|
|
294
|
+
(pi === parts.length - 1 ||
|
|
295
|
+
chunks.at(-1)!.length === 0 ||
|
|
296
|
+
!config.isCallPart!(parts[pi + 1]))
|
|
297
|
+
) {
|
|
298
|
+
pushPart();
|
|
299
|
+
if (config.isCallPart!(chunks.at(-1)!.at(-1)!)) {
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Remaining chunks: collect non-call parts then call parts
|
|
305
|
+
while (pi < parts.length) {
|
|
306
|
+
pushChunk();
|
|
307
|
+
while (pi < parts.length && !config.isCallPart!(parts[pi])) {
|
|
308
|
+
pushPart();
|
|
309
|
+
}
|
|
310
|
+
while (pi < parts.length && config.isCallPart!(parts[pi])) {
|
|
311
|
+
pushPart();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
for (let ci = 0; ci < chunks.length; ci++) {
|
|
316
|
+
const chunk = chunks[ci];
|
|
317
|
+
const chunkExpr = [];
|
|
318
|
+
for (let cpi = 0; cpi < chunk.length; cpi++) {
|
|
319
|
+
if (ci === 0 && cpi === 0) {
|
|
320
|
+
chunkExpr.push(config.getBase(chunk[0]));
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
const part = chunk[cpi];
|
|
324
|
+
const prevPart = cpi === 0 ? chunks[ci - 1].at(-1)! : chunk[cpi - 1];
|
|
325
|
+
chunkExpr.push(config.formatPart(part, prevPart, true));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
expression.push(
|
|
329
|
+
ci === 0 ? chunkExpr : (
|
|
330
|
+
<>
|
|
331
|
+
<sbr />
|
|
332
|
+
{chunkExpr}
|
|
333
|
+
</>
|
|
334
|
+
),
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return (
|
|
339
|
+
<group>
|
|
340
|
+
<indent>{expression}</indent>
|
|
341
|
+
</group>
|
|
342
|
+
);
|
|
343
|
+
});
|
|
344
|
+
}
|
|
@@ -2,6 +2,7 @@ import { computed } from "@vue/reactivity";
|
|
|
2
2
|
import { join } from "pathe";
|
|
3
3
|
import { useContext } from "../context.js";
|
|
4
4
|
import { SourceDirectoryContext } from "../context/source-directory.js";
|
|
5
|
+
import { emitDiagnostic } from "../diagnostics.js";
|
|
5
6
|
import { createFileResource } from "../resource.js";
|
|
6
7
|
import { Children, isComponentCreator } from "../runtime/component.js";
|
|
7
8
|
import { childrenArray } from "../utils.jsx";
|
|
@@ -98,9 +99,11 @@ export function AppendFile(props: AppendFileProps): Children {
|
|
|
98
99
|
} else if ("content" in regionProps) {
|
|
99
100
|
content = regionProps.content;
|
|
100
101
|
} else {
|
|
101
|
-
|
|
102
|
-
`AppendRegion "${regionProps.id}" must have either children or content`,
|
|
103
|
-
|
|
102
|
+
emitDiagnostic({
|
|
103
|
+
message: `AppendRegion "${regionProps.id}" must have either children or content`,
|
|
104
|
+
severity: "error",
|
|
105
|
+
});
|
|
106
|
+
// Still register the region to avoid duplicate "region not found" diagnostic
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
appendRegions[regionProps.id] = content;
|
|
@@ -115,9 +118,10 @@ export function AppendFile(props: AppendFileProps): Children {
|
|
|
115
118
|
// Validate that all requested regions have corresponding AppendRegion children
|
|
116
119
|
for (const regionId of regions) {
|
|
117
120
|
if (!(regionId in appendRegions)) {
|
|
118
|
-
|
|
119
|
-
`Region "${regionId}" specified but no corresponding AppendRegion child found`,
|
|
120
|
-
|
|
121
|
+
emitDiagnostic({
|
|
122
|
+
message: `Region "${regionId}" specified but no corresponding AppendRegion child found`,
|
|
123
|
+
severity: "error",
|
|
124
|
+
});
|
|
121
125
|
}
|
|
122
126
|
}
|
|
123
127
|
|
|
@@ -181,9 +185,10 @@ export function AppendFile(props: AppendFileProps): Children {
|
|
|
181
185
|
for (const regionId of regions) {
|
|
182
186
|
const info = sigilInfo[regionId];
|
|
183
187
|
if (info && info.start !== null && info.end === null) {
|
|
184
|
-
|
|
185
|
-
`Region "${regionId}" has start sigil but no corresponding end sigil`,
|
|
186
|
-
|
|
188
|
+
emitDiagnostic({
|
|
189
|
+
message: `Region "${regionId}" has start sigil but no corresponding end sigil`,
|
|
190
|
+
severity: "error",
|
|
191
|
+
});
|
|
187
192
|
}
|
|
188
193
|
}
|
|
189
194
|
|
package/src/components/Block.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createSymbol } from "../binder.js";
|
|
1
2
|
import { useContext } from "../context.js";
|
|
2
3
|
import { BinderContext } from "../context/binder.js";
|
|
3
4
|
import { DeclarationContext } from "../context/declaration.js";
|
|
@@ -83,7 +84,7 @@ export function Declaration(props: DeclarationProps) {
|
|
|
83
84
|
);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
declaration =
|
|
87
|
+
declaration = createSymbol(BasicSymbol, props.name, scope.symbols, {
|
|
87
88
|
binder,
|
|
88
89
|
refkeys: [props.refkey ?? []].flat(),
|
|
89
90
|
metadata: props.metadata,
|
package/src/components/For.tsx
CHANGED
|
@@ -80,15 +80,19 @@ export function For<
|
|
|
80
80
|
const cb = props.children;
|
|
81
81
|
const options = baseListPropsToMapJoinArgs(props);
|
|
82
82
|
options.skipFalsy = props.skipFalsy;
|
|
83
|
-
return memo(
|
|
84
|
-
|
|
83
|
+
return memo(
|
|
84
|
+
() => {
|
|
85
|
+
const maybeRef = props.each;
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
return (mapJoin as any)(
|
|
88
|
+
typeof maybeRef === "function" ? maybeRef : (
|
|
89
|
+
() => (isRef(maybeRef) ? maybeRef.value : maybeRef)
|
|
90
|
+
),
|
|
91
|
+
cb,
|
|
92
|
+
options,
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
undefined,
|
|
96
|
+
"For",
|
|
97
|
+
);
|
|
94
98
|
}
|
package/src/components/List.tsx
CHANGED
|
@@ -57,10 +57,13 @@ export interface ListProps extends BaseListProps {
|
|
|
57
57
|
*/
|
|
58
58
|
export function List(props: ListProps) {
|
|
59
59
|
const [rest, forProps] = splitProps(props, ["children"]);
|
|
60
|
-
const resolvedChildren = memo(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
const resolvedChildren = memo(
|
|
61
|
+
() =>
|
|
62
|
+
childrenArray(() => rest.children, {
|
|
63
|
+
preserveFragments: true,
|
|
64
|
+
}),
|
|
65
|
+
undefined,
|
|
66
|
+
"List:children",
|
|
64
67
|
);
|
|
65
68
|
return (
|
|
66
69
|
<For each={resolvedChildren} {...forProps} skipFalsy>
|
package/src/components/Prose.tsx
CHANGED
package/src/components/Scope.tsx
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { createScope } from "../binder.js";
|
|
1
2
|
import { ScopeContext, useScope } from "../context/scope.js";
|
|
3
|
+
import { debug } from "../debug/index.js";
|
|
2
4
|
import type { Children } from "../runtime/component.js";
|
|
3
5
|
import { BasicScope } from "../symbols/basic-scope.js";
|
|
4
6
|
import { OutputScope } from "../symbols/output-scope.js";
|
|
@@ -51,6 +53,7 @@ export function Scope(props: ScopeProps) {
|
|
|
51
53
|
let scope: OutputScope;
|
|
52
54
|
if ("value" in props) {
|
|
53
55
|
scope = props.value;
|
|
56
|
+
debug.symbols.relocateScope(scope);
|
|
54
57
|
} else {
|
|
55
58
|
const parentScope = useScope();
|
|
56
59
|
if (parentScope && !(parentScope instanceof BasicScope)) {
|
|
@@ -58,7 +61,9 @@ export function Scope(props: ScopeProps) {
|
|
|
58
61
|
"Scope component can only make scopes within a BasicScope",
|
|
59
62
|
);
|
|
60
63
|
}
|
|
61
|
-
|
|
64
|
+
const binder = parentScope?.binder;
|
|
65
|
+
scope = createScope(BasicScope, props.name ?? "", parentScope, {
|
|
66
|
+
binder,
|
|
62
67
|
metadata: props.metadata,
|
|
63
68
|
ownerSymbol: props.ownerSymbol,
|
|
64
69
|
});
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { shallowReactive } from "@vue/reactivity";
|
|
2
1
|
import { join } from "pathe";
|
|
3
2
|
import { useContext } from "../context.js";
|
|
4
3
|
import { SourceDirectoryContext } from "../context/source-directory.js";
|
|
5
|
-
import { getContext } from "../reactivity.js";
|
|
4
|
+
import { getContext, shallowReactive } from "../reactivity.js";
|
|
6
5
|
import type { Children } from "../runtime/component.js";
|
|
7
6
|
|
|
8
7
|
export interface SourceDirectoryProps {
|
|
@@ -27,15 +27,19 @@ export function Switch(props: SwitchProps) {
|
|
|
27
27
|
const children = childrenArray(() => props.children);
|
|
28
28
|
const matches = findKeyedChildren(children, matchTag);
|
|
29
29
|
|
|
30
|
-
return memo(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
return memo(
|
|
31
|
+
() => {
|
|
32
|
+
for (const match of matches) {
|
|
33
|
+
if (match.props.when || match.props.else) {
|
|
34
|
+
return match.props.children;
|
|
35
|
+
}
|
|
34
36
|
}
|
|
35
|
-
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
return undefined;
|
|
39
|
+
},
|
|
40
|
+
undefined,
|
|
41
|
+
"Switch",
|
|
42
|
+
);
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
export interface MatchProps {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { computed } from "@vue/reactivity";
|
|
2
|
+
import { emitDiagnostic } from "../diagnostics.js";
|
|
2
3
|
import { createFileResource } from "../resource.js";
|
|
3
4
|
import { Children, isComponentCreator } from "../runtime/component.js";
|
|
4
5
|
import { childrenArray } from "../utils.jsx";
|
|
@@ -85,9 +86,12 @@ export function TemplateFile(props: TemplateFileProps): Children {
|
|
|
85
86
|
} else if ("value" in variableProps) {
|
|
86
87
|
value = variableProps.value;
|
|
87
88
|
} else {
|
|
88
|
-
|
|
89
|
-
`TemplateVariable "${variableProps.name}" must have either children or value`,
|
|
90
|
-
|
|
89
|
+
emitDiagnostic({
|
|
90
|
+
message: `TemplateVariable "${variableProps.name}" must have either children or value`,
|
|
91
|
+
severity: "error",
|
|
92
|
+
});
|
|
93
|
+
// Still register the variable to avoid duplicate diagnostics
|
|
94
|
+
value = "";
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
templateVariables[variableProps.name] = value;
|
|
@@ -100,9 +104,11 @@ export function TemplateFile(props: TemplateFileProps): Children {
|
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
if (templateResource.error) {
|
|
103
|
-
|
|
104
|
-
`Failed to read template file "${props.src}": ${templateResource.error}`,
|
|
105
|
-
|
|
107
|
+
emitDiagnostic({
|
|
108
|
+
message: `Failed to read template file "${props.src}": ${templateResource.error}`,
|
|
109
|
+
severity: "error",
|
|
110
|
+
});
|
|
111
|
+
return "";
|
|
106
112
|
}
|
|
107
113
|
|
|
108
114
|
const templateContent = templateResource.data!;
|
|
@@ -131,9 +137,12 @@ export function TemplateFile(props: TemplateFileProps): Children {
|
|
|
131
137
|
if (variableName in templateVariables) {
|
|
132
138
|
result.push(templateVariables[variableName]);
|
|
133
139
|
} else {
|
|
134
|
-
|
|
135
|
-
`Template variable "${variableName}" not found in TemplateVariable children`,
|
|
136
|
-
|
|
140
|
+
emitDiagnostic({
|
|
141
|
+
message: `Template variable "${variableName}" not found in TemplateVariable children`,
|
|
142
|
+
severity: "error",
|
|
143
|
+
});
|
|
144
|
+
// Keep the placeholder in the output to make the error visible
|
|
145
|
+
result.push(`{{ ${variableName} }}`);
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
lastIndex = matchStart + fullMatch.length;
|
package/src/components/index.tsx
CHANGED
package/src/content-slot.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { computed, Ref, shallowRef } from "@vue/reactivity";
|
|
2
2
|
import { Show } from "./components/Show.jsx";
|
|
3
|
-
import { getContext } from "./reactivity.js";
|
|
3
|
+
import { ensureIsEmpty, getContext } from "./reactivity.js";
|
|
4
4
|
import { Children, Component } from "./runtime/component.js";
|
|
5
5
|
|
|
6
6
|
export interface ContentSlot {
|
|
@@ -54,14 +54,14 @@ export interface ContentSlot {
|
|
|
54
54
|
* ```
|
|
55
55
|
*/
|
|
56
56
|
export function createContentSlot(): ContentSlot {
|
|
57
|
-
|
|
57
|
+
// Holds a reference to the rendering context's isEmpty ref once ContentSlot
|
|
58
|
+
// renders. Before that, reads fall through to a default of "not empty".
|
|
59
|
+
const isEmptySource = shallowRef<Ref<boolean>>();
|
|
60
|
+
const isEmpty = computed(() => isEmptySource.value?.value ?? false);
|
|
58
61
|
|
|
59
62
|
function ContentSlot(props: { children: Children }) {
|
|
60
63
|
const context = getContext()!;
|
|
61
|
-
|
|
62
|
-
isEmpty.value = context.isEmpty!.value;
|
|
63
|
-
});
|
|
64
|
-
|
|
64
|
+
isEmptySource.value = ensureIsEmpty(context);
|
|
65
65
|
return props.children;
|
|
66
66
|
}
|
|
67
67
|
ContentSlot.ref = isEmpty;
|
package/src/context.ts
CHANGED
|
@@ -20,8 +20,8 @@ export function useContext<T>(context: ComponentContext<T>): T | undefined {
|
|
|
20
20
|
// context must come from a parent
|
|
21
21
|
let current = getContext();
|
|
22
22
|
while (current) {
|
|
23
|
-
if (Object.hasOwn(current.context
|
|
24
|
-
return current.context
|
|
23
|
+
if (current.context && Object.hasOwn(current.context, context.id)) {
|
|
24
|
+
return current.context[context.id] as T | undefined;
|
|
25
25
|
}
|
|
26
26
|
current = current.owner;
|
|
27
27
|
}
|
|
@@ -38,12 +38,22 @@ export function createContext<T = unknown>(
|
|
|
38
38
|
const id = Symbol(name ?? "context");
|
|
39
39
|
function Provider(props: ContextProviderProps<T>) {
|
|
40
40
|
const context = getContext();
|
|
41
|
+
const contextName = name ?? "anonymous";
|
|
41
42
|
|
|
42
43
|
const rendered = shallowRef();
|
|
43
|
-
effect(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
effect(
|
|
45
|
+
() => {
|
|
46
|
+
(context!.context ??= {})[id] = props.value;
|
|
47
|
+
rendered.value = () => props.children;
|
|
48
|
+
},
|
|
49
|
+
undefined,
|
|
50
|
+
{
|
|
51
|
+
debug: {
|
|
52
|
+
name: `context:provider:${contextName}`,
|
|
53
|
+
type: "context",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
);
|
|
47
57
|
|
|
48
58
|
return rendered.value;
|
|
49
59
|
}
|
|
@@ -54,6 +64,7 @@ export function createContext<T = unknown>(
|
|
|
54
64
|
Provider,
|
|
55
65
|
ProviderStc: stc(Provider),
|
|
56
66
|
};
|
|
67
|
+
(Provider as any).contextName = name;
|
|
57
68
|
contextsByKey.set(id, ctx);
|
|
58
69
|
return ctx;
|
|
59
70
|
}
|