Skip to content

Commit

Permalink
WIP: debugging
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalerba committed Aug 14, 2024
1 parent 41b0143 commit a084ae3
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 24 deletions.
32 changes: 16 additions & 16 deletions samples/advanced/src/app/database/database.component.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 35 additions & 8 deletions src/zones.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,29 @@ export class ɵZoneScheduler implements SchedulerLike {
}

class BlockUntilFirstOperator<T> implements Operator<T, T> {
call(subscriber: Subscriber<T>, source: Observable<T>): TeardownLogic {
private readonly taskDone;

constructor() {
// maybe this is a race condition, invoke in a timeout
// hold for 10ms while I try to figure out what is going on
const taskDone = createPendingTask(10);
this.taskDone = (r: string) => {
console.warn(`>>> DONE: BlockUntilFirstOperator ${taskDone.id} ${r}`);
taskDone();
};
}

call(subscriber: Subscriber<T>, source: Observable<T>): TeardownLogic {
return source
.pipe(
tap({
next: taskDone,
complete: taskDone,
error: taskDone,
next: () => this.taskDone('(next)'),
complete: () => this.taskDone('(complete)'),
error: () => this.taskDone('(error)'),
})
)
.subscribe(subscriber)
.add(taskDone);
.add(() => this.taskDone('(unsubscribed)'));
}
}

Expand Down Expand Up @@ -175,20 +183,34 @@ const zoneWrapFn = (
};
};

let nextId = 0;

/**
* Creates a pending tasks and returns a callback that can be used to complete it.
* Optionally takes a timeout, in ms, to delay the completion of the task after the callback is
* invoked.
*/
export function createPendingTask(timeout?: number): VoidFunction {
export function createPendingTask(
timeout?: number
): VoidFunction & { id: number } {
const taskDone = run(() => getSchedulers().pendingTasks.add());
return timeout !== undefined ? () => setTimeout(taskDone, timeout) : taskDone;
const r =
timeout !== undefined ? () => setTimeout(taskDone, timeout) : taskDone;
(r as any).id = nextId++;
console.warn(`>>> PENDING ${(r as any).id}`);
return r as any;
}

const rename = (f, n) =>
new Function(
`const f = arguments[0]; return function ${n} () { return f.apply(this, arguments); }`
)(f);

export const ɵzoneWrap = <T extends (...args: any[]) => unknown>(
it: T,
blockUntilFirst: boolean
): T => {
console.warn(`>>> WRAP ${it.name ?? '(unknown)'}`);
return ((...args: unknown[]) => {
let argsTaskDone: VoidFunction | undefined;

Expand All @@ -205,7 +227,7 @@ export const ɵzoneWrap = <T extends (...args: any[]) => unknown>(
}

// Run the function outside the NgZone, passing the wrapped arguments.
const ret = runOutsideAngular(() => it.apply(this, args));
let ret = runOutsideAngular(() => it.apply(this, args));

// If we're not blocking we don't need to take out a pending task.
if (!blockUntilFirst) {
Expand All @@ -220,7 +242,12 @@ export const ɵzoneWrap = <T extends (...args: any[]) => unknown>(
}
}

if (typeof ret === 'function') {
ret = ɵzoneWrap(rename(ret, `${it.name}_return`), blockUntilFirst);
}

if (ret instanceof Observable) {
console.warn(`>>> PIPE OBSERVABLE`);
// If we're blocking and about to return an `Observable`, keep Angular unstable until we
// receive the first value.
return ret.pipe(keepUnstableUntilFirst);
Expand Down

0 comments on commit a084ae3

Please sign in to comment.