Skip to content

Commit 0da9f44

Browse files
authored
Core semantics (#6434)
* docs: remove line about perf tests that no longer made sense. * docs: Start core semantics document * docs: fix typos * chore: Add more information * chore: Fix formatting on Creation Functions header
1 parent 366b029 commit 0da9f44

File tree

2 files changed

+51
-19
lines changed

2 files changed

+51
-19
lines changed

CONTRIBUTING.md

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,24 @@ it still applies to you. Ignorance is not an exemption.
55

66
Contents
77

8-
- [Submitting a Pull Request (PR)](#submitting-a-pull-request-pr)
9-
- [After your pull request is merged](#after-your-pull-request-is-merged)
10-
- [Coding Style Guidelines](#coding-style-guidelines)
11-
- [Documentation](#documentation)
12-
- [Unit Tests](#unit-tests)
13-
- [CI Tests](#ci-tests)
14-
- [Performance Tests](#performance-tests)
15-
- [Macro](#macro)
16-
- [Micro](#micro)
17-
- [Commit Message Guidelines](#commit-message-guidelines)
18-
- [Commit Message Format](#commit-message-format)
19-
- [Revert](#revert)
20-
- [Type](#type)
21-
- [Scope](#scope)
22-
- [Subject](#subject)
23-
- [Body](#body)
24-
- [Footer](#footer)
8+
- [Contributing to RxJS](#contributing-to-rxjs)
9+
- [Submitting a Pull Request (PR)](#submitting-a-pull-request-pr)
10+
- [After your pull request is merged](#after-your-pull-request-is-merged)
11+
- [Coding Style Guidelines](#coding-style-guidelines)
12+
- [Documentation](#documentation)
13+
- [Unit Tests](#unit-tests)
14+
- [CI Tests](#ci-tests)
15+
- [Performance Tests](#performance-tests)
16+
- [Macro](#macro)
17+
- [Micro](#micro)
18+
- [Commit Message Guidelines](#commit-message-guidelines)
19+
- [Commit Message Format](#commit-message-format)
20+
- [Revert](#revert)
21+
- [Type](#type)
22+
- [Scope](#scope)
23+
- [Subject](#subject)
24+
- [Body](#body)
25+
- [Footer](#footer)
2526

2627
---
2728

@@ -47,8 +48,6 @@ Before you submit your Pull Request (PR) consider the following guidelines:
4748

4849
- Create your patch, following [code style guidelines](#coding-style-guidelines), and **including appropriate test cases**.
4950
- Run the full test suite and ensure that all tests pass.
50-
- Run the micro and macro performance tests against your feature branch and compare against master
51-
to ensure performance wasn't changed for the worse.
5251
- Commit your changes using a descriptive commit message that follows our
5352
[commit message guidelines](#commit-message-guidelines). Adherence to these conventions
5453
is necessary because release notes are automatically generated from these messages.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# RxJS Core Semantics
2+
3+
Starting in version 8, all RxJS operators that are provided in the core library MUST meet the following semantics. In the current version, version 7, all operators SHOULD meet the following semantics (as guidelines). If they do not, we need to track the issue on [GitHub](https://github.com/ReactiveX/rxjs/issues).
4+
5+
## Purpose
6+
7+
The purpose of these semantics is provide predictable behavior for the users of our library, and to ensure consistent behavior between our many different operators. It should be noted that at the time of this writing, we don't always adhere to these semantic guidelines. This document is to serve as a goalpost for upcoming changes and work as much as it is to help describe the library. This is also a "living document" and is subject to change.
8+
9+
## General Design Guidelines
10+
11+
**Functions such as operators, constructors, and creation functions, should use named parameters in cases where there is more than 1 argument, and arguments after the first are non-obvious.** The primary use case should be streamlined to work without configuration. For example, `fakeFlattenMap(n => of(n))` is fine, but `fakeFlattenMap(n => of(n), 1)` is less readable than `fakeFlattenMap(n => of(n), { maxConcurrent: 1 })`. Other things, like `of(1, 2, 3)` are obvious enough that named parameters don't make sense.
12+
13+
## Operators
14+
15+
- MUST be a function that returns an [operator function](https://rxjs.dev/api/index/interface/OperatorFunction). That is `(source: Observable<In>) => Observable<Out>`.
16+
- The returned operator function MUST be [referentially transparent](https://en.wikipedia.org/wiki/Referential_transparency). That is to say, that if you capture the return value of the operator (e.g. `const double => map(x => x + x)`), you can use that value to operate on any many observables as you like without changing any underlying state in the operator reference. (e.g. `a$.pipe(double)` and `b$.pipe(double)`).
17+
- The observable returned by the operator function MUST subscribe to the source.
18+
- If the operation performed by the operator can tell it not change anything about the output of the source, it MUST return the reference to the source. For example `take(Infinity)` or `skip(0)`.
19+
- Operators that accept a "notifier", that is another observable source that is used to trigger some behavior, must accept any type that can be converted to an `Observable` with `from`. For example `takeUntil`.
20+
- Operators that accept "notifiers" (as described above), MUST ONLY recognized next values from the notifier as "notifications". Emitted completions may not be used a source of notification.
21+
- "Notifiers" provided directly to the operator MUST be subscribed to _before_ the source is subscribed to. "Notifiers" created via factory function provided to the operator SHOULD be subscribed to at the earliest possible moment.
22+
- The observable returned by the operator function is considered to be the "consumer" of the source. As such, the consumer MUST unsubscribe from the source as soon as it knows it no longer needs values before proceeding to do _any_ action.
23+
- Events that happen after the completion of a source SHOULD happen after the source finalizes. This is to ensure that finalization always happens in a predictable time frame relative to the event.
24+
- `Error` objects MUST NOT be retained longer than necessary. This is a possible source of memory pressure.
25+
- `Promise` references MUST NOT be retained longer than necessary. This is a possible source of memory pressure.
26+
- IF they perform a related operation to a creation function, they SHOULD share the creation function's name only with the suffix `With`. (e.g. `concat` and `concatWith`).
27+
- SHOULD NOT have "result selectors". This is a secondary argument that provides the ability to "map" values after performing the primary operation of the operator.
28+
29+
## Creation Functions
30+
31+
- Names MUST NOT end in `With`. That is reserved for the operator counter parts of creation functions.
32+
- MAY have "result selectors". This is a secondary argument that provides the ability to "map" values before they're emitted from the resulting observable.
33+
- IF the creation function accepts a "result selector", it must not accept "n-arguments" ahead of that result selector. Instead, it should accept an array or possibly an object. (bad: `combineThings(sourceA$, sourceB$, (a, b) => a + b)`, good: `combineThings([sourceA$, sourceB$], (a, b) => a + b)`. In this case, it may be okay to provide the result selector as a second argument, rather than as a named parameter, as the use should be fairly obvious.

0 commit comments

Comments
 (0)