Skip to content

Adopt the state of promises used as resolutions per Promises/A+ - #241

Draft
GrahamCampbell wants to merge 1 commit into
3.0from
aplus-state-adoption
Draft

Adopt the state of promises used as resolutions per Promises/A+#241
GrahamCampbell wants to merge 1 commit into
3.0from
aplus-state-adoption

Conversation

@GrahamCampbell

Copy link
Copy Markdown
Member

Resolving a promise with another promise, or returning one from a then() handler, settled the promise immediately: getState() reported fulfilled while the inner promise was still pending, and wait() could later throw on a promise whose state said it had fulfilled, violating Promises/A+ section 2.3.2. The promise now stays pending and adopts the thenable's eventual state, adopting an already-settled promise synchronously so that state polling around the synchronous wait() path keeps working. Handlers attached before adoption are merged onto the adopted promise behind a marker entry, which keeps dispatch as flat as the previous handler merge; a 5000-deep resolution chain runs within about 1.6 times the 3.x time while using a quarter of the memory. Rejection reasons are never adopted: reject() and Create::rejectionFor() now refuse promises with an InvalidArgumentException, matching RejectedPromise, and resolving or rejecting a promise with itself rejects it with a TypeError per section 2.3.1. Resolutions arriving while a promise adopts another promise are ignored per section 2.3.3.3.3, and cancelling an adopting promise forwards the cancellation to the adopted promise. Guzzle's full test suite passes unchanged against this branch. Drafted against 3.0 until a 4.0 branch is cut. Fixes #101.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

State inconsistency with chained promises

1 participant