effection
Advanced tools
Comparing version 0.3.3-00a19e9 to 0.3.3-4f53cf6
@@ -35,3 +35,3 @@ 'use strict'; | ||
promise.then(value => succeed(value)).catch(error => fail(error)); // this execution has passed out of scope, so we don't care | ||
promise.then(value => succeed(value), error => fail(error)); // this execution has passed out of scope, so we don't care | ||
// what happened to the promise, so make the callbacks noops. | ||
@@ -76,75 +76,17 @@ // this effectively "unsubscribes" to the promise. | ||
/** | ||
* Function composition that implements the `Promise` API; | ||
* | ||
* // f(g(x)) | ||
* Contiunation.of(g).then(f); | ||
*/ | ||
class Continuation { | ||
static of(fn) { | ||
return new Continuation(fn); | ||
} | ||
static resolve(value) { | ||
return Continuation.of(() => value); | ||
} | ||
static reject(error) { | ||
return Continuation.of(() => { | ||
throw error; | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
static empty() { | ||
return Continuation.of(x => x); | ||
} | ||
constructor(call) { | ||
this.call = call; | ||
} | ||
then(fn) { | ||
return flatMap(this, call => Continuation.of(x => { | ||
let next = fn(call(x)); | ||
if (next instanceof Continuation) { | ||
return next.call(x); | ||
} else { | ||
return next; | ||
} | ||
})); | ||
} | ||
catch(fn) { | ||
return flatMap(this, call => Continuation.of(x => { | ||
try { | ||
return call(x); | ||
} catch (e) { | ||
return fn(e); | ||
} | ||
})); | ||
} | ||
finally(fn) { | ||
return flatMap(this, call => Continuation.of(x => { | ||
try { | ||
return call(x); | ||
} finally { | ||
fn(x); | ||
} | ||
})); | ||
} | ||
return obj; | ||
} | ||
function flatMap(continuation, sequence) { | ||
let next = sequence(continuation.call); | ||
if (!(next instanceof Continuation)) { | ||
throw new Error(`chaining function must return a Continuation, not '${next}`); | ||
} | ||
return next; | ||
} | ||
class Fork { | ||
@@ -211,2 +153,3 @@ get isUnstarted() { | ||
constructor(operation, parent, sync) { | ||
this.id = Fork.ids++; | ||
this.operation = toGeneratorFunction(operation); | ||
@@ -218,26 +161,23 @@ this.parent = parent; | ||
this.exitPrevious = noop; | ||
this.continuation = Continuation.of(frame => { | ||
if (frame.isErrored) { | ||
let error = frame.result; | ||
error.frame = frame; | ||
throw error; | ||
} else { | ||
return frame; | ||
} | ||
} | ||
get promise() { | ||
this._promise = new Promise((resolve, reject) => { | ||
this.resolve = resolve; | ||
this.reject = reject; | ||
}); | ||
this.finalizePromise(); | ||
return this._promise; | ||
} | ||
then(fn) { | ||
this.continuation = this.continuation.then(fn); | ||
return this; | ||
then(...args) { | ||
return this.promise.then(...args); | ||
} | ||
catch(fn) { | ||
this.continuation = this.continuation.catch(fn); | ||
return this; | ||
catch(...args) { | ||
return this.promise.catch(...args); | ||
} | ||
finally(fn) { | ||
this.continuation = this.continuation.finally(fn); | ||
return this; | ||
finally(...args) { | ||
return this.promise.finally(...args); | ||
} | ||
@@ -295,3 +235,2 @@ | ||
fork(operation, sync = false) { | ||
// console.log(`parent.fork(${operation}, ${sync})`); | ||
let child = new Fork(operation, this, sync); | ||
@@ -350,5 +289,16 @@ this.children.add(child); | ||
thunk(fn) { | ||
let next; | ||
let previouslyExecuting = Fork.currentlyExecuting; | ||
try { | ||
let next = this.enter(fn); | ||
Fork.currentlyExecuting = this; | ||
this.exitPrevious(); | ||
try { | ||
next = fn(this.iterator); | ||
} catch (error) { | ||
this.finalize('errored', error); | ||
return; | ||
} | ||
if (next.done) { | ||
@@ -366,14 +316,2 @@ if (this.hasBlockingChildren) { | ||
} | ||
} catch (error) { | ||
this.finalize('errored', error); | ||
} | ||
} | ||
enter(fn) { | ||
let previouslyExecuting = Fork.currentlyExecuting; | ||
try { | ||
Fork.currentlyExecuting = this; | ||
this.exitPrevious(); | ||
return fn(this.iterator); | ||
} finally { | ||
@@ -394,4 +332,22 @@ Fork.currentlyExecuting = previouslyExecuting; | ||
this.parent.join(this); | ||
} | ||
this.finalizePromise(); | ||
} | ||
finalizePromise() { | ||
if (this.isCompleted && this.resolve) { | ||
this.resolve(this.result); | ||
} else if (this.isErrored && this.reject) { | ||
this.reject(this.result); | ||
} else if (this.isHalted && this.reject) { | ||
this.reject(new HaltError(this.result)); | ||
} | ||
} | ||
get root() { | ||
if (this.parent) { | ||
return this.parent.root; | ||
} else { | ||
this.continuation.call(this); | ||
return this; | ||
} | ||
@@ -402,2 +358,4 @@ } | ||
_defineProperty(Fork, "ids", 0); | ||
function fork(operation, parent = Fork.currentlyExecuting) { | ||
@@ -411,2 +369,10 @@ if (parent) { | ||
class HaltError extends Error { | ||
constructor(cause) { | ||
super("halt"); | ||
this.cause = cause; | ||
} | ||
} | ||
function controllerFor(value) { | ||
@@ -419,3 +385,3 @@ if (isGeneratorFunction(value) || isGenerator(value)) { | ||
return x => x; | ||
} else if (typeof value.then === 'function' && typeof value.catch === 'function') { | ||
} else if (typeof value.then === 'function') { | ||
return promiseOf(value); | ||
@@ -422,0 +388,0 @@ } else { |
@@ -0,5 +1,6 @@ | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
import { noop } from "./noop.js"; | ||
import { promiseOf } from "./promise-of.js"; | ||
import { isGenerator, isGeneratorFunction, toGeneratorFunction } from "./generator-function.js"; | ||
import Continuation from "./continuation.js"; | ||
@@ -46,2 +47,3 @@ class Fork { | ||
constructor(operation, parent, sync) { | ||
this.id = Fork.ids++; | ||
this.operation = toGeneratorFunction(operation); | ||
@@ -53,26 +55,23 @@ this.parent = parent; | ||
this.exitPrevious = noop; | ||
this.continuation = Continuation.of(frame => { | ||
if (frame.isErrored) { | ||
let error = frame.result; | ||
error.frame = frame; | ||
throw error; | ||
} else { | ||
return frame; | ||
} | ||
} | ||
get promise() { | ||
this._promise = new Promise((resolve, reject) => { | ||
this.resolve = resolve; | ||
this.reject = reject; | ||
}); | ||
this.finalizePromise(); | ||
return this._promise; | ||
} | ||
then(fn) { | ||
this.continuation = this.continuation.then(fn); | ||
return this; | ||
then(...args) { | ||
return this.promise.then(...args); | ||
} | ||
catch(fn) { | ||
this.continuation = this.continuation.catch(fn); | ||
return this; | ||
catch(...args) { | ||
return this.promise.catch(...args); | ||
} | ||
finally(fn) { | ||
this.continuation = this.continuation.finally(fn); | ||
return this; | ||
finally(...args) { | ||
return this.promise.finally(...args); | ||
} | ||
@@ -130,3 +129,2 @@ | ||
fork(operation, sync = false) { | ||
// console.log(`parent.fork(${operation}, ${sync})`); | ||
let child = new Fork(operation, this, sync); | ||
@@ -185,5 +183,16 @@ this.children.add(child); | ||
thunk(fn) { | ||
let next; | ||
let previouslyExecuting = Fork.currentlyExecuting; | ||
try { | ||
let next = this.enter(fn); | ||
Fork.currentlyExecuting = this; | ||
this.exitPrevious(); | ||
try { | ||
next = fn(this.iterator); | ||
} catch (error) { | ||
this.finalize('errored', error); | ||
return; | ||
} | ||
if (next.done) { | ||
@@ -201,14 +210,2 @@ if (this.hasBlockingChildren) { | ||
} | ||
} catch (error) { | ||
this.finalize('errored', error); | ||
} | ||
} | ||
enter(fn) { | ||
let previouslyExecuting = Fork.currentlyExecuting; | ||
try { | ||
Fork.currentlyExecuting = this; | ||
this.exitPrevious(); | ||
return fn(this.iterator); | ||
} finally { | ||
@@ -229,4 +226,22 @@ Fork.currentlyExecuting = previouslyExecuting; | ||
this.parent.join(this); | ||
} | ||
this.finalizePromise(); | ||
} | ||
finalizePromise() { | ||
if (this.isCompleted && this.resolve) { | ||
this.resolve(this.result); | ||
} else if (this.isErrored && this.reject) { | ||
this.reject(this.result); | ||
} else if (this.isHalted && this.reject) { | ||
this.reject(new HaltError(this.result)); | ||
} | ||
} | ||
get root() { | ||
if (this.parent) { | ||
return this.parent.root; | ||
} else { | ||
this.continuation.call(this); | ||
return this; | ||
} | ||
@@ -237,2 +252,4 @@ } | ||
_defineProperty(Fork, "ids", 0); | ||
export function fork(operation, parent = Fork.currentlyExecuting) { | ||
@@ -246,2 +263,10 @@ if (parent) { | ||
class HaltError extends Error { | ||
constructor(cause) { | ||
super("halt"); | ||
this.cause = cause; | ||
} | ||
} | ||
function controllerFor(value) { | ||
@@ -254,3 +279,3 @@ if (isGeneratorFunction(value) || isGenerator(value)) { | ||
return x => x; | ||
} else if (typeof value.then === 'function' && typeof value.catch === 'function') { | ||
} else if (typeof value.then === 'function') { | ||
return promiseOf(value); | ||
@@ -257,0 +282,0 @@ } else { |
@@ -13,3 +13,3 @@ /** | ||
promise.then(value => succeed(value)).catch(error => fail(error)); // this execution has passed out of scope, so we don't care | ||
promise.then(value => succeed(value), error => fail(error)); // this execution has passed out of scope, so we don't care | ||
// what happened to the promise, so make the callbacks noops. | ||
@@ -16,0 +16,0 @@ // this effectively "unsubscribes" to the promise. |
@@ -32,3 +32,3 @@ /** | ||
promise.then(value => succeed(value)).catch(error => fail(error)); // this execution has passed out of scope, so we don't care | ||
promise.then(value => succeed(value), error => fail(error)); // this execution has passed out of scope, so we don't care | ||
// what happened to the promise, so make the callbacks noops. | ||
@@ -77,75 +77,17 @@ // this effectively "unsubscribes" to the promise. | ||
/** | ||
* Function composition that implements the `Promise` API; | ||
* | ||
* // f(g(x)) | ||
* Contiunation.of(g).then(f); | ||
*/ | ||
class Continuation { | ||
static of(fn) { | ||
return new Continuation(fn); | ||
} | ||
static resolve(value) { | ||
return Continuation.of(() => value); | ||
} | ||
static reject(error) { | ||
return Continuation.of(() => { | ||
throw error; | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
static empty() { | ||
return Continuation.of(x => x); | ||
} | ||
constructor(call) { | ||
this.call = call; | ||
} | ||
then(fn) { | ||
return flatMap(this, call => Continuation.of(x => { | ||
let next = fn(call(x)); | ||
if (next instanceof Continuation) { | ||
return next.call(x); | ||
} else { | ||
return next; | ||
} | ||
})); | ||
} | ||
catch(fn) { | ||
return flatMap(this, call => Continuation.of(x => { | ||
try { | ||
return call(x); | ||
} catch (e) { | ||
return fn(e); | ||
} | ||
})); | ||
} | ||
finally(fn) { | ||
return flatMap(this, call => Continuation.of(x => { | ||
try { | ||
return call(x); | ||
} finally { | ||
fn(x); | ||
} | ||
})); | ||
} | ||
return obj; | ||
} | ||
function flatMap(continuation, sequence) { | ||
let next = sequence(continuation.call); | ||
if (!(next instanceof Continuation)) { | ||
throw new Error("chaining function must return a Continuation, not '".concat(next)); | ||
} | ||
return next; | ||
} | ||
class Fork { | ||
@@ -191,2 +133,3 @@ get isUnstarted() { | ||
constructor(operation, parent, sync) { | ||
this.id = Fork.ids++; | ||
this.operation = toGeneratorFunction(operation); | ||
@@ -198,26 +141,23 @@ this.parent = parent; | ||
this.exitPrevious = noop; | ||
this.continuation = Continuation.of(frame => { | ||
if (frame.isErrored) { | ||
let error = frame.result; | ||
error.frame = frame; | ||
throw error; | ||
} else { | ||
return frame; | ||
} | ||
} | ||
get promise() { | ||
this._promise = new Promise((resolve, reject) => { | ||
this.resolve = resolve; | ||
this.reject = reject; | ||
}); | ||
this.finalizePromise(); | ||
return this._promise; | ||
} | ||
then(fn) { | ||
this.continuation = this.continuation.then(fn); | ||
return this; | ||
then() { | ||
return this.promise.then(...arguments); | ||
} | ||
catch(fn) { | ||
this.continuation = this.continuation.catch(fn); | ||
return this; | ||
catch() { | ||
return this.promise.catch(...arguments); | ||
} | ||
finally(fn) { | ||
this.continuation = this.continuation.finally(fn); | ||
return this; | ||
finally() { | ||
return this.promise.finally(...arguments); | ||
} | ||
@@ -262,3 +202,2 @@ | ||
let sync = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
// console.log(`parent.fork(${operation}, ${sync})`); | ||
let child = new Fork(operation, this, sync); | ||
@@ -303,5 +242,16 @@ this.children.add(child); | ||
thunk(fn) { | ||
let next; | ||
let previouslyExecuting = Fork.currentlyExecuting; | ||
try { | ||
let next = this.enter(fn); | ||
Fork.currentlyExecuting = this; | ||
this.exitPrevious(); | ||
try { | ||
next = fn(this.iterator); | ||
} catch (error) { | ||
this.finalize('errored', error); | ||
return; | ||
} | ||
if (next.done) { | ||
@@ -319,14 +269,2 @@ if (this.hasBlockingChildren) { | ||
} | ||
} catch (error) { | ||
this.finalize('errored', error); | ||
} | ||
} | ||
enter(fn) { | ||
let previouslyExecuting = Fork.currentlyExecuting; | ||
try { | ||
Fork.currentlyExecuting = this; | ||
this.exitPrevious(); | ||
return fn(this.iterator); | ||
} finally { | ||
@@ -347,4 +285,22 @@ Fork.currentlyExecuting = previouslyExecuting; | ||
this.parent.join(this); | ||
} | ||
this.finalizePromise(); | ||
} | ||
finalizePromise() { | ||
if (this.isCompleted && this.resolve) { | ||
this.resolve(this.result); | ||
} else if (this.isErrored && this.reject) { | ||
this.reject(this.result); | ||
} else if (this.isHalted && this.reject) { | ||
this.reject(new HaltError(this.result)); | ||
} | ||
} | ||
get root() { | ||
if (this.parent) { | ||
return this.parent.root; | ||
} else { | ||
this.continuation.call(this); | ||
return this; | ||
} | ||
@@ -355,2 +311,4 @@ } | ||
_defineProperty(Fork, "ids", 0); | ||
function fork(operation) { | ||
@@ -366,2 +324,10 @@ let parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Fork.currentlyExecuting; | ||
class HaltError extends Error { | ||
constructor(cause) { | ||
super("halt"); | ||
this.cause = cause; | ||
} | ||
} | ||
function controllerFor(value) { | ||
@@ -374,3 +340,3 @@ if (isGeneratorFunction(value) || isGenerator(value)) { | ||
return x => x; | ||
} else if (typeof value.then === 'function' && typeof value.catch === 'function') { | ||
} else if (typeof value.then === 'function') { | ||
return promiseOf(value); | ||
@@ -377,0 +343,0 @@ } else { |
@@ -9,2 +9,3 @@ declare module "effection" { | ||
export interface Execution<T = any> { | ||
id: number; | ||
resume(result: T): void; | ||
@@ -11,0 +12,0 @@ throw(error: Error): void; |
{ | ||
"name": "effection", | ||
"description": "Effortlessly composable structured concurrency primitive for JavaScript", | ||
"version": "0.3.3-00a19e9", | ||
"version": "0.3.3-4f53cf6", | ||
"license": "MIT", | ||
@@ -20,2 +20,3 @@ "files": [ | ||
"@babel/core": "7.4.4", | ||
"@babel/plugin-proposal-class-properties": "^7.7.0", | ||
"@babel/preset-env": "7.4.4", | ||
@@ -22,0 +23,0 @@ "@babel/register": "7.4.4", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
36913
18
13
906