@alloy-js/core 0.3.0 → 0.4.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.
Files changed (136) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/src/binder.d.ts +28 -5
  3. package/dist/src/binder.d.ts.map +1 -1
  4. package/dist/src/binder.js +107 -7
  5. package/dist/src/binder.js.map +1 -1
  6. package/dist/src/components/Declaration.d.ts +1 -1
  7. package/dist/src/components/Declaration.d.ts.map +1 -1
  8. package/dist/src/components/Declaration.js.map +1 -1
  9. package/dist/src/components/Indent.d.ts +1 -1
  10. package/dist/src/components/Indent.d.ts.map +1 -1
  11. package/dist/src/components/Indent.js.map +1 -1
  12. package/dist/src/components/MemberDeclaration.d.ts +1 -1
  13. package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
  14. package/dist/src/components/MemberDeclaration.js.map +1 -1
  15. package/dist/src/components/MemberScope.d.ts +1 -1
  16. package/dist/src/components/MemberScope.d.ts.map +1 -1
  17. package/dist/src/components/Output.d.ts +1 -1
  18. package/dist/src/components/Output.d.ts.map +1 -1
  19. package/dist/src/components/Output.js +5 -3
  20. package/dist/src/components/Output.js.map +1 -1
  21. package/dist/src/components/Scope.d.ts +1 -1
  22. package/dist/src/components/Scope.d.ts.map +1 -1
  23. package/dist/src/components/Scope.js.map +1 -1
  24. package/dist/src/components/SourceDirectory.d.ts +1 -1
  25. package/dist/src/components/SourceDirectory.d.ts.map +1 -1
  26. package/dist/src/components/SourceDirectory.js +1 -1
  27. package/dist/src/components/SourceDirectory.js.map +1 -1
  28. package/dist/src/components/SourceFile.d.ts +1 -1
  29. package/dist/src/components/SourceFile.d.ts.map +1 -1
  30. package/dist/src/components/SourceFile.js +1 -1
  31. package/dist/src/components/SourceFile.js.map +1 -1
  32. package/dist/src/context/assignment.d.ts.map +1 -1
  33. package/dist/src/context/assignment.js +2 -2
  34. package/dist/src/context/assignment.js.map +1 -1
  35. package/dist/src/context/binder.d.ts.map +1 -1
  36. package/dist/src/context/binder.js +2 -2
  37. package/dist/src/context/binder.js.map +1 -1
  38. package/dist/src/context/declaration.d.ts.map +1 -1
  39. package/dist/src/context/declaration.js +2 -2
  40. package/dist/src/context/declaration.js.map +1 -1
  41. package/dist/src/context/indent.d.ts.map +1 -1
  42. package/dist/src/context/indent.js +2 -2
  43. package/dist/src/context/indent.js.map +1 -1
  44. package/dist/src/context/member-declaration.d.ts.map +1 -1
  45. package/dist/src/context/member-declaration.js +2 -2
  46. package/dist/src/context/member-declaration.js.map +1 -1
  47. package/dist/src/context/member-scope.d.ts.map +1 -1
  48. package/dist/src/context/member-scope.js +2 -2
  49. package/dist/src/context/member-scope.js.map +1 -1
  50. package/dist/src/context/name-policy.d.ts.map +1 -1
  51. package/dist/src/context/name-policy.js +2 -2
  52. package/dist/src/context/name-policy.js.map +1 -1
  53. package/dist/src/context/scope.d.ts.map +1 -1
  54. package/dist/src/context/scope.js +2 -2
  55. package/dist/src/context/scope.js.map +1 -1
  56. package/dist/src/context/source-directory.d.ts.map +1 -1
  57. package/dist/src/context/source-directory.js +2 -2
  58. package/dist/src/context/source-directory.js.map +1 -1
  59. package/dist/src/context/source-file.d.ts.map +1 -1
  60. package/dist/src/context/source-file.js +2 -2
  61. package/dist/src/context/source-file.js.map +1 -1
  62. package/dist/src/context.d.ts +5 -2
  63. package/dist/src/context.d.ts.map +1 -1
  64. package/dist/src/context.js +11 -4
  65. package/dist/src/context.js.map +1 -1
  66. package/dist/src/debug.d.ts +14 -0
  67. package/dist/src/debug.d.ts.map +1 -0
  68. package/dist/src/debug.js +163 -0
  69. package/dist/src/debug.js.map +1 -0
  70. package/dist/src/index.d.ts +2 -1
  71. package/dist/src/index.d.ts.map +1 -1
  72. package/dist/src/index.js +2 -1
  73. package/dist/src/index.js.map +1 -1
  74. package/dist/src/jsx-runtime.d.ts +6 -2
  75. package/dist/src/jsx-runtime.d.ts.map +1 -1
  76. package/dist/src/jsx-runtime.js +8 -6
  77. package/dist/src/jsx-runtime.js.map +1 -1
  78. package/dist/src/render.d.ts +1 -1
  79. package/dist/src/render.d.ts.map +1 -1
  80. package/dist/src/render.js +3 -3
  81. package/dist/src/render.js.map +1 -1
  82. package/dist/src/slot.d.ts +15 -0
  83. package/dist/src/slot.d.ts.map +1 -0
  84. package/dist/src/slot.js +51 -0
  85. package/dist/src/slot.js.map +1 -0
  86. package/dist/src/utils.d.ts +2 -7
  87. package/dist/src/utils.d.ts.map +1 -1
  88. package/dist/src/utils.js +1 -34
  89. package/dist/src/utils.js.map +1 -1
  90. package/dist/src/write-output.browser.d.ts +2 -0
  91. package/dist/src/write-output.browser.d.ts.map +1 -0
  92. package/dist/src/write-output.browser.js +4 -0
  93. package/dist/src/write-output.browser.js.map +1 -0
  94. package/dist/src/write-output.d.ts +7 -0
  95. package/dist/src/write-output.d.ts.map +1 -0
  96. package/dist/src/write-output.js +34 -0
  97. package/dist/src/write-output.js.map +1 -0
  98. package/dist/test/components/slot.test.d.ts +2 -0
  99. package/dist/test/components/slot.test.d.ts.map +1 -0
  100. package/dist/testing/render.d.ts +1 -1
  101. package/dist/testing/render.d.ts.map +1 -1
  102. package/dist/tsconfig.tsbuildinfo +1 -1
  103. package/package.json +8 -5
  104. package/src/binder.ts +181 -6
  105. package/src/components/Declaration.tsx +1 -1
  106. package/src/components/Indent.tsx +1 -1
  107. package/src/components/MemberDeclaration.tsx +1 -1
  108. package/src/components/MemberScope.tsx +1 -1
  109. package/src/components/Output.tsx +3 -2
  110. package/src/components/Scope.tsx +1 -1
  111. package/src/components/SourceDirectory.tsx +1 -1
  112. package/src/components/SourceFile.tsx +1 -5
  113. package/src/context/assignment.ts +6 -2
  114. package/src/context/binder.ts +7 -2
  115. package/src/context/declaration.ts +2 -2
  116. package/src/context/indent.ts +13 -6
  117. package/src/context/member-declaration.ts +2 -2
  118. package/src/context/member-scope.ts +6 -2
  119. package/src/context/name-policy.ts +6 -2
  120. package/src/context/scope.ts +7 -2
  121. package/src/context/source-directory.ts +2 -2
  122. package/src/context/source-file.ts +2 -2
  123. package/src/context.ts +15 -4
  124. package/src/debug.ts +209 -0
  125. package/src/index.ts +2 -1
  126. package/src/jsx-runtime.ts +19 -8
  127. package/src/render.ts +8 -8
  128. package/src/slot.ts +90 -0
  129. package/src/utils.ts +2 -34
  130. package/src/write-output.browser.ts +3 -0
  131. package/src/write-output.ts +33 -0
  132. package/temp/api.json +575 -69
  133. package/test/components/slot.test.tsx +172 -0
  134. package/test/rendering/basic.test.tsx +1 -1
  135. package/test/symbols.test.ts +102 -0
  136. package/testing/render.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alloy-js/core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "",
