@alloy-js/core 0.16.0 → 0.18.0-dev.2

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 (249) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/src/binder.d.ts +19 -235
  3. package/dist/src/binder.d.ts.map +1 -1
  4. package/dist/src/binder.js +85 -386
  5. package/dist/src/code.d.ts +1 -1
  6. package/dist/src/code.d.ts.map +1 -1
  7. package/dist/src/components/Block.d.ts +1 -1
  8. package/dist/src/components/Block.d.ts.map +1 -1
  9. package/dist/src/components/Block.js +3 -1
  10. package/dist/src/components/Declaration.d.ts +2 -2
  11. package/dist/src/components/Declaration.d.ts.map +1 -1
  12. package/dist/src/components/Declaration.js +6 -5
  13. package/dist/src/components/For.d.ts +1 -1
  14. package/dist/src/components/For.d.ts.map +1 -1
  15. package/dist/src/components/For.js +1 -1
  16. package/dist/src/components/Indent.d.ts +1 -1
  17. package/dist/src/components/Indent.d.ts.map +1 -1
  18. package/dist/src/components/List.d.ts +1 -1
  19. package/dist/src/components/List.d.ts.map +1 -1
  20. package/dist/src/components/List.js +3 -1
  21. package/dist/src/components/MemberDeclaration.d.ts +3 -3
  22. package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
  23. package/dist/src/components/MemberDeclaration.js +4 -4
  24. package/dist/src/components/MemberScope.d.ts +2 -2
  25. package/dist/src/components/MemberScope.d.ts.map +1 -1
  26. package/dist/src/components/MemberScope.js +0 -2
  27. package/dist/src/components/Output.d.ts +1 -1
  28. package/dist/src/components/Output.d.ts.map +1 -1
  29. package/dist/src/components/Output.js +1 -1
  30. package/dist/src/components/Prose.d.ts +1 -1
  31. package/dist/src/components/Prose.d.ts.map +1 -1
  32. package/dist/src/components/ReferenceOrContent.d.ts +1 -1
  33. package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
  34. package/dist/src/components/Scope.d.ts +2 -2
  35. package/dist/src/components/Scope.d.ts.map +1 -1
  36. package/dist/src/components/Scope.js +3 -6
  37. package/dist/src/components/Show.d.ts +1 -1
  38. package/dist/src/components/Show.d.ts.map +1 -1
  39. package/dist/src/components/SourceDirectory.d.ts +1 -1
  40. package/dist/src/components/SourceDirectory.d.ts.map +1 -1
  41. package/dist/src/components/SourceDirectory.js +1 -1
  42. package/dist/src/components/SourceFile.d.ts +1 -1
  43. package/dist/src/components/SourceFile.d.ts.map +1 -1
  44. package/dist/src/components/SourceFile.js +1 -1
  45. package/dist/src/components/StatementList.d.ts +1 -1
  46. package/dist/src/components/StatementList.d.ts.map +1 -1
  47. package/dist/src/components/StatementList.js +1 -1
  48. package/dist/src/components/Switch.d.ts +2 -2
  49. package/dist/src/components/Switch.d.ts.map +1 -1
  50. package/dist/src/components/Switch.js +2 -1
  51. package/dist/src/components/Wrap.d.ts +1 -1
  52. package/dist/src/components/Wrap.d.ts.map +1 -1
  53. package/dist/src/context/assignment.d.ts +1 -1
  54. package/dist/src/context/assignment.d.ts.map +1 -1
  55. package/dist/src/context/binder.d.ts +3 -3
  56. package/dist/src/context/binder.d.ts.map +1 -1
  57. package/dist/src/context/declaration.d.ts +1 -1
  58. package/dist/src/context/declaration.d.ts.map +1 -1
  59. package/dist/src/context/member-declaration.d.ts +1 -1
  60. package/dist/src/context/member-declaration.d.ts.map +1 -1
  61. package/dist/src/context/member-declaration.js +0 -1
  62. package/dist/src/context/member-scope.d.ts +1 -1
  63. package/dist/src/context/member-scope.d.ts.map +1 -1
  64. package/dist/src/context/name-policy.d.ts +1 -1
  65. package/dist/src/context/name-policy.d.ts.map +1 -1
  66. package/dist/src/context/scope.d.ts +1 -1
  67. package/dist/src/context/scope.d.ts.map +1 -1
  68. package/dist/src/context/source-directory.d.ts +1 -1
  69. package/dist/src/context/source-directory.d.ts.map +1 -1
  70. package/dist/src/context/source-file.d.ts +2 -2
  71. package/dist/src/context/source-file.d.ts.map +1 -1
  72. package/dist/src/context.d.ts +2 -2
  73. package/dist/src/context.d.ts.map +1 -1
  74. package/dist/src/context.js +1 -1
  75. package/dist/src/debug.d.ts +1 -0
  76. package/dist/src/debug.d.ts.map +1 -1
  77. package/dist/src/debug.js +4 -1
  78. package/dist/src/index.d.ts +8 -2
  79. package/dist/src/index.d.ts.map +1 -1
  80. package/dist/src/index.js +8 -2
  81. package/dist/src/jsx-runtime.d.ts +4 -272
  82. package/dist/src/jsx-runtime.d.ts.map +1 -1
  83. package/dist/src/jsx-runtime.js +3 -315
  84. package/dist/src/props-combinators.d.ts +19 -0
  85. package/dist/src/props-combinators.d.ts.map +1 -0
  86. package/dist/src/props-combinators.js +108 -0
  87. package/dist/src/reactive-union-set.d.ts +29 -0
  88. package/dist/src/reactive-union-set.d.ts.map +1 -0
  89. package/dist/src/reactive-union-set.js +183 -0
  90. package/dist/src/reactivity.d.ts +75 -0
  91. package/dist/src/reactivity.d.ts.map +1 -0
  92. package/dist/src/reactivity.js +141 -0
  93. package/dist/src/refkey.d.ts +36 -0
  94. package/dist/src/refkey.d.ts.map +1 -1
  95. package/dist/src/refkey.js +40 -0
  96. package/dist/src/render.d.ts +5 -1
  97. package/dist/src/render.d.ts.map +1 -1
  98. package/dist/src/render.js +68 -15
  99. package/dist/src/runtime/component.d.ts +24 -0
  100. package/dist/src/runtime/component.d.ts.map +1 -0
  101. package/dist/src/runtime/component.js +19 -0
  102. package/dist/src/runtime/intrinsic.d.ts +168 -0
  103. package/dist/src/runtime/intrinsic.d.ts.map +1 -0
  104. package/dist/src/runtime/intrinsic.js +11 -0
  105. package/dist/src/scheduler.d.ts +2 -2
  106. package/dist/src/scheduler.d.ts.map +1 -1
  107. package/dist/src/scheduler.js +27 -6
  108. package/dist/src/slot.d.ts +2 -2
  109. package/dist/src/slot.d.ts.map +1 -1
  110. package/dist/src/slot.js +1 -1
  111. package/dist/src/stc.d.ts +1 -1
  112. package/dist/src/stc.d.ts.map +1 -1
  113. package/dist/src/sti.d.ts +7 -6
  114. package/dist/src/sti.d.ts.map +1 -1
  115. package/dist/src/sti.js +1 -1
  116. package/dist/src/symbols/flags.d.ts +70 -0
  117. package/dist/src/symbols/flags.d.ts.map +1 -0
  118. package/dist/src/symbols/flags.js +72 -0
  119. package/dist/src/symbols/index.d.ts +7 -0
  120. package/dist/src/symbols/index.d.ts.map +1 -0
  121. package/dist/src/symbols/index.js +6 -0
  122. package/dist/src/symbols/output-scope.d.ts +94 -0
  123. package/dist/src/symbols/output-scope.d.ts.map +1 -0
  124. package/dist/src/symbols/output-scope.js +222 -0
  125. package/dist/src/symbols/output-symbol.d.ts +89 -0
  126. package/dist/src/symbols/output-symbol.d.ts.map +1 -0
  127. package/dist/src/symbols/output-symbol.js +333 -0
  128. package/dist/src/symbols/symbol-flow.d.ts +13 -0
  129. package/dist/src/symbols/symbol-flow.d.ts.map +1 -0
  130. package/dist/src/symbols/symbol-flow.js +74 -0
  131. package/dist/src/symbols/symbol-slot.d.ts +12 -0
  132. package/dist/src/symbols/symbol-slot.d.ts.map +1 -0
  133. package/dist/src/symbols/symbol-slot.js +36 -0
  134. package/dist/src/symbols/symbol-table.d.ts +14 -0
  135. package/dist/src/symbols/symbol-table.d.ts.map +1 -0
  136. package/dist/src/symbols/symbol-table.js +42 -0
  137. package/dist/src/tap.d.ts +3 -2
  138. package/dist/src/tap.d.ts.map +1 -1
  139. package/dist/src/tracer.d.ts +238 -0
  140. package/dist/src/tracer.d.ts.map +1 -0
  141. package/dist/src/tracer.js +496 -0
  142. package/dist/src/tsdoc-metadata.json +1 -1
  143. package/dist/src/utils.d.ts +4 -3
  144. package/dist/src/utils.d.ts.map +1 -1
  145. package/dist/src/utils.js +2 -1
  146. package/dist/test/components/slot.test.js +5 -7
  147. package/dist/test/props-with-defaults.test.js +1 -1
  148. package/dist/test/reactive-union-set.test.d.ts +2 -0
  149. package/dist/test/reactive-union-set.test.d.ts.map +1 -0
  150. package/dist/test/reactive-union-set.test.js +170 -0
  151. package/dist/test/reactivity/cleanup.test.js +2 -1
  152. package/dist/test/reactivity/memo.test.js +1 -1
  153. package/dist/test/reactivity/untrack.test.js +1 -1
  154. package/dist/test/rendering/memoization.test.js +2 -1
  155. package/dist/test/split-props.test.js +1 -1
  156. package/dist/test/symbols/output-scope.test.d.ts +2 -0
  157. package/dist/test/symbols/output-scope.test.d.ts.map +1 -0
  158. package/dist/test/symbols/output-scope.test.js +343 -0
  159. package/dist/test/symbols/output-symbol.test.d.ts +2 -0
  160. package/dist/test/symbols/output-symbol.test.d.ts.map +1 -0
  161. package/dist/test/symbols/output-symbol.test.js +447 -0
  162. package/dist/test/symbols/resolution.test.d.ts +2 -0
  163. package/dist/test/symbols/resolution.test.d.ts.map +1 -0
  164. package/dist/test/symbols/resolution.test.js +141 -0
  165. package/dist/test/symbols/utils.d.ts +25 -0
  166. package/dist/test/symbols/utils.d.ts.map +1 -0
  167. package/dist/test/symbols/utils.js +47 -0
  168. package/dist/testing/extend-expect.d.ts +15 -0
  169. package/dist/testing/extend-expect.d.ts.map +1 -1
  170. package/dist/testing/extend-expect.js +2 -1
  171. package/dist/testing/render.d.ts +1 -1
  172. package/dist/testing/render.d.ts.map +1 -1
  173. package/dist/tsconfig.tsbuildinfo +1 -1
  174. package/package.json +28 -24
  175. package/src/binder.ts +146 -672
  176. package/src/code.ts +1 -1
  177. package/src/components/Block.tsx +4 -1
  178. package/src/components/Declaration.tsx +8 -7
  179. package/src/components/For.tsx +2 -1
  180. package/src/components/Indent.tsx +1 -1
  181. package/src/components/List.tsx +3 -1
  182. package/src/components/MemberDeclaration.tsx +7 -6
  183. package/src/components/MemberScope.tsx +2 -5
  184. package/src/components/Output.tsx +2 -1
  185. package/src/components/Prose.tsx +1 -1
  186. package/src/components/ReferenceOrContent.tsx +1 -1
  187. package/src/components/Scope.tsx +3 -7
  188. package/src/components/Show.tsx +1 -1
  189. package/src/components/SourceDirectory.tsx +2 -1
  190. package/src/components/SourceFile.tsx +2 -1
  191. package/src/components/StatementList.tsx +2 -1
  192. package/src/components/Switch.tsx +2 -1
  193. package/src/components/Wrap.tsx +1 -1
  194. package/src/context/assignment.ts +1 -1
  195. package/src/context/binder.ts +3 -3
  196. package/src/context/declaration.ts +1 -1
  197. package/src/context/member-declaration.ts +1 -1
  198. package/src/context/member-scope.ts +1 -1
  199. package/src/context/name-policy.ts +1 -1
  200. package/src/context/scope.ts +1 -1
  201. package/src/context/source-directory.ts +1 -1
  202. package/src/context/source-file.ts +2 -2
  203. package/src/context.ts +3 -7
  204. package/src/debug.ts +5 -1
  205. package/src/index.ts +15 -1
  206. package/src/jsx-runtime.ts +15 -674
  207. package/src/props-combinators.ts +148 -0
  208. package/src/reactive-union-set.ts +238 -0
  209. package/src/reactivity.ts +230 -0
  210. package/src/refkey.ts +40 -0
  211. package/src/render.ts +97 -26
  212. package/src/runtime/component.ts +67 -0
  213. package/src/runtime/intrinsic.ts +199 -0
  214. package/src/scheduler.ts +31 -6
  215. package/src/slot.ts +3 -4
  216. package/src/stc.ts +2 -2
  217. package/src/sti.ts +11 -11
  218. package/src/symbols/flags.ts +82 -0
  219. package/src/symbols/index.ts +6 -0
  220. package/src/symbols/output-scope.ts +296 -0
  221. package/src/symbols/output-symbol.ts +459 -0
  222. package/src/symbols/symbol-flow.ts +100 -0
  223. package/src/symbols/symbol-slot.tsx +48 -0
  224. package/src/symbols/symbol-table.ts +72 -0
  225. package/src/tap.ts +3 -2
  226. package/src/tracer.ts +474 -0
  227. package/src/utils.tsx +7 -5
  228. package/temp/api.json +7446 -5133
  229. package/test/components/slot.test.tsx +8 -11
  230. package/test/props-with-defaults.test.ts +1 -1
  231. package/test/reactive-union-set.test.tsx +191 -0
  232. package/test/reactivity/cleanup.test.tsx +2 -1
  233. package/test/reactivity/memo.test.tsx +1 -1
  234. package/test/reactivity/untrack.test.ts +1 -1
  235. package/test/rendering/basic.test.tsx +1 -1
  236. package/test/rendering/memoization.test.tsx +1 -1
  237. package/test/split-props.test.ts +1 -1
  238. package/test/symbols/output-scope.test.ts +300 -0
  239. package/test/symbols/output-symbol.test.ts +456 -0
  240. package/test/symbols/resolution.test.ts +170 -0
  241. package/test/symbols/utils.ts +93 -0
  242. package/test/utils.test.tsx +1 -1
  243. package/testing/extend-expect.ts +16 -0
  244. package/testing/render.ts +1 -2
  245. package/LICENSE +0 -7
  246. package/dist/test/symbols.test.d.ts +0 -2
  247. package/dist/test/symbols.test.d.ts.map +0 -1
  248. package/dist/test/symbols.test.js +0 -884
  249. package/test/symbols.test.ts +0 -1006
package/src/render.ts CHANGED
@@ -3,26 +3,29 @@ import { Doc, doc } from "prettier";
3
3
  import prettier from "prettier/doc.js";
4
4
  import { useContext } from "./context.js";
5
5
  import { SourceFileContext } from "./context/source-file.js";
6
+ import { shouldDebug } from "./debug.js";
6
7
  import {
7
- Child,
8
- Children,
9
8
  Context,
10
9
  CustomContext,
11
10
  effect,
12
11
  getContext,
13
12
  getElementCache,
14
- IntrinsicElement,
15
- isComponentCreator,
16
13
  isCustomContext,
17
- isIntrinsicElement,
18
- popStack,
19
- printRenderStack,
20
- pushStack,
21
14
  root,
22
15
  untrack,
23
- } from "./jsx-runtime.js";
16
+ } from "./reactivity.js";
24
17
  import { isRefkey } from "./refkey.js";
18
+ import {
19
+ Child,
20
+ Children,
21
+ Component,
22
+ isComponentCreator,
23
+ Props,
24
+ } from "./runtime/component.js";
25
+ import { IntrinsicElement, isIntrinsicElement } from "./runtime/intrinsic.js";
25
26
  import { flushJobs } from "./scheduler.js";
27
+ import { trace, TracePhase } from "./tracer.js";
28
+
26
29
  const {
27
30
  builders: {
28
31
  align,
@@ -172,11 +175,6 @@ export function isPrintHook(type: unknown): type is PrintHook {
172
175
 
173
176
  export type RenderedTextTree = (string | RenderedTextTree | PrintHook)[];
174
177
 
175
- function traceRender(phase: string, message: () => string) {
176
- return false;
177
- //console.log(`[\x1b[34m${phase}\x1b[0m]: ${message()}`);
178
- }
179
-
180
178
  export function render(
181
179
  children: Children,
182
180
  options?: PrintTreeOptions,
@@ -284,7 +282,12 @@ export function renderTree(children: Children) {
284
282
  }
285
283
 
286
284
  function renderWorker(node: RenderedTextTree, children: Children) {
287
- traceRender("render", () => dumpChildren(children));
285
+ if (!getContext()) {
286
+ throw new Error(
287
+ "Cannot render without a context. Make sure you are using the Output component.",
288
+ );
289
+ }
290
+ trace(TracePhase.render.worker, () => dumpChildren(children));
288
291
 
289
292
  if (Array.isArray(node)) {
290
293
  nodesToContext.set(node, getContext()!);
@@ -300,7 +303,7 @@ function renderWorker(node: RenderedTextTree, children: Children) {
300
303
  }
301
304
 
302
305
  function appendChild(node: RenderedTextTree, rawChild: Child) {
303
- traceRender("appendChild", () => debugPrintChild(rawChild));
306
+ trace(TracePhase.render.appendChild, () => debugPrintChild(rawChild));
304
307
  const child = normalizeChild(rawChild);
305
308
 
306
309
  if (typeof child === "string") {
@@ -308,12 +311,18 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
308
311
  } else {
309
312
  const cache = getElementCache();
310
313
  if (cache.has(child as any)) {
311
- traceRender("appendChild:cached", () => debugPrintChild(child));
314
+ trace(
315
+ TracePhase.render.appendChild,
316
+ () => "Cached: " + debugPrintChild(child),
317
+ );
312
318
  node.push(cache.get(child as any)!);
313
319
  return;
314
320
  }
315
321
  if (isCustomContext(child)) {
316
- traceRender("appendChild:custom-context", () => debugPrintChild(child));
322
+ trace(
323
+ TracePhase.render.appendChild,
324
+ () => "CustomContext: " + debugPrintChild(child),
325
+ );
317
326
  child.useCustomContext((children) => {
318
327
  const newNode: RenderedTextTree = [];
319
328
  renderWorker(newNode, children);
@@ -321,10 +330,11 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
321
330
  cache.set(child, newNode);
322
331
  });
323
332
  } else if (isIntrinsicElement(child)) {
324
- // don't need a new context here because intrinsics are never reactive
325
- traceRender("appendChild:intrinsic-element", () =>
326
- debugPrintChild(child),
333
+ trace(
334
+ TracePhase.render.appendChild,
335
+ () => "IntrinsicElement: " + debugPrintChild(child),
327
336
  );
337
+ // don't need a new context here because intrinsics are never reactive
328
338
  const newNode: RenderedTextTree = [];
329
339
 
330
340
  function formatHookWithChildren(command: (doc: Doc) => Doc) {
@@ -442,20 +452,26 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
442
452
  }
443
453
  } else if (isComponentCreator(child)) {
444
454
  effect(() => {
445
- traceRender("appendChild:component", () => debugPrintChild(child));
455
+ trace(
456
+ TracePhase.render.appendChild,
457
+ () => "Component: " + debugPrintChild(child),
458
+ );
446
459
  const componentRoot: RenderedTextTree = [];
447
460
  pushStack(child.component, child.props);
448
461
  renderWorker(componentRoot, untrack(child));
449
462
  popStack();
450
463
  node.push(componentRoot);
451
464
  cache.set(child, componentRoot);
452
- traceRender("appendChild:component-done", () => debugPrintChild(child));
465
+ trace(
466
+ TracePhase.render.appendChild,
467
+ () => "Component done: " + debugPrintChild(child),
468
+ );
453
469
  });
454
470
  } else if (typeof child === "function") {
455
- traceRender("appendChild:memo", () => child.toString());
471
+ trace(TracePhase.render.appendChild, () => "Memo: " + child.toString());
456
472
  const index = node.length;
457
473
  effect(() => {
458
- traceRender("memoEffect:run", () => "");
474
+ trace(TracePhase.render.renderEffect, () => "");
459
475
  let res = child();
460
476
  while (typeof res === "function" && !isComponentCreator(res)) {
461
477
  res = res();
@@ -466,7 +482,6 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
466
482
  cache.set(child, newNodes);
467
483
  return newNodes;
468
484
  });
469
- traceRender("appendChild:memo-done", () => "");
470
485
  } else {
471
486
  throw new Error("Unexpected child type");
472
487
  }
@@ -525,6 +540,8 @@ function debugPrintChild(child: Children): string {
525
540
  return "$memo";
526
541
  } else if (isRef(child)) {
527
542
  return "$ref";
543
+ } else if (isIntrinsicElement(child)) {
544
+ return `<${child.name}>`;
528
545
  } else {
529
546
  return JSON.stringify(child);
530
547
  }
@@ -588,3 +605,57 @@ function printTreeWorker(tree: RenderedTextTree): Doc {
588
605
 
589
606
  return doc;
590
607
  }
608
+ // debugging utilities
609
+ const renderStack: {
610
+ component: Component<any>;
611
+ props: Props;
612
+ }[] = [];
613
+
614
+ export function pushStack(component: Component<any>, props: Props) {
615
+ if (!shouldDebug()) return;
616
+ renderStack.push({ component, props });
617
+ }
618
+
619
+ export function popStack() {
620
+ if (!shouldDebug()) return;
621
+ renderStack.pop();
622
+ }
623
+
624
+ export function printRenderStack() {
625
+ if (!shouldDebug()) return;
626
+
627
+ // eslint-disable-next-line no-console
628
+ console.error("Error rendering:");
629
+ for (let i = renderStack.length - 1; i >= 0; i--) {
630
+ const { component, props } = renderStack[i];
631
+ // eslint-disable-next-line no-console
632
+ console.error(` at ${component.name}(${inspectProps(props)})`);
633
+ }
634
+ }
635
+
636
+ function inspectProps(props: Props) {
637
+ return JSON.stringify(
638
+ Object.fromEntries(
639
+ Object.entries(props).map(([key, value]) => {
640
+ let safeValue;
641
+ switch (typeof value) {
642
+ case "string":
643
+ case "number":
644
+ case "boolean":
645
+ safeValue = value;
646
+ break;
647
+ case "undefined":
648
+ safeValue = "undefined";
649
+ break;
650
+ case "object":
651
+ safeValue = value ? "{...}" : null;
652
+ break;
653
+ case "function":
654
+ safeValue = "function";
655
+ break;
656
+ }
657
+ return [key, safeValue];
658
+ }),
659
+ ),
660
+ );
661
+ }
@@ -0,0 +1,67 @@
1
+ import { Ref } from "@vue/reactivity";
2
+ import { CustomContext } from "../reactivity.js";
3
+ import { Refkey } from "../refkey.js";
4
+ import { IntrinsicElement } from "./intrinsic.js";
5
+
6
+ export type Child =
7
+ | string
8
+ | boolean
9
+ | number
10
+ | undefined
11
+ | null
12
+ | void
13
+ | (() => Children)
14
+ | Ref
15
+ | Refkey
16
+ | CustomContext
17
+ | IntrinsicElement;
18
+
19
+ export type Children = Child | Children[];
20
+ export type Props = Record<string, any>;
21
+
22
+ export interface ComponentDefinition<TProps = Props> {
23
+ (props: TProps): Children;
24
+ }
25
+ export interface Component<TProps = Props> {
26
+ (props: TProps): Children;
27
+ tag?: symbol;
28
+ }
29
+
30
+ export interface ComponentCreator<TProps = Props> {
31
+ component: Component<TProps>;
32
+ (): Children;
33
+ props: TProps;
34
+ tag?: symbol;
35
+ }
36
+
37
+ export function isComponentCreator<TProps = any>(
38
+ item: unknown,
39
+ component?: Component<TProps>,
40
+ ): item is ComponentCreator<TProps> {
41
+ if (!component) {
42
+ return typeof item === "function" && (item as any).component;
43
+ }
44
+ return typeof item === "function" && (item as any).component === component;
45
+ }
46
+
47
+ export function createComponent<TProps extends Props = Props>(
48
+ C: Component<TProps>,
49
+ props: TProps,
50
+ ): ComponentCreator<TProps> {
51
+ const creator: ComponentCreator<TProps> = () => /* */ C(props);
52
+ creator.props = props;
53
+ creator.component = C;
54
+ if (C.tag) {
55
+ creator.tag = C.tag;
56
+ }
57
+
58
+ return creator;
59
+ }
60
+
61
+ export function taggedComponent<TProps = Props>(
62
+ tag: symbol,
63
+ component: Component<TProps>,
64
+ ): Component<TProps> & Required<Pick<Component<TProps>, "tag">> {
65
+ component.tag = tag;
66
+ return component as any;
67
+ }
@@ -0,0 +1,199 @@
1
+ import type { Children } from "./component.js";
2
+ export interface IntrinsicElements {
3
+ /**
4
+ * Attempt to render the children on a single line if possible. If a group
5
+ * contains `<breakParent />` or a hard line, or if the group exceeds the
6
+ * print width, all linebreaks in the group will be broken.
7
+ */
8
+ group: { shouldBreak?: boolean; id?: symbol; children: Children };
9
+
10
+ /**
11
+ * A regular line break. This will break if the line exceeds the print
12
+ * width, otherwise it will be a space.
13
+ */
14
+ line: {};
15
+
16
+ /**
17
+ * A regular line break. This will break if the line exceeds the print
18
+ * width, otherwise it will be a space.
19
+ */
20
+ br: {};
21
+
22
+ /**
23
+ * A hard line break. This is a line that will always break, even if the
24
+ * group does not exceed print width.
25
+ */
26
+ hardline: {};
27
+
28
+ /**
29
+ * A hard line break. This is a line that will always break, even if the
30
+ * group does not exceed print width.
31
+ */
32
+ hbr: {};
33
+
34
+ /**
35
+ * A soft line break. This will break if the line exceeds the print width,
36
+ * otherwise it will be be nothing.
37
+ */
38
+ softline: {};
39
+
40
+ /**
41
+ * A soft line break. This will break if the line exceeds the print width,
42
+ * otherwise it will be be nothing.
43
+ */
44
+ sbr: {};
45
+
46
+ /**
47
+ * A literal line break. This will always break, even if the group does not
48
+ * exceed print width. The new line will ignore indentation.
49
+ */
50
+ literalline: {};
51
+
52
+ /**
53
+ * A literal line break. This will always break, even if the group does not
54
+ * exceed print width. The new line will ignore indentation.
55
+ */
56
+ lbr: {};
57
+
58
+ /**
59
+ * Increase the indentation level of the children of this component.
60
+ * Indentation is determined by the print options provided to the Output
61
+ * component or source file.
62
+ */
63
+ indent: { children: Children };
64
+
65
+ /**
66
+ * Indent the children of this component if the group specified by `groupId`
67
+ * is broken (or not broken if `negate` is passed). The specified group must
68
+ * already be printed.
69
+ */
70
+ indentIfBreak: { children: Children; groupId: symbol; negate?: boolean };
71
+
72
+ /**
73
+ * Similar to `group`, but will only place a line break before the last
74
+ * segment to exceed the print width. This is useful for formatting
75
+ * paragraphs of text where breaks are inserted prior to words which would
76
+ * otherwise exceed the print width.
77
+ */
78
+ fill: { children: Children };
79
+
80
+ /**
81
+ * Force the parent group to break.
82
+ */
83
+ breakParent: {};
84
+
85
+ /**
86
+ * Print children if the current group or already printed group specified by
87
+ * `groupId` is broken. Otherwise, `flatContents` is printed instead.
88
+ */
89
+ ifBreak: { children: Children; flatContents?: Children; groupId?: symbol };
90
+
91
+ /**
92
+ * Print this content at the end of the line. Useful for things like line
93
+ * comments.
94
+ */
95
+ lineSuffix: { children: Children };
96
+
97
+ /**
98
+ * Force any line suffixes to print at this point.
99
+ */
100
+ lineSuffixBoundary: {};
101
+
102
+ /**
103
+ * Decrease the indentation level of the children of this component.
104
+ * Indentation is determined by the print options provided to the Output
105
+ * component or source file.
106
+ */
107
+ dedent: { children: Children };
108
+
109
+ /**
110
+ * Indent the children of this component by either the number of characters
111
+ * indicated by the `width` prop, or by the provided string indicated by the
112
+ * `string` prop.
113
+ */
114
+ align:
115
+ | { children: Children; width: number }
116
+ | { children: Children; string: string };
117
+
118
+ /**
119
+ * Mark the current indentation level as "root" for the purposes of literal
120
+ * line breaks and `dedentToRoot`.
121
+ */
122
+ markAsRoot: { children: Children };
123
+
124
+ /**
125
+ * Decrease the indentation level to the root level specified by
126
+ * `<markAsRoot />`, or else to no indentation.
127
+ */
128
+ dedentToRoot: { children: Children };
129
+ }
130
+ export interface IntrinsicElementBase<
131
+ TKey extends keyof IntrinsicElements = keyof IntrinsicElements,
132
+ > {
133
+ [intrinsicElementKey]: true;
134
+ name: TKey;
135
+ props: IntrinsicElements[TKey];
136
+ }
137
+
138
+ export function createIntrinsic<TKey extends keyof IntrinsicElements>(
139
+ name: TKey,
140
+ props: IntrinsicElements[TKey],
141
+ ): IntrinsicElementBase<TKey> {
142
+ return {
143
+ [intrinsicElementKey]: true,
144
+ name,
145
+ props,
146
+ };
147
+ }
148
+
149
+ export function isIntrinsicElement(type: unknown): type is IntrinsicElement {
150
+ return (
151
+ typeof type === "object" && type !== null && intrinsicElementKey in type
152
+ );
153
+ }
154
+
155
+ export const intrinsicElementKey = Symbol();
156
+ export type IndentIntrinsicElement = IntrinsicElementBase<"indent">;
157
+ export type IndentIfBreakIntrinsicElement =
158
+ IntrinsicElementBase<"indentIfBreak">;
159
+ export type BrIntrinsicElement = IntrinsicElementBase<"br">;
160
+ export type LineIntrinsicElement = IntrinsicElementBase<"line">;
161
+ export type HbrIntrinsicElement = IntrinsicElementBase<"hbr">;
162
+ export type HardlineIntrinsicElement = IntrinsicElementBase<"hardline">;
163
+ export type SbrIntrinsicElement = IntrinsicElementBase<"sbr">;
164
+ export type SoftlineIntrinsicElement = IntrinsicElementBase<"softline">;
165
+ export type GroupIntrinsicElement = IntrinsicElementBase<"group">;
166
+ export type AlignIntrinsicElement = IntrinsicElementBase<"align">;
167
+ export type FillIntrinsicElement = IntrinsicElementBase<"fill">;
168
+ export type BreakParentIntrinsicElement = IntrinsicElementBase<"breakParent">;
169
+ export type LineSuffixIntrinsicElement = IntrinsicElementBase<"lineSuffix">;
170
+ export type LineSuffixBoundaryIntrinsicElement =
171
+ IntrinsicElementBase<"lineSuffixBoundary">;
172
+ export type DedentIntrinsicElement = IntrinsicElementBase<"dedent">;
173
+ export type DedentToRootIntrinsicElement = IntrinsicElementBase<"dedentToRoot">;
174
+ export type MarkAsRootIntrinsicElement = IntrinsicElementBase<"markAsRoot">;
175
+ export type LiterallineIntrinsicElement = IntrinsicElementBase<"literalline">;
176
+ export type LbrIntrinsicElement = IntrinsicElementBase<"lbr">;
177
+ export type IfBreakIntrinsicElement = IntrinsicElementBase<"ifBreak">;
178
+
179
+ export type IntrinsicElement =
180
+ | IndentIntrinsicElement
181
+ | IndentIfBreakIntrinsicElement
182
+ | BrIntrinsicElement
183
+ | LineIntrinsicElement
184
+ | HbrIntrinsicElement
185
+ | HardlineIntrinsicElement
186
+ | SbrIntrinsicElement
187
+ | SoftlineIntrinsicElement
188
+ | GroupIntrinsicElement
189
+ | AlignIntrinsicElement
190
+ | FillIntrinsicElement
191
+ | BreakParentIntrinsicElement
192
+ | LineSuffixIntrinsicElement
193
+ | LineSuffixBoundaryIntrinsicElement
194
+ | DedentIntrinsicElement
195
+ | LiterallineIntrinsicElement
196
+ | LbrIntrinsicElement
197
+ | DedentToRootIntrinsicElement
198
+ | MarkAsRootIntrinsicElement
199
+ | IfBreakIntrinsicElement;
package/src/scheduler.ts CHANGED
@@ -3,22 +3,47 @@ import { ReactiveEffectRunner } from "@vue/reactivity";
3
3
  export interface QueueJob {
4
4
  (): any;
5
5
  }
6
+ const immediateQueue = new Set<QueueJob>();
6
7
  const queue = new Set<QueueJob>();
7
8
 
8
- export function scheduler(jobGetter: () => ReactiveEffectRunner) {
9
+ export function scheduler(
10
+ jobGetter: () => ReactiveEffectRunner,
11
+ immediate = false,
12
+ ) {
9
13
  return () => {
10
- queueJob(jobGetter());
14
+ queueJob(jobGetter(), immediate);
11
15
  };
12
16
  }
13
- export function queueJob(job: QueueJob) {
17
+ export function queueJob(job: QueueJob, immediate = false) {
18
+ // if we have an immediate job, we don't need to queue the normal job.
14
19
  // the set is serving an important purpose here in deduping the effects we run
15
20
  // (which in effect coalesces multiple update effects together).
16
- queue.add(job);
21
+ if (immediate) {
22
+ immediateQueue.add(job);
23
+ } else {
24
+ queue.add(job);
25
+ }
17
26
  }
18
27
 
19
28
  export function flushJobs() {
20
- for (const job of queue) {
21
- queue.delete(job);
29
+ let job;
30
+ while ((job = takeJob()) !== null) {
22
31
  job();
23
32
  }
24
33
  }
34
+
35
+ function takeJob() {
36
+ if (immediateQueue.size > 0) {
37
+ // return first item in immediateQueue
38
+ const job = immediateQueue.values().next().value!;
39
+ immediateQueue.delete(job);
40
+ return job;
41
+ }
42
+ if (queue.size > 0) {
43
+ // return first item in queue
44
+ const job = queue.values().next().value!;
45
+ queue.delete(job);
46
+ return job;
47
+ }
48
+ return null;
49
+ }
package/src/slot.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  import { ref, Ref } from "@vue/reactivity";
2
- import { OutputSymbol } from "./binder.js";
2
+ import { effect, memo } from "./reactivity.js";
3
3
  import {
4
4
  Children,
5
5
  Component,
6
6
  ComponentDefinition,
7
- effect,
8
- memo,
9
- } from "./jsx-runtime.js";
7
+ } from "./runtime/component.js";
8
+ import type { OutputSymbol } from "./symbols/output-symbol.js";
10
9
 
11
10
  export interface SlotInstance extends ComponentDefinition {}
12
11
 
package/src/stc.ts CHANGED
@@ -1,9 +1,9 @@
1
+ import { code, text } from "./code.js";
1
2
  import {
2
3
  Children,
3
4
  ComponentCreator,
4
5
  ComponentDefinition,
5
- } from "@alloy-js/core/jsx-runtime";
6
- import { code, text } from "./code.js";
6
+ } from "./runtime/component.js";
7
7
 
8
8
  export type MakeChildrenOptional<T extends object> =
9
9
  T extends { children?: any } ?
package/src/sti.ts CHANGED
@@ -1,19 +1,19 @@
1
+ import { code, text } from "./code.js";
2
+ import { Children } from "./runtime/component.js";
1
3
  import {
2
- Children,
3
4
  createIntrinsic,
4
5
  IntrinsicElementBase,
5
- JSX,
6
- } from "@alloy-js/core/jsx-runtime";
7
- import { code, text } from "./code.js";
6
+ IntrinsicElements,
7
+ } from "./runtime/intrinsic.js";
8
8
 
9
- export type StiSignature<T extends keyof JSX.IntrinsicElements> = (
9
+ export type StiSignature<T extends keyof IntrinsicElements> = (
10
10
  ...args: unknown extends T ? []
11
- : {} extends Omit<JSX.IntrinsicElements[T], "children"> ?
12
- [props?: JSX.IntrinsicElements[T]]
13
- : [props: JSX.IntrinsicElements[T]]
11
+ : {} extends Omit<IntrinsicElements[T], "children"> ?
12
+ [props?: IntrinsicElements[T]]
13
+ : [props: IntrinsicElements[T]]
14
14
  ) => StiComponentCreator<T>;
15
15
 
16
- export type StiComponentCreator<T extends keyof JSX.IntrinsicElements> =
16
+ export type StiComponentCreator<T extends keyof IntrinsicElements> =
17
17
  (() => IntrinsicElementBase<T>) & {
18
18
  code(
19
19
  template: TemplateStringsArray,
@@ -26,11 +26,11 @@ export type StiComponentCreator<T extends keyof JSX.IntrinsicElements> =
26
26
  children(...children: Children[]): () => IntrinsicElementBase<T>;
27
27
  };
28
28
 
29
- export function sti<T extends keyof JSX.IntrinsicElements>(
29
+ export function sti<T extends keyof IntrinsicElements>(
30
30
  name: T,
31
31
  ): StiSignature<T> {
32
32
  return (...args) => {
33
- const props: JSX.IntrinsicElements[T] | undefined = args[0];
33
+ const props: IntrinsicElements[T] | undefined = args[0];
34
34
  const fn: StiComponentCreator<T> = () => createIntrinsic(name, props!);
35
35
  fn.children = (...children: Children[]) => {
36
36
  const propsWithChildren = {
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Flags that describe an output scope.
3
+ */
4
+ export enum OutputScopeFlags {
5
+ None = 0,
6
+
7
+ /**
8
+ * This scope is a static member scope.
9
+ */
10
+ StaticMemberScope = 1 << 0,
11
+
12
+ /**
13
+ * This scope is an instance member scope.
14
+ */
15
+ InstanceMemberScope = 1 << 1,
16
+
17
+ /**
18
+ * This scope is transient, and only exists to be merged with other scopes.
19
+ */
20
+ Transient = 1 << 2,
21
+
22
+ /**
23
+ * This scope is a member scope. Scopes with this flag will have an `owner`
24
+ * property that points to the symbol whose member this scope holds.
25
+ */
26
+ MemberScope = StaticMemberScope | InstanceMemberScope,
27
+ }
28
+
29
+ /**
30
+ * Flags that describe an output symbol.
31
+ */
32
+ export enum OutputSymbolFlags {
33
+ None = 0,
34
+
35
+ /**
36
+ * The symbol is an instance member container. Symbols with this flag will have a
37
+ * instanceMemberScope property that contains symbols for instance members.
38
+ */
39
+ InstanceMemberContainer = 1 << 0,
40
+
41
+ /**
42
+ * The symbol is a static member container. Symbols with this flag will have a
43
+ * staticMemberScope property that contains symbols for static members.
44
+ */
45
+ StaticMemberContainer = 1 << 1,
46
+
47
+ /**
48
+ * Whether this symbol contains members of any kind.
49
+ */
50
+ MemberContainer = InstanceMemberContainer | StaticMemberContainer,
51
+
52
+ /**
53
+ * Whether this symbol is an instance member of another symbol (i.e that it is
54
+ * stored in an instance member scope).
55
+ */
56
+ InstanceMember = 1 << 2,
57
+
58
+ /**
59
+ * Whether this symbol is a static member of another symbol (i.e that it is
60
+ * stored in a static member scope).
61
+ */
62
+ StaticMember = 1 << 3,
63
+
64
+ /**
65
+ * Transient symbols are not added to symbol tables and do not create
66
+ * referencable refkeys. They are used for temporary symbols that are intended
67
+ * to be used to calculate other symbols.
68
+ */
69
+ Transient = 1 << 4,
70
+
71
+ /**
72
+ * This symbol aliases another symbol. Only its name, flags, and scope are
73
+ * stored in this symbol. Otherwise, everything else is located on the alias
74
+ * target.
75
+ */
76
+ Alias = 1 << 5,
77
+
78
+ /**
79
+ * Whether this is an instance member or static member of another symbol.
80
+ */
81
+ Member = InstanceMember | StaticMember,
82
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./flags.js";
2
+ export * from "./output-scope.js";
3
+ export * from "./output-symbol.js";
4
+ export * from "./symbol-flow.js";
5
+ export * from "./symbol-slot.js";
6
+ export * from "./symbol-table.js";