@alloy-js/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +7 -0
- package/api-extractor.json +11 -0
- package/babel.config.cjs +4 -0
- package/dist/src/binder.d.ts +333 -0
- package/dist/src/binder.d.ts.map +1 -0
- package/dist/src/binder.js +444 -0
- package/dist/src/binder.js.map +1 -0
- package/dist/src/code.d.ts +3 -0
- package/dist/src/code.d.ts.map +1 -0
- package/dist/src/code.js +156 -0
- package/dist/src/code.js.map +1 -0
- package/dist/src/components/Declaration.d.ts +29 -0
- package/dist/src/components/Declaration.d.ts.map +1 -0
- package/dist/src/components/Declaration.js +47 -0
- package/dist/src/components/Declaration.js.map +1 -0
- package/dist/src/components/Indent.d.ts +13 -0
- package/dist/src/components/Indent.d.ts.map +1 -0
- package/dist/src/components/Indent.js +23 -0
- package/dist/src/components/Indent.js.map +1 -0
- package/dist/src/components/MemberDeclaration.d.ts +30 -0
- package/dist/src/components/MemberDeclaration.d.ts.map +1 -0
- package/dist/src/components/MemberDeclaration.js +52 -0
- package/dist/src/components/MemberDeclaration.js.map +1 -0
- package/dist/src/components/MemberName.d.ts +2 -0
- package/dist/src/components/MemberName.d.ts.map +1 -0
- package/dist/src/components/MemberName.js +11 -0
- package/dist/src/components/MemberName.js.map +1 -0
- package/dist/src/components/MemberScope.d.ts +27 -0
- package/dist/src/components/MemberScope.d.ts.map +1 -0
- package/dist/src/components/MemberScope.js +28 -0
- package/dist/src/components/MemberScope.js.map +1 -0
- package/dist/src/components/Name.d.ts +2 -0
- package/dist/src/components/Name.d.ts.map +1 -0
- package/dist/src/components/Name.js +11 -0
- package/dist/src/components/Name.js.map +1 -0
- package/dist/src/components/Output.d.ts +31 -0
- package/dist/src/components/Output.d.ts.map +1 -0
- package/dist/src/components/Output.js +44 -0
- package/dist/src/components/Output.js.map +1 -0
- package/dist/src/components/Scope.d.ts +10 -0
- package/dist/src/components/Scope.d.ts.map +1 -0
- package/dist/src/components/Scope.js +25 -0
- package/dist/src/components/Scope.js.map +1 -0
- package/dist/src/components/SourceDirectory.d.ts +7 -0
- package/dist/src/components/SourceDirectory.d.ts.map +1 -0
- package/dist/src/components/SourceDirectory.js +38 -0
- package/dist/src/components/SourceDirectory.js.map +1 -0
- package/dist/src/components/SourceFile.d.ts +12 -0
- package/dist/src/components/SourceFile.d.ts.map +1 -0
- package/dist/src/components/SourceFile.js +26 -0
- package/dist/src/components/SourceFile.js.map +1 -0
- package/dist/src/components/index.d.ts +11 -0
- package/dist/src/components/index.d.ts.map +1 -0
- package/dist/src/components/index.js +11 -0
- package/dist/src/components/index.js.map +1 -0
- package/dist/src/components/stc/index.d.ts +26 -0
- package/dist/src/components/stc/index.d.ts.map +1 -0
- package/dist/src/components/stc/index.js +9 -0
- package/dist/src/components/stc/index.js.map +1 -0
- package/dist/src/context/assignment.d.ts +39 -0
- package/dist/src/context/assignment.d.ts.map +1 -0
- package/dist/src/context/assignment.js +39 -0
- package/dist/src/context/assignment.js.map +1 -0
- package/dist/src/context/binder.d.ts +9 -0
- package/dist/src/context/binder.d.ts.map +1 -0
- package/dist/src/context/binder.js +12 -0
- package/dist/src/context/binder.js.map +1 -0
- package/dist/src/context/declaration.d.ts +4 -0
- package/dist/src/context/declaration.d.ts.map +1 -0
- package/dist/src/context/declaration.js +3 -0
- package/dist/src/context/declaration.js.map +1 -0
- package/dist/src/context/indent.d.ts +5 -0
- package/dist/src/context/indent.d.ts.map +1 -0
- package/dist/src/context/indent.js +8 -0
- package/dist/src/context/indent.js.map +1 -0
- package/dist/src/context/index.d.ts +11 -0
- package/dist/src/context/index.d.ts.map +1 -0
- package/dist/src/context/index.js +11 -0
- package/dist/src/context/index.js.map +1 -0
- package/dist/src/context/member-declaration.d.ts +9 -0
- package/dist/src/context/member-declaration.d.ts.map +1 -0
- package/dist/src/context/member-declaration.js +9 -0
- package/dist/src/context/member-declaration.js.map +1 -0
- package/dist/src/context/member-scope.d.ts +13 -0
- package/dist/src/context/member-scope.d.ts.map +1 -0
- package/dist/src/context/member-scope.js +12 -0
- package/dist/src/context/member-scope.js.map +1 -0
- package/dist/src/context/name-policy.d.ts +5 -0
- package/dist/src/context/name-policy.d.ts.map +1 -0
- package/dist/src/context/name-policy.js +10 -0
- package/dist/src/context/name-policy.js.map +1 -0
- package/dist/src/context/scope.d.ts +5 -0
- package/dist/src/context/scope.d.ts.map +1 -0
- package/dist/src/context/scope.js +6 -0
- package/dist/src/context/scope.js.map +1 -0
- package/dist/src/context/source-directory.d.ts +9 -0
- package/dist/src/context/source-directory.d.ts.map +1 -0
- package/dist/src/context/source-directory.js +3 -0
- package/dist/src/context/source-directory.js.map +1 -0
- package/dist/src/context/source-file.d.ts +12 -0
- package/dist/src/context/source-file.d.ts.map +1 -0
- package/dist/src/context/source-file.js +3 -0
- package/dist/src/context/source-file.js.map +1 -0
- package/dist/src/context.d.ts +13 -0
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +30 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/index.d.ts +13 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +13 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/jsx-runtime.d.ts +43 -0
- package/dist/src/jsx-runtime.d.ts.map +1 -0
- package/dist/src/jsx-runtime.js +172 -0
- package/dist/src/jsx-runtime.js.map +1 -0
- package/dist/src/name-policy.d.ts +5 -0
- package/dist/src/name-policy.d.ts.map +1 -0
- package/dist/src/name-policy.js +8 -0
- package/dist/src/name-policy.js.map +1 -0
- package/dist/src/refkey.d.ts +9 -0
- package/dist/src/refkey.d.ts.map +1 -0
- package/dist/src/refkey.js +44 -0
- package/dist/src/refkey.js.map +1 -0
- package/dist/src/render.d.ts +147 -0
- package/dist/src/render.d.ts.map +1 -0
- package/dist/src/render.js +317 -0
- package/dist/src/render.js.map +1 -0
- package/dist/src/tsdoc-metadata.json +11 -0
- package/dist/src/utils.d.ts +80 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +219 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/test/children.test.d.ts +2 -0
- package/dist/test/children.test.d.ts.map +1 -0
- package/dist/test/components/source-file.test.d.ts +2 -0
- package/dist/test/components/source-file.test.d.ts.map +1 -0
- package/dist/test/name-policy.test.d.ts +2 -0
- package/dist/test/name-policy.test.d.ts.map +1 -0
- package/dist/test/reactivity/ref-rendering.test.d.ts +2 -0
- package/dist/test/reactivity/ref-rendering.test.d.ts.map +1 -0
- package/dist/test/reactivity/test.test.d.ts +2 -0
- package/dist/test/reactivity/test.test.d.ts.map +1 -0
- package/dist/test/refkey.test.d.ts +2 -0
- package/dist/test/refkey.test.d.ts.map +1 -0
- package/dist/test/rendering/basic.test.d.ts +2 -0
- package/dist/test/rendering/basic.test.d.ts.map +1 -0
- package/dist/test/rendering/code.test.d.ts +2 -0
- package/dist/test/rendering/code.test.d.ts.map +1 -0
- package/dist/test/rendering/indent.test.d.ts +2 -0
- package/dist/test/rendering/indent.test.d.ts.map +1 -0
- package/dist/test/rendering/linebreaks.test.d.ts +2 -0
- package/dist/test/rendering/linebreaks.test.d.ts.map +1 -0
- package/dist/test/rendering/refkeys.test.d.ts +2 -0
- package/dist/test/rendering/refkeys.test.d.ts.map +1 -0
- package/dist/test/stc.test.d.ts +2 -0
- package/dist/test/stc.test.d.ts.map +1 -0
- package/dist/test/symbols.test.d.ts +2 -0
- package/dist/test/symbols.test.d.ts.map +1 -0
- package/dist/test/utils.test.d.ts +2 -0
- package/dist/test/utils.test.d.ts.map +1 -0
- package/dist/testing/extend-expect.d.ts +2 -0
- package/dist/testing/extend-expect.d.ts.map +1 -0
- package/dist/testing/extend-expect.js +22 -0
- package/dist/testing/extend-expect.js.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +3 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/render.d.ts +7 -0
- package/dist/testing/render.d.ts.map +1 -0
- package/dist/testing/render.js +25 -0
- package/dist/testing/render.js.map +1 -0
- package/dist/testing/vitest.d.js +1 -0
- package/dist/testing/vitest.d.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +64 -0
- package/src/binder.ts +838 -0
- package/src/code.ts +220 -0
- package/src/components/Declaration.tsx +53 -0
- package/src/components/Indent.tsx +33 -0
- package/src/components/MemberDeclaration.tsx +62 -0
- package/src/components/MemberName.tsx +11 -0
- package/src/components/MemberScope.tsx +40 -0
- package/src/components/Name.tsx +11 -0
- package/src/components/Output.tsx +69 -0
- package/src/components/Scope.tsx +27 -0
- package/src/components/SourceDirectory.tsx +43 -0
- package/src/components/SourceFile.tsx +33 -0
- package/src/components/index.tsx +10 -0
- package/src/components/stc/index.ts +9 -0
- package/src/context/assignment.ts +57 -0
- package/src/context/binder.ts +14 -0
- package/src/context/declaration.ts +5 -0
- package/src/context/indent.ts +10 -0
- package/src/context/index.ts +10 -0
- package/src/context/member-declaration.ts +10 -0
- package/src/context/member-scope.ts +17 -0
- package/src/context/name-policy.ts +13 -0
- package/src/context/scope.ts +8 -0
- package/src/context/source-directory.ts +11 -0
- package/src/context/source-file.ts +12 -0
- package/src/context.ts +53 -0
- package/src/index.ts +21 -0
- package/src/jsx-runtime.ts +266 -0
- package/src/name-policy.ts +13 -0
- package/src/refkey.ts +62 -0
- package/src/render.ts +389 -0
- package/src/utils.ts +288 -0
- package/temp/api.json +8840 -0
- package/test/children.test.tsx +33 -0
- package/test/components/source-file.test.tsx +45 -0
- package/test/name-policy.test.tsx +19 -0
- package/test/reactivity/ref-rendering.test.tsx +50 -0
- package/test/reactivity/test.test.tsx +83 -0
- package/test/refkey.test.ts +32 -0
- package/test/rendering/basic.test.tsx +156 -0
- package/test/rendering/code.test.tsx +62 -0
- package/test/rendering/indent.test.tsx +608 -0
- package/test/rendering/linebreaks.test.tsx +72 -0
- package/test/rendering/refkeys.test.tsx +35 -0
- package/test/stc.test.tsx +21 -0
- package/test/symbols.test.ts +406 -0
- package/test/utils.test.tsx +150 -0
- package/testing/extend-expect.ts +20 -0
- package/testing/index.ts +2 -0
- package/testing/render.ts +37 -0
- package/testing/vitest.d.ts +10 -0
- package/tsconfig.json +17 -0
- package/vitest.config.ts +18 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Binder } from "../binder.js";
|
|
2
|
+
import { ComponentContext, createContext, useContext } from "../context.js";
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4
|
+
import type { Output } from "../components/Output.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The binder context provides the binder instance to all components. This
|
|
8
|
+
* context is provided by the {@link Output | output component}.
|
|
9
|
+
*/
|
|
10
|
+
export const BinderContext: ComponentContext<Binder> = createContext();
|
|
11
|
+
|
|
12
|
+
export function useBinder() {
|
|
13
|
+
return useContext(BinderContext)!;
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IndentState } from "../components/Indent.jsx";
|
|
2
|
+
import { ComponentContext, createContext } from "../context.js";
|
|
3
|
+
|
|
4
|
+
export const IndentContext: ComponentContext<IndentState> = createContext({
|
|
5
|
+
level: 0,
|
|
6
|
+
indent: " ",
|
|
7
|
+
indentString: "",
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const TestContext: ComponentContext<string> = createContext("test");
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./assignment.js";
|
|
2
|
+
export * from "./binder.js";
|
|
3
|
+
export * from "./declaration.js";
|
|
4
|
+
export * from "./indent.js";
|
|
5
|
+
export * from "./member-declaration.js";
|
|
6
|
+
export * from "./member-scope.js";
|
|
7
|
+
export * from "./name-policy.js";
|
|
8
|
+
export * from "./scope.js";
|
|
9
|
+
export * from "./source-directory.js";
|
|
10
|
+
export * from "./source-file.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { OutputSymbol } from "../binder.js";
|
|
2
|
+
import { ComponentContext, createContext } from "../context.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Provides the symbol for the member currently being declared.
|
|
6
|
+
*
|
|
7
|
+
* @see {@link DeclarationContext} for getting the symbol for the current non-member declaration.
|
|
8
|
+
*/
|
|
9
|
+
export const MemberDeclarationContext: ComponentContext<OutputSymbol> =
|
|
10
|
+
createContext();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OutputScope } from "../binder.js";
|
|
2
|
+
import { ComponentContext, createContext, useContext } from "../context.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The member scope context provides the instance and static member scopes that
|
|
6
|
+
* are used for member declarations and instance member resolution.
|
|
7
|
+
*/
|
|
8
|
+
export interface MemberScopeContext {
|
|
9
|
+
staticMembers?: OutputScope;
|
|
10
|
+
instanceMembers?: OutputScope;
|
|
11
|
+
}
|
|
12
|
+
export const MemberScopeContext: ComponentContext<MemberScopeContext> =
|
|
13
|
+
createContext();
|
|
14
|
+
|
|
15
|
+
export function useMemberScope() {
|
|
16
|
+
return useContext(MemberScopeContext)!;
|
|
17
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ComponentContext, createContext, useContext } from "../context.js";
|
|
2
|
+
import { NamePolicy } from "../name-policy.js";
|
|
3
|
+
|
|
4
|
+
export const NamePolicyContext: ComponentContext<NamePolicy<string>> =
|
|
5
|
+
createContext<NamePolicy<string>>({
|
|
6
|
+
getName(name) {
|
|
7
|
+
return name;
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export function useNamePolicy() {
|
|
12
|
+
return useContext(NamePolicyContext)!;
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { OutputScope } from "../binder.js";
|
|
2
|
+
import { ComponentContext, createContext, useContext } from "../context.js";
|
|
3
|
+
|
|
4
|
+
export const ScopeContext: ComponentContext<OutputScope> = createContext();
|
|
5
|
+
|
|
6
|
+
export function useScope() {
|
|
7
|
+
return useContext(ScopeContext)!;
|
|
8
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ComponentContext, createContext } from "../context.js";
|
|
2
|
+
import { SourceFileContext } from "./source-file.js";
|
|
3
|
+
|
|
4
|
+
export interface SourceDirectoryContext {
|
|
5
|
+
contents: (SourceDirectoryContext | SourceFileContext)[];
|
|
6
|
+
addContent(content: SourceDirectoryContext | SourceFileContext): void;
|
|
7
|
+
path: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const SourceDirectoryContext: ComponentContext<SourceDirectoryContext> =
|
|
11
|
+
createContext();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ComponentContext, createContext } from "../context.js";
|
|
2
|
+
import { ComponentDefinition } from "../jsx-runtime.js";
|
|
3
|
+
import { Refkey } from "../refkey.js";
|
|
4
|
+
|
|
5
|
+
export interface SourceFileContext {
|
|
6
|
+
path: string;
|
|
7
|
+
filetype: string;
|
|
8
|
+
reference?: ComponentDefinition<{ refkey: Refkey }>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const SourceFileContext: ComponentContext<SourceFileContext> =
|
|
12
|
+
createContext();
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Children,
|
|
3
|
+
ComponentDefinition,
|
|
4
|
+
effect,
|
|
5
|
+
getContext,
|
|
6
|
+
untrack,
|
|
7
|
+
} from "@alloy-js/core/jsx-runtime";
|
|
8
|
+
import { shallowRef } from "@vue/reactivity";
|
|
9
|
+
|
|
10
|
+
export interface ComponentContext<T> {
|
|
11
|
+
id: symbol;
|
|
12
|
+
default: T | undefined;
|
|
13
|
+
Provider: ComponentDefinition<ContextProviderProps<T>>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ContextProviderProps<T = unknown> {
|
|
17
|
+
value?: T;
|
|
18
|
+
children?: Children;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function useContext<T>(context: ComponentContext<T>): T | undefined {
|
|
22
|
+
// context must come from a parent
|
|
23
|
+
let current = getContext();
|
|
24
|
+
while (current) {
|
|
25
|
+
if (Object.hasOwn(current.context!, context.id)) {
|
|
26
|
+
return current.context![context.id] as T | undefined;
|
|
27
|
+
}
|
|
28
|
+
current = current.owner;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return context.default;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createContext<T = unknown>(
|
|
35
|
+
defaultValue?: T,
|
|
36
|
+
): ComponentContext<T> {
|
|
37
|
+
const id = Symbol("context");
|
|
38
|
+
return {
|
|
39
|
+
id,
|
|
40
|
+
default: defaultValue,
|
|
41
|
+
Provider(props: ContextProviderProps<T>) {
|
|
42
|
+
const context = getContext();
|
|
43
|
+
|
|
44
|
+
const rendered = shallowRef();
|
|
45
|
+
effect(() => {
|
|
46
|
+
context!.context![id] = props.value;
|
|
47
|
+
rendered.value = untrack(() => props.children);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return rendered.value;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
export {
|
|
3
|
+
computed,
|
|
4
|
+
isProxy,
|
|
5
|
+
reactive,
|
|
6
|
+
ref,
|
|
7
|
+
shallowReactive,
|
|
8
|
+
shallowRef,
|
|
9
|
+
toRaw,
|
|
10
|
+
type Ref,
|
|
11
|
+
} from "@vue/reactivity";
|
|
12
|
+
export * from "./binder.js";
|
|
13
|
+
export * from "./code.js";
|
|
14
|
+
export * from "./components/index.js";
|
|
15
|
+
export * from "./context.js";
|
|
16
|
+
export * from "./context/index.js";
|
|
17
|
+
export * from "./jsx-runtime.js";
|
|
18
|
+
export * from "./name-policy.js";
|
|
19
|
+
export * from "./refkey.js";
|
|
20
|
+
export * from "./render.js";
|
|
21
|
+
export * from "./utils.js";
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// Much of the implementations in this file are inspired by vuerx-js
|
|
2
|
+
// See: https://github.com/ryansolid/vuerx-jsx.
|
|
3
|
+
import {
|
|
4
|
+
pauseTracking,
|
|
5
|
+
Ref,
|
|
6
|
+
resetTracking,
|
|
7
|
+
shallowRef,
|
|
8
|
+
stop,
|
|
9
|
+
effect as vueEffect,
|
|
10
|
+
} from "@vue/reactivity";
|
|
11
|
+
import { Refkey } from "./refkey.js";
|
|
12
|
+
|
|
13
|
+
if ((globalThis as any).ALLOY) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
"Multiple versions of the JSX Runtime have been loaded. This will likely cause undesirable behavior.",
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
(globalThis as any).ALLOY = true;
|
|
19
|
+
|
|
20
|
+
export interface Disposable {
|
|
21
|
+
(): void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface Context {
|
|
25
|
+
disposables: Disposable[];
|
|
26
|
+
owner: Context | null;
|
|
27
|
+
|
|
28
|
+
// context providers
|
|
29
|
+
context?: Record<symbol, unknown>;
|
|
30
|
+
|
|
31
|
+
// store random info about the node
|
|
32
|
+
meta?: Record<string, any>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let globalContext: Context | null = null;
|
|
36
|
+
export function getContext() {
|
|
37
|
+
return globalContext;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function root<T>(fn: (d: Disposable) => T, src?: string): T {
|
|
41
|
+
globalContext = {
|
|
42
|
+
src,
|
|
43
|
+
disposables: [],
|
|
44
|
+
owner: globalContext,
|
|
45
|
+
context: {},
|
|
46
|
+
} as any;
|
|
47
|
+
let ret;
|
|
48
|
+
try {
|
|
49
|
+
ret = untrack(() =>
|
|
50
|
+
fn(() => {
|
|
51
|
+
for (const d of globalContext!.disposables) {
|
|
52
|
+
d();
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
} finally {
|
|
57
|
+
globalContext = globalContext!.owner;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return ret;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function untrack<T>(fn: () => T): T {
|
|
64
|
+
pauseTracking();
|
|
65
|
+
const v = fn();
|
|
66
|
+
resetTracking();
|
|
67
|
+
return v;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function memo<T>(fn: () => T, equal?: boolean): () => T {
|
|
71
|
+
const o = shallowRef();
|
|
72
|
+
effect((prev) => {
|
|
73
|
+
const res = fn();
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
75
|
+
(!equal || prev !== res) && (o.value = res);
|
|
76
|
+
return res;
|
|
77
|
+
});
|
|
78
|
+
return () => o.value;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function effect<T>(fn: (prev?: T) => T, current?: T) {
|
|
82
|
+
const context = {
|
|
83
|
+
src: "effect",
|
|
84
|
+
context: {},
|
|
85
|
+
disposables: [] as (() => void)[],
|
|
86
|
+
owner: globalContext,
|
|
87
|
+
} as any;
|
|
88
|
+
|
|
89
|
+
const cleanupFn = (final: boolean) => {
|
|
90
|
+
const d = context.disposables;
|
|
91
|
+
context.disposables = [];
|
|
92
|
+
for (let k = 0, len = d.length; k < len; k++) d[k]();
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
94
|
+
final && stop(c);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const c = vueEffect(() => {
|
|
98
|
+
cleanupFn(false);
|
|
99
|
+
const oldContext = globalContext;
|
|
100
|
+
globalContext = context;
|
|
101
|
+
try {
|
|
102
|
+
current = fn(current);
|
|
103
|
+
} finally {
|
|
104
|
+
globalContext = oldContext;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
cleanup(() => cleanupFn(true));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function cleanup(fn: Disposable) {
|
|
112
|
+
if (globalContext != null) {
|
|
113
|
+
globalContext.disposables.push(fn);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export type Child =
|
|
118
|
+
| string
|
|
119
|
+
| boolean
|
|
120
|
+
| number
|
|
121
|
+
| undefined
|
|
122
|
+
| null
|
|
123
|
+
| (() => Child | Children)
|
|
124
|
+
| Child[]
|
|
125
|
+
| Ref
|
|
126
|
+
| Refkey;
|
|
127
|
+
|
|
128
|
+
export type Children = Child | Child[];
|
|
129
|
+
export type Props = Record<string, unknown>;
|
|
130
|
+
|
|
131
|
+
export interface ComponentDefinition<TProps = Props> {
|
|
132
|
+
(props: TProps): Child | Children;
|
|
133
|
+
}
|
|
134
|
+
export interface Component<TProps = Props> {
|
|
135
|
+
(props: TProps): Child | Children;
|
|
136
|
+
tag?: symbol;
|
|
137
|
+
}
|
|
138
|
+
export interface ComponentCreator<TProps = Props> {
|
|
139
|
+
component: Component<TProps>;
|
|
140
|
+
(): Child | Children;
|
|
141
|
+
props: Props;
|
|
142
|
+
tag?: symbol;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// debugging utilities
|
|
146
|
+
const renderStack: {
|
|
147
|
+
component: Component<any>;
|
|
148
|
+
props: Props;
|
|
149
|
+
}[] = [];
|
|
150
|
+
|
|
151
|
+
export const shouldDebug = !!process.env.ALLOY_DEBUG;
|
|
152
|
+
|
|
153
|
+
export function pushStack(component: Component<any>, props: Props) {
|
|
154
|
+
if (!shouldDebug) return;
|
|
155
|
+
renderStack.push({ component, props });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function popStack() {
|
|
159
|
+
if (!shouldDebug) return;
|
|
160
|
+
renderStack.pop();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function printRenderStack() {
|
|
164
|
+
if (!shouldDebug) return;
|
|
165
|
+
|
|
166
|
+
// eslint-disable-next-line no-console
|
|
167
|
+
console.error("Error rendering:");
|
|
168
|
+
for (let i = renderStack.length - 1; i >= 0; i--) {
|
|
169
|
+
const { component, props } = renderStack[i];
|
|
170
|
+
// eslint-disable-next-line no-console
|
|
171
|
+
console.error(` at ${component.name}(${inspectProps(props)})`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function inspectProps(props: Props) {
|
|
176
|
+
return JSON.stringify(
|
|
177
|
+
Object.fromEntries(
|
|
178
|
+
Object.entries(props).map(([key, value]) => {
|
|
179
|
+
let safeValue;
|
|
180
|
+
switch (typeof value) {
|
|
181
|
+
case "string":
|
|
182
|
+
case "number":
|
|
183
|
+
case "boolean":
|
|
184
|
+
safeValue = value;
|
|
185
|
+
break;
|
|
186
|
+
case "undefined":
|
|
187
|
+
safeValue = "undefined";
|
|
188
|
+
break;
|
|
189
|
+
case "object":
|
|
190
|
+
safeValue = value ? "{...}" : null;
|
|
191
|
+
break;
|
|
192
|
+
case "function":
|
|
193
|
+
safeValue = "function";
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
return [key, safeValue];
|
|
197
|
+
}),
|
|
198
|
+
),
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// These can be removed with a smarter transform that encodes the information we
|
|
203
|
+
// need in the compiled JSX output.
|
|
204
|
+
export function isComponentCreator(item: unknown): item is ComponentCreator {
|
|
205
|
+
return typeof item === "function" && (item as any).component;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function createComponent<TProps extends Props = Props>(
|
|
209
|
+
C: Component<TProps>,
|
|
210
|
+
props: TProps,
|
|
211
|
+
): ComponentCreator<TProps> {
|
|
212
|
+
const creator: ComponentCreator<TProps> = () => /* */ C(props);
|
|
213
|
+
creator.props = props;
|
|
214
|
+
creator.component = C;
|
|
215
|
+
if (C.tag) {
|
|
216
|
+
creator.tag = C.tag;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return creator;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function taggedComponent<TProps = Props>(
|
|
223
|
+
tag: symbol,
|
|
224
|
+
component: Component<TProps>,
|
|
225
|
+
): Component<TProps> {
|
|
226
|
+
component.tag = tag;
|
|
227
|
+
return component;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function mergeProps<T, U>(source: T, source1: U): T & U;
|
|
231
|
+
export function mergeProps<T, U, V>(
|
|
232
|
+
source: T,
|
|
233
|
+
source1: U,
|
|
234
|
+
source2: V,
|
|
235
|
+
): T & U & V;
|
|
236
|
+
export function mergeProps<T, U, V, W>(
|
|
237
|
+
source: T,
|
|
238
|
+
source1: U,
|
|
239
|
+
source2: V,
|
|
240
|
+
source3: W,
|
|
241
|
+
): T & U & V & W;
|
|
242
|
+
export function mergeProps(...sources: any): any {
|
|
243
|
+
const target = {};
|
|
244
|
+
for (let i = 0; i < sources.length; i++) {
|
|
245
|
+
let source = sources[i];
|
|
246
|
+
if (typeof source === "function") source = source();
|
|
247
|
+
if (source) {
|
|
248
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
249
|
+
for (const key in descriptors) {
|
|
250
|
+
if (key in target) continue;
|
|
251
|
+
Object.defineProperty(target, key, {
|
|
252
|
+
enumerable: true,
|
|
253
|
+
get() {
|
|
254
|
+
for (let i = sources.length - 1; i >= 0; i--) {
|
|
255
|
+
let s = sources[i];
|
|
256
|
+
if (typeof s === "function") s = s();
|
|
257
|
+
const v = (s || {})[key];
|
|
258
|
+
if (v !== undefined) return v;
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return target;
|
|
266
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface NamePolicy<TElements extends string> {
|
|
2
|
+
getName(originalName: string, element: TElements): string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function createNamePolicy<T extends string>(
|
|
6
|
+
namer: (name: string, elements: T) => string,
|
|
7
|
+
): NamePolicy<T> {
|
|
8
|
+
return {
|
|
9
|
+
getName(name, element) {
|
|
10
|
+
return namer(name, element);
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
}
|
package/src/refkey.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { markRaw } from "@vue/reactivity";
|
|
2
|
+
|
|
3
|
+
const objectIds = new WeakMap<WeakKey, Refkey>();
|
|
4
|
+
let objId = 0;
|
|
5
|
+
|
|
6
|
+
function getObjectKey(value: WeakKey) {
|
|
7
|
+
if (objectIds.has(value)) {
|
|
8
|
+
return objectIds.get(value)!;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const key = createRefkey(`o${objId++}`);
|
|
12
|
+
objectIds.set(value, key);
|
|
13
|
+
|
|
14
|
+
return key;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const RefkeySym: unique symbol = Symbol();
|
|
18
|
+
|
|
19
|
+
export type Refkey = { key: string; [RefkeySym]: true };
|
|
20
|
+
|
|
21
|
+
function createRefkey(key: string): Refkey {
|
|
22
|
+
const refkey: Refkey = {
|
|
23
|
+
key,
|
|
24
|
+
[RefkeySym]: true,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
markRaw(refkey);
|
|
28
|
+
|
|
29
|
+
return refkey;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function isRefkey(value: unknown): value is Refkey {
|
|
33
|
+
return (
|
|
34
|
+
typeof value === "object" &&
|
|
35
|
+
value !== null &&
|
|
36
|
+
Object.hasOwn(value, RefkeySym)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getKey(value: unknown): Refkey {
|
|
41
|
+
if (isRefkey(value)) {
|
|
42
|
+
return value;
|
|
43
|
+
} else if (typeof value === "object" && value !== null) {
|
|
44
|
+
return getObjectKey(value);
|
|
45
|
+
} else {
|
|
46
|
+
return createRefkey(`s${String(value)}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const knownRefkeys = new Map<string, Refkey>();
|
|
51
|
+
export function refkey(...args: unknown[]): Refkey {
|
|
52
|
+
const keys = args.length === 0 ? [getKey({})] : args.map((v) => getKey(v));
|
|
53
|
+
|
|
54
|
+
const compositeKey = keys.map((v) => v.key).join("\u2063");
|
|
55
|
+
if (knownRefkeys.has(compositeKey)) {
|
|
56
|
+
return knownRefkeys.get(compositeKey)!;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const key = createRefkey(compositeKey);
|
|
60
|
+
knownRefkeys.set(compositeKey, key);
|
|
61
|
+
return key;
|
|
62
|
+
}
|