5
5
  "main": "./dist/src/index.js",
6
6
  "exports": {
@@ -25,6 +25,10 @@
25
25
  "import": "./dist/src/components/index.js"
26
26
  }
27
27
  },
28
+ "browser": {
29
+ "./dist/src/write-output.js": "./dist/src/write-output.browser.js",
30
+ "./src/write-output.ts": "./src/write-output.browser.ts"
31
+ },
28
32
  "keywords": [],
29
33
  "author": "brian.terlson@microsoft.com",
30
34
  "license": "MIT",
@@ -32,6 +36,8 @@
32
36
  "@babel/core": "^7.24.7",
33
37
  "@babel/preset-typescript": "^7.24.7",
34
38
  "@vue/reactivity": "^3.4.30",
39
+ "chalk": "^5.3.0",
40
+ "cli-table3": "^0.6.5",
35
41
  "pathe": "^1.1.2",
36
42
  "@alloy-js/babel-preset": "~0.1.1"
37
43
  },
@@ -42,10 +48,7 @@
42
48
  "@rollup/plugin-typescript": "^11.1.6",
43
49
  "concurrently": "^8.2.2",
44
50
  "typescript": "^5.5.4",
45
- "vitest": "^2.0.5"
46
- },
47
- "overrides": {
48
- "esbuild": "0.23"
51
+ "vitest": "^3.0.4"
49
52
  },
