Skip to content

Commit 47d45c6

Browse files
Misc cleanup (#18)
* removed redundant loop * dispose queue manips belong to the node * Less conditional state * Removed deprecated/redudant checks * Delegate node reassignment to the node itself.
1 parent 6000550 commit 47d45c6

File tree

7 files changed

+57
-84
lines changed

7 files changed

+57
-84
lines changed

src/Environment.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { ProbingContext } from './ApiTypes';
1919
export type DisposeOp = () => void;
2020
export interface Environment {
2121
_onDispose: (op: DisposeOp) => void;
22-
_getProbingContext: () => ProbingContext | undefined;
22+
_getProbingContext: () => ProbingContext;
2323
}
2424

2525
let _currentEnv: Environment | null = null;
@@ -50,10 +50,5 @@ export function useProbingContext(): ProbingContext {
5050
throw new Error('Environment underflow');
5151
}
5252

53-
const result = _currentEnv!._getProbingContext();
54-
if (process.env.NODE_ENV !== 'production' && !result) {
55-
throw new Error('There is no active probing context');
56-
}
57-
58-
return result!;
53+
return _currentEnv!._getProbingContext();
5954
}

src/Node.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ export interface NodeBuildData {
2525
_cb: (...arg: unknown[]) => unknown;
2626
_args: unknown[];
2727

28-
_next?: IPNode;
29-
_resolveAs?: IPNode;
28+
_next?: BaseNode;
29+
_resolveAs: BaseNode;
3030
_prober: IProber;
3131
_context: ProbingContext;
3232
}
@@ -43,17 +43,24 @@ export abstract class BaseNode implements IPNode {
4343
}
4444

4545
dispose(): void {
46-
if (this._onDispose) {
47-
this._onDispose.forEach((c) => c());
48-
this._onDispose = undefined;
49-
}
46+
// Nodes should only ever be disposed once
47+
this._onDispose.forEach((c) => c());
48+
}
49+
50+
_addToDispose(ops: DisposeOp[]): void {
51+
this._onDispose.push(...ops);
52+
}
53+
54+
_assign(rhs: BaseNode): void {
55+
this._result = rhs._result;
56+
this._onDispose.push(...rhs._onDispose);
5057
}
5158

5259
abstract get result(): unknown;
5360

5461
_result?: unknown;
5562
_probed_pnodetype?: number;
56-
_onDispose?: DisposeOp[];
63+
_onDispose: DisposeOp[] = [];
5764

5865
_buildData?: NodeBuildData;
5966
_uniqueNodeId?: number;

src/Prober.ts

Lines changed: 36 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,6 @@ const isIntrinsic = <I>(cb: IKeys<I> | ((...args: unknown[]) => unknown)): cb is
2020
return typeof cb === 'string';
2121
};
2222

23-
const addToDisposeQueue = (node: BaseNode, ops: DisposeOp[]) => {
24-
if (!node._onDispose) {
25-
node._onDispose = ops;
26-
} else {
27-
node._onDispose = node._onDispose.concat(ops);
28-
}
29-
};
30-
3123
let _NextUniqueNodeId = 0;
3224

3325
interface NodeQueue {
@@ -45,14 +37,14 @@ class Prober<I extends FuncMap> implements IProber {
4537
private _intrinsics: Partial<I>;
4638
private _fallback?: IntrinsicFallback<I>;
4739
private _stack: ProberStackFrame[] = [];
48-
private _current: ProberStackFrame = { _disposeOps: [] };
40+
private _currentFrame: ProberStackFrame = { _disposeOps: [] };
4941

5042
_onDispose(op: DisposeOp): void {
51-
this._current._disposeOps.push(op);
43+
this._currentFrame._disposeOps.push(op);
5244
}
5345

54-
_getProbingContext(): ProbingContext | undefined {
55-
return this._current!._node!._buildData!._context;
46+
_getProbingContext(): ProbingContext {
47+
return this._currentFrame!._node!._buildData!._context;
5648
}
5749

5850
constructor(intrinsics: Partial<I>, fallback?: IntrinsicFallback<I>) {
@@ -79,14 +71,15 @@ class Prober<I extends FuncMap> implements IProber {
7971
newNode._uniqueNodeId = _NextUniqueNodeId++;
8072
}
8173

82-
if (!this._current._announced) {
83-
this._current._announced = { _head: newNode, _tail: newNode };
74+
if (!this._currentFrame._announced) {
75+
this._currentFrame._announced = { _head: newNode, _tail: newNode };
8476
} else {
85-
this._current._announced._tail._buildData!._next = newNode;
86-
this._current._announced._tail = newNode;
77+
this._currentFrame._announced._tail._buildData!._next = newNode;
78+
this._currentFrame._announced._tail = newNode;
8779
}
8880

8981
newNode._buildData = {
82+
_resolveAs: newNode,
9083
_cb,
9184
_prober: this,
9285
_args,
@@ -100,41 +93,33 @@ class Prober<I extends FuncMap> implements IProber {
10093

10194
_finalizeNode(node: BaseNode) {
10295
// If a component returns a Node (as opposed to a value), then we short-circuit to the parent.
103-
let destinationNode = node;
104-
while (destinationNode._buildData && destinationNode._buildData._resolveAs) {
105-
destinationNode = destinationNode._buildData!._resolveAs;
106-
}
96+
const bd = node._buildData!;
97+
const destinationNode = bd._resolveAs;
10798

108-
this._current._node = node;
109-
const { _cb, _args } = node._buildData!;
110-
const cbResult = _cb(..._args, node._buildData!._context);
99+
this._currentFrame._node = node;
100+
const cbResult = bd._cb(...bd._args, bd._context);
111101

112102
if (isPNode(cbResult)) {
113103
if (cbResult.finalized) {
114-
// Post-ex-facto proxying.
115-
destinationNode._result = cbResult._result;
116-
if (cbResult._onDispose) {
117-
addToDisposeQueue(destinationNode, cbResult._onDispose);
118-
cbResult._onDispose = [];
119-
}
104+
destinationNode._assign(cbResult);
120105
} else {
121106
cbResult._buildData!._resolveAs = destinationNode;
122107
}
123108
} else {
124109
destinationNode._result = cbResult;
125110
}
126111

127-
if (this._current._disposeOps.length > 0) {
128-
addToDisposeQueue(destinationNode, this._current._disposeOps);
129-
this._current._disposeOps = [];
112+
if (this._currentFrame._disposeOps.length > 0) {
113+
destinationNode._addToDispose(this._currentFrame._disposeOps);
114+
this._currentFrame._disposeOps = [];
130115
}
131116
}
132117

133118
_finalize(target: IPNode): void {
134119
if (process.env.NODE_ENV === 'check') {
135120
let lookup: BaseNode | undefined;
136-
if (this._current._announced) {
137-
lookup = this._current._announced._head;
121+
if (this._currentFrame._announced) {
122+
lookup = this._currentFrame._announced._head;
138123
}
139124
while (lookup && lookup !== target) {
140125
lookup = lookup._buildData!._next;
@@ -144,58 +129,51 @@ class Prober<I extends FuncMap> implements IProber {
144129
}
145130
}
146131

147-
let node: BaseNode = this._current._announced!._head!;
148-
let end: BaseNode = target as BaseNode;
132+
let node = this._currentFrame._announced!._head!;
133+
let end = target as BaseNode;
149134

150135
if (end._buildData!._next) {
151-
this._current._announced!._head = end._buildData!._next;
136+
this._currentFrame._announced!._head = end._buildData!._next;
152137
} else {
153-
this._current._announced = undefined;
138+
this._currentFrame._announced = undefined;
154139
}
155140
end._buildData!._next = undefined;
156141

157-
/*
158-
//These two steps are, I suspect, Technically unnecessary
159-
160-
if (!this._current._announced._head) {
161-
this._current._announced = {};
162-
}
163-
*/
164142
pushEnv(this);
165-
this._stack.push(this._current);
166-
this._current = { _node: node, _disposeOps: [] };
143+
this._stack.push(this._currentFrame);
144+
this._currentFrame = { _node: node, _disposeOps: [] };
167145

168146
let done = false;
169147
while (!done) {
170148
this._finalizeNode(node);
171149

172-
// Queue up any work that was discovered in the process.
173-
if (this._current._announced) {
174-
end = this._current._announced._tail;
175-
node._buildData!._next = this._current._announced._head;
176-
this._current._announced = undefined;
150+
// Queue up any work that was discovered in the process,
151+
// and update our end target so that we complete it before
152+
// returning.
153+
if (this._currentFrame._announced) {
154+
end = this._currentFrame._announced._tail;
155+
node._buildData!._next = this._currentFrame._announced._head;
156+
this._currentFrame._announced = undefined;
177157
}
178158

179159
done = node === end;
180-
const nextNode = node._buildData!._next as BaseNode;
160+
const nextNode = node._buildData!._next;
181161
node._buildData = undefined;
182-
node = nextNode;
162+
node = nextNode!;
183163
}
184164

185-
this._current = this._stack.pop()!;
165+
this._currentFrame = this._stack.pop()!;
186166
popEnv();
187167
}
188168

189169
private _getCb<T extends IKeys<I> | ComponentCb>(what: T): { _cb: ComponentCb; _name: string } {
190170
if (isIntrinsic<I>(what)) {
191171
let _cb: ComponentCb | undefined = this._intrinsics[what];
192-
const _name = what.toString();
193172
if (!_cb) {
194-
// This is safe, it's caught at the start of _announce()
195173
_cb = this._fallback!;
196174
}
197175

198-
return { _cb: _cb!, _name };
176+
return { _cb: _cb!, _name: what.toString() };
199177
} else {
200178
return { _cb: what as ComponentCb, _name: (what as ComponentCb).name };
201179
}

tests/dynamicList.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const cleanup = () => {
2727
beforeEach(() => {
2828
pushEnv({
2929
_onDispose: (op: DisposeOp) => disposeQueue.push(op),
30-
_getProbingContext: () => undefined,
30+
_getProbingContext: () => ({ componentName: '' }),
3131
});
3232
});
3333

tests/dynamicOperations.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const cleanup = () => {
2727
beforeEach(() => {
2828
pushEnv({
2929
_onDispose: (op: DisposeOp) => disposeQueue.push(op),
30-
_getProbingContext: () => undefined,
30+
_getProbingContext: () => ({ componentName: '' }),
3131
});
3232
});
3333

tests/dynamicVal.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const cleanup = () => {
2626
beforeEach(() => {
2727
pushEnv({
2828
_onDispose: (op: DisposeOp) => disposeQueue.push(op),
29-
_getProbingContext: () => undefined,
29+
_getProbingContext: () => ({ componentName: '' }),
3030
});
3131
});
3232

tests/environment.test.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ describe('useOnDispose ', () => {
2020

2121
class TestEnv implements Environment {
2222
count = 0;
23-
probeContext?: ProbingContext;
23+
probeContext: ProbingContext = { componentName: '' };
2424
_onDispose(): void {
2525
this.count += 1;
2626
}
2727

28-
_getProbingContext(): ProbingContext | undefined {
28+
_getProbingContext(): ProbingContext {
2929
return this.probeContext;
3030
}
3131
}
@@ -77,13 +77,6 @@ describe('useProbingContext ', () => {
7777
expectThrowInNotProd(useProbingContext);
7878
});
7979

80-
it('Fails if probing context is set', () => {
81-
const env = new TestEnv();
82-
pushEnv(env);
83-
expectThrowInNotProd(useProbingContext);
84-
popEnv();
85-
});
86-
8780
it('Works if a probing context is set', () => {
8881
const env = new TestEnv();
8982
env.probeContext = { componentName: 'aaa' };

0 commit comments

Comments
 (0)