signalium 2.2.2 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/cjs/development/config-B0MtLBgx.js.map +1 -1
- package/dist/cjs/development/{debug-DuXQhd5q.js → debug-gCDAvnLM.js} +237 -214
- package/dist/cjs/development/debug-gCDAvnLM.js.map +1 -0
- package/dist/cjs/development/debug.js +9 -3
- package/dist/cjs/development/debug.js.map +1 -1
- package/dist/cjs/development/index.js +8 -8
- package/dist/cjs/development/react/index.js +43 -38
- package/dist/cjs/development/react/index.js.map +1 -1
- package/dist/cjs/development/snapshot-Di0yziPX.js +147 -0
- package/dist/cjs/development/snapshot-Di0yziPX.js.map +1 -0
- package/dist/cjs/development/transform/index.js +137 -118
- package/dist/cjs/development/transform/index.js.map +1 -1
- package/dist/cjs/development/utils.js +5 -3
- package/dist/cjs/development/utils.js.map +1 -1
- package/dist/cjs/production/config-B0MtLBgx.js.map +1 -1
- package/dist/cjs/production/{contexts-DOH1tHd8.js → contexts-Wgq2NOVX.js} +156 -140
- package/dist/cjs/production/contexts-Wgq2NOVX.js.map +1 -0
- package/dist/cjs/production/debug.js +61 -66
- package/dist/cjs/production/debug.js.map +1 -1
- package/dist/cjs/production/index.js +8 -8
- package/dist/cjs/production/react/index.js +43 -38
- package/dist/cjs/production/react/index.js.map +1 -1
- package/dist/cjs/production/snapshot-YJJyLbxS.js +147 -0
- package/dist/cjs/production/snapshot-YJJyLbxS.js.map +1 -0
- package/dist/cjs/production/transform/index.js +137 -118
- package/dist/cjs/production/transform/index.js.map +1 -1
- package/dist/cjs/production/utils.js +5 -3
- package/dist/cjs/production/utils.js.map +1 -1
- package/dist/esm/development/config-CPQL7hX-.js.map +1 -1
- package/dist/esm/development/{debug-E2E1pZe5.js → debug-AoHfqs62.js} +221 -196
- package/dist/esm/development/debug-AoHfqs62.js.map +1 -0
- package/dist/esm/development/debug.js +1 -1
- package/dist/esm/development/index.js +6 -6
- package/dist/esm/development/react/index.js +43 -38
- package/dist/esm/development/react/index.js.map +1 -1
- package/dist/esm/development/snapshot-Bq0Um_hQ.js +148 -0
- package/dist/esm/development/snapshot-Bq0Um_hQ.js.map +1 -0
- package/dist/esm/development/transform/index.js +137 -118
- package/dist/esm/development/transform/index.js.map +1 -1
- package/dist/esm/development/utils.js +7 -4
- package/dist/esm/development/utils.js.map +1 -1
- package/dist/esm/internals/async.d.ts.map +1 -1
- package/dist/esm/internals/core-api.d.ts +2 -2
- package/dist/esm/internals/core-api.d.ts.map +1 -1
- package/dist/esm/internals/edge.d.ts +4 -4
- package/dist/esm/internals/edge.d.ts.map +1 -1
- package/dist/esm/internals/reactive.d.ts +14 -4
- package/dist/esm/internals/reactive.d.ts.map +1 -1
- package/dist/esm/internals/scheduling.d.ts.map +1 -1
- package/dist/esm/internals/signal.d.ts.map +1 -1
- package/dist/esm/internals/utils/snapshot.d.ts +29 -0
- package/dist/esm/internals/utils/snapshot.d.ts.map +1 -0
- package/dist/esm/production/config-CPQL7hX-.js.map +1 -1
- package/dist/esm/production/{contexts-Dj9Y86xW.js → contexts-X0gSj6rQ.js} +159 -143
- package/dist/esm/production/contexts-X0gSj6rQ.js.map +1 -0
- package/dist/esm/production/debug.js +51 -54
- package/dist/esm/production/debug.js.map +1 -1
- package/dist/esm/production/index.js +7 -7
- package/dist/esm/production/react/index.js +43 -38
- package/dist/esm/production/react/index.js.map +1 -1
- package/dist/esm/production/snapshot-CDS1d8mq.js +148 -0
- package/dist/esm/production/snapshot-CDS1d8mq.js.map +1 -0
- package/dist/esm/production/transform/index.js +137 -118
- package/dist/esm/production/transform/index.js.map +1 -1
- package/dist/esm/production/utils.js +7 -4
- package/dist/esm/production/utils.js.map +1 -1
- package/dist/esm/react/index.d.ts +1 -1
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/provider.d.ts.map +1 -1
- package/dist/esm/react/use-reactive.d.ts +1 -0
- package/dist/esm/react/use-reactive.d.ts.map +1 -1
- package/dist/esm/transform/callback.d.ts.map +1 -1
- package/dist/esm/transform/promise.d.ts.map +1 -1
- package/dist/esm/types.d.ts +5 -1
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.d.ts.map +1 -1
- package/package.json +7 -5
- package/dist/cjs/development/core-api-C8J7lYBC.js +0 -55
- package/dist/cjs/development/core-api-C8J7lYBC.js.map +0 -1
- package/dist/cjs/development/debug-DuXQhd5q.js.map +0 -1
- package/dist/cjs/production/contexts-DOH1tHd8.js.map +0 -1
- package/dist/cjs/production/core-api-Cx2_AumW.js +0 -55
- package/dist/cjs/production/core-api-Cx2_AumW.js.map +0 -1
- package/dist/esm/development/core-api-CF5aK2Lx.js +0 -56
- package/dist/esm/development/core-api-CF5aK2Lx.js.map +0 -1
- package/dist/esm/development/debug-E2E1pZe5.js.map +0 -1
- package/dist/esm/production/contexts-Dj9Y86xW.js.map +0 -1
- package/dist/esm/production/core-api-D_uw3umM.js +0 -56
- package/dist/esm/production/core-api-D_uw3umM.js.map +0 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { c as createReactiveDefinition, S as SignalScope, g as getCurrentScope, a as createReactiveSignal, b as createTask, d as createRelay, e as getScopeOwner, i as isReactivePromise } from "./debug-AoHfqs62.js";
|
|
2
|
+
const DERIVED_DEFINITION_MAP = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
function getReactiveFnAndDefinition(fn, opts) {
|
|
4
|
+
let fnAndDef = DERIVED_DEFINITION_MAP.get(fn);
|
|
5
|
+
if (!fnAndDef) {
|
|
6
|
+
const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey, void 0);
|
|
7
|
+
const defScope = getCurrentScope();
|
|
8
|
+
const reactiveFn = (...args) => {
|
|
9
|
+
const scope = getCurrentScope(defScope);
|
|
10
|
+
const signal = scope.get(def, args);
|
|
11
|
+
return signal.value;
|
|
12
|
+
};
|
|
13
|
+
fnAndDef = [reactiveFn, def];
|
|
14
|
+
DERIVED_DEFINITION_MAP.set(fn, fnAndDef);
|
|
15
|
+
}
|
|
16
|
+
return fnAndDef;
|
|
17
|
+
}
|
|
18
|
+
function reactive(fn, opts) {
|
|
19
|
+
return getReactiveFnAndDefinition(fn, opts)[0];
|
|
20
|
+
}
|
|
21
|
+
const reactiveMethod = (owner, fn, opts) => {
|
|
22
|
+
const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey, void 0);
|
|
23
|
+
const reactiveFn = (...args) => {
|
|
24
|
+
return getScopeOwner(owner).get(def, args).value;
|
|
25
|
+
};
|
|
26
|
+
DERIVED_DEFINITION_MAP.set(reactiveFn, [reactiveFn, def]);
|
|
27
|
+
return reactiveFn;
|
|
28
|
+
};
|
|
29
|
+
function relay(activate, opts) {
|
|
30
|
+
const scope = getCurrentScope();
|
|
31
|
+
return createRelay(activate, scope, opts);
|
|
32
|
+
}
|
|
33
|
+
const task = (fn, opts) => {
|
|
34
|
+
const scope = getCurrentScope();
|
|
35
|
+
return createTask(fn, scope, opts);
|
|
36
|
+
};
|
|
37
|
+
function watcher(fn, opts) {
|
|
38
|
+
const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, void 0, opts?.tracer);
|
|
39
|
+
const scope = opts?.isolate ? new SignalScope([]) : getCurrentScope();
|
|
40
|
+
return createReactiveSignal(def, void 0, void 0, scope);
|
|
41
|
+
}
|
|
42
|
+
const reactiveSignal = (compute, opts) => {
|
|
43
|
+
const def = createReactiveDefinition(opts?.id, opts?.desc, compute, opts?.equals, false, void 0, void 0);
|
|
44
|
+
const scope = opts?.isolate ? new SignalScope([]) : getCurrentScope();
|
|
45
|
+
return createReactiveSignal(def, void 0, void 0, scope);
|
|
46
|
+
};
|
|
47
|
+
const getProto = Object.getPrototypeOf;
|
|
48
|
+
function snapshotArray(current, prev, snap) {
|
|
49
|
+
const prevArr = Array.isArray(prev) ? prev : void 0;
|
|
50
|
+
let changed = !prevArr || prevArr.length !== current.length;
|
|
51
|
+
const result = new Array(current.length);
|
|
52
|
+
for (let i = 0; i < current.length; i++) {
|
|
53
|
+
result[i] = snap(current[i], prevArr?.[i]);
|
|
54
|
+
if (!changed && result[i] !== prevArr[i]) {
|
|
55
|
+
changed = true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return changed ? result : prevArr;
|
|
59
|
+
}
|
|
60
|
+
function snapshotPlainObject(current, prev, snap) {
|
|
61
|
+
const prevObj = prev !== null && prev !== void 0 && typeof prev === "object" && !Array.isArray(prev) ? prev : void 0;
|
|
62
|
+
const keys = Object.keys(current);
|
|
63
|
+
let changed = !prevObj || Object.keys(prevObj).length !== keys.length;
|
|
64
|
+
const result = {};
|
|
65
|
+
for (let i = 0; i < keys.length; i++) {
|
|
66
|
+
const key = keys[i];
|
|
67
|
+
result[key] = snap(current[key], prevObj?.[key]);
|
|
68
|
+
if (!changed && result[key] !== prevObj[key]) {
|
|
69
|
+
changed = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return changed ? result : prevObj;
|
|
73
|
+
}
|
|
74
|
+
function snapshotReactivePromise(current, prev, snap) {
|
|
75
|
+
const prevObj = prev !== null && prev !== void 0 && typeof prev === "object" ? prev : void 0;
|
|
76
|
+
const value = snap(current.value, prevObj?.value);
|
|
77
|
+
const error = current.error;
|
|
78
|
+
const isPending = current.isPending;
|
|
79
|
+
const isRejected = current.isRejected;
|
|
80
|
+
const isResolved = current.isResolved;
|
|
81
|
+
const isReady = current.isReady;
|
|
82
|
+
const isSettled = current.isSettled;
|
|
83
|
+
if (prevObj && value === prevObj.value && error === prevObj.error && isPending === prevObj.isPending && isRejected === prevObj.isRejected && isResolved === prevObj.isResolved && isReady === prevObj.isReady && isSettled === prevObj.isSettled) {
|
|
84
|
+
return prevObj;
|
|
85
|
+
}
|
|
86
|
+
return { value, error, isPending, isRejected, isResolved, isReady, isSettled };
|
|
87
|
+
}
|
|
88
|
+
function snapshotMap(current, prev, snap) {
|
|
89
|
+
const prevMap = prev instanceof Map ? prev : void 0;
|
|
90
|
+
let changed = !prevMap || prevMap.size !== current.size;
|
|
91
|
+
const result = /* @__PURE__ */ new Map();
|
|
92
|
+
for (const [key, val] of current) {
|
|
93
|
+
const snapped = snap(val, prevMap?.get(key));
|
|
94
|
+
result.set(key, snapped);
|
|
95
|
+
if (!changed && snapped !== prevMap.get(key)) {
|
|
96
|
+
changed = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return changed ? result : prevMap;
|
|
100
|
+
}
|
|
101
|
+
function snapshotSet(current, prev, _snap) {
|
|
102
|
+
const prevSet = prev instanceof Set ? prev : void 0;
|
|
103
|
+
let changed = !prevSet || prevSet.size !== current.size;
|
|
104
|
+
const result = /* @__PURE__ */ new Set();
|
|
105
|
+
for (const val of current) {
|
|
106
|
+
const snapped = snapshot(val, prevSet?.has(val) ? val : void 0);
|
|
107
|
+
result.add(snapped);
|
|
108
|
+
if (!changed && !prevSet.has(snapped)) {
|
|
109
|
+
changed = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return changed ? result : prevSet;
|
|
113
|
+
}
|
|
114
|
+
const PROTO_TO_SNAPSHOT = /* @__PURE__ */ new Map([
|
|
115
|
+
[Object.prototype, snapshotPlainObject],
|
|
116
|
+
[Array.prototype, snapshotArray],
|
|
117
|
+
[Map.prototype, snapshotMap],
|
|
118
|
+
[Set.prototype, snapshotSet],
|
|
119
|
+
[null, snapshotPlainObject]
|
|
120
|
+
]);
|
|
121
|
+
const registerCustomSnapshot = (ctor, snapshotFn) => {
|
|
122
|
+
PROTO_TO_SNAPSHOT.set(ctor.prototype, snapshotFn);
|
|
123
|
+
};
|
|
124
|
+
function snapshot(currentValue, prevValue) {
|
|
125
|
+
if (currentValue === null || typeof currentValue !== "object") {
|
|
126
|
+
return currentValue;
|
|
127
|
+
}
|
|
128
|
+
if (isReactivePromise(currentValue)) {
|
|
129
|
+
return snapshotReactivePromise(currentValue, prevValue, snapshot);
|
|
130
|
+
}
|
|
131
|
+
const handler = PROTO_TO_SNAPSHOT.get(getProto(currentValue));
|
|
132
|
+
if (handler !== void 0) {
|
|
133
|
+
return handler(currentValue, prevValue, snapshot);
|
|
134
|
+
}
|
|
135
|
+
return currentValue;
|
|
136
|
+
}
|
|
137
|
+
export {
|
|
138
|
+
registerCustomSnapshot as a,
|
|
139
|
+
reactive as b,
|
|
140
|
+
reactiveMethod as c,
|
|
141
|
+
relay as d,
|
|
142
|
+
getReactiveFnAndDefinition as g,
|
|
143
|
+
reactiveSignal as r,
|
|
144
|
+
snapshot as s,
|
|
145
|
+
task as t,
|
|
146
|
+
watcher as w
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=snapshot-Bq0Um_hQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-Bq0Um_hQ.js","sources":["../../../.tsc-out/internals/core-api.js","../../../.tsc-out/internals/utils/snapshot.js"],"sourcesContent":["import { getCurrentScope, getScopeOwner, SignalScope } from './contexts.js';\nimport { createReactiveDefinition, createReactiveSignal, } from './reactive.js';\nimport { createRelay, createTask } from './async.js';\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport const DERIVED_DEFINITION_MAP = new WeakMap();\nexport function getReactiveFnAndDefinition(fn, opts) {\n let fnAndDef = DERIVED_DEFINITION_MAP.get(fn);\n if (!fnAndDef) {\n const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey, undefined);\n const defScope = getCurrentScope();\n const reactiveFn = (...args) => {\n const scope = getCurrentScope(defScope);\n const signal = scope.get(def, args);\n return signal.value;\n };\n fnAndDef = [reactiveFn, def];\n DERIVED_DEFINITION_MAP.set(fn, fnAndDef);\n }\n return fnAndDef;\n}\nexport function reactive(fn, opts) {\n return getReactiveFnAndDefinition(fn, opts)[0];\n}\nexport const reactiveMethod = (owner, fn, opts) => {\n const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey, undefined);\n const reactiveFn = (...args) => {\n return getScopeOwner(owner).get(def, args).value;\n };\n DERIVED_DEFINITION_MAP.set(reactiveFn, [reactiveFn, def]);\n return reactiveFn;\n};\nexport function relay(activate, opts) {\n const scope = getCurrentScope();\n return createRelay(activate, scope, opts);\n}\nexport const task = (fn, opts) => {\n const scope = getCurrentScope();\n return createTask(fn, scope, opts);\n};\nexport function watcher(fn, opts) {\n const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, undefined, opts?.tracer);\n const scope = opts?.isolate ? new SignalScope([]) : getCurrentScope();\n return createReactiveSignal(def, undefined, undefined, scope);\n}\n/**\n * Creates a reactive signal from a compute function. This is useful for when you\n * want to create a signal that does not receive parameters, but is still reactive.\n *\n * @param compute\n * @param opts\n * @returns\n */\nexport const reactiveSignal = (compute, opts) => {\n const def = createReactiveDefinition(opts?.id, opts?.desc, compute, opts?.equals, false, undefined, undefined);\n const scope = opts?.isolate ? new SignalScope([]) : getCurrentScope();\n return createReactiveSignal(def, undefined, undefined, scope);\n};\n","import { isReactivePromise } from '../async.js';\nconst getProto = Object.getPrototypeOf;\nfunction snapshotArray(current, prev, snap) {\n const prevArr = Array.isArray(prev) ? prev : undefined;\n let changed = !prevArr || prevArr.length !== current.length;\n const result = new Array(current.length);\n for (let i = 0; i < current.length; i++) {\n result[i] = snap(current[i], prevArr?.[i]);\n if (!changed && result[i] !== prevArr[i]) {\n changed = true;\n }\n }\n return changed ? result : prevArr;\n}\nfunction snapshotPlainObject(current, prev, snap) {\n const prevObj = prev !== null && prev !== undefined && typeof prev === 'object' && !Array.isArray(prev)\n ? prev\n : undefined;\n const keys = Object.keys(current);\n let changed = !prevObj || Object.keys(prevObj).length !== keys.length;\n const result = {};\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n result[key] = snap(current[key], prevObj?.[key]);\n if (!changed && result[key] !== prevObj[key]) {\n changed = true;\n }\n }\n return changed ? result : prevObj;\n}\nfunction snapshotReactivePromise(current, prev, snap) {\n const prevObj = prev !== null && prev !== undefined && typeof prev === 'object' ? prev : undefined;\n const value = snap(current.value, prevObj?.value);\n const error = current.error;\n const isPending = current.isPending;\n const isRejected = current.isRejected;\n const isResolved = current.isResolved;\n const isReady = current.isReady;\n const isSettled = current.isSettled;\n if (prevObj &&\n value === prevObj.value &&\n error === prevObj.error &&\n isPending === prevObj.isPending &&\n isRejected === prevObj.isRejected &&\n isResolved === prevObj.isResolved &&\n isReady === prevObj.isReady &&\n isSettled === prevObj.isSettled) {\n return prevObj;\n }\n return { value, error, isPending, isRejected, isResolved, isReady, isSettled };\n}\nfunction snapshotMap(current, prev, snap) {\n const prevMap = prev instanceof Map ? prev : undefined;\n let changed = !prevMap || prevMap.size !== current.size;\n const result = new Map();\n for (const [key, val] of current) {\n const snapped = snap(val, prevMap?.get(key));\n result.set(key, snapped);\n if (!changed && snapped !== prevMap.get(key)) {\n changed = true;\n }\n }\n return changed ? result : prevMap;\n}\nfunction snapshotSet(current, prev, _snap) {\n const prevSet = prev instanceof Set ? prev : undefined;\n let changed = !prevSet || prevSet.size !== current.size;\n const result = new Set();\n for (const val of current) {\n const snapped = snapshot(val, prevSet?.has(val) ? val : undefined);\n result.add(snapped);\n if (!changed && !prevSet.has(snapped)) {\n changed = true;\n }\n }\n return changed ? result : prevSet;\n}\nconst PROTO_TO_SNAPSHOT = new Map([\n [Object.prototype, snapshotPlainObject],\n [Array.prototype, snapshotArray],\n [Map.prototype, snapshotMap],\n [Set.prototype, snapshotSet],\n [null, snapshotPlainObject],\n]);\n/**\n * Register a custom snapshot function for instances of a class.\n * The function receives the current value, the previous snapshot (or undefined),\n * and the recursive `snapshot` function for snapshotting nested values.\n *\n * Return `prev` when nothing has changed to preserve reference stability.\n *\n * @example\n * ```ts\n * registerCustomSnapshot(MyEntity, (current, prev, snapshot) => {\n * const name = snapshot(current.name, prev?.name);\n * const age = current.age;\n * if (prev && name === prev.name && age === prev.age) return prev;\n * return { name, age };\n * });\n * ```\n */\nexport const registerCustomSnapshot = (ctor, snapshotFn) => {\n PROTO_TO_SNAPSHOT.set(ctor.prototype, snapshotFn);\n};\n/**\n * Recursively snapshot a value with structural sharing.\n *\n * - Plain objects and arrays are deep-cloned; unchanged subtrees keep the same reference.\n * - ReactivePromise instances are read (establishing deps) and flattened to a plain object.\n * - Class instances (non-plain prototypes) are returned as-is unless a custom handler is registered.\n * - Primitives are returned directly.\n */\nexport function snapshot(currentValue, prevValue) {\n if (currentValue === null || typeof currentValue !== 'object') {\n return currentValue;\n }\n if (isReactivePromise(currentValue)) {\n return snapshotReactivePromise(currentValue, prevValue, snapshot);\n }\n const handler = PROTO_TO_SNAPSHOT.get(getProto(currentValue));\n if (handler !== undefined) {\n return handler(currentValue, prevValue, snapshot);\n }\n return currentValue;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -19,53 +19,56 @@ const createTransformedImports = (defaultImports, additionalImports, globalImpor
|
|
|
19
19
|
return transformedImports;
|
|
20
20
|
};
|
|
21
21
|
function createSignaliumAsyncTransform(api, opts) {
|
|
22
|
-
const transformedImports = createTransformedImports(
|
|
23
|
-
[
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
],
|
|
31
|
-
opts?.transformedImports,
|
|
32
|
-
opts?.importPaths
|
|
33
|
-
);
|
|
22
|
+
const transformedImports = createTransformedImports([
|
|
23
|
+
["callback", ["signalium"]],
|
|
24
|
+
["reactive", ["signalium"]],
|
|
25
|
+
["reactiveMethod", ["signalium"]],
|
|
26
|
+
["relay", ["signalium"]],
|
|
27
|
+
["task", ["signalium"]],
|
|
28
|
+
["watcher", ["signalium"]]
|
|
29
|
+
], opts?.transformedImports, opts?.importPaths);
|
|
34
30
|
const t = api.types;
|
|
35
31
|
const isTrackedImport = (localName, path) => {
|
|
36
32
|
const binding = path.scope.getBinding(localName);
|
|
37
|
-
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
33
|
+
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
34
|
+
return false;
|
|
38
35
|
const importSpec = binding.path.node;
|
|
39
36
|
const importedName = importSpec.imported.name;
|
|
40
37
|
const importDecl = binding.path.parent;
|
|
41
|
-
if (!t.isImportDeclaration(importDecl))
|
|
38
|
+
if (!t.isImportDeclaration(importDecl))
|
|
39
|
+
return false;
|
|
42
40
|
const importPaths = transformedImports.get(importedName);
|
|
43
|
-
if (!importPaths)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
);
|
|
41
|
+
if (!importPaths)
|
|
42
|
+
return false;
|
|
43
|
+
return importPaths.some((p) => typeof p === "string" ? importDecl.source.value === p : p.test(importDecl.source.value));
|
|
47
44
|
};
|
|
48
45
|
const isReactiveCall = (path) => {
|
|
49
|
-
if (!t.isCallExpression(path.node))
|
|
46
|
+
if (!t.isCallExpression(path.node))
|
|
47
|
+
return false;
|
|
50
48
|
const callee = path.node.callee;
|
|
51
|
-
if (!t.isIdentifier(callee))
|
|
49
|
+
if (!t.isIdentifier(callee))
|
|
50
|
+
return false;
|
|
52
51
|
return isTrackedImport(callee.name, path);
|
|
53
52
|
};
|
|
54
53
|
const isWithinTrackedCall = (path) => {
|
|
55
54
|
let current = path.parentPath;
|
|
56
55
|
while (current) {
|
|
57
|
-
if (current.isCallExpression() && isReactiveCall(current))
|
|
56
|
+
if (current.isCallExpression() && isReactiveCall(current))
|
|
57
|
+
return true;
|
|
58
58
|
current = current.parentPath;
|
|
59
59
|
}
|
|
60
60
|
return false;
|
|
61
61
|
};
|
|
62
62
|
function convertReactiveToGenerator(path) {
|
|
63
|
-
if (!isWithinTrackedCall(path))
|
|
64
|
-
|
|
63
|
+
if (!isWithinTrackedCall(path))
|
|
64
|
+
return;
|
|
65
|
+
if (!path.node.async)
|
|
66
|
+
return;
|
|
65
67
|
path.traverse({
|
|
66
68
|
AwaitExpression(awaitPath) {
|
|
67
69
|
const funcParent = awaitPath.getFunctionParent();
|
|
68
|
-
if (funcParent?.node !== path.node)
|
|
70
|
+
if (funcParent?.node !== path.node)
|
|
71
|
+
return;
|
|
69
72
|
awaitPath.replaceWith(t.yieldExpression(awaitPath.node.argument));
|
|
70
73
|
}
|
|
71
74
|
});
|
|
@@ -103,37 +106,37 @@ function signaliumAsyncTransform(apiOrOpts, maybeOpts) {
|
|
|
103
106
|
return (api) => createSignaliumAsyncTransform(api, apiOrOpts);
|
|
104
107
|
}
|
|
105
108
|
function createSignaliumCallbackTransform(api, opts) {
|
|
106
|
-
const transformedImports = createTransformedImports(
|
|
107
|
-
[
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
opts?.transformedImports,
|
|
115
|
-
opts?.importPaths
|
|
116
|
-
);
|
|
109
|
+
const transformedImports = createTransformedImports([
|
|
110
|
+
["component", ["signalium/react"]],
|
|
111
|
+
["reactive", ["signalium"]],
|
|
112
|
+
["reactiveMethod", ["signalium"]],
|
|
113
|
+
["relay", ["signalium"]],
|
|
114
|
+
["task", ["signalium"]],
|
|
115
|
+
["watcher", ["signalium"]]
|
|
116
|
+
], opts?.transformedImports, opts?.importPaths);
|
|
117
117
|
const t = api.types;
|
|
118
118
|
const callbackImportPath = opts?.callbackImportPath ?? "signalium";
|
|
119
119
|
const isTrackedImport = (localName, path) => {
|
|
120
120
|
const binding = path.scope.getBinding(localName);
|
|
121
|
-
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
121
|
+
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
122
|
+
return false;
|
|
122
123
|
const importSpec = binding.path.node;
|
|
123
124
|
const importedName = importSpec.imported.name;
|
|
124
125
|
const importDecl = binding.path.parent;
|
|
125
|
-
if (!t.isImportDeclaration(importDecl))
|
|
126
|
+
if (!t.isImportDeclaration(importDecl))
|
|
127
|
+
return false;
|
|
126
128
|
const importPaths = transformedImports.get(importedName);
|
|
127
|
-
if (!importPaths)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
);
|
|
129
|
+
if (!importPaths)
|
|
130
|
+
return false;
|
|
131
|
+
const matches = importPaths.find((p) => typeof p === "string" ? importDecl.source.value === p : p.test(importDecl.source.value));
|
|
131
132
|
return matches ? typeof matches === "string" ? matches : importDecl.source.value : false;
|
|
132
133
|
};
|
|
133
134
|
const isTargetWrapperCall = (path) => {
|
|
134
|
-
if (!t.isCallExpression(path.node))
|
|
135
|
+
if (!t.isCallExpression(path.node))
|
|
136
|
+
return false;
|
|
135
137
|
const callee = path.node.callee;
|
|
136
|
-
if (!t.isIdentifier(callee))
|
|
138
|
+
if (!t.isIdentifier(callee))
|
|
139
|
+
return false;
|
|
137
140
|
return !!isTrackedImport(callee.name, path);
|
|
138
141
|
};
|
|
139
142
|
function isIdentifierInTypePosition(refPath) {
|
|
@@ -143,7 +146,8 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
143
146
|
const nodeType = current.node.type;
|
|
144
147
|
if (nodeType && nodeType.startsWith("TS")) {
|
|
145
148
|
if (current.isTSAsExpression() || current.isTSSatisfiesExpression?.() || current.isTSNonNullExpression() || current.isTSInstantiationExpression?.()) {
|
|
146
|
-
if (child.key === "expression")
|
|
149
|
+
if (child.key === "expression")
|
|
150
|
+
return false;
|
|
147
151
|
return true;
|
|
148
152
|
}
|
|
149
153
|
return true;
|
|
@@ -155,9 +159,11 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
155
159
|
}
|
|
156
160
|
function ensureCallbackIdentifier(programPath) {
|
|
157
161
|
for (const bodyPath of programPath.get("body")) {
|
|
158
|
-
if (!bodyPath.isImportDeclaration())
|
|
162
|
+
if (!bodyPath.isImportDeclaration())
|
|
163
|
+
continue;
|
|
159
164
|
const importDecl2 = bodyPath.node;
|
|
160
|
-
if (importDecl2.source.value !== callbackImportPath)
|
|
165
|
+
if (importDecl2.source.value !== callbackImportPath)
|
|
166
|
+
continue;
|
|
161
167
|
for (const spec of importDecl2.specifiers) {
|
|
162
168
|
if (spec.type === "ImportSpecifier") {
|
|
163
169
|
const ispec = spec;
|
|
@@ -169,18 +175,17 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
169
175
|
}
|
|
170
176
|
}
|
|
171
177
|
for (const bodyPath of programPath.get("body")) {
|
|
172
|
-
if (!bodyPath.isImportDeclaration())
|
|
178
|
+
if (!bodyPath.isImportDeclaration())
|
|
179
|
+
continue;
|
|
173
180
|
const node = bodyPath.node;
|
|
174
|
-
if (node.source.value !== callbackImportPath)
|
|
181
|
+
if (node.source.value !== callbackImportPath)
|
|
182
|
+
continue;
|
|
175
183
|
const localName2 = programPath.scope.generateUidIdentifier("callback").name;
|
|
176
184
|
node.specifiers.push(t.importSpecifier(t.identifier(localName2), t.identifier("callback")));
|
|
177
185
|
return localName2;
|
|
178
186
|
}
|
|
179
187
|
const localName = "callback";
|
|
180
|
-
const importDecl = t.importDeclaration(
|
|
181
|
-
[t.importSpecifier(t.identifier(localName), t.identifier("callback"))],
|
|
182
|
-
t.stringLiteral(callbackImportPath)
|
|
183
|
-
);
|
|
188
|
+
const importDecl = t.importDeclaration([t.importSpecifier(t.identifier(localName), t.identifier("callback"))], t.stringLiteral(callbackImportPath));
|
|
184
189
|
const [first] = programPath.get("body");
|
|
185
190
|
if (first) {
|
|
186
191
|
first.insertBefore(importDecl);
|
|
@@ -196,18 +201,24 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
196
201
|
innerFn.traverse({
|
|
197
202
|
ReferencedIdentifier(refPath) {
|
|
198
203
|
const nearestFn = refPath.getFunctionParent();
|
|
199
|
-
if (!nearestFn || nearestFn.node !== innerNode)
|
|
204
|
+
if (!nearestFn || nearestFn.node !== innerNode)
|
|
205
|
+
return;
|
|
200
206
|
const name = refPath.node.name;
|
|
201
207
|
const binding = refPath.scope.getBinding(name);
|
|
202
|
-
if (!binding)
|
|
203
|
-
|
|
204
|
-
if (
|
|
208
|
+
if (!binding)
|
|
209
|
+
return;
|
|
210
|
+
if (isIdentifierInTypePosition(refPath))
|
|
211
|
+
return;
|
|
212
|
+
if (binding.scope.path.isProgram())
|
|
213
|
+
return;
|
|
205
214
|
let declScope = binding.scope;
|
|
206
215
|
while (declScope) {
|
|
207
|
-
if (declScope === innerScope)
|
|
216
|
+
if (declScope === innerScope)
|
|
217
|
+
return;
|
|
208
218
|
declScope = declScope.parent;
|
|
209
219
|
}
|
|
210
|
-
if (binding.kind === "param" && binding.scope === innerScope)
|
|
220
|
+
if (binding.kind === "param" && binding.scope === innerScope)
|
|
221
|
+
return;
|
|
211
222
|
depNames.add(name);
|
|
212
223
|
}
|
|
213
224
|
});
|
|
@@ -217,10 +228,13 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
217
228
|
name: "signalium-transform-callback-wrapping",
|
|
218
229
|
visitor: {
|
|
219
230
|
CallExpression(callPath) {
|
|
220
|
-
if (!isTargetWrapperCall(callPath))
|
|
231
|
+
if (!isTargetWrapperCall(callPath))
|
|
232
|
+
return;
|
|
221
233
|
const arg0 = callPath.get("arguments")[0];
|
|
222
|
-
if (!arg0)
|
|
223
|
-
|
|
234
|
+
if (!arg0)
|
|
235
|
+
return;
|
|
236
|
+
if (!(arg0.isFunctionExpression() || arg0.isArrowFunctionExpression()))
|
|
237
|
+
return;
|
|
224
238
|
const outerFn = arg0;
|
|
225
239
|
const programPath = callPath.findParent((p) => p.isProgram());
|
|
226
240
|
const callbackName = ensureCallbackIdentifier(programPath);
|
|
@@ -235,10 +249,12 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
235
249
|
// Initialize counters for any function-like node when first seen
|
|
236
250
|
FunctionExpression: {
|
|
237
251
|
enter(fnPath) {
|
|
238
|
-
if (!counters.has(fnPath.node))
|
|
252
|
+
if (!counters.has(fnPath.node))
|
|
253
|
+
counters.set(fnPath.node, 0);
|
|
239
254
|
},
|
|
240
255
|
exit(innerFnPath) {
|
|
241
|
-
if (innerFnPath.node === outerFn.node)
|
|
256
|
+
if (innerFnPath.node === outerFn.node)
|
|
257
|
+
return;
|
|
242
258
|
const immediateParent = innerFnPath.parentPath;
|
|
243
259
|
if (immediateParent && immediateParent.isCallExpression()) {
|
|
244
260
|
const callee = immediateParent.node.callee;
|
|
@@ -285,10 +301,12 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
285
301
|
},
|
|
286
302
|
ArrowFunctionExpression: {
|
|
287
303
|
enter(fnPath) {
|
|
288
|
-
if (!counters.has(fnPath.node))
|
|
304
|
+
if (!counters.has(fnPath.node))
|
|
305
|
+
counters.set(fnPath.node, 0);
|
|
289
306
|
},
|
|
290
307
|
exit(innerFnPath) {
|
|
291
|
-
if (innerFnPath.node === outerFn.node)
|
|
308
|
+
if (innerFnPath.node === outerFn.node)
|
|
309
|
+
return;
|
|
292
310
|
const immediateParent = innerFnPath.parentPath;
|
|
293
311
|
if (immediateParent && immediateParent.isCallExpression()) {
|
|
294
312
|
const callee = immediateParent.node.callee;
|
|
@@ -335,18 +353,14 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
335
353
|
},
|
|
336
354
|
FunctionDeclaration: {
|
|
337
355
|
enter(fnPath) {
|
|
338
|
-
if (!counters.has(fnPath.node))
|
|
356
|
+
if (!counters.has(fnPath.node))
|
|
357
|
+
counters.set(fnPath.node, 0);
|
|
339
358
|
},
|
|
340
359
|
exit(innerDeclPath) {
|
|
341
360
|
const id = innerDeclPath.node.id;
|
|
342
|
-
if (!id)
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
innerDeclPath.node.params,
|
|
346
|
-
innerDeclPath.node.body,
|
|
347
|
-
innerDeclPath.node.generator,
|
|
348
|
-
innerDeclPath.node.async
|
|
349
|
-
);
|
|
361
|
+
if (!id)
|
|
362
|
+
return;
|
|
363
|
+
const fnExpr = t.functionExpression(id, innerDeclPath.node.params, innerDeclPath.node.body, innerDeclPath.node.generator, innerDeclPath.node.async);
|
|
350
364
|
const deps = Array.from(collectDeps(innerDeclPath));
|
|
351
365
|
const parentFn = innerDeclPath.parentPath?.getFunctionParent() || outerFn;
|
|
352
366
|
const argIndex = getNextIndexFor(parentFn.node);
|
|
@@ -362,17 +376,13 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
362
376
|
},
|
|
363
377
|
ObjectMethod: {
|
|
364
378
|
enter(fnPath) {
|
|
365
|
-
if (!counters.has(fnPath.node))
|
|
379
|
+
if (!counters.has(fnPath.node))
|
|
380
|
+
counters.set(fnPath.node, 0);
|
|
366
381
|
},
|
|
367
382
|
exit(innerMethodPath) {
|
|
368
|
-
if (innerMethodPath.node.kind !== "method")
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
innerMethodPath.node.params,
|
|
372
|
-
innerMethodPath.node.body,
|
|
373
|
-
innerMethodPath.node.generator,
|
|
374
|
-
innerMethodPath.node.async
|
|
375
|
-
);
|
|
383
|
+
if (innerMethodPath.node.kind !== "method")
|
|
384
|
+
return;
|
|
385
|
+
const fnExpr = t.functionExpression(null, innerMethodPath.node.params, innerMethodPath.node.body, innerMethodPath.node.generator, innerMethodPath.node.async);
|
|
376
386
|
const deps = Array.from(collectDeps(innerMethodPath));
|
|
377
387
|
const parentFn = innerMethodPath.parentPath?.getFunctionParent() || outerFn;
|
|
378
388
|
const argIndex = getNextIndexFor(parentFn.node);
|
|
@@ -402,51 +412,54 @@ function signaliumCallbackTransform(apiOrOpts, opts) {
|
|
|
402
412
|
}
|
|
403
413
|
const PROMISE_STATIC_METHODS = /* @__PURE__ */ new Set(["all", "race", "any", "allSettled", "resolve", "reject", "withResolvers"]);
|
|
404
414
|
function createSignaliumPromiseMethodsTransform(api, opts) {
|
|
405
|
-
const transformedImports = createTransformedImports(
|
|
406
|
-
[
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
opts?.transformedImports,
|
|
414
|
-
opts?.importPaths
|
|
415
|
-
);
|
|
415
|
+
const transformedImports = createTransformedImports([
|
|
416
|
+
["callback", ["signalium"]],
|
|
417
|
+
["reactive", ["signalium"]],
|
|
418
|
+
["reactiveMethod", ["signalium"]],
|
|
419
|
+
["relay", ["signalium"]],
|
|
420
|
+
["task", ["signalium"]],
|
|
421
|
+
["watcher", ["signalium"]]
|
|
422
|
+
], opts?.transformedImports, opts?.importPaths);
|
|
416
423
|
const t = api.types;
|
|
417
424
|
const promiseImportPath = opts?.promiseImportPath ?? "signalium";
|
|
418
425
|
const isTrackedImport = (localName, path) => {
|
|
419
426
|
const binding = path.scope.getBinding(localName);
|
|
420
|
-
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
427
|
+
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
428
|
+
return false;
|
|
421
429
|
const importSpec = binding.path.node;
|
|
422
430
|
const importedName = importSpec.imported.name;
|
|
423
431
|
const importDecl = binding.path.parent;
|
|
424
|
-
if (!t.isImportDeclaration(importDecl))
|
|
432
|
+
if (!t.isImportDeclaration(importDecl))
|
|
433
|
+
return false;
|
|
425
434
|
const importPaths = transformedImports.get(importedName);
|
|
426
|
-
if (!importPaths)
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
);
|
|
435
|
+
if (!importPaths)
|
|
436
|
+
return false;
|
|
437
|
+
return importPaths.some((p) => typeof p === "string" ? importDecl.source.value === p : p.test(importDecl.source.value));
|
|
430
438
|
};
|
|
431
439
|
const isReactiveCall = (path) => {
|
|
432
|
-
if (!t.isCallExpression(path.node))
|
|
440
|
+
if (!t.isCallExpression(path.node))
|
|
441
|
+
return false;
|
|
433
442
|
const callee = path.node.callee;
|
|
434
|
-
if (!t.isIdentifier(callee))
|
|
443
|
+
if (!t.isIdentifier(callee))
|
|
444
|
+
return false;
|
|
435
445
|
return isTrackedImport(callee.name, path);
|
|
436
446
|
};
|
|
437
447
|
const isWithinTrackedCall = (path) => {
|
|
438
448
|
let current = path.parentPath;
|
|
439
449
|
while (current) {
|
|
440
|
-
if (current.isCallExpression() && isReactiveCall(current))
|
|
450
|
+
if (current.isCallExpression() && isReactiveCall(current))
|
|
451
|
+
return true;
|
|
441
452
|
current = current.parentPath;
|
|
442
453
|
}
|
|
443
454
|
return false;
|
|
444
455
|
};
|
|
445
456
|
function ensureReactivePromiseIdentifier(programPath) {
|
|
446
457
|
for (const bodyPath of programPath.get("body")) {
|
|
447
|
-
if (!bodyPath.isImportDeclaration())
|
|
458
|
+
if (!bodyPath.isImportDeclaration())
|
|
459
|
+
continue;
|
|
448
460
|
const importDecl2 = bodyPath.node;
|
|
449
|
-
if (importDecl2.source.value !== promiseImportPath)
|
|
461
|
+
if (importDecl2.source.value !== promiseImportPath)
|
|
462
|
+
continue;
|
|
450
463
|
for (const spec of importDecl2.specifiers) {
|
|
451
464
|
if (spec.type === "ImportSpecifier") {
|
|
452
465
|
const ispec = spec;
|
|
@@ -458,18 +471,17 @@ function createSignaliumPromiseMethodsTransform(api, opts) {
|
|
|
458
471
|
}
|
|
459
472
|
}
|
|
460
473
|
for (const bodyPath of programPath.get("body")) {
|
|
461
|
-
if (!bodyPath.isImportDeclaration())
|
|
474
|
+
if (!bodyPath.isImportDeclaration())
|
|
475
|
+
continue;
|
|
462
476
|
const node = bodyPath.node;
|
|
463
|
-
if (node.source.value !== promiseImportPath)
|
|
477
|
+
if (node.source.value !== promiseImportPath)
|
|
478
|
+
continue;
|
|
464
479
|
const localName2 = "ReactivePromise";
|
|
465
480
|
node.specifiers.push(t.importSpecifier(t.identifier(localName2), t.identifier("ReactivePromise")));
|
|
466
481
|
return localName2;
|
|
467
482
|
}
|
|
468
483
|
const localName = "ReactivePromise";
|
|
469
|
-
const importDecl = t.importDeclaration(
|
|
470
|
-
[t.importSpecifier(t.identifier(localName), t.identifier("ReactivePromise"))],
|
|
471
|
-
t.stringLiteral(promiseImportPath)
|
|
472
|
-
);
|
|
484
|
+
const importDecl = t.importDeclaration([t.importSpecifier(t.identifier(localName), t.identifier("ReactivePromise"))], t.stringLiteral(promiseImportPath));
|
|
473
485
|
const [first] = programPath.get("body");
|
|
474
486
|
if (first) {
|
|
475
487
|
first.insertBefore(importDecl);
|
|
@@ -482,17 +494,24 @@ function createSignaliumPromiseMethodsTransform(api, opts) {
|
|
|
482
494
|
name: "signalium-transform-reactive-promise-methods",
|
|
483
495
|
visitor: {
|
|
484
496
|
CallExpression(callPath) {
|
|
485
|
-
if (!isWithinTrackedCall(callPath))
|
|
497
|
+
if (!isWithinTrackedCall(callPath))
|
|
498
|
+
return;
|
|
486
499
|
const callee = callPath.node.callee;
|
|
487
|
-
if (!t.isMemberExpression(callee))
|
|
488
|
-
|
|
500
|
+
if (!t.isMemberExpression(callee))
|
|
501
|
+
return;
|
|
502
|
+
if (callee.computed)
|
|
503
|
+
return;
|
|
489
504
|
const object = callee.object;
|
|
490
505
|
const property = callee.property;
|
|
491
|
-
if (!t.isIdentifier(object, { name: "Promise" }))
|
|
492
|
-
|
|
493
|
-
if (
|
|
506
|
+
if (!t.isIdentifier(object, { name: "Promise" }))
|
|
507
|
+
return;
|
|
508
|
+
if (callPath.scope.getBinding("Promise"))
|
|
509
|
+
return;
|
|
510
|
+
if (!t.isIdentifier(property))
|
|
511
|
+
return;
|
|
494
512
|
const methodName = property.name;
|
|
495
|
-
if (!PROMISE_STATIC_METHODS.has(methodName))
|
|
513
|
+
if (!PROMISE_STATIC_METHODS.has(methodName))
|
|
514
|
+
return;
|
|
496
515
|
const programPath = callPath.findParent((p) => p.isProgram());
|
|
497
516
|
const reactivePromiseId = ensureReactivePromiseIdentifier(programPath);
|
|
498
517
|
const newCallee = t.memberExpression(t.identifier(reactivePromiseId), t.identifier(methodName));
|