50
53
  "type": "module",
51
54
  "scripts": {
package/src/binder.ts CHANGED
@@ -1,14 +1,15 @@
1
- import { memo } from "@alloy-js/core/jsx-runtime";
2
1
  import {
3
2
  computed,
4
3
  effect,
5
4
  reactive,
5
+ ref,
6
6
  Ref,
7
7
  ShallowRef,
8
8
  shallowRef,
9
9
  } from "@vue/reactivity";
10
10
  import { useMemberScope } from "./context/member-scope.js";
11
11
  import { useScope } from "./context/scope.js";
12
+ import { memo, untrack } from "./jsx-runtime.js";
12
13
  import { refkey, Refkey } from "./refkey.js";
13
14
  export type Metadata = object;
14
15
 
@@ -302,6 +303,42 @@ export interface Binder {
302
303
  key: Refkey,
303
304
  ): Ref<ResolutionResult<TScope, TSymbol> | undefined>;
304
305
 
306
+ /**
307
+ * Find a symbol with a given name in the given scope. Returns a ref
308
+ * for the symbol, such that when the symbol is available, the ref value
309
+ * will update.
310
+ */
311
+ findSymbolName<
312
+ TScope extends OutputScope = OutputScope,
313
+ TSymbol extends OutputSymbol = OutputSymbol,
314
+ >(
315
+ currentScope: TScope | undefined,
316
+ name: string,
317
+ ): Ref<TSymbol | undefined>;
318
+
319
+ findScopeName<TScope extends OutputScope = OutputScope>(
320
+ currentScope: TScope | undefined,
321
+ name: string,
322
+ ): Ref<TScope | undefined>;
323
+
324
+ /**
325
+ * Resolve a fully qualified name to a symbol. Access a nested scope by name
326
+ * with `::`, a nested static member with `.` and a nested instance member
327
+ * with `#`.
328
+ *
329
+ * Per-language packages may provide their own resolveFQN function that uses
330
+ * syntax more natural to that language.
331
+ */
332
+ resolveFQN<
333
+ TScope extends OutputScope = OutputScope,
334
+ TSymbol extends OutputSymbol = OutputSymbol,
335
+ >(
336
+ fqn: string,
337
+ ): Ref<TSymbol | TScope | undefined>;
338
+
339
+ /**
340
+ * The global scope. This is the root scope for all symbols.
341
+ */
305
342
  globalScope: OutputScope;
306
343
  }
307
344
 
@@ -325,11 +362,15 @@ export interface Binder {
325
362
  * When we resolve the refkey for `bar` from within `namespace scope 2`, we will get the following
326
363
  * resolution result:
327
364
  *
328
- * * **targetDeclaration**: symbol bar, the symbol we resolved.
329
- * * **commonScope**: global scope, because this is the most specific scope that contains both the declaration and the reference.
330
- * * **pathUp**: [namespace scope 2], because this is the scope between the reference and the common scope.
331
- * * **pathDown**: [namespace scope 1], because this is the scope between the common scope and the declaration
332
- * * **memberPath**: [foo, bar], because we resolved a member symbol and these are the symbols that lead from the base declaration to the member symbol.
365
+ * **targetDeclaration**: symbol bar, the symbol we resolved.
366
+ *
367
+ * **commonScope**: global scope, because this is the most specific scope that contains both the declaration and the reference.
368
+ *
369
+ * **pathUp**: [namespace scope 2], because this is the scope between the reference and the common scope.
370
+ *
371
+ * **pathDown**: [namespace scope 1], because this is the scope between the common scope and the declaration
372
+ *
373
+ * **memberPath**: [foo, bar], because we resolved a member symbol and these are the symbols that lead from the base declaration to the member symbol.
333
374
  */
334
375
  export interface ResolutionResult<
335
376
  TScope extends OutputScope,
@@ -377,6 +418,9 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
377
418
  addStaticMembersToSymbol,
378
419
  addInstanceMembersToSymbol,
379
420
  instantiateSymbolInto,
421
+ findSymbolName,
422
+ findScopeName,
423
+ resolveFQN: resolveFQN as any,
380
424
  globalScope: undefined as any,
381
425
  };
382
426
 
@@ -396,6 +440,14 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
396
440
 
397
441
  const knownDeclarations = new Map<Refkey, OutputSymbol>();
398
442
  const waitingDeclarations = new Map<Refkey, Ref<OutputSymbol | undefined>>();
443
+ const waitingSymbolNames = new Map<
444
+ OutputScope,
445
+ Map<string, Ref<OutputSymbol | undefined>>
446
+ >();
447
+ const waitingScopeNames = new Map<
448
+ OutputScope,
449
+ Map<string, Ref<OutputScope | undefined>>
450
+ >();
399
451
 
400
452
  return binder;
401
453
 
@@ -454,6 +506,14 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
454
506
  parentScope.children.add(scope);
455
507
  }
456
508
 
509
+ if (waitingScopeNames.has(parentScope!)) {
510
+ const waiting = waitingScopeNames.get(parentScope!);
511
+ if (waiting?.has(name)) {
512
+ const ref = waiting.get(name)!;
513
+ ref.value = scope;
514
+ }
515
+ }
516
+
457
517
  return scope as T;
458
518
  }
459
519
 
@@ -757,6 +817,121 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
757
817
  const signal = waitingDeclarations.get(refkey)!;
758
818
  signal.value = symbol;
759
819
  }
820
+
821
+ const waitingScope = waitingSymbolNames.get(symbol.scope);
822
+ if (waitingScope) {
823
+ const waitingName = waitingScope.get(symbol.name);
824
+ if (waitingName) {
825
+ waitingName.value = symbol;
826
+ }
827
+ }
828
+ }
829
+
830
+ function findSymbolName<TSymbol extends OutputSymbol = OutputSymbol>(
831
+ scope: OutputScope | undefined,
832
+ name: string,
833
+ ): Ref<TSymbol | undefined> {
834
+ return untrack(() => {
835
+ scope ??= binder.globalScope;
836
+ for (const sym of scope.symbols) {
837
+ if (sym.name === name) {
838
+ return shallowRef(sym) as Ref<TSymbol>;
839
+ }
840
+ }
841
+
842
+ const symRef = shallowRef<OutputSymbol | undefined>(undefined);
843
+ if (!waitingSymbolNames.has(scope)) {
844
+ waitingSymbolNames.set(scope, new Map());
845
+ }
846
+ const waiting = waitingSymbolNames.get(scope)!;
847
+ waiting.set(name, symRef);
848
+ return symRef as Ref<TSymbol | undefined>;
849
+ });
850
+ }
851
+
852
+ function findScopeName<TScope extends OutputScope = OutputScope>(
853
+ scope: OutputScope | undefined,
854
+ name: string,
855
+ ): Ref<TScope | undefined> {
856
+ return untrack(() => {
857
+ scope ??= binder.globalScope;
858
+ for (const child of scope.children) {
859
+ if (child.name === name) {
860
+ return ref(child) as Ref<TScope>;
861
+ }
862
+ }
863
+
864
+ const scopeRef = shallowRef<OutputScope | undefined>(undefined);
865
+ if (!waitingScopeNames.has(scope)) {
866
+ waitingScopeNames.set(scope, new Map());
867
+ }
868
+ const waiting = waitingScopeNames.get(scope)!;
869
+ waiting.set(name, scopeRef);
870
+
871
+ return scopeRef as Ref<TScope | undefined>;
872
+ });
873
+ }
874
+
875
+ function findScopeOrSymbolName(scope: OutputScope, name: string) {
876
+ return untrack(() => {
877
+ return computed(() => {
878
+ return (
879
+ findSymbolName(scope, name).value ?? findScopeName(scope, name).value
880
+ );
881
+ });
882
+ });
883
+ }
884
+
885
+ function resolveFQN(
886
+ fqn: string,
887
+ ): Ref<OutputScope | OutputSymbol | undefined> {
888
+ const parts = fqn.match(/[^.#]+|[.#]/g);
889
+ if (!parts) return ref(undefined);
890
+ if (parts.length === 0) return ref(undefined);
891
+
892
+ parts.unshift(".");
893
+
894
+ return computed(() => {
895
+ let base: OutputScope | OutputSymbol | undefined = binder.globalScope;
896
+
897
+ for (let i = 0; i < parts.length; i += 2) {
898
+ if (base === undefined) {
899
+ return;
900
+ }
901
+
902
+ const op = parts[i];
903
+ const name = parts[i + 1];
904
+
905
+ if (op === ".") {
906
+ if ("originalName" in base) {
907
+ if (!base.staticMemberScope) {
908
+ return undefined;
909
+ }
910
+
911
+ base = findSymbolName(
912
+ (base as OutputSymbol).staticMemberScope,
913
+ name,
914
+ ).value;
915
+ } else {
916
+ base = findScopeOrSymbolName(base, name).value;
917
+ }
918
+ } else if (op === "#") {
919
+ if ("originalName" in base) {
920
+ if (!base.instanceMemberScope) {
921
+ return undefined;
922
+ }
923
+ base = findSymbolName(
924
+ (base as OutputSymbol).instanceMemberScope,
925
+ name,
926
+ ).value;
927
+ } else {
928
+ return undefined;
929
+ }
930
+ }
931
+ }
932
+
933
+ return base;
934
+ });
760
935
  }
761
936
  }
762
937
 
@@ -1,8 +1,8 @@
1
- import { Children } from "@alloy-js/core/jsx-runtime";
2
1
  import { OutputSymbol } from "../binder.js";
3
2
  import { useContext } from "../context.js";
4
3
  import { BinderContext } from "../context/binder.js";
5
4
  import { DeclarationContext } from "../context/declaration.js";
5
+ import { Children } from "../jsx-runtime.js";
6
6
  import { Refkey, refkey } from "../refkey.js";
7
7
 
8
8
  export interface DeclarationProps {
@@ -1,6 +1,6 @@
1
- import { Children } from "@alloy-js/core/jsx-runtime";
2
1
  import { useContext } from "../context.js";
3
2
  import { IndentContext } from "../context/indent.js";
3
+ import { Children } from "../jsx-runtime.js";
4
4
 
5
5
  export interface IndentProps {
6
6
  children?: Children;
@@ -1,8 +1,8 @@
1
- import { Children } from "@alloy-js/core/jsx-runtime";
2
1
  import { OutputSymbol, OutputSymbolFlags } from "../binder.js";
3
2
  import { useContext } from "../context.js";
4
3
  import { BinderContext } from "../context/binder.js";
5
4
  import { MemberDeclarationContext } from "../context/member-declaration.js";
5
+ import { Children } from "../jsx-runtime.js";
6
6
  import { Refkey, refkey } from "../refkey.js";
7
7
 
8
8
  export interface MemberDeclarationProps {
@@ -1,5 +1,5 @@
1
- import { Children } from "@alloy-js/core/jsx-runtime";
2
1
  import { OutputSymbol } from "../binder.js";
2
+ import { Children } from "../jsx-runtime.js";
3
3
 
4
4
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
5
  import { OutputSymbolFlags } from "../binder.js";
@@ -1,4 +1,3 @@
1
- import { Children } from "@alloy-js/core/jsx-runtime";
2
1
  import {
3
2
  createOutputBinder,
4
3
  getSymbolCreator,
@@ -6,9 +5,11 @@ import {
6
5
  } from "../binder.js";
7
6
  import { BinderContext } from "../context/binder.js";
8
7
  import { NamePolicyContext } from "../context/name-policy.js";
8
+ import { Children } from "../jsx-runtime.js";
9
9
  import { NamePolicy } from "../name-policy.js";
10
10
  import { SourceDirectory } from "./SourceDirectory.js";
11
11
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
12
+ import { extensionEffects } from "../slot.js";
12
13
  import { SourceFile } from "./SourceFile.js";
13
14
 
14
15
  export interface OutputProps {
@@ -58,7 +59,7 @@ export function Output(props: OutputProps) {
58
59
  }
59
60
 
60
61
  return <BinderContext.Provider value={binder}>
61
- {
62
+ {() => { extensionEffects.forEach(e => e())}}{
62
63
  props.namePolicy ?
63
64
  <NamePolicyContext.Provider value={props.namePolicy}>
64
65
  {dir}
@@ -1,8 +1,8 @@
1
- import { Children } from "@alloy-js/core/jsx-runtime";
2
1
  import { OutputScope } from "../binder.js";
3
2
  import { useContext } from "../context.js";
4
3
  import { BinderContext } from "../context/binder.js";
5
4
  import { ScopeContext } from "../context/scope.js";
5
+ import { Children } from "../jsx-runtime.js";
6
6
 
7
7
  export interface ScopeProps {
8
8
  kind?: string;
@@ -1,8 +1,8 @@
1
- import { Children, getContext } from "@alloy-js/core/jsx-runtime";
2
1
  import { shallowReactive } from "@vue/reactivity";
3
2
  import { join } from "pathe";
4
3
  import { useContext } from "../context.js";
5
4
  import { SourceDirectoryContext } from "../context/source-directory.js";
5
+ import { Children, getContext } from "../jsx-runtime.js";
6
6
 
7
7
  export interface SourceDirectoryProps {
8
8
  path: string;
@@ -1,13 +1,9 @@
1
- import {
2
- Children,
3
- ComponentDefinition,
4
- getContext,
5
- } from "@alloy-js/core/jsx-runtime";
6
1
  import { join } from "pathe";
7
2
  import { useContext } from "../context.js";
8
3
  import { IndentContext } from "../context/indent.js";
9
4
  import { SourceDirectoryContext } from "../context/source-directory.js";
10
5
  import { SourceFileContext } from "../context/source-file.js";
6
+ import { Children, ComponentDefinition, getContext } from "../jsx-runtime.js";
11
7
  import { Refkey } from "../refkey.js";
12
8
 
13
9
  export interface SourceFileProps {
@@ -1,5 +1,9 @@
1
1
  import { OutputSymbol } from "../binder.js";
2
- import { ComponentContext, createContext, useContext } from "../context.js";
2
+ import {
3
+ ComponentContext,
4
+ createNamedContext,
5
+ useContext,
6
+ } from "../context.js";
3
7
 
4
8
  export interface AssignmentContext {
5
9
  /**
@@ -31,7 +35,7 @@ export interface AssignmentContext {
31
35
  * symbols for the object value's properties.
32
36
  */
33
37
  export const AssignmentContext: ComponentContext<AssignmentContext> =
34
- createContext();
38
+ createNamedContext("Assignment");
35
39
 
36
40
  /**
37
41
  * Creates a new {@link (AssignmentContext:interface)}.
@@ -1,5 +1,9 @@
1
1
  import { Binder } from "../binder.js";
2
- import { ComponentContext, createContext, useContext } from "../context.js";
2
+ import {
3
+ ComponentContext,
4
+ createNamedContext,
5
+ useContext,
6
+ } from "../context.js";
3
7
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
4
8
  import type { Output } from "../components/Output.js";
5
9
 
@@ -7,7 +11,8 @@ import type { Output } from "../components/Output.js";
7
11
  * The binder context provides the binder instance to all components. This
8
12
  * context is provided by the {@link Output | output component}.
9
13
  */
10
- export const BinderContext: ComponentContext<Binder> = createContext();
14
+ export const BinderContext: ComponentContext<Binder> =
15
+ createNamedContext("Binder");
11
16
 
12
17
  export function useBinder() {
13
18
  return useContext(BinderContext)!;
@@ -1,5 +1,5 @@
1
1
  import { OutputSymbol } from "../binder.js";
2
- import { ComponentContext, createContext } from "../context.js";
2
+ import { ComponentContext, createNamedContext } from "../context.js";
3
3
 
4
4
  export const DeclarationContext: ComponentContext<OutputSymbol> =
5
- createContext();
5
+ createNamedContext("Declaration");
@@ -1,10 +1,17 @@
1
1
  import { IndentState } from "../components/Indent.jsx";
2
- import { ComponentContext, createContext } from "../context.js";
2
+ import {
3
+ ComponentContext,
4
+ createContext,
5
+ createNamedContext,
6
+ } from "../context.js";
3
7
 
4
- export const IndentContext: ComponentContext<IndentState> = createContext({
5
- level: 0,
6
- indent: " ",
7
- indentString: "",
8
- });
8
+ export const IndentContext: ComponentContext<IndentState> = createNamedContext(
9
+ "Indent",
10
+ {
11
+ level: 0,
12
+ indent: " ",
13
+ indentString: "",
14
+ },
15
+ );
9
16
 
10
17
  export const TestContext: ComponentContext<string> = createContext("test");
@@ -1,5 +1,5 @@
1
1
  import { OutputSymbol } from "../binder.js";
2
- import { ComponentContext, createContext } from "../context.js";
2
+ import { ComponentContext, createNamedContext } from "../context.js";
3
3
 
4
4
  /**
5
5
  * Provides the symbol for the member currently being declared.
@@ -7,4 +7,4 @@ import { ComponentContext, createContext } from "../context.js";
7
7
  * @see {@link DeclarationContext} for getting the symbol for the current non-member declaration.
8
8
  */
9
9
  export const MemberDeclarationContext: ComponentContext<OutputSymbol> =
10
- createContext();
10
+ createNamedContext("MemberDeclaration");
@@ -1,5 +1,9 @@
1
1
  import { OutputScope } from "../binder.js";
2
- import { ComponentContext, createContext, useContext } from "../context.js";
2
+ import {
3
+ ComponentContext,
4
+ createNamedContext,
5
+ useContext,
6
+ } from "../context.js";
3
7
 
4
8
  /**
5
9
  * The member scope context provides the instance and static member scopes that
@@ -10,7 +14,7 @@ export interface MemberScopeContext {
10
14
  instanceMembers?: OutputScope;
11
15
  }
12
16
  export const MemberScopeContext: ComponentContext<MemberScopeContext> =
13
- createContext();
17
+ createNamedContext("MemberScope");
14
18
 
15
19
  export function useMemberScope() {
16
20
  return useContext(MemberScopeContext)!;
@@ -1,8 +1,12 @@
1
- import { ComponentContext, createContext, useContext } from "../context.js";
1
+ import {
2
+ ComponentContext,
3
+ createNamedContext,
4
+ useContext,
5
+ } from "../context.js";
2
6
  import { NamePolicy } from "../name-policy.js";
3
7
 
4
8
  export const NamePolicyContext: ComponentContext<NamePolicy<string>> =
5
- createContext<NamePolicy<string>>({
9
+ createNamedContext<NamePolicy<string>>("NamePolicy", {
6
10
  getName(name) {
7
11
  return name;
8
12
  },
@@ -1,7 +1,12 @@
1
1
  import { OutputScope } from "../binder.js";
2
- import { ComponentContext, createContext, useContext } from "../context.js";
2
+ import {
3
+ ComponentContext,
4
+ createNamedContext,
5
+ useContext,
6
+ } from "../context.js";
3
7
 
4
- export const ScopeContext: ComponentContext<OutputScope> = createContext();
8
+ export const ScopeContext: ComponentContext<OutputScope> =
9
+ createNamedContext("Scope");
5
10
 
6
11
  export function useScope() {
7
12
  return useContext(ScopeContext)!;
@@ -1,4 +1,4 @@
1
- import { ComponentContext, createContext } from "../context.js";
1
+ import { ComponentContext, createNamedContext } from "../context.js";
2
2
  import { SourceFileContext } from "./source-file.js";
3
3
 
4
4
  export interface SourceDirectoryContext {
@@ -8,4 +8,4 @@ export interface SourceDirectoryContext {
8
8
  }
9
9
 
10
10
  export const SourceDirectoryContext: ComponentContext<SourceDirectoryContext> =
11
- createContext();
11
+ createNamedContext("SourceDirectory");
@@ -1,4 +1,4 @@
1
- import { ComponentContext, createContext } from "../context.js";
1
+ import { ComponentContext, createNamedContext } from "../context.js";
2
2
  import { ComponentDefinition } from "../jsx-runtime.js";
3
3
  import { Refkey } from "../refkey.js";
4
4
 
@@ -9,4 +9,4 @@ export interface SourceFileContext {
9
9
  }
10
10
 
11
11
  export const SourceFileContext: ComponentContext<SourceFileContext> =
12
- createContext();
12
+ createNamedContext("SourceFile");
package/src/context.ts CHANGED
@@ -1,16 +1,17 @@
1
+ import { shallowRef } from "@vue/reactivity";
1
2
  import {
2
3
  Children,
3
4
  ComponentDefinition,
4
5
  effect,
5
6
  getContext,
6
7
  untrack,
7
- } from "@alloy-js/core/jsx-runtime";
8
- import { shallowRef } from "@vue/reactivity";
8
+ } from "./jsx-runtime.js";
9
9
 
10
10
  export interface ComponentContext<T> {
11
11
  id: symbol;
12
12
  default: T | undefined;
13
13
  Provider: ComponentDefinition<ContextProviderProps<T>>;
14
+ name?: string;
14
15
  }
15
16
 
16
17
  export interface ContextProviderProps<T = unknown> {
@@ -31,13 +32,17 @@ export function useContext<T>(context: ComponentContext<T>): T | undefined {
31
32
  return context.default;
32
33
  }
33
34
 
35
+ export const contextsByKey = new Map<symbol, ComponentContext<any>>();
36
+
34
37
  export function createContext<T = unknown>(
35
38
  defaultValue?: T,
39
+ name?: string,
36
40
  ): ComponentContext<T> {
37
- const id = Symbol("context");
38
- return {
41
+ const id = Symbol(name ?? "context");
42
+ const ctx = {
39
43
  id,
40
44
  default: defaultValue,
45
+ name,
41
46
  Provider(props: ContextProviderProps<T>) {
42
47
  const context = getContext();
43
48
 
@@ -50,4 +55,10 @@ export function createContext<T = unknown>(
50
55
  return rendered.value;
51
56
  },
52
57
  };
58
+ contextsByKey.set(id, ctx);
59
+ return ctx;
60
+ }
61
+
62
+ export function createNamedContext<T>(name: string, defaultValue?: T) {
63
+ return createContext<T>(defaultValue, name);
53
64
  }