signalium 2.2.3 → 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 +10 -0
- package/dist/cjs/development/config-B0MtLBgx.js.map +1 -1
- package/dist/cjs/development/{debug-3nd-6Gnf.js → debug-gCDAvnLM.js} +211 -207
- 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-DoZWv_3I.js → contexts-Wgq2NOVX.js} +130 -133
- 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-BfudYKc4.js → debug-AoHfqs62.js} +195 -189
- 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/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.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-CilfS6eG.js → contexts-X0gSj6rQ.js} +133 -136
- 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/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-C6HCIyL3.js +0 -55
- package/dist/cjs/development/core-api-C6HCIyL3.js.map +0 -1
- package/dist/cjs/development/debug-3nd-6Gnf.js.map +0 -1
- package/dist/cjs/production/contexts-DoZWv_3I.js.map +0 -1
- package/dist/cjs/production/core-api-CUviCxtM.js +0 -55
- package/dist/cjs/production/core-api-CUviCxtM.js.map +0 -1
- package/dist/esm/development/core-api-CjsScNn1.js +0 -56
- package/dist/esm/development/core-api-CjsScNn1.js.map +0 -1
- package/dist/esm/development/debug-BfudYKc4.js.map +0 -1
- package/dist/esm/production/contexts-CilfS6eG.js.map +0 -1
- package/dist/esm/production/core-api-tTQttL8R.js +0 -56
- package/dist/esm/production/core-api-tTQttL8R.js.map +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const debug = require("./debug-gCDAvnLM.js");
|
|
3
|
+
const DERIVED_DEFINITION_MAP = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
function getReactiveFnAndDefinition(fn, opts) {
|
|
5
|
+
let fnAndDef = DERIVED_DEFINITION_MAP.get(fn);
|
|
6
|
+
if (!fnAndDef) {
|
|
7
|
+
const def = debug.createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey, void 0);
|
|
8
|
+
const defScope = debug.getCurrentScope();
|
|
9
|
+
const reactiveFn = (...args) => {
|
|
10
|
+
const scope = debug.getCurrentScope(defScope);
|
|
11
|
+
const signal = scope.get(def, args);
|
|
12
|
+
return signal.value;
|
|
13
|
+
};
|
|
14
|
+
fnAndDef = [reactiveFn, def];
|
|
15
|
+
DERIVED_DEFINITION_MAP.set(fn, fnAndDef);
|
|
16
|
+
}
|
|
17
|
+
return fnAndDef;
|
|
18
|
+
}
|
|
19
|
+
function reactive(fn, opts) {
|
|
20
|
+
return getReactiveFnAndDefinition(fn, opts)[0];
|
|
21
|
+
}
|
|
22
|
+
const reactiveMethod = (owner, fn, opts) => {
|
|
23
|
+
const def = debug.createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey, void 0);
|
|
24
|
+
const reactiveFn = (...args) => {
|
|
25
|
+
return debug.getScopeOwner(owner).get(def, args).value;
|
|
26
|
+
};
|
|
27
|
+
DERIVED_DEFINITION_MAP.set(reactiveFn, [reactiveFn, def]);
|
|
28
|
+
return reactiveFn;
|
|
29
|
+
};
|
|
30
|
+
function relay(activate, opts) {
|
|
31
|
+
const scope = debug.getCurrentScope();
|
|
32
|
+
return debug.createRelay(activate, scope, opts);
|
|
33
|
+
}
|
|
34
|
+
const task = (fn, opts) => {
|
|
35
|
+
const scope = debug.getCurrentScope();
|
|
36
|
+
return debug.createTask(fn, scope, opts);
|
|
37
|
+
};
|
|
38
|
+
function watcher(fn, opts) {
|
|
39
|
+
const def = debug.createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, void 0, opts?.tracer);
|
|
40
|
+
const scope = opts?.isolate ? new debug.SignalScope([]) : debug.getCurrentScope();
|
|
41
|
+
return debug.createReactiveSignal(def, void 0, void 0, scope);
|
|
42
|
+
}
|
|
43
|
+
const reactiveSignal = (compute, opts) => {
|
|
44
|
+
const def = debug.createReactiveDefinition(opts?.id, opts?.desc, compute, opts?.equals, false, void 0, void 0);
|
|
45
|
+
const scope = opts?.isolate ? new debug.SignalScope([]) : debug.getCurrentScope();
|
|
46
|
+
return debug.createReactiveSignal(def, void 0, void 0, scope);
|
|
47
|
+
};
|
|
48
|
+
const getProto = Object.getPrototypeOf;
|
|
49
|
+
function snapshotArray(current, prev, snap) {
|
|
50
|
+
const prevArr = Array.isArray(prev) ? prev : void 0;
|
|
51
|
+
let changed = !prevArr || prevArr.length !== current.length;
|
|
52
|
+
const result = new Array(current.length);
|
|
53
|
+
for (let i = 0; i < current.length; i++) {
|
|
54
|
+
result[i] = snap(current[i], prevArr?.[i]);
|
|
55
|
+
if (!changed && result[i] !== prevArr[i]) {
|
|
56
|
+
changed = true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return changed ? result : prevArr;
|
|
60
|
+
}
|
|
61
|
+
function snapshotPlainObject(current, prev, snap) {
|
|
62
|
+
const prevObj = prev !== null && prev !== void 0 && typeof prev === "object" && !Array.isArray(prev) ? prev : void 0;
|
|
63
|
+
const keys = Object.keys(current);
|
|
64
|
+
let changed = !prevObj || Object.keys(prevObj).length !== keys.length;
|
|
65
|
+
const result = {};
|
|
66
|
+
for (let i = 0; i < keys.length; i++) {
|
|
67
|
+
const key = keys[i];
|
|
68
|
+
result[key] = snap(current[key], prevObj?.[key]);
|
|
69
|
+
if (!changed && result[key] !== prevObj[key]) {
|
|
70
|
+
changed = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return changed ? result : prevObj;
|
|
74
|
+
}
|
|
75
|
+
function snapshotReactivePromise(current, prev, snap) {
|
|
76
|
+
const prevObj = prev !== null && prev !== void 0 && typeof prev === "object" ? prev : void 0;
|
|
77
|
+
const value = snap(current.value, prevObj?.value);
|
|
78
|
+
const error = current.error;
|
|
79
|
+
const isPending = current.isPending;
|
|
80
|
+
const isRejected = current.isRejected;
|
|
81
|
+
const isResolved = current.isResolved;
|
|
82
|
+
const isReady = current.isReady;
|
|
83
|
+
const isSettled = current.isSettled;
|
|
84
|
+
if (prevObj && value === prevObj.value && error === prevObj.error && isPending === prevObj.isPending && isRejected === prevObj.isRejected && isResolved === prevObj.isResolved && isReady === prevObj.isReady && isSettled === prevObj.isSettled) {
|
|
85
|
+
return prevObj;
|
|
86
|
+
}
|
|
87
|
+
return { value, error, isPending, isRejected, isResolved, isReady, isSettled };
|
|
88
|
+
}
|
|
89
|
+
function snapshotMap(current, prev, snap) {
|
|
90
|
+
const prevMap = prev instanceof Map ? prev : void 0;
|
|
91
|
+
let changed = !prevMap || prevMap.size !== current.size;
|
|
92
|
+
const result = /* @__PURE__ */ new Map();
|
|
93
|
+
for (const [key, val] of current) {
|
|
94
|
+
const snapped = snap(val, prevMap?.get(key));
|
|
95
|
+
result.set(key, snapped);
|
|
96
|
+
if (!changed && snapped !== prevMap.get(key)) {
|
|
97
|
+
changed = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return changed ? result : prevMap;
|
|
101
|
+
}
|
|
102
|
+
function snapshotSet(current, prev, _snap) {
|
|
103
|
+
const prevSet = prev instanceof Set ? prev : void 0;
|
|
104
|
+
let changed = !prevSet || prevSet.size !== current.size;
|
|
105
|
+
const result = /* @__PURE__ */ new Set();
|
|
106
|
+
for (const val of current) {
|
|
107
|
+
const snapped = snapshot(val, prevSet?.has(val) ? val : void 0);
|
|
108
|
+
result.add(snapped);
|
|
109
|
+
if (!changed && !prevSet.has(snapped)) {
|
|
110
|
+
changed = true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return changed ? result : prevSet;
|
|
114
|
+
}
|
|
115
|
+
const PROTO_TO_SNAPSHOT = /* @__PURE__ */ new Map([
|
|
116
|
+
[Object.prototype, snapshotPlainObject],
|
|
117
|
+
[Array.prototype, snapshotArray],
|
|
118
|
+
[Map.prototype, snapshotMap],
|
|
119
|
+
[Set.prototype, snapshotSet],
|
|
120
|
+
[null, snapshotPlainObject]
|
|
121
|
+
]);
|
|
122
|
+
const registerCustomSnapshot = (ctor, snapshotFn) => {
|
|
123
|
+
PROTO_TO_SNAPSHOT.set(ctor.prototype, snapshotFn);
|
|
124
|
+
};
|
|
125
|
+
function snapshot(currentValue, prevValue) {
|
|
126
|
+
if (currentValue === null || typeof currentValue !== "object") {
|
|
127
|
+
return currentValue;
|
|
128
|
+
}
|
|
129
|
+
if (debug.isReactivePromise(currentValue)) {
|
|
130
|
+
return snapshotReactivePromise(currentValue, prevValue, snapshot);
|
|
131
|
+
}
|
|
132
|
+
const handler = PROTO_TO_SNAPSHOT.get(getProto(currentValue));
|
|
133
|
+
if (handler !== void 0) {
|
|
134
|
+
return handler(currentValue, prevValue, snapshot);
|
|
135
|
+
}
|
|
136
|
+
return currentValue;
|
|
137
|
+
}
|
|
138
|
+
exports.getReactiveFnAndDefinition = getReactiveFnAndDefinition;
|
|
139
|
+
exports.reactive = reactive;
|
|
140
|
+
exports.reactiveMethod = reactiveMethod;
|
|
141
|
+
exports.reactiveSignal = reactiveSignal;
|
|
142
|
+
exports.registerCustomSnapshot = registerCustomSnapshot;
|
|
143
|
+
exports.relay = relay;
|
|
144
|
+
exports.snapshot = snapshot;
|
|
145
|
+
exports.task = task;
|
|
146
|
+
exports.watcher = watcher;
|
|
147
|
+
//# sourceMappingURL=snapshot-Di0yziPX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-Di0yziPX.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":["createReactiveDefinition","getCurrentScope","getScopeOwner","createRelay","createTask","SignalScope","createReactiveSignal","isReactivePromise"],"mappings":"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"}
|
|
@@ -21,53 +21,56 @@ const createTransformedImports = (defaultImports, additionalImports, globalImpor
|
|
|
21
21
|
return transformedImports;
|
|
22
22
|
};
|
|
23
23
|
function createSignaliumAsyncTransform(api, opts) {
|
|
24
|
-
const transformedImports = createTransformedImports(
|
|
25
|
-
[
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
],
|
|
33
|
-
opts?.transformedImports,
|
|
34
|
-
opts?.importPaths
|
|
35
|
-
);
|
|
24
|
+
const transformedImports = createTransformedImports([
|
|
25
|
+
["callback", ["signalium"]],
|
|
26
|
+
["reactive", ["signalium"]],
|
|
27
|
+
["reactiveMethod", ["signalium"]],
|
|
28
|
+
["relay", ["signalium"]],
|
|
29
|
+
["task", ["signalium"]],
|
|
30
|
+
["watcher", ["signalium"]]
|
|
31
|
+
], opts?.transformedImports, opts?.importPaths);
|
|
36
32
|
const t = api.types;
|
|
37
33
|
const isTrackedImport = (localName, path) => {
|
|
38
34
|
const binding = path.scope.getBinding(localName);
|
|
39
|
-
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
35
|
+
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
36
|
+
return false;
|
|
40
37
|
const importSpec = binding.path.node;
|
|
41
38
|
const importedName = importSpec.imported.name;
|
|
42
39
|
const importDecl = binding.path.parent;
|
|
43
|
-
if (!t.isImportDeclaration(importDecl))
|
|
40
|
+
if (!t.isImportDeclaration(importDecl))
|
|
41
|
+
return false;
|
|
44
42
|
const importPaths = transformedImports.get(importedName);
|
|
45
|
-
if (!importPaths)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
);
|
|
43
|
+
if (!importPaths)
|
|
44
|
+
return false;
|
|
45
|
+
return importPaths.some((p) => typeof p === "string" ? importDecl.source.value === p : p.test(importDecl.source.value));
|
|
49
46
|
};
|
|
50
47
|
const isReactiveCall = (path) => {
|
|
51
|
-
if (!t.isCallExpression(path.node))
|
|
48
|
+
if (!t.isCallExpression(path.node))
|
|
49
|
+
return false;
|
|
52
50
|
const callee = path.node.callee;
|
|
53
|
-
if (!t.isIdentifier(callee))
|
|
51
|
+
if (!t.isIdentifier(callee))
|
|
52
|
+
return false;
|
|
54
53
|
return isTrackedImport(callee.name, path);
|
|
55
54
|
};
|
|
56
55
|
const isWithinTrackedCall = (path) => {
|
|
57
56
|
let current = path.parentPath;
|
|
58
57
|
while (current) {
|
|
59
|
-
if (current.isCallExpression() && isReactiveCall(current))
|
|
58
|
+
if (current.isCallExpression() && isReactiveCall(current))
|
|
59
|
+
return true;
|
|
60
60
|
current = current.parentPath;
|
|
61
61
|
}
|
|
62
62
|
return false;
|
|
63
63
|
};
|
|
64
64
|
function convertReactiveToGenerator(path) {
|
|
65
|
-
if (!isWithinTrackedCall(path))
|
|
66
|
-
|
|
65
|
+
if (!isWithinTrackedCall(path))
|
|
66
|
+
return;
|
|
67
|
+
if (!path.node.async)
|
|
68
|
+
return;
|
|
67
69
|
path.traverse({
|
|
68
70
|
AwaitExpression(awaitPath) {
|
|
69
71
|
const funcParent = awaitPath.getFunctionParent();
|
|
70
|
-
if (funcParent?.node !== path.node)
|
|
72
|
+
if (funcParent?.node !== path.node)
|
|
73
|
+
return;
|
|
71
74
|
awaitPath.replaceWith(t.yieldExpression(awaitPath.node.argument));
|
|
72
75
|
}
|
|
73
76
|
});
|
|
@@ -105,37 +108,37 @@ function signaliumAsyncTransform(apiOrOpts, maybeOpts) {
|
|
|
105
108
|
return (api) => createSignaliumAsyncTransform(api, apiOrOpts);
|
|
106
109
|
}
|
|
107
110
|
function createSignaliumCallbackTransform(api, opts) {
|
|
108
|
-
const transformedImports = createTransformedImports(
|
|
109
|
-
[
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
opts?.transformedImports,
|
|
117
|
-
opts?.importPaths
|
|
118
|
-
);
|
|
111
|
+
const transformedImports = createTransformedImports([
|
|
112
|
+
["component", ["signalium/react"]],
|
|
113
|
+
["reactive", ["signalium"]],
|
|
114
|
+
["reactiveMethod", ["signalium"]],
|
|
115
|
+
["relay", ["signalium"]],
|
|
116
|
+
["task", ["signalium"]],
|
|
117
|
+
["watcher", ["signalium"]]
|
|
118
|
+
], opts?.transformedImports, opts?.importPaths);
|
|
119
119
|
const t = api.types;
|
|
120
120
|
const callbackImportPath = opts?.callbackImportPath ?? "signalium";
|
|
121
121
|
const isTrackedImport = (localName, path) => {
|
|
122
122
|
const binding = path.scope.getBinding(localName);
|
|
123
|
-
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
123
|
+
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
124
|
+
return false;
|
|
124
125
|
const importSpec = binding.path.node;
|
|
125
126
|
const importedName = importSpec.imported.name;
|
|
126
127
|
const importDecl = binding.path.parent;
|
|
127
|
-
if (!t.isImportDeclaration(importDecl))
|
|
128
|
+
if (!t.isImportDeclaration(importDecl))
|
|
129
|
+
return false;
|
|
128
130
|
const importPaths = transformedImports.get(importedName);
|
|
129
|
-
if (!importPaths)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
);
|
|
131
|
+
if (!importPaths)
|
|
132
|
+
return false;
|
|
133
|
+
const matches = importPaths.find((p) => typeof p === "string" ? importDecl.source.value === p : p.test(importDecl.source.value));
|
|
133
134
|
return matches ? typeof matches === "string" ? matches : importDecl.source.value : false;
|
|
134
135
|
};
|
|
135
136
|
const isTargetWrapperCall = (path) => {
|
|
136
|
-
if (!t.isCallExpression(path.node))
|
|
137
|
+
if (!t.isCallExpression(path.node))
|
|
138
|
+
return false;
|
|
137
139
|
const callee = path.node.callee;
|
|
138
|
-
if (!t.isIdentifier(callee))
|
|
140
|
+
if (!t.isIdentifier(callee))
|
|
141
|
+
return false;
|
|
139
142
|
return !!isTrackedImport(callee.name, path);
|
|
140
143
|
};
|
|
141
144
|
function isIdentifierInTypePosition(refPath) {
|
|
@@ -145,7 +148,8 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
145
148
|
const nodeType = current.node.type;
|
|
146
149
|
if (nodeType && nodeType.startsWith("TS")) {
|
|
147
150
|
if (current.isTSAsExpression() || current.isTSSatisfiesExpression?.() || current.isTSNonNullExpression() || current.isTSInstantiationExpression?.()) {
|
|
148
|
-
if (child.key === "expression")
|
|
151
|
+
if (child.key === "expression")
|
|
152
|
+
return false;
|
|
149
153
|
return true;
|
|
150
154
|
}
|
|
151
155
|
return true;
|
|
@@ -157,9 +161,11 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
157
161
|
}
|
|
158
162
|
function ensureCallbackIdentifier(programPath) {
|
|
159
163
|
for (const bodyPath of programPath.get("body")) {
|
|
160
|
-
if (!bodyPath.isImportDeclaration())
|
|
164
|
+
if (!bodyPath.isImportDeclaration())
|
|
165
|
+
continue;
|
|
161
166
|
const importDecl2 = bodyPath.node;
|
|
162
|
-
if (importDecl2.source.value !== callbackImportPath)
|
|
167
|
+
if (importDecl2.source.value !== callbackImportPath)
|
|
168
|
+
continue;
|
|
163
169
|
for (const spec of importDecl2.specifiers) {
|
|
164
170
|
if (spec.type === "ImportSpecifier") {
|
|
165
171
|
const ispec = spec;
|
|
@@ -171,18 +177,17 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
171
177
|
}
|
|
172
178
|
}
|
|
173
179
|
for (const bodyPath of programPath.get("body")) {
|
|
174
|
-
if (!bodyPath.isImportDeclaration())
|
|
180
|
+
if (!bodyPath.isImportDeclaration())
|
|
181
|
+
continue;
|
|
175
182
|
const node = bodyPath.node;
|
|
176
|
-
if (node.source.value !== callbackImportPath)
|
|
183
|
+
if (node.source.value !== callbackImportPath)
|
|
184
|
+
continue;
|
|
177
185
|
const localName2 = programPath.scope.generateUidIdentifier("callback").name;
|
|
178
186
|
node.specifiers.push(t.importSpecifier(t.identifier(localName2), t.identifier("callback")));
|
|
179
187
|
return localName2;
|
|
180
188
|
}
|
|
181
189
|
const localName = "callback";
|
|
182
|
-
const importDecl = t.importDeclaration(
|
|
183
|
-
[t.importSpecifier(t.identifier(localName), t.identifier("callback"))],
|
|
184
|
-
t.stringLiteral(callbackImportPath)
|
|
185
|
-
);
|
|
190
|
+
const importDecl = t.importDeclaration([t.importSpecifier(t.identifier(localName), t.identifier("callback"))], t.stringLiteral(callbackImportPath));
|
|
186
191
|
const [first] = programPath.get("body");
|
|
187
192
|
if (first) {
|
|
188
193
|
first.insertBefore(importDecl);
|
|
@@ -198,18 +203,24 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
198
203
|
innerFn.traverse({
|
|
199
204
|
ReferencedIdentifier(refPath) {
|
|
200
205
|
const nearestFn = refPath.getFunctionParent();
|
|
201
|
-
if (!nearestFn || nearestFn.node !== innerNode)
|
|
206
|
+
if (!nearestFn || nearestFn.node !== innerNode)
|
|
207
|
+
return;
|
|
202
208
|
const name = refPath.node.name;
|
|
203
209
|
const binding = refPath.scope.getBinding(name);
|
|
204
|
-
if (!binding)
|
|
205
|
-
|
|
206
|
-
if (
|
|
210
|
+
if (!binding)
|
|
211
|
+
return;
|
|
212
|
+
if (isIdentifierInTypePosition(refPath))
|
|
213
|
+
return;
|
|
214
|
+
if (binding.scope.path.isProgram())
|
|
215
|
+
return;
|
|
207
216
|
let declScope = binding.scope;
|
|
208
217
|
while (declScope) {
|
|
209
|
-
if (declScope === innerScope)
|
|
218
|
+
if (declScope === innerScope)
|
|
219
|
+
return;
|
|
210
220
|
declScope = declScope.parent;
|
|
211
221
|
}
|
|
212
|
-
if (binding.kind === "param" && binding.scope === innerScope)
|
|
222
|
+
if (binding.kind === "param" && binding.scope === innerScope)
|
|
223
|
+
return;
|
|
213
224
|
depNames.add(name);
|
|
214
225
|
}
|
|
215
226
|
});
|
|
@@ -219,10 +230,13 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
219
230
|
name: "signalium-transform-callback-wrapping",
|
|
220
231
|
visitor: {
|
|
221
232
|
CallExpression(callPath) {
|
|
222
|
-
if (!isTargetWrapperCall(callPath))
|
|
233
|
+
if (!isTargetWrapperCall(callPath))
|
|
234
|
+
return;
|
|
223
235
|
const arg0 = callPath.get("arguments")[0];
|
|
224
|
-
if (!arg0)
|
|
225
|
-
|
|
236
|
+
if (!arg0)
|
|
237
|
+
return;
|
|
238
|
+
if (!(arg0.isFunctionExpression() || arg0.isArrowFunctionExpression()))
|
|
239
|
+
return;
|
|
226
240
|
const outerFn = arg0;
|
|
227
241
|
const programPath = callPath.findParent((p) => p.isProgram());
|
|
228
242
|
const callbackName = ensureCallbackIdentifier(programPath);
|
|
@@ -237,10 +251,12 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
237
251
|
// Initialize counters for any function-like node when first seen
|
|
238
252
|
FunctionExpression: {
|
|
239
253
|
enter(fnPath) {
|
|
240
|
-
if (!counters.has(fnPath.node))
|
|
254
|
+
if (!counters.has(fnPath.node))
|
|
255
|
+
counters.set(fnPath.node, 0);
|
|
241
256
|
},
|
|
242
257
|
exit(innerFnPath) {
|
|
243
|
-
if (innerFnPath.node === outerFn.node)
|
|
258
|
+
if (innerFnPath.node === outerFn.node)
|
|
259
|
+
return;
|
|
244
260
|
const immediateParent = innerFnPath.parentPath;
|
|
245
261
|
if (immediateParent && immediateParent.isCallExpression()) {
|
|
246
262
|
const callee = immediateParent.node.callee;
|
|
@@ -287,10 +303,12 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
287
303
|
},
|
|
288
304
|
ArrowFunctionExpression: {
|
|
289
305
|
enter(fnPath) {
|
|
290
|
-
if (!counters.has(fnPath.node))
|
|
306
|
+
if (!counters.has(fnPath.node))
|
|
307
|
+
counters.set(fnPath.node, 0);
|
|
291
308
|
},
|
|
292
309
|
exit(innerFnPath) {
|
|
293
|
-
if (innerFnPath.node === outerFn.node)
|
|
310
|
+
if (innerFnPath.node === outerFn.node)
|
|
311
|
+
return;
|
|
294
312
|
const immediateParent = innerFnPath.parentPath;
|
|
295
313
|
if (immediateParent && immediateParent.isCallExpression()) {
|
|
296
314
|
const callee = immediateParent.node.callee;
|
|
@@ -337,18 +355,14 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
337
355
|
},
|
|
338
356
|
FunctionDeclaration: {
|
|
339
357
|
enter(fnPath) {
|
|
340
|
-
if (!counters.has(fnPath.node))
|
|
358
|
+
if (!counters.has(fnPath.node))
|
|
359
|
+
counters.set(fnPath.node, 0);
|
|
341
360
|
},
|
|
342
361
|
exit(innerDeclPath) {
|
|
343
362
|
const id = innerDeclPath.node.id;
|
|
344
|
-
if (!id)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
innerDeclPath.node.params,
|
|
348
|
-
innerDeclPath.node.body,
|
|
349
|
-
innerDeclPath.node.generator,
|
|
350
|
-
innerDeclPath.node.async
|
|
351
|
-
);
|
|
363
|
+
if (!id)
|
|
364
|
+
return;
|
|
365
|
+
const fnExpr = t.functionExpression(id, innerDeclPath.node.params, innerDeclPath.node.body, innerDeclPath.node.generator, innerDeclPath.node.async);
|
|
352
366
|
const deps = Array.from(collectDeps(innerDeclPath));
|
|
353
367
|
const parentFn = innerDeclPath.parentPath?.getFunctionParent() || outerFn;
|
|
354
368
|
const argIndex = getNextIndexFor(parentFn.node);
|
|
@@ -364,17 +378,13 @@ function createSignaliumCallbackTransform(api, opts) {
|
|
|
364
378
|
},
|
|
365
379
|
ObjectMethod: {
|
|
366
380
|
enter(fnPath) {
|
|
367
|
-
if (!counters.has(fnPath.node))
|
|
381
|
+
if (!counters.has(fnPath.node))
|
|
382
|
+
counters.set(fnPath.node, 0);
|
|
368
383
|
},
|
|
369
384
|
exit(innerMethodPath) {
|
|
370
|
-
if (innerMethodPath.node.kind !== "method")
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
innerMethodPath.node.params,
|
|
374
|
-
innerMethodPath.node.body,
|
|
375
|
-
innerMethodPath.node.generator,
|
|
376
|
-
innerMethodPath.node.async
|
|
377
|
-
);
|
|
385
|
+
if (innerMethodPath.node.kind !== "method")
|
|
386
|
+
return;
|
|
387
|
+
const fnExpr = t.functionExpression(null, innerMethodPath.node.params, innerMethodPath.node.body, innerMethodPath.node.generator, innerMethodPath.node.async);
|
|
378
388
|
const deps = Array.from(collectDeps(innerMethodPath));
|
|
379
389
|
const parentFn = innerMethodPath.parentPath?.getFunctionParent() || outerFn;
|
|
380
390
|
const argIndex = getNextIndexFor(parentFn.node);
|
|
@@ -404,51 +414,54 @@ function signaliumCallbackTransform(apiOrOpts, opts) {
|
|
|
404
414
|
}
|
|
405
415
|
const PROMISE_STATIC_METHODS = /* @__PURE__ */ new Set(["all", "race", "any", "allSettled", "resolve", "reject", "withResolvers"]);
|
|
406
416
|
function createSignaliumPromiseMethodsTransform(api, opts) {
|
|
407
|
-
const transformedImports = createTransformedImports(
|
|
408
|
-
[
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
opts?.transformedImports,
|
|
416
|
-
opts?.importPaths
|
|
417
|
-
);
|
|
417
|
+
const transformedImports = createTransformedImports([
|
|
418
|
+
["callback", ["signalium"]],
|
|
419
|
+
["reactive", ["signalium"]],
|
|
420
|
+
["reactiveMethod", ["signalium"]],
|
|
421
|
+
["relay", ["signalium"]],
|
|
422
|
+
["task", ["signalium"]],
|
|
423
|
+
["watcher", ["signalium"]]
|
|
424
|
+
], opts?.transformedImports, opts?.importPaths);
|
|
418
425
|
const t = api.types;
|
|
419
426
|
const promiseImportPath = opts?.promiseImportPath ?? "signalium";
|
|
420
427
|
const isTrackedImport = (localName, path) => {
|
|
421
428
|
const binding = path.scope.getBinding(localName);
|
|
422
|
-
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
429
|
+
if (!binding || !t.isImportSpecifier(binding.path.node))
|
|
430
|
+
return false;
|
|
423
431
|
const importSpec = binding.path.node;
|
|
424
432
|
const importedName = importSpec.imported.name;
|
|
425
433
|
const importDecl = binding.path.parent;
|
|
426
|
-
if (!t.isImportDeclaration(importDecl))
|
|
434
|
+
if (!t.isImportDeclaration(importDecl))
|
|
435
|
+
return false;
|
|
427
436
|
const importPaths = transformedImports.get(importedName);
|
|
428
|
-
if (!importPaths)
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
);
|
|
437
|
+
if (!importPaths)
|
|
438
|
+
return false;
|
|
439
|
+
return importPaths.some((p) => typeof p === "string" ? importDecl.source.value === p : p.test(importDecl.source.value));
|
|
432
440
|
};
|
|
433
441
|
const isReactiveCall = (path) => {
|
|
434
|
-
if (!t.isCallExpression(path.node))
|
|
442
|
+
if (!t.isCallExpression(path.node))
|
|
443
|
+
return false;
|
|
435
444
|
const callee = path.node.callee;
|
|
436
|
-
if (!t.isIdentifier(callee))
|
|
445
|
+
if (!t.isIdentifier(callee))
|
|
446
|
+
return false;
|
|
437
447
|
return isTrackedImport(callee.name, path);
|
|
438
448
|
};
|
|
439
449
|
const isWithinTrackedCall = (path) => {
|
|
440
450
|
let current = path.parentPath;
|
|
441
451
|
while (current) {
|
|
442
|
-
if (current.isCallExpression() && isReactiveCall(current))
|
|
452
|
+
if (current.isCallExpression() && isReactiveCall(current))
|
|
453
|
+
return true;
|
|
443
454
|
current = current.parentPath;
|
|
444
455
|
}
|
|
445
456
|
return false;
|
|
446
457
|
};
|
|
447
458
|
function ensureReactivePromiseIdentifier(programPath) {
|
|
448
459
|
for (const bodyPath of programPath.get("body")) {
|
|
449
|
-
if (!bodyPath.isImportDeclaration())
|
|
460
|
+
if (!bodyPath.isImportDeclaration())
|
|
461
|
+
continue;
|
|
450
462
|
const importDecl2 = bodyPath.node;
|
|
451
|
-
if (importDecl2.source.value !== promiseImportPath)
|
|
463
|
+
if (importDecl2.source.value !== promiseImportPath)
|
|
464
|
+
continue;
|
|
452
465
|
for (const spec of importDecl2.specifiers) {
|
|
453
466
|
if (spec.type === "ImportSpecifier") {
|
|
454
467
|
const ispec = spec;
|
|
@@ -460,18 +473,17 @@ function createSignaliumPromiseMethodsTransform(api, opts) {
|
|
|
460
473
|
}
|
|
461
474
|
}
|
|
462
475
|
for (const bodyPath of programPath.get("body")) {
|
|
463
|
-
if (!bodyPath.isImportDeclaration())
|
|
476
|
+
if (!bodyPath.isImportDeclaration())
|
|
477
|
+
continue;
|
|
464
478
|
const node = bodyPath.node;
|
|
465
|
-
if (node.source.value !== promiseImportPath)
|
|
479
|
+
if (node.source.value !== promiseImportPath)
|
|
480
|
+
continue;
|
|
466
481
|
const localName2 = "ReactivePromise";
|
|
467
482
|
node.specifiers.push(t.importSpecifier(t.identifier(localName2), t.identifier("ReactivePromise")));
|
|
468
483
|
return localName2;
|
|
469
484
|
}
|
|
470
485
|
const localName = "ReactivePromise";
|
|
471
|
-
const importDecl = t.importDeclaration(
|
|
472
|
-
[t.importSpecifier(t.identifier(localName), t.identifier("ReactivePromise"))],
|
|
473
|
-
t.stringLiteral(promiseImportPath)
|
|
474
|
-
);
|
|
486
|
+
const importDecl = t.importDeclaration([t.importSpecifier(t.identifier(localName), t.identifier("ReactivePromise"))], t.stringLiteral(promiseImportPath));
|
|
475
487
|
const [first] = programPath.get("body");
|
|
476
488
|
if (first) {
|
|
477
489
|
first.insertBefore(importDecl);
|
|
@@ -484,17 +496,24 @@ function createSignaliumPromiseMethodsTransform(api, opts) {
|
|
|
484
496
|
name: "signalium-transform-reactive-promise-methods",
|
|
485
497
|
visitor: {
|
|
486
498
|
CallExpression(callPath) {
|
|
487
|
-
if (!isWithinTrackedCall(callPath))
|
|
499
|
+
if (!isWithinTrackedCall(callPath))
|
|
500
|
+
return;
|
|
488
501
|
const callee = callPath.node.callee;
|
|
489
|
-
if (!t.isMemberExpression(callee))
|
|
490
|
-
|
|
502
|
+
if (!t.isMemberExpression(callee))
|
|
503
|
+
return;
|
|
504
|
+
if (callee.computed)
|
|
505
|
+
return;
|
|
491
506
|
const object = callee.object;
|
|
492
507
|
const property = callee.property;
|
|
493
|
-
if (!t.isIdentifier(object, { name: "Promise" }))
|
|
494
|
-
|
|
495
|
-
if (
|
|
508
|
+
if (!t.isIdentifier(object, { name: "Promise" }))
|
|
509
|
+
return;
|
|
510
|
+
if (callPath.scope.getBinding("Promise"))
|
|
511
|
+
return;
|
|
512
|
+
if (!t.isIdentifier(property))
|
|
513
|
+
return;
|
|
496
514
|
const methodName = property.name;
|
|
497
|
-
if (!PROMISE_STATIC_METHODS.has(methodName))
|
|
515
|
+
if (!PROMISE_STATIC_METHODS.has(methodName))
|
|
516
|
+
return;
|
|
498
517
|
const programPath = callPath.findParent((p) => p.isProgram());
|
|
499
518
|
const reactivePromiseId = ensureReactivePromiseIdentifier(programPath);
|
|
500
519
|
const newCallee = t.memberExpression(t.identifier(reactivePromiseId), t.identifier(methodName));
|