From 5152a04b77bc472ce676c3b2cdb3e21fc30641b2 Mon Sep 17 00:00:00 2001 From: Hubol Date: Tue, 3 Sep 2024 23:07:21 -0500 Subject: [PATCH] Abandoning this too --- src/lib/zone/prommy.ts | 65 +++++++++++++++-------------- test/tests/test-prommy-more.ts | 76 +++++++++++++++++++++++++++------- test/tests/test-prommy.ts | 6 +-- 3 files changed, 99 insertions(+), 48 deletions(-) diff --git a/src/lib/zone/prommy.ts b/src/lib/zone/prommy.ts index b955f2f..9ef5502 100644 --- a/src/lib/zone/prommy.ts +++ b/src/lib/zone/prommy.ts @@ -4,20 +4,19 @@ import { ForceAliasType } from "../types/force-alias-type"; const PrommyGlobal = { $root: Force(), - $push, + $push: $push as any as (p: PromiseLike) => PromiseLike, $pop, } let installed = false; export function installPrommy() { - if (installed) - return; + if (!installed) { + installed = true; - installed = true; - - globalThis.$p = PrommyGlobal; - redefinePromise(); + globalThis.$p = PrommyGlobal; + redefinePromise(); + } return { $p: PrommyGlobal }; } @@ -27,10 +26,6 @@ export const Prommy = { create, } -export const _Internal_Prommy = { - create: create as (...args: Parameters>) => Prommy & PrivatePromise, -} - function createRoot(executor: () => Promise, context: any) { return new PrommyRoot(executor, context); } @@ -46,7 +41,6 @@ function create(executor: (resolve: (value: T | PromiseLike) => void, reje interface PrivatePromise { $isPromise?: true; $root: PrommyRoot; - $pushed?: boolean; } // TODO it may be possible to modify the prototype constructor @@ -71,31 +65,36 @@ const Promise_resolve = Promise.resolve; const Promise_reject = Promise.reject; function redefinePromise() { - // globalThis.Promise = function (this: Promise & PrivatePromise, executor) { - // const p = new Promise_ctor(executor) as Promise & PrivatePromise; - // p.$root = PrommyGlobal.$root; - // return p; - // } as any; + globalThis.Promise = function (this: Promise & PrivatePromise, executor) { + const p = new Promise_ctor(executor) as Promise & PrivatePromise; + p.$root = PrommyGlobal.$root; + return p; + } as any; + + new Promise(() => {}).finally() Object.defineProperties(Promise.prototype, { then: { value: function (this: Promise & PrivatePromise, onfulfilled?, onrejected?) { - return Promise_then.call(this, + const p = Promise_then.call(this, onfulfilled && ((value) => { - PrommyGlobal.$root = this.$root; + debugSetGlobal(this.$root, 'Promise.then.onfulfilled'); + // PrommyGlobal.$root = this.$root; const result = onfulfilled(value); if (isPromise(result)) { result.$root = this.$root; } else if (isPromiseLike(result)) { // TODO I think a Prommy can be constructed from it - console.error("Don't know how to handle this case!"); + console.error("then: Don't know how to handle this case!"); } return result; }), // TODO not sure if this is correct - onrejected); + onrejected) as Promise & PrivatePromise; + p.$root = this.$root; + return p; }, configurable: true, }, @@ -153,7 +152,7 @@ function isAwaitedPrommyResult(value: any): value is AwaitedPrommyResult { function $pop(awaitedResult: unknown) { if (isAwaitedPrommyResult(awaitedResult)) { - PrommyGlobal.$root = awaitedResult.$root; + debugSetGlobal(awaitedResult.$root, '$pop.isAwaitedPrommyResult'); return awaitedResult.$value; } @@ -163,14 +162,15 @@ function $pop(awaitedResult: unknown) { } function $push(promise: PromiseLike & PrivatePromise) { - if (promise.$pushed) - return promise; if (!isPromise(promise)) { // TODO I think a Prommy can be constructed from it - console.error("Don't know how to handle this case!"); + console.error("$push: Don't know how to handle this case!"); } - const p = Promise_then.call(promise, $value => ({ $value, $root: promise.$root })) as Promise & PrivatePromise; - p.$pushed = true; + const $root = promise.$root || PrommyGlobal.$root || null; + promise.$root = $root; + debugSetGlobal($root, '$push'); + const p = promise.then($value => ({ $value, $root })) as Promise & PrivatePromise; + p.$root = $root; return p; } @@ -186,9 +186,9 @@ export class PrommyRoot { this.context = context; const previous = PrommyGlobal.$root; - PrommyGlobal.$root = this; - this._promise = executor().catch(e => {}); - PrommyGlobal.$root = previous; + debugSetGlobal(this, 'new PrommyRoot push'); + this._promise = executor().catch(console.error); + debugSetGlobal(previous, 'new PrommyRoot pop'); } } @@ -198,4 +198,9 @@ export const PrommyContext = { current() { return PrommyGlobal.$root.context; } +} + +function debugSetGlobal(root: PrommyRoot, info: string) { + console.log('-->', root?.context || null, ':', info); + PrommyGlobal.$root = root; } \ No newline at end of file diff --git a/test/tests/test-prommy-more.ts b/test/tests/test-prommy-more.ts index c1f0d8c..b67b00d 100644 --- a/test/tests/test-prommy-more.ts +++ b/test/tests/test-prommy-more.ts @@ -1,20 +1,68 @@ -import { Prommy, PrommyContext } from "../../src/lib/zone/prommy"; +import { Prommy, PrommyContext, installPrommy } from "../../src/lib/zone/prommy"; import { Assert } from "../lib/assert"; import { TestPromise } from "../lib/test-promise"; -export async function morePrommyAndChainingWorks() { +const { $p } = installPrommy(); +export async function morePrommyThenChainingWorks() { + const events: string[] = []; + + Prommy.createRoot(async () => { + Assert(PrommyContext.current()).toStrictlyBe('rootA'); + $p.$pop(await $p.$push(asyncFunction().then(() => { + Assert(PrommyContext.current()).toStrictlyBe('rootA'); + events.push('a'); + }))); + Assert(PrommyContext.current()).toStrictlyBe('rootA'); + $p.$pop(await $p.$push(asyncFunction().then(() => { + Assert(PrommyContext.current()).toStrictlyBe('rootA'); + events.push('c'); + }).then(() => { + Assert(PrommyContext.current()).toStrictlyBe('rootA'); + return ticks(10); + }))); + Assert(PrommyContext.current()).toStrictlyBe('rootA'); + events.push('e'); + }, 'rootA'); + + Prommy.createRoot(async () => { + Assert(PrommyContext.current()).toStrictlyBe('rootB'); + $p.$pop(await $p.$push(asyncFunction().then(() => { + Assert(PrommyContext.current()).toStrictlyBe('rootB'); + return ticks(2); + }).then(() => events.push('b')))); + Assert(PrommyContext.current()).toStrictlyBe('rootB'); + $p.$pop(await $p.$push(asyncFunction())); + Assert(PrommyContext.current()).toStrictlyBe('rootB'); + events.push('d'); + }, 'rootB'); + + for (let i = 0; i < 30; i++) { + tick(); + await TestPromise.flush(); + } + + Assert(events.length).toStrictlyBe(5); + Assert(events[0]).toStrictlyBe('a'); + Assert(events[1]).toStrictlyBe('b'); + Assert(events[2]).toStrictlyBe('c'); + Assert(events[3]).toStrictlyBe('d'); + Assert(events[4]).toStrictlyBe('e'); } export async function morePrommyAllWorks() { } -async function returnsPromisePrommy() { - console.log('a'); - (globalThis.$prommyResult = await ticks(2), globalThis.$prommyPop(), globalThis.$prommyResult) - console.log('b'); - (globalThis.$prommyResult = await ticks(2), globalThis.$prommyPop(), globalThis.$prommyResult) +async function asyncFunction() { + const initialContext = PrommyContext.current(); + console.log(initialContext); + Assert(PrommyContext.current()).toBeTruthy(); + $p.$pop(await $p.$push(ticks(2))); + Assert(PrommyContext.current()).toStrictlyBe(initialContext); + $p.$pop(await $p.$push(ticks(2))); + Assert(PrommyContext.current()).toStrictlyBe(initialContext); + return 3; } export async function morePrommyUtilityFunctionWorks() { @@ -23,10 +71,9 @@ export async function morePrommyUtilityFunctionWorks() { Prommy.createRoot(async () => { Assert(PrommyContext.current()).toStrictlyBe('root1'); - (globalThis.$prommyResult = await new Prommy(returnsPromisePrommy()), globalThis.$prommyPop(), globalThis.$prommyResult) - // await returnsPromisePrommy(); + $p.$pop(await $p.$push(asyncFunction())); Assert(PrommyContext.current()).toStrictlyBe('root1'); - (globalThis.$prommyResult = await new Prommy(returnsPromisePrommy()), globalThis.$prommyPop(), globalThis.$prommyResult) + $p.$pop(await $p.$push(asyncFunction())); Assert(PrommyContext.current()).toStrictlyBe('root1'); finished1 = true; }, 'root1'); @@ -34,9 +81,9 @@ export async function morePrommyUtilityFunctionWorks() { Prommy.createRoot(async () => { Assert(PrommyContext.current()).toStrictlyBe('root2'); // TODO this transformation needs to happen in TSvvvvvvvv - (globalThis.$prommyResult = await new Prommy(returnsPromisePrommy()), globalThis.$prommyPop(), globalThis.$prommyResult) + $p.$pop(await $p.$push(asyncFunction())); Assert(PrommyContext.current()).toStrictlyBe('root2'); - (globalThis.$prommyResult = await new Prommy(returnsPromisePrommy()), globalThis.$prommyPop(), globalThis.$prommyResult) + $p.$pop(await $p.$push(asyncFunction())); Assert(PrommyContext.current()).toStrictlyBe('root2'); finished2 = true; }, 'root2'); @@ -48,7 +95,6 @@ export async function morePrommyUtilityFunctionWorks() { Assert(finished1).toBeTruthy(); Assert(finished2).toBeTruthy(); - Assert(PrommyContext._internalStackLength).toStrictlyBe(0); } function tick() { @@ -67,7 +113,7 @@ function tick() { const tickMap: Map = new Map(); function ticks(count: number) { - return new Prommy(resolve => { - tickMap.set(resolve, count); + return Prommy.create(resolve => { + tickMap.set(() => resolve(count), count); }); } diff --git a/test/tests/test-prommy.ts b/test/tests/test-prommy.ts index bd6cc22..c063ddd 100644 --- a/test/tests/test-prommy.ts +++ b/test/tests/test-prommy.ts @@ -1,4 +1,4 @@ -import { Prommy, PrommyContext, _Internal_Prommy, installPrommy } from "../../src/lib/zone/prommy"; +import { Prommy, PrommyContext, installPrommy } from "../../src/lib/zone/prommy"; import { Assert } from "../lib/assert"; import { TestPromise } from "../lib/test-promise"; @@ -157,13 +157,13 @@ function tick() { const tickMap: Map = new Map(); function ticks(count: number) { - return _Internal_Prommy.create(resolve => { + return Prommy.create(resolve => { tickMap.set(resolve, count); }); } function rejectAfterTicks(count: number, message: string) { - return _Internal_Prommy.create((resolve, reject) => { + return Prommy.create((resolve, reject) => { tickMap.set(() => reject(message), count); }); } \ No newline at end of file