Skip to content

Commit

Permalink
update Observable by actual version of the spec, fixes #257, #276
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Dec 8, 2017
1 parent 347223e commit f2ac3fb
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 132 deletions.
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,6 @@ module.exports = {
'library/**',
'modules/**',
'stage/**',
'tests/observables/**',
'tests/promises-aplus/**',
'web/**',
],
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: node_js
node_js:
- "5.7"
- "9.2"

sudo: false
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- `Reflect.enumerate` (removed from the spec)
- Unnecessary iteration methods from `CSSRuleList`, `MediaList`, `StyleSheetList`
- Updated proposals:
- [`Observable`](https://github.com/tc39/proposal-observable) ([#257](https://github.com/zloirock/core-js/issues/257), [#276](https://github.com/zloirock/core-js/issues/276), etc.)
- `Array#flatten` and `Array#flatMap` updated and moved to the stage 3
- `Symbol.asyncIterator` moved to the stage 3
- ES2016 and ES2017 features marked as stable:
Expand Down
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1520,12 +1520,11 @@ for (let [_, d, D] of '1111a2b3cccc'.matchAll(/(\d)(\D)/)) {
* `Observable` [proposal](https://github.com/zenparsing/es-observable) - modules [`esnext.observable`](https://github.com/zloirock/core-js/blob/v3/modules/esnext.observable.js) and [`esnext.symbol.observable`](https://github.com/zloirock/core-js/blob/v3/modules/esnext.symbol.observable.js)
```js
class Observable {
constructor(fn: Function): Observable
subscribe(observer: Observer): Subscription;
forEach(fn: Function): Promise;
constructor(subscriber: Function): Observable;
subscribe(observer: Function | { next?: Function, error?: Function, complete?: Function }): Subscription;
@@observable(): this;
static of(...items: Aray<mixed>): Observable
static from(x: Observable | Iterable): Observable
static of(...items: Aray<mixed>): Observable;
static from(x: Observable | Iterable): Observable;
static get @@species: this;
}

Expand All @@ -1544,8 +1543,10 @@ new Observable(observer => {
observer.next('hello');
observer.next('world');
observer.complete();
}).forEach(it => console.log(it))
.then(() => console.log('!'));
}).subscribe({
next(it) { console.log(it); },
complete() { console.log('!'); }
});
```
* `Math.{clamp, DEG_PER_RAD, degrees, fscale, rad-per-deg, radians, scale}`
[proposal](https://github.com/rwaldron/proposal-math-extensions) - modules
Expand Down
7 changes: 7 additions & 0 deletions modules/_host-report-errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var global = require('./_global');
module.exports = function (a, b) {
var console = global.console;
if (console && console.error) {
arguments.length === 1 ? console.error(a) : console.error(a, b);
}
};
7 changes: 3 additions & 4 deletions modules/es.promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var microtask = require('./_microtask')();
var newPromiseCapabilityModule = require('./_new-promise-capability');
var perform = require('./_perform');
var promiseResolve = require('./_promise-resolve');
var hostReportErrors = require('./_host-report-errors');
var PROMISE = 'Promise';
var TypeError = global.TypeError;
var process = global.process;
Expand Down Expand Up @@ -86,16 +87,14 @@ var onUnhandled = function (promise) {
task.call(global, function () {
var value = promise._v;
var unhandled = isUnhandled(promise);
var result, handler, console;
var result, handler;
if (unhandled) {
result = perform(function () {
if (isNode) {
process.emit('unhandledRejection', value, promise);
} else if (handler = global.onunhandledrejection) {
handler({ promise: promise, reason: value });
} else if ((console = global.console) && console.error) {
console.error('Unhandled promise rejection', value);
}
} else hostReportErrors('Unhandled promise rejection', value);
});
// Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
promise._h = isNode || isUnhandled(promise) ? 2 : 1;
Expand Down
171 changes: 81 additions & 90 deletions modules/esnext.observable.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
'use strict';
// https://github.com/zenparsing/es-observable
var $export = require('./_export');
var global = require('./_global');
var core = require('./_core');
var microtask = require('./_microtask')();
var OBSERVABLE = require('./_wks')('observable');
var aFunction = require('./_a-function');
var anObject = require('./_an-object');
var isObject = require('./_is-object');
var anInstance = require('./_an-instance');
var redefineAll = require('./_redefine-all');
var hide = require('./_hide');
var getIterator = require('./core.get-iterator');
var forOf = require('./_for-of');
var hostReportErrors = require('./_host-report-errors');
var dP = require('./_object-dp').f;
var DESCRIPTORS = require('./_descriptors');
var OBSERVABLE = require('./_wks')('observable');
var RETURN = forOf.RETURN;

var getMethod = function (fn) {
Expand All @@ -21,7 +23,11 @@ var cleanupSubscription = function (subscription) {
var cleanup = subscription._c;
if (cleanup) {
subscription._c = undefined;
cleanup();
try {
cleanup();
} catch (e) {
hostReportErrors(e);
}
}
};

Expand All @@ -31,26 +37,39 @@ var subscriptionClosed = function (subscription) {

var closeSubscription = function (subscription) {
if (!subscriptionClosed(subscription)) {
subscription._o = undefined;
close(subscription);
cleanupSubscription(subscription);
}
};

var close = function (subscription) {
if (!DESCRIPTORS) {
subscription.closed = true;
var subscriptionObserver = subscription._s;
if (subscriptionObserver) subscriptionObserver.closed = true;
} subscription._o = undefined;
};

var Subscription = function (observer, subscriber) {
anObject(observer);
var start;
if (!DESCRIPTORS) this.closed = false;
this._c = undefined;
this._o = observer;
observer = new SubscriptionObserver(this);
this._o = anObject(observer);
try {
var cleanup = subscriber(observer);
if (start = getMethod(observer.start)) start.call(observer, this);
} catch (e) {
hostReportErrors(e);
}
if (subscriptionClosed(this)) return;
var subscriptionObserver = this._s = new SubscriptionObserver(this);
try {
var cleanup = subscriber(subscriptionObserver);
var subscription = cleanup;
if (cleanup != null) {
if (typeof cleanup.unsubscribe === 'function') cleanup = function () { subscription.unsubscribe(); };
else aFunction(cleanup);
this._c = cleanup;
}
if (cleanup != null) this._c = typeof cleanup.unsubscribe === 'function'
? function () { subscription.unsubscribe(); }
: aFunction(cleanup);
} catch (e) {
observer.error(e);
subscriptionObserver.error(e);
return;
} if (subscriptionClosed(this)) cleanupSubscription(this);
};
Expand All @@ -59,8 +78,16 @@ Subscription.prototype = redefineAll({}, {
unsubscribe: function unsubscribe() { closeSubscription(this); }
});

if (DESCRIPTORS) dP(Subscription.prototype, 'closed', {
configurable: true,
get: function () {
return subscriptionClosed(this);
}
});

var SubscriptionObserver = function (subscription) {
this._s = subscription;
if (!DESCRIPTORS) this.closed = false;
};

SubscriptionObserver.prototype = redefineAll({}, {
Expand All @@ -70,79 +97,59 @@ SubscriptionObserver.prototype = redefineAll({}, {
var observer = subscription._o;
try {
var m = getMethod(observer.next);
if (m) return m.call(observer, value);
if (m) m.call(observer, value);
} catch (e) {
try {
closeSubscription(subscription);
} finally {
throw e;
}
hostReportErrors(e);
}
}
},
error: function error(value) {
var subscription = this._s;
if (subscriptionClosed(subscription)) throw value;
var observer = subscription._o;
subscription._o = undefined;
try {
var m = getMethod(observer.error);
if (!m) throw value;
value = m.call(observer, value);
} catch (e) {
if (!subscriptionClosed(subscription)) {
var observer = subscription._o;
close(subscription);
try {
cleanupSubscription(subscription);
} finally {
throw e;
}
} cleanupSubscription(subscription);
return value;
var m = getMethod(observer.error);
if (m) m.call(observer, value);
else hostReportErrors(value);
} catch (e) {
hostReportErrors(e);
} cleanupSubscription(subscription);
}
},
complete: function complete(value) {
complete: function complete() {
var subscription = this._s;
if (!subscriptionClosed(subscription)) {
var observer = subscription._o;
subscription._o = undefined;
close(subscription);
try {
var m = getMethod(observer.complete);
value = m ? m.call(observer, value) : undefined;
if (m) m.call(observer);
} catch (e) {
try {
cleanupSubscription(subscription);
} finally {
throw e;
}
hostReportErrors(e);
} cleanupSubscription(subscription);
return value;
}
}
});

if (DESCRIPTORS) dP(SubscriptionObserver.prototype, 'closed', {
configurable: true,
get: function () {
return subscriptionClosed(this._s);
}
});

var $Observable = function Observable(subscriber) {
anInstance(this, $Observable, 'Observable', '_f')._f = aFunction(subscriber);
};

redefineAll($Observable.prototype, {
subscribe: function subscribe(observer) {
return new Subscription(observer, this._f);
},
forEach: function forEach(fn) {
var that = this;
return new (core.Promise || global.Promise)(function (resolve, reject) {
aFunction(fn);
var subscription = that.subscribe({
next: function (value) {
try {
return fn(value);
} catch (e) {
reject(e);
subscription.unsubscribe();
}
},
error: reject,
complete: resolve
});
});
return new Subscription(typeof observer === 'function' ? {
next: observer,
error: arguments.length > 1 ? arguments[1] : undefined,
complete: arguments.length > 2 ? arguments[2] : undefined
} : isObject(observer) ? observer : {}, this._f);
}
});

Expand All @@ -156,38 +163,22 @@ redefineAll($Observable, {
return observable.subscribe(observer);
});
}
var iterator = getIterator(x);
return new C(function (observer) {
var done = false;
microtask(function () {
if (!done) {
try {
if (forOf(x, false, function (it) {
observer.next(it);
if (done) return RETURN;
}) === RETURN) return;
} catch (e) {
if (done) throw e;
observer.error(e);
return;
} observer.complete();
}
});
return function () { done = true; };
forOf(iterator, false, function (it) {
observer.next(it);
if (observer.closed) return RETURN;
}, undefined, true);
observer.complete();
});
},
of: function of() {
for (var i = 0, l = arguments.length, items = new Array(l); i < l;) items[i] = arguments[i++];
return new (typeof this === 'function' ? this : $Observable)(function (observer) {
var done = false;
microtask(function () {
if (!done) {
for (var j = 0; j < items.length; ++j) {
observer.next(items[j]);
if (done) return;
} observer.complete();
}
});
return function () { done = true; };
for (var j = 0; j < items.length; ++j) {
observer.next(items[j]);
if (observer.closed) return;
} observer.complete();
});
}
});
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"main": "index.js",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-check-es2015-constants": "^6.22.0",
Expand All @@ -27,7 +28,7 @@
"babel-plugin-transform-es3-property-literals": "^6.22.0",
"babel-plugin-transform-exponentiation-operator": "^6.24.1",
"babel-plugin-transform-for-of-as-array": "^1.0.4",
"es-observable-tests": "0.2.x",
"es-observable": "git+https://github.com/tc39/proposal-observable.git#bf4d87144b6189e793593868e3c022eb51a7d292",
"eslint": "4.12.x",
"eslint-plugin-import": "2.8.x",
"grunt": "^1.0.1",
Expand All @@ -42,6 +43,7 @@
"karma-qunit": "1.2.x",
"karma-phantomjs-launcher": "1.0.x",
"mkdirp": "^0.5.1",
"moon-unit": "^0.2.2",
"phantomjs-prebuilt": "2.1.x",
"promises-aplus-tests": "^2.1.2",
"qunitjs": "2.4.x",
Expand All @@ -53,7 +55,7 @@
"lint": "eslint ./",
"promises-tests": "promises-aplus-tests tests/promises-aplus/adapter",
"bundle-promises-tests": "npm run grunt webpack:promises-aplus-tests",
"observables-tests": "node tests/observables/adapter && node tests/observables/adapter-library",
"observables-tests": "babel node_modules/es-observable/test/ -d tests/bundles/observables-tests/ --plugins=transform-es2015-modules-commonjs && node tests/observables/adapter && node tests/observables/adapter-library",
"test": "npm run grunt clean copy && npm run lint && npm run grunt webpack:helpers webpack:tests client karma:default && npm run grunt webpack:library library karma:library && npm run promises-tests && npm run observables-tests && node tests/commonjs"
},
"license": "MIT",
Expand Down

0 comments on commit f2ac3fb

Please sign in to comment.