-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DOM: Implement the
first()
Observable operator
See WICG/observable#131. For WPTs: Co-authored-by: [email protected] [email protected] Bug: 40282760 Change-Id: I81a2b482dcfdbc149d60ddbc5b98ddadb6dafc89 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5412443 Reviewed-by: Joey Arhar <[email protected]> Commit-Queue: Dominic Farolino <[email protected]> Cr-Commit-Position: refs/heads/main@{#1281639}
- Loading branch information
1 parent
a3da076
commit 1e07357
Showing
1 changed file
with
114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
promise_test(async () => { | ||
const results = []; | ||
|
||
const source = new Observable(subscriber => { | ||
subscriber.addTeardown(() => results.push('teardown')); | ||
subscriber.next(1); | ||
results.push(subscriber.active ? 'active' : 'inactive'); | ||
results.push(subscriber.signal.aborted ? 'aborted' : 'not aborted') | ||
|
||
// Ignored. | ||
subscriber.next(2); | ||
subscriber.complete(); | ||
}); | ||
|
||
const value = await source.first(); | ||
|
||
assert_array_equals(results, ['teardown', 'inactive', 'aborted']); | ||
assert_equals(value, 1, | ||
"Promise resolves with the first value from the source Observable"); | ||
}, "first(): Promise resolves with the first value from the source Observable"); | ||
|
||
promise_test(async () => { | ||
const error = new Error("error from source"); | ||
const source = new Observable(subscriber => { | ||
subscriber.error(error); | ||
}); | ||
|
||
let rejection; | ||
try { | ||
await source.first(); | ||
} catch (e) { | ||
rejection = e; | ||
} | ||
|
||
assert_equals(rejection, error, "Promise rejects with source Observable error"); | ||
}, "first(): Promise rejects with the error emitted from the source Observable"); | ||
|
||
promise_test(async () => { | ||
const source = new Observable(subscriber => { | ||
subscriber.complete(); | ||
}); | ||
|
||
let rejection; | ||
try { | ||
await source.first(); | ||
} catch (e) { | ||
rejection = e; | ||
} | ||
|
||
assert_true(rejection instanceof RangeError, | ||
"Upon complete(), first() Promise rejects with RangeError"); | ||
assert_equals(rejection.message, "No values in Observable"); | ||
}, "first(): Promise rejects with RangeError when source Observable " + | ||
"completes without emitting any values"); | ||
|
||
promise_test(async () => { | ||
const source = new Observable(subscriber => {}); | ||
|
||
const controller = new AbortController(); | ||
const promise = source.first({ signal: controller.signal }); | ||
|
||
controller.abort(); | ||
|
||
let rejection; | ||
try { | ||
await promise; | ||
} catch (e) { | ||
rejection = e; | ||
} | ||
|
||
assert_true(rejection instanceof DOMException, | ||
"Promise rejects with a DOMException for abortion"); | ||
assert_equals(rejection.name, "AbortError", | ||
"Rejected with 'AbortError' DOMException"); | ||
assert_equals(rejection.message, "signal is aborted without reason"); | ||
}, "first(): Aborting a signal rejects the Promise with an AbortError DOMException"); | ||
|
||
promise_test(async () => { | ||
const results = []; | ||
|
||
const source = new Observable(subscriber => { | ||
results.push("source subscribe"); | ||
subscriber.addTeardown(() => results.push("source teardown")); | ||
subscriber.signal.addEventListener("abort", () => results.push("source abort")); | ||
results.push("before source next 1"); | ||
subscriber.next(1); | ||
results.push("after source next 1"); | ||
}); | ||
|
||
results.push("calling first"); | ||
const promise = source.first(); | ||
|
||
assert_array_equals(results, [ | ||
"calling first", | ||
"source subscribe", | ||
"before source next 1", | ||
"source teardown", | ||
"source abort", | ||
"after source next 1" | ||
], "Array values after first() is called"); | ||
|
||
const firstValue = await promise; | ||
results.push(`first resolved with: ${firstValue}`); | ||
|
||
assert_array_equals(results, [ | ||
"calling first", | ||
"source subscribe", | ||
"before source next 1", | ||
"source teardown", | ||
"source abort", | ||
"after source next 1", | ||
"first resolved with: 1", | ||
], "Array values after Promise is awaited"); | ||
}, "first(): Lifecycle"); |