Skip to content
This repository was archived by the owner on Apr 20, 2018. It is now read-only.

Commit 4a23957

Browse files
Highlighting Code of Conduct
1 parent efc6d6b commit 4a23957

22 files changed

Lines changed: 559 additions & 382 deletions

code-of-conduct.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Code of Conduct #
2+
3+
[_Adapted from the Rust Code of Conduct_](https://github.com/rust-lang/rust/wiki/Note-development-policy#conduct)
4+
5+
We are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, disability, ethnicity, religion, or similar personal characteristic.
6+
- On any communication medium, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all.
7+
- Please be kind and courteous. There's no need to be mean or rude.
8+
- Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer.
9+
- Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works.
10+
- We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the [Citizen Code of Conduct](http://citizencodeofconduct.org/); if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups.
11+
- Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one the RxJS team immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back.
12+
- Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome.

contributing.md

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# Contributing to RxJS #
2+
3+
Want to contribute to the Reactive Extensions for JavaScript (RxJS)? There are many ways of helping whether contributing code, documentation, examples, podcasts, videos and presentations.
4+
5+
# Get Involved!
6+
7+
In [the issue tracker](https://github.com/Reactive-Extensions/RxJS/issues), bugs can only be assigned to people who have commit access. Also, we aspire to make as many bugs as possible "owned" by assigning them to a core Rx contributor. Therefore, just because a bug is assigned doesn't mean it's being actively worked on. We (the core contributors) are all busy, and welcome help from the community. If you see a bug you'd like to work on that's assigned but appears to be dormant, communicate with the bug's owner with an @-reply in a comment on the issue page. If you see a bug you'd like to work on that's unassigned, it's fair game: comment to say you'd like to work on it so that we know it's getting attention.
8+
9+
# Pull Requests
10+
11+
To make a pull request, you will need a GitHub account; if you're unclear on this process, see GitHub's documentation on [forking](https://help.github.com/articles/fork-a-repo/) and [pull requests](https://help.github.com/articles/using-pull-requests). Pull requests should be targeted at RxJS's master branch. Before pushing to your Github repo and issuing the pull request, please do two things:
12+
13+
1. Rebase your local changes against the master branch. Resolve any conflicts that arise.
14+
2. Run the full RxJS test suite by running `grunt` in the root of the repository.
15+
16+
Pull requests will be treated as "review requests", and we will give feedback we expect to see corrected on style and substance before pulling. Changes contributed via pull request should focus on a single issue at a time, like any other. We will not look kindly on pull-requests that try to "sneak" unrelated changes in. Note for bug fixes, regression tests should be included, denoted by Issue Number so that we have full traceability.
17+
18+
# What Are We Looking For?
19+
20+
For documentation, we are looking for the following:
21+
- API Documentation that is missing or out of date
22+
- "How Do I?" examples
23+
- Comparison to other libraries
24+
- Comparison to Promises
25+
- Introduction material
26+
- Tutorials
27+
28+
For coding, we have strict standards that must be adhere to when working on RxJS. In order for us to accept pull requests, they must abide by the following:
29+
- [Coding Standard](#coding-standard)
30+
- [Tests](#tests)
31+
- [Documentation](#documentation)
32+
33+
## Coding Standard
34+
35+
For RxJS, we follow the [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml) and adhere to it strictly in areas such as documentation using JSDoc. The only exception to extending native prototypes is to polyfill behavior which may not exist in all browsers yet, for example, many of the [Array#extras](http://blogs.msdn.com/b/ie/archive/2010/12/13/ecmascript-5-part-2-array-extras.aspx) are implemented in compatibility builds. We also strictly follow [our design guidelines](https://github.com/Reactive-Extensions/RxJS/tree/master/doc/designguidelines) as well.
36+
37+
### Supporting Multiple Platforms
38+
39+
RxJS runs on a number of platforms and supports many styles of programming. RxJS supports [Universal Module Definition (UMD)](https://github.com/umdjs/umd) which allows the library to work in a number of environments such as [Asynchronous Module Definition (AMD)](https://github.com/amdjs/amdjs-api/wiki/AMD), [CommonJS](http://wiki.commonjs.org/wiki/CommonJS), [Node.js](http://nodejs.org), [RingoJS](http://ringojs.org/), [Narwhal](https://github.com/280north/narwhal), the browser and other environments such as [Windows Script Host (WSH)](http://msdn.microsoft.com/en-us/library/9bbdkx3k.aspx) and embedded devices such as [Tessel](http://tessel.io).
40+
41+
RxJS is committed to using the latest JavaScript standards as they start to arrive, for example, supporting generators, Maps, Sets, and Observable versions of new Array methods. We also are committed to supporting legacy code as well through compatibility builds, even supporting browsers back to IE6, Firefox 3, and older versions of Node.js. Should behavior not exist in those platforms, that behavior must be polyfilled, and made available in `*.compat.js` files only. For example, we have `rx.lite.js` which supports modern browsers greater than or equal to IE9, and `rx.lite.compat.js` for older browsers before IE9 and modern Firefox builds. In special cases such as event handling is different, we must provide a mainstream version of the file as well as a compat file, the latter which is included in the compat file.
42+
43+
### Implementing Custom Operators
44+
45+
We welcome custom operators to RxJS if they make sense in the core RxJS, as opposed to belonging in user land. There are a number of rules that must be adhered to when implementing a custom operator including:
46+
- Prefer composition over implementing a totally new operator from scratch
47+
- If the operator introduces any notion of concurrency, then a scheduler must introduced. Usage of concurrency primitives such as `setTimeout`, `setInterval`, etc are forbidden. This is to ensure easy testability.
48+
- The scheduler must be optional with the appropriate default picked
49+
- `Rx.Scheduler.immediate` for any immediate blocking operations
50+
- `Rx.Scheduler.currentThread` for any immediate blocking operators that require re-entrant behavior such as recursive scheduling.
51+
- `Rx.Scheduler.timeout` for any operator that has a notion of time
52+
53+
To make this concrete, let's implement a custom operator such as an implementation of `_.reject` from [Underscore.js](http://underscorejs.org/) / [Lo-Dash](http://lodash.com/).
54+
55+
```js
56+
/**
57+
* The opposite of _.filter this method returns the elements of a collection that the callback does **not** return truthy for.
58+
* @param {Function} [callback] The function called per iteration.
59+
* @param {Any} [thisArg] The this binding of callback.
60+
* @returns {Observable} An Observable sequence which contains items that the callback does not return truthy for.
61+
*/
62+
Rx.Observable.prototype.reject = function (callback, thisArg) {
63+
callback || (callback = Rx.helpers.identity);
64+
var source = this;
65+
return new Rx.AnonymousObservable(function (observer) {
66+
var i = 0;
67+
return source.subscribe(
68+
function (x) {
69+
var noYield = true;
70+
try {
71+
noYield = callback.call(thisArg, x, i++, source);
72+
} catch (e) {
73+
observer.onError(e);
74+
return;
75+
}
76+
77+
if (!noYield) { observer.onNext(x); }
78+
},
79+
observer.onError.bind(observer),
80+
observer.onCompleted.bind(observer)
81+
);
82+
});
83+
};
84+
```
85+
86+
Of course, we could have implemented this using composition as well, such as using `Rx.Observable.prototype.filter`.
87+
88+
```js
89+
/**
90+
* The opposite of _.filter this method returns the elements of a collection that the callback does **not** return truthy for.
91+
* @param {Function} [callback] The function called per iteration.
92+
* @param {Any} [thisArg] The this binding of callback.
93+
* @returns {Observable} An Observable sequence which contains items that the callback does not return truthy for.
94+
*/
95+
Rx.Observable.prototype.reject = function (callback, thisArg) {
96+
callback || (callback = Rx.helpers.identity);
97+
return this.filter(function (x, i, o) { return !callback.call(thisArg, x, i o); });
98+
};
99+
```
100+
101+
To show an operator that introduces a level of concurrency, let's implement a custom operator such as an implementation of `_.pairs` from [Underscore.js](http://underscorejs.org/) / [Lo-Dash](http://lodash.com/). Note that since this requires recursion to implement properly, we'll use the `Rx.Scheduler.currentThread` scheduler.
102+
103+
```js
104+
var keysFunction = Object.keys || someKeysPolyfill;
105+
106+
/**
107+
* Creates an Observable with an of an object’s key-value pairs.
108+
* @param {Object} obj The object to inspect.
109+
* @returns {Observable} An Observable with an of an object’s key-value pairs.
110+
*/
111+
Rx.Observable.pairs = function (obj, scheduler) {
112+
scheduler || (scheduler = Rx.Scheduler.currentThread);
113+
return new Rx.AnonymousObservable(function (observer) {
114+
var keys = keysFunction(object),
115+
i = 0,
116+
len = keys.length;
117+
return scheduler.scheduleRecursive(function (self) {
118+
if (i < len) {
119+
var key = keys[i++], value = obj[key];
120+
observer.onNext([key, value]);
121+
self();
122+
} else {
123+
observer.onCompleted();
124+
}
125+
});
126+
});
127+
};
128+
```
129+
130+
Note that all operators must have the documentation and must be split out into its own file. This allows us to be able to put it in different files, or make it available in custom builds.
131+
132+
## Tests
133+
134+
When a new operator is written for RxJS, in order to accepted, must be accompanied by tests. RxJS currently uses [QUnit](http://qunitjs.com/) as a straight forward way to test our code. These tests are automatically executed by our [Grunt](http://gruntjs.com/) setup to concatenate files, minimize, create source maps, and finally run all the tests in the [tests folder](https://github.com/Reactive-Extensions/RxJS/tree/master/tests). Each file that we produce, for example, `rx.js` has an accompanying test file such as `rx.html`, which includes tests for all operators included in that file.
135+
136+
Each operator under test must be in its own file to cover the following cases:
137+
- Never
138+
- Empty
139+
- Single/Multiple Values
140+
- Error in the sequence
141+
- Never ending sequences
142+
- Early disposal in sequences
143+
144+
If the operator has a callback, then it must cover the following cases:
145+
- Success with all values in the callback
146+
- Success with the context, if any allowed in the operator signature
147+
- If an error is thrown
148+
149+
To get a good feeling on what kind of rigor is required for testing, check out the following examples:
150+
- [`concatMap`](https://github.com/Reactive-Extensions/RxJS/blob/master/tests/observable/concatmap.js)
151+
- [`from`](https://github.com/Reactive-Extensions/RxJS/blob/master/tests/observable/from.js)
152+
153+
## Documentation
154+
155+
Documentation is also a must, as all external operators and types must be documented and put in the [API Folder](https://github.com/Reactive-Extensions/RxJS/tree/master/doc/api). Each operator on an Observable must have its own file in the [Operators Folder](https://github.com/Reactive-Extensions/RxJS/tree/master/doc/api/core/operators).
156+
157+
For operators, they must be linked from the [`Observable`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md) API document. In addition, each operator must be listed in which file it belongs in the [Libraries Folder](https://github.com/Reactive-Extensions/RxJS/tree/master/doc/libraries).
158+
159+
The standard format of operators must be such as the [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md) operator which includes:
160+
- File Location
161+
- Method signature
162+
- Method description
163+
- List of Arguments
164+
- Return type (if there is one)
165+
- An example
166+
- File Distribution(s)
167+
- NuGet Distribution
168+
- NPM Distribution
169+
- Unit Tests

dist/rx.all.compat.js

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6343,77 +6343,76 @@ var spawn = Observable.spawn = function () {
63436343
});
63446344
}
63456345

6346-
function toObservable(obj) {
6347-
if (!obj) { return obj; }
6348-
if (Observable.isObservable(obj)) { return obj; }
6349-
if (isPromise(obj)) { return Observable.fromPromise(obj); }
6350-
if (isGeneratorFunction(obj) || isGenerator(obj)) { return spawn.call(this, obj); }
6351-
if (isFunction(obj)) { return thunkToObservable.call(this, obj); }
6352-
if (isArrayLike(obj) || isIterable(obj)) { return arrayToObservable.call(this, obj); }
6353-
if (isObject(obj)) return objectToObservable.call(this, obj);
6354-
return obj;
6355-
}
6346+
function toObservable(obj) {
6347+
if (!obj) { return obj; }
6348+
if (Observable.isObservable(obj)) { return obj; }
6349+
if (isPromise(obj)) { return Observable.fromPromise(obj); }
6350+
if (isGeneratorFunction(obj) || isGenerator(obj)) { return spawn.call(this, obj); }
6351+
if (isFunction(obj)) { return thunkToObservable.call(this, obj); }
6352+
if (isArrayLike(obj) || isIterable(obj)) { return arrayToObservable.call(this, obj); }
6353+
if (isObject(obj)) {return objectToObservable.call(this, obj);}
6354+
return obj;
6355+
}
63566356

6357-
function arrayToObservable (obj) {
6358-
return Observable.from(obj)
6357+
function arrayToObservable (obj) {
6358+
return Observable.from(obj)
63596359
.flatMap(toObservable)
63606360
.toArray();
6361-
}
6361+
}
63626362

6363-
function objectToObservable (obj) {
6364-
var results = new obj.constructor(), keys = Object.keys(obj), observables = [];
6365-
for (var i = 0, len = keys.length; i < len; i++) {
6366-
var key = keys[i], observable = toObservable.call(this, obj[key]);
6367-
if (observable && Observable.isObservable(observable)) {
6368-
defer(observable, key);
6369-
} else {
6370-
results[key] = obj[key];
6371-
}
6372-
}
6373-
return Observable.concat(observables).startWith(results);
6363+
function objectToObservable (obj) {
6364+
var results = new obj.constructor(), keys = Object.keys(obj), observables = [];
6365+
for (var i = 0, len = keys.length; i < len; i++) {
6366+
var key = keys[i];
6367+
var observable = toObservable.call(this, obj[key]);
63746368

6375-
function defer (observable, key) {
6376-
results[key] = undefined;
6377-
observables.push(new AnonymousObservable(function (o) {
6378-
return observable.subscribe(function (next) {
6379-
results[key] = next;
6380-
o.onCompleted();
6381-
});
6382-
}));
6369+
if(observable && Observable.isObservable(observable)) {
6370+
defer(observable, key);
6371+
} else {
6372+
results[key] = obj[key];
63836373
}
63846374
}
63856375

6386-
function thunkToObservable(fn) {
6387-
var self = this;
6388-
return new AnonymousObservable(function (o) {
6389-
fn.call(self, function () {
6390-
var err = arguments[0], res = arguments[1];
6391-
if (err) { return o.onError(err); }
6392-
if (arguments.length > 2) {
6393-
var args = [];
6394-
for (var i = 1, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
6395-
res = args;
6396-
}
6397-
o.onNext(res);
6398-
o.onCompleted();
6399-
});
6400-
});
6401-
}
6376+
return Observable.forkJoin.apply(Observable, observables).map(function() {
6377+
return results;
6378+
});
64026379

6403-
function isGenerator(obj) {
6404-
return isFunction (obj.next) && isFunction (obj.throw);
6405-
}
64066380

6407-
function isGeneratorFunction(obj) {
6408-
var ctor = obj.constructor;
6409-
if (!ctor) { return false; }
6410-
if (ctor.name === 'GeneratorFunction' || ctor.displayName === 'GeneratorFunction') { return true; }
6411-
return isGenerator(ctor.prototype);
6381+
function defer (observable, key) {
6382+
results[key] = undefined;
6383+
observables.push(observable.map(function (next) {
6384+
results[key] = next;
6385+
}));
64126386
}
6387+
}
64136388

6414-
function isObject(val) {
6415-
return Object == val.constructor;
6416-
}
6389+
function thunkToObservable(fn) {
6390+
var self = this;
6391+
return new AnonymousObservable(function (o) {
6392+
fn.call(self, function () {
6393+
var err = arguments[0], res = arguments[1];
6394+
if (err) { return o.onError(err); }
6395+
if (arguments.length > 2) {
6396+
var args = [];
6397+
for (var i = 1, len = arguments.length; i < len; i++) { args.push(arguments[i]); }
6398+
res = args;
6399+
}
6400+
o.onNext(res);
6401+
o.onCompleted();
6402+
});
6403+
});
6404+
}
6405+
6406+
function isGenerator(obj) {
6407+
return isFunction (obj.next) && isFunction (obj.throw);
6408+
}
6409+
6410+
function isGeneratorFunction(obj) {
6411+
var ctor = obj.constructor;
6412+
if (!ctor) { return false; }
6413+
if (ctor.name === 'GeneratorFunction' || ctor.displayName === 'GeneratorFunction') { return true; }
6414+
return isGenerator(ctor.prototype);
6415+
}
64176416

64186417
/**
64196418
* Invokes the specified function asynchronously on the specified scheduler, surfacing the result through an observable sequence.

dist/rx.all.compat.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/rx.all.compat.min.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)