evnty
Version:
Async-first, reactive event handling library for complex event flows in browser and Node.js
628 lines (626 loc) • 22 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "AsyncIteratorObject", {
enumerable: true,
get: function() {
return AsyncIteratorObject;
}
});
const _utilscjs = require("./utils.cjs");
class OpState {
index;
remaining;
dropping;
value;
initialized = false;
constructor(index, remaining, dropping, value){
this.index = index;
this.remaining = remaining;
this.dropping = dropping;
this.value = value;
}
static from(op) {
switch(op.kind){
case 5:
return new OpState(op.start, 0, false, undefined);
case 6:
return new OpState(0, op.limit, false, undefined);
case 7:
return new OpState(0, op.count, false, undefined);
case 9:
return new OpState(0, 0, true, undefined);
case 10:
return new OpState(0, 0, false, op.init);
default:
return new OpState(0, 0, false, undefined);
}
}
}
class ProcessResult {
value;
shouldYield;
done;
expandIterator;
expandOpIndex;
flatMapIterator;
flatMapOpIndex;
constructor(value, shouldYield, done, expandIterator, expandOpIndex, flatMapIterator, flatMapOpIndex){
this.value = value;
this.shouldYield = shouldYield;
this.done = done;
this.expandIterator = expandIterator;
this.expandOpIndex = expandOpIndex;
this.flatMapIterator = flatMapIterator;
this.flatMapOpIndex = flatMapOpIndex;
}
static continue() {
return new ProcessResult(undefined, false, false, null, -1, null, -1);
}
static yield(value) {
return new ProcessResult(value, true, false, null, -1, null, -1);
}
static done() {
return new ProcessResult(undefined, false, true, null, -1, null, -1);
}
static expand(iterator, opIndex) {
return new ProcessResult(undefined, false, false, iterator, opIndex, null, -1);
}
static flatMap(iterator, opIndex) {
return new ProcessResult(undefined, false, false, null, -1, iterator, opIndex);
}
}
function findTakeStates(ops, opStates) {
const takeStates = [];
for(let i = 0; i < ops.length; i++){
if (ops[i].kind === 6) takeStates.push(opStates[i]);
}
return takeStates;
}
function hasExpandingOps(ops) {
for(let i = 0; i < ops.length; i++){
const kind = ops[i].kind;
if (kind === 11 || kind === 12) return true;
}
return false;
}
function checkTakeExhausted(takeStates) {
for(let i = 0; i < takeStates.length; i++){
if (takeStates[i].remaining <= 0) return true;
}
return false;
}
async function processOps(inputValue, ops, opStates, startIndex) {
let value = inputValue;
for(let i = startIndex; i < ops.length; i++){
const op = ops[i];
const state = opStates[i];
switch(op.kind){
case 0:
value = op.fn(value, state.index++);
break;
case 1:
{
const result = op.fn(value, state.index++);
const passed = (0, _utilscjs.isThenable)(result) ? await result : result;
if (!passed) return ProcessResult.continue();
break;
}
case 2:
{
const result = op.fn(value, state.index++);
const resolved = (0, _utilscjs.isThenable)(result) ? await result : result;
if (resolved === undefined) return ProcessResult.continue();
value = resolved;
break;
}
case 3:
value = await value;
break;
case 4:
{
const result = op.fn(value, state.index++);
if ((0, _utilscjs.isThenable)(result)) await result;
break;
}
case 5:
value = [
state.index++,
value
];
break;
case 6:
if (state.remaining <= 0) return ProcessResult.done();
state.remaining--;
break;
case 8:
{
const result = op.fn(value, state.index++);
const passed = (0, _utilscjs.isThenable)(result) ? await result : result;
if (!passed) return ProcessResult.done();
break;
}
case 7:
if (state.remaining > 0) {
state.remaining--;
return ProcessResult.continue();
}
break;
case 9:
if (state.dropping) {
const result = op.fn(value, state.index++);
const passed = (0, _utilscjs.isThenable)(result) ? await result : result;
if (passed) return ProcessResult.continue();
state.dropping = false;
}
break;
case 10:
{
if (!state.initialized) {
state.initialized = true;
if (op.hasInit) {
const result = op.fn(state.value, value, state.index++);
state.value = (0, _utilscjs.isThenable)(result) ? await result : result;
value = state.value;
} else {
state.value = value;
return ProcessResult.continue();
}
} else {
const result = op.fn(state.value, value, state.index++);
state.value = (0, _utilscjs.isThenable)(result) ? await result : result;
value = state.value;
}
break;
}
case 11:
{
const iterable = op.fn(value, state.index++);
return ProcessResult.flatMap(iterable[Symbol.asyncIterator](), i);
}
case 12:
{
const result = op.fn(value, state.index++);
const expanded = (0, _utilscjs.isThenable)(result) ? await result : result;
return ProcessResult.expand(expanded[Symbol.iterator](), i);
}
}
}
return ProcessResult.yield(value);
}
async function processOpsSimple(inputValue, ops, opStates) {
let value = inputValue;
for(let i = 0; i < ops.length; i++){
const op = ops[i];
const state = opStates[i];
switch(op.kind){
case 0:
value = op.fn(value, state.index++);
break;
case 1:
{
const result = op.fn(value, state.index++);
const passed = (0, _utilscjs.isThenable)(result) ? await result : result;
if (!passed) return {
value: undefined,
shouldYield: false,
done: false
};
break;
}
case 2:
{
const result = op.fn(value, state.index++);
const resolved = (0, _utilscjs.isThenable)(result) ? await result : result;
if (resolved === undefined) return {
value: undefined,
shouldYield: false,
done: false
};
value = resolved;
break;
}
case 3:
value = await value;
break;
case 4:
{
const result = op.fn(value, state.index++);
if ((0, _utilscjs.isThenable)(result)) await result;
break;
}
case 5:
value = [
state.index++,
value
];
break;
case 6:
state.remaining--;
break;
case 8:
{
const result = op.fn(value, state.index++);
const passed = (0, _utilscjs.isThenable)(result) ? await result : result;
if (!passed) return {
value: undefined,
shouldYield: false,
done: true
};
break;
}
case 7:
if (state.remaining > 0) {
state.remaining--;
return {
value: undefined,
shouldYield: false,
done: false
};
}
break;
case 9:
if (state.dropping) {
const result = op.fn(value, state.index++);
const passed = (0, _utilscjs.isThenable)(result) ? await result : result;
if (passed) return {
value: undefined,
shouldYield: false,
done: false
};
state.dropping = false;
}
break;
case 10:
{
if (!state.initialized) {
state.initialized = true;
if (op.hasInit) {
const result = op.fn(state.value, value, state.index++);
state.value = (0, _utilscjs.isThenable)(result) ? await result : result;
value = state.value;
} else {
state.value = value;
return {
value: undefined,
shouldYield: false,
done: false
};
}
} else {
const result = op.fn(state.value, value, state.index++);
state.value = (0, _utilscjs.isThenable)(result) ? await result : result;
value = state.value;
}
break;
}
}
}
return {
value,
shouldYield: true,
done: false
};
}
function collectOps(iter) {
const ops = [];
let current = iter;
while(current){
const op = current.op;
if (op) ops.push(op);
current = current.parent;
}
ops.reverse();
return ops;
}
function getSource(iter) {
let current = iter;
while(current.parent){
current = current.parent;
}
return current.iterable;
}
function createSimpleIterable(source, ops) {
return {
[Symbol.asyncIterator]: ()=>{
const iterator = source[Symbol.asyncIterator]();
const opStates = ops.map(OpState.from);
const takeStates = findTakeStates(ops, opStates);
let done = false;
return {
async next () {
while(!done){
if (checkTakeExhausted(takeStates)) {
done = true;
await iterator.return?.();
return {
value: undefined,
done: true
};
}
const sourceResult = await iterator.next();
if (sourceResult.done) {
done = true;
return {
value: undefined,
done: true
};
}
const result = await processOpsSimple(sourceResult.value, ops, opStates);
if (result.done) {
done = true;
await iterator.return?.();
return {
value: undefined,
done: true
};
}
if (result.shouldYield) return {
value: result.value,
done: false
};
}
return {
value: undefined,
done: true
};
},
async return (returnValue) {
done = true;
await iterator.return?.(returnValue);
return {
value: undefined,
done: true
};
},
async throw (error) {
done = true;
if (iterator.throw) {
await iterator.throw(error);
}
throw error;
}
};
}
};
}
function createExpandingIterable(source, ops) {
return {
[Symbol.asyncIterator]: ()=>{
const iterator = source[Symbol.asyncIterator]();
const opStates = ops.map(OpState.from);
const takeStates = findTakeStates(ops, opStates);
let done = false;
const innerStack = [];
const closeInnerIterators = async ()=>{
for (const frame of innerStack){
if (frame.type === 'flatMap') {
await frame.iterator.return?.();
}
}
innerStack.length = 0;
};
const handleResult = async (result)=>{
if (result.done) {
done = true;
await closeInnerIterators();
await iterator.return?.();
return {
value: undefined,
done: true
};
}
if (result.expandIterator) {
innerStack.push({
type: 'expand',
iterator: result.expandIterator,
opIndex: result.expandOpIndex
});
return null;
}
if (result.flatMapIterator) {
innerStack.push({
type: 'flatMap',
iterator: result.flatMapIterator,
opIndex: result.flatMapOpIndex
});
return null;
}
if (result.shouldYield) {
return {
value: result.value,
done: false
};
}
return null;
};
return {
async next () {
while(!done){
if (innerStack.length > 0) {
const frame = innerStack[innerStack.length - 1];
if (frame.type === 'expand') {
const expandResult = frame.iterator.next();
if (!expandResult.done) {
const result = await processOps(expandResult.value, ops, opStates, frame.opIndex + 1);
const handled = await handleResult(result);
if (handled) return handled;
continue;
}
innerStack.pop();
continue;
} else {
const flatMapResult = await frame.iterator.next();
if (!flatMapResult.done) {
const result = await processOps(flatMapResult.value, ops, opStates, frame.opIndex + 1);
const handled = await handleResult(result);
if (handled) return handled;
continue;
}
innerStack.pop();
continue;
}
}
if (checkTakeExhausted(takeStates)) {
done = true;
await iterator.return?.();
return {
value: undefined,
done: true
};
}
const sourceResult = await iterator.next();
if (sourceResult.done) {
done = true;
return {
value: undefined,
done: true
};
}
const result = await processOps(sourceResult.value, ops, opStates, 0);
const handled = await handleResult(result);
if (handled) return handled;
}
return {
value: undefined,
done: true
};
},
async return (returnValue) {
done = true;
await closeInnerIterators();
await iterator.return?.(returnValue);
return {
value: undefined,
done: true
};
},
async throw (error) {
done = true;
await closeInnerIterators();
if (iterator.throw) {
await iterator.throw(error);
}
throw error;
}
};
}
};
}
function createFusedIterable(iter) {
const source = getSource(iter);
const ops = iter.cachedOps ?? (iter.cachedOps = collectOps(iter));
if (ops.length === 0) {
return source;
}
return hasExpandingOps(ops) ? createExpandingIterable(source, ops) : createSimpleIterable(source, ops);
}
class AsyncIteratorObject {
static from(iterable) {
const asyncIterable = (0, _utilscjs.toAsyncIterable)(iterable);
return new AsyncIteratorObject(asyncIterable);
}
static merge(...iterables) {
return new AsyncIteratorObject((0, _utilscjs.mergeIterables)(...iterables));
}
iterable;
parent;
op;
cachedOps = null;
[Symbol.toStringTag] = 'AsyncIteratorObject';
constructor(iterable, parent = null, op = null){
this.iterable = iterable;
this.parent = parent;
this.op = op;
}
pipe(generatorFactory, signal) {
const materialized = createFusedIterable(this);
const generator = (0, _utilscjs.pipe)(materialized, generatorFactory, signal);
return new AsyncIteratorObject(generator);
}
awaited() {
return new AsyncIteratorObject(this.iterable, this, {
kind: 3
});
}
map(callbackfn) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 0,
fn: callbackfn
});
}
filter(predicate) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 1,
fn: predicate
});
}
filterMap(callbackfn) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 2,
fn: callbackfn
});
}
inspect(callbackfn) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 4,
fn: callbackfn
});
}
enumerate(start = 0) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 5,
start
});
}
take(limit) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 6,
limit
});
}
takeWhile(predicate) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 8,
fn: predicate
});
}
drop(count) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 7,
count
});
}
dropWhile(predicate) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 9,
fn: predicate
});
}
flatMap(callback) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 11,
fn: callback
});
}
reduce(callbackfn, ...args) {
const hasInit = args.length > 0;
return new AsyncIteratorObject(this.iterable, this, {
kind: 10,
fn: callbackfn,
init: args[0],
hasInit
});
}
expand(callbackfn) {
return new AsyncIteratorObject(this.iterable, this, {
kind: 12,
fn: callbackfn
});
}
[Symbol.asyncIterator]() {
return createFusedIterable(this)[Symbol.asyncIterator]();
}
}
//# sourceMappingURL=iterator.cjs.map