Comparing version 0.0.9-beta.8 to 0.0.9-beta.9
@@ -154,3 +154,3 @@ import $$observable from 'symbol-observable'; | ||
var ignore = function(fn) { | ||
var ignore$1 = function(fn) { | ||
var disposables; | ||
@@ -244,3 +244,3 @@ ({disposables} = Core.context || {}); | ||
var S, Selector, Signal, Stream, counter, observableProvider, promiseProvider, resolveAsync, rxCompat, sequenceCounter; | ||
var S, Selector, Signal, Stream, counter, fromObservable, fromPromise, resolveAsync, rxCompat, sequenceCounter; | ||
@@ -251,27 +251,40 @@ counter = 0; | ||
promiseProvider = function(promise) { | ||
return function(stream) { | ||
promise.then(function(value) { | ||
stream._value = value; | ||
return stream.notify('next', value); | ||
}).catch(err)(function() { | ||
return stream.notify('error', err); | ||
}); | ||
fromPromise = function(promise) { | ||
return { | ||
start: function(stream) { | ||
var complete; | ||
complete = false; | ||
return promise.then((value) => { | ||
if (complete) { | ||
return; | ||
} | ||
return stream._next(value); | ||
}).catch(err)(() => { | ||
return stream._error(err); | ||
}); | ||
}, | ||
stop: function() { | ||
var complete; | ||
return complete = true; | ||
} | ||
}; | ||
}; | ||
observableProvider = function(observable) { | ||
return function(stream) { | ||
var disposable; | ||
disposable = observable.subscribe((value) => { | ||
stream._value = value; | ||
return stream.notify('next', value); | ||
}, (error) => { | ||
return stream.notify('error', error); | ||
}, () => { | ||
return stream.notify('complete'); | ||
}); | ||
return () => { | ||
return disposable.unsubscribe(); | ||
}; | ||
fromObservable = function(observable) { | ||
var disposable; | ||
disposable = null; | ||
return { | ||
start: function(stream) { | ||
return disposable = observable.subscribe((value) => { | ||
return stream._next(value); | ||
}, (error) => { | ||
return stream._error(error); | ||
}, () => { | ||
return stream._complete(); | ||
}); | ||
}, | ||
stop: function() { | ||
disposable.unsubscribe(); | ||
return disposable = null; | ||
} | ||
}; | ||
@@ -349,2 +362,10 @@ }; | ||
error(value) { | ||
return this.notify('error', value); | ||
} | ||
complete() { | ||
return this.notify('complete'); | ||
} | ||
subscribe(observer) { | ||
@@ -360,7 +381,14 @@ var d; | ||
_subscribe(observer) { | ||
var onComplete; | ||
if (typeof observer !== 'object' || observer === null) { | ||
onComplete = arguments[2]; | ||
observer = { | ||
next: observer, | ||
error: arguments[1], | ||
complete: arguments[2] | ||
complete: () => { | ||
if (typeof onComplete === "function") { | ||
onComplete(); | ||
} | ||
return this.unsubscribe(observer); | ||
} | ||
}; | ||
@@ -396,2 +424,178 @@ } | ||
map(fn) { | ||
return new Selector(() => { | ||
var v; | ||
if ((v = obsv.value) === void 0) { | ||
return; | ||
} | ||
return ignore(() => { | ||
return fn(v); | ||
}); | ||
}, { | ||
notifyAlways: true | ||
}); | ||
} | ||
memo(mapFn) { | ||
var disposables, length, list, mapped, signals, trackIndex; | ||
mapped = []; | ||
list = []; | ||
disposables = []; | ||
length = 0; | ||
if ((trackIndex = mapFn.length > 1)) { | ||
signals = []; | ||
} | ||
Core$1.context.disposables.push(function() { | ||
var d, k, len; | ||
for (k = 0, len = disposables.length; k < len; k++) { | ||
d = disposables[k]; | ||
d(); | ||
} | ||
return disposables = mapped = list = signals = null; | ||
}); | ||
return this.map((newList) => { | ||
var d, end, i, indexedItems, item, itemIndex, j, k, l, len, len1, len2, m, mappedFn, newEnd, newLength, newListUnwrapped, newMapped, start, tempDisposables, tempSignals; | ||
// non-arrays | ||
newListUnwrapped = unwrap(newList, true); | ||
if (!Array.isArray(newListUnwrapped)) { | ||
if ((newListUnwrapped == null) || newListUnwrapped === false) { | ||
mapped = []; | ||
list = []; | ||
for (k = 0, len = disposables.length; k < len; k++) { | ||
d = disposables[k]; | ||
d(); | ||
} | ||
disposables = []; | ||
if (trackIndex) { | ||
signals = []; | ||
} | ||
return null; | ||
} | ||
if (list[0] === newListUnwrapped) { | ||
return mapped[0]; | ||
} | ||
for (l = 0, len1 = disposables.length; l < len1; l++) { | ||
d = disposables[l]; | ||
d(); | ||
} | ||
disposables = []; | ||
list[0] = newListUnwrapped; | ||
return mapped[0] = root(function(dispose) { | ||
disposables[0] = dispose; | ||
return mapFn(newList); | ||
}); | ||
} | ||
mappedFn = function(dispose) { | ||
disposables[j] = dispose; | ||
if (trackIndex) { | ||
return mapFn((typeof newList.peek === "function" ? newList.peek(j) : void 0) || newList[j], signals[j] = new Signal(j), newList); | ||
} | ||
return mapFn((typeof newList.peek === "function" ? newList.peek(j) : void 0) || newList[j]); | ||
}; | ||
newLength = newListUnwrapped.length; | ||
if (newLength === 0) { | ||
if (length !== 0) { | ||
list = []; | ||
mapped = []; | ||
length = 0; | ||
for (m = 0, len2 = disposables.length; m < len2; m++) { | ||
d = disposables[m]; | ||
d(); | ||
} | ||
disposables = []; | ||
if (trackIndex) { | ||
signals = []; | ||
} | ||
} | ||
} else if (length === 0) { | ||
j = 0; | ||
while (j < newLength) { | ||
list[j] = newListUnwrapped[j]; | ||
mapped[j] = root(mappedFn); | ||
j++; | ||
} | ||
length = newLength; | ||
} else { | ||
newMapped = new Array(newLength); | ||
tempDisposables = new Array(newLength); | ||
indexedItems = new Map(); | ||
if (trackIndex) { | ||
tempSignals = new Array(newLength); | ||
} | ||
end = Math.min(length, newLength); | ||
// reduce from both ends | ||
start = 0; | ||
while (start < end && newListUnwrapped[start] === list[start]) { | ||
start++; | ||
} | ||
end = length - 1; | ||
newEnd = newLength - 1; | ||
while (end >= 0 && newEnd >= 0 && newListUnwrapped[newEnd] === list[end]) { | ||
newMapped[newEnd] = mapped[end]; | ||
tempDisposables[newEnd] = disposables[end]; | ||
if (trackIndex) { | ||
tempSignals[newEnd] = signals[end]; | ||
} | ||
end--; | ||
newEnd--; | ||
} | ||
// create indices | ||
j = newEnd; | ||
while (j >= start) { | ||
item = newListUnwrapped[j]; | ||
itemIndex = indexedItems.get(item); | ||
if (itemIndex != null) { | ||
itemIndex.push(j); | ||
} else { | ||
indexedItems.set(item, [j]); | ||
} | ||
j--; | ||
} | ||
// find old items | ||
i = start; | ||
while (i <= end) { | ||
item = list[i]; | ||
itemIndex = indexedItems.get(item); | ||
if ((itemIndex != null) && itemIndex.length > 0) { | ||
j = itemIndex.pop(); | ||
newMapped[j] = mapped[i]; | ||
tempDisposables[j] = disposables[i]; | ||
if (trackIndex) { | ||
tempSignals[j] = signals[i]; | ||
} | ||
} else { | ||
disposables[i](); | ||
} | ||
i++; | ||
} | ||
// set all new values | ||
j = start; | ||
while (j < newLength) { | ||
if (newMapped.hasOwnProperty(j)) { | ||
mapped[j] = newMapped[j]; | ||
disposables[j] = tempDisposables[j]; | ||
if (trackIndex) { | ||
signals[j] = tempSignals[j]; | ||
if (signals[j].peek() !== j) { | ||
signals[j].next(j); | ||
} | ||
} | ||
} else { | ||
mapped[j] = root(mappedFn); | ||
} | ||
j++; | ||
} | ||
// truncate extra length | ||
length = mapped.length = disposables.length = newLength; | ||
if (trackIndex) { | ||
signals.length = newLength; | ||
} | ||
// save list for next iteration | ||
list = newListUnwrapped.slice(0); | ||
} | ||
return mapped; | ||
}); | ||
} | ||
// RxJS compatibility | ||
lift(op) { | ||
@@ -408,5 +612,5 @@ return rxCompat(this, op); | ||
Stream = class Stream extends Signal { | ||
constructor(provider) { | ||
constructor(provider, {value}) { | ||
var ref; | ||
super(); | ||
super(value); | ||
this.provider = provider; | ||
@@ -423,3 +627,3 @@ if ((ref = Core$1.context) != null) { | ||
if (!oldSize && this._subscriptions.size && !this.initialized) { | ||
this.disposable = this.provider(this); | ||
this.provider.start(this); | ||
this.initialized = true; | ||
@@ -435,6 +639,3 @@ } | ||
if (!this._subscriptions.size) { | ||
if (typeof this.disposable === "function") { | ||
this.disposable(); | ||
} | ||
delete this.disposable; | ||
this.provider.stop(this); | ||
return delete this.initialized; | ||
@@ -449,5 +650,21 @@ } | ||
error() {} | ||
complete() {} | ||
_next(value) { | ||
return super.next(value); | ||
} | ||
_error(value) { | ||
return super.error(value); | ||
} | ||
_complete() { | ||
return super.complete(); | ||
} | ||
peek() { | ||
if (!this.initialized) { | ||
this.disposable = this.provider(this); | ||
this.provider.start(this); | ||
this.initialized = true; | ||
@@ -462,5 +679,3 @@ } | ||
} | ||
if (typeof this.disposable === "function") { | ||
this.disposable(); | ||
} | ||
this.provider.stop(this); | ||
return delete this.initialized; | ||
@@ -472,5 +687,5 @@ } | ||
Selector = class Selector extends Signal { | ||
constructor(handler1, {defer, notifyAlways} = {}) { | ||
constructor(handler1, {defer, notifyAlways, value} = {}) { | ||
var ref; | ||
super(); | ||
super(value); | ||
this.handler = handler1; | ||
@@ -511,2 +726,6 @@ this.notifyAlways = notifyAlways; | ||
error() {} | ||
complete() {} | ||
peek() { | ||
@@ -541,6 +760,6 @@ if (!this.disposables.length) { | ||
clean() { | ||
var disposable, j, len, ref; | ||
var disposable, k, len, ref; | ||
ref = this.disposables; | ||
for (j = 0, len = ref.length; j < len; j++) { | ||
disposable = ref[j]; | ||
for (k = 0, len = ref.length; k < len; k++) { | ||
disposable = ref[k]; | ||
disposable(); | ||
@@ -573,10 +792,25 @@ } | ||
if ($$observable in payload) { | ||
return new Stream(observableProvider(payload[$$observable]())); | ||
return new Stream(fromObservable(payload[$$observable]()), options); | ||
} | ||
if ('then' in payload) { | ||
return new Stream(promiseProvider(payload)); | ||
return new Stream(fromPromise(payload), options); | ||
} | ||
if ('start' in payload && 'stop' in payload) { | ||
return new Stream(payload, options); | ||
} | ||
return new Signal(payload); | ||
}; | ||
var map = function(fn) { | ||
return function(obsv) { | ||
return S(obsv).map(fn); | ||
}; | ||
}; | ||
var memo = function(fn) { | ||
return function(obsv) { | ||
return S(obsv).memo(fn); | ||
}; | ||
}; | ||
var pipe = function(...fns) { | ||
@@ -1464,2 +1698,2 @@ if (!fns) { | ||
export { index as State, index$1 as ImmutableState, Sync$1 as Sync, ignore, root, unwrap, isEqual, onClean, Signal$1 as S, pipe }; | ||
export { index as State, index$1 as ImmutableState, Sync$1 as Sync, ignore$1 as ignore, root, unwrap, isEqual, onClean, Signal$1 as S, map, memo, pipe }; |
# Observables | ||
Observables are the glue that hold the library together. They often are invisible but interact in very powerful ways that you get more familiar with Solid they unlock a lot of potential. So consider this an intermediate to advanced topic. In the end there are only 3 objects we are talking about here in Solid: Signals, Syncs, and Selectors. And in most cases you will need to write them explicitly even if they are what are being used under the hood when you are using state.select or binding. | ||
Observables are the glue that hold the library together. They often are invisible but interact in very powerful ways that you get more familiar with Solid they unlock a lot of potential. So consider this an intermediate to advanced topic. | ||
@@ -9,3 +9,3 @@ ### Observable | ||
However, this behavior from a UI perspective is a bit undesireable, sort of unexpected, and gets in the way of the function of this library. In Solid.js we like our Observables to be hot and multicast. Luckily its easy conversion that we do at all points we accept Observables. We do a conversion anyway to expose our Observables to pull-based interfaces, like State and computations so their dependencies can be automatically tracked. These pullable Observables are called Signals. | ||
However, this behavior from a UI perspective is a bit undesireable, sort of unexpected, and gets in the way of the function of this library. In Solid.js we like our Observables to be hot and multicast. Luckily its easy conversion that we do at all points we accept Observables. We do a conversion anyway to expose our Observables to pull-based interfaces, like State and computations so their dependencies can be automatically tracked. We call these pullable observables Signals. | ||
@@ -36,3 +36,3 @@ ### Computation | ||
### Signals | ||
## Signals | ||
@@ -43,3 +43,3 @@ These are the most primitive of the Observables in Solid, and resemble BehaviorSubjects in RxJS. They are multicast, and have no provider of data. Instead the next method is called on them manually to push updates to subscribers. Their value can be fetched from their value property useful for computations. The can manually be subscribed to as any other Observable. | ||
name$ = S('John'); | ||
const name$ = S('John'); | ||
new Sync(() => { | ||
@@ -54,5 +54,5 @@ console.log(name$.value); | ||
Its important to note this factory treats all non-Observables, non-Promises as basaic values. An array is just an array. Combine with other libraries if you need to use more complicated streams. | ||
Its important to note this factory treats all non-Observables, non-Promises as basic values. An array is just an array. Combine with other libraries if you need to use more complicated streams. | ||
## Selector | ||
## Selectors | ||
@@ -63,5 +63,5 @@ These computations are also Observables. They are pure functions that allow the merging of mapping of several observable values. They are similar to combineLatest in RxJS except the dependencies aren't explicit and they also behave like flatMap. They support asynchronous return types allowing them to be the only method used in most places and are key to the state.select method. | ||
state = new State({count: 1}); | ||
const state = new State({count: 1}); | ||
countx3$ = S(() => state.count * 3); | ||
const countx3$ = S(() => state.count * 3); | ||
new Sync(() => { | ||
@@ -76,4 +76,29 @@ console.log(countx3$.value); | ||
### Stream | ||
Selectors as dynamic multi-tracking map functions are very powerful without resorting to chaining/composing operators. You can represent pretty much any operator using them which makes them a strong fallback for any solution. | ||
They have a few conventions. They by default don't notify changes on equal primitive values. If you want that behavior you need to pass {notifyAlways: true} to the send options parameter of S. | ||
Returning 'undefined' is considered not a value and does not notify. If you want to notify use 'null'. This is useful for filtering or no-op scenarios as well as tracking data initialization. | ||
They also pass the previous value on each execution. This is useful for reducing operations (obligatory Redux in a couple lines example): | ||
const reducer = (state, action) => { | ||
switch(action.type) { | ||
case 'LIST/ADD': | ||
return {...state, list: [...state.list, action.payload]}; | ||
default: | ||
return state; | ||
} | ||
} | ||
// redux | ||
const actions$ = S() | ||
const store$ = S((state = {list: []}) => reducer(state, actions$.value)); | ||
// subscription and dispatch | ||
store$.subscribe(({list}) => console.log(list)); | ||
actions$.next({type: 'LIST/ADD', payload: {id: 1, title: 'New Value'}}) | ||
## Streams | ||
These are wrappers of existing of Observables and Promises. They trigger on changes to the underlying object and have all the characteristics of Signals. | ||
@@ -95,1 +120,79 @@ | ||
Streams are driven off of a producer, so it is also possible to write a custom Producer. Producers have start/stop methods to control the stream. You can access _ prefixed versions of the observer properties to propogate events through the stream. | ||
function fromEvent(el, eventName) { | ||
var handler; | ||
return { | ||
start(stream) { | ||
handler = stream._next.bind(stream); | ||
el.addEventListener(eventName, handler); | ||
} | ||
stop() { | ||
el.removeEventListener(eventName, handler); | ||
handler = null; | ||
} | ||
} | ||
} | ||
S(fromEvent(window, 'resize')) | ||
## Operators | ||
Operators in Solid are functionally composable or pipeable(RxJS) and constructed using currying. They all take their arguments and return a function that takes a function, Observable, or Promise. In so when using Solid you may find you aren't explicitly using the Signal factory as much as you might expect although basic operators are available as chain syntax on Solid observables. | ||
import { S, State, pipe, map } from 'solid-js' | ||
state = new State({name: 'Heather', count: 1}); | ||
// single expression | ||
upperName$ = map((name) => name.toUpperCase())(() => state.name) | ||
// in steps | ||
reverseName = map((name) => name.reverse()) | ||
reverseUpperName$ = reverseName(upperName$) | ||
// chain syntax | ||
reverseUpperNameChained$ = S(() => state.name) | ||
.map((name) => name.toUpperCase()) | ||
.map((name) => name.reverse()) | ||
Solid.js only contains a very small subset of operators helpful for rendering or connecting other observable libraries. If you require more operators it's recommended to write your own or use with a more complete library like RxJS. | ||
Current operators: | ||
### map((item) =>....) | ||
Maps a value to a new value. | ||
### memo((item) =>....) | ||
Memoized map useful for rendering. It returns existing mapped value if input value hasn't changed and clears on false values. Maps to values or items in a Array depending on the data type. | ||
### pipe(...obsv) | ||
This composes a sequence of operators into a single operator. | ||
It is not difficult to write your own: | ||
import { S } from 'solid-js' | ||
function filter(filterFn) { | ||
return (source) => | ||
S(source).map((value) => { | ||
if (fn(value)) return value; | ||
return; | ||
}) | ||
} | ||
state = new State({number: 2}); | ||
<div>{ | ||
S(() => state.number).pipe( | ||
.filter((num) => num % 2 === 0) | ||
.map((num) => `${num} is even.`) | ||
) | ||
}</div> | ||
state.set({number: 3}); // will be skipped in display | ||
state.set({number: 6}); | ||
324
lib/solid.js
@@ -160,3 +160,3 @@ 'use strict'; | ||
var ignore = function(fn) { | ||
var ignore$1 = function(fn) { | ||
var disposables; | ||
@@ -250,3 +250,3 @@ ({disposables} = Core.context || {}); | ||
var S, Selector, Signal, Stream, counter, observableProvider, promiseProvider, resolveAsync, rxCompat, sequenceCounter; | ||
var S, Selector, Signal, Stream, counter, fromObservable, fromPromise, resolveAsync, rxCompat, sequenceCounter; | ||
@@ -257,27 +257,40 @@ counter = 0; | ||
promiseProvider = function(promise) { | ||
return function(stream) { | ||
promise.then(function(value) { | ||
stream._value = value; | ||
return stream.notify('next', value); | ||
}).catch(err)(function() { | ||
return stream.notify('error', err); | ||
}); | ||
fromPromise = function(promise) { | ||
return { | ||
start: function(stream) { | ||
var complete; | ||
complete = false; | ||
return promise.then((value) => { | ||
if (complete) { | ||
return; | ||
} | ||
return stream._next(value); | ||
}).catch(err)(() => { | ||
return stream._error(err); | ||
}); | ||
}, | ||
stop: function() { | ||
var complete; | ||
return complete = true; | ||
} | ||
}; | ||
}; | ||
observableProvider = function(observable) { | ||
return function(stream) { | ||
var disposable; | ||
disposable = observable.subscribe((value) => { | ||
stream._value = value; | ||
return stream.notify('next', value); | ||
}, (error) => { | ||
return stream.notify('error', error); | ||
}, () => { | ||
return stream.notify('complete'); | ||
}); | ||
return () => { | ||
return disposable.unsubscribe(); | ||
}; | ||
fromObservable = function(observable) { | ||
var disposable; | ||
disposable = null; | ||
return { | ||
start: function(stream) { | ||
return disposable = observable.subscribe((value) => { | ||
return stream._next(value); | ||
}, (error) => { | ||
return stream._error(error); | ||
}, () => { | ||
return stream._complete(); | ||
}); | ||
}, | ||
stop: function() { | ||
disposable.unsubscribe(); | ||
return disposable = null; | ||
} | ||
}; | ||
@@ -355,2 +368,10 @@ }; | ||
error(value) { | ||
return this.notify('error', value); | ||
} | ||
complete() { | ||
return this.notify('complete'); | ||
} | ||
subscribe(observer) { | ||
@@ -366,7 +387,14 @@ var d; | ||
_subscribe(observer) { | ||
var onComplete; | ||
if (typeof observer !== 'object' || observer === null) { | ||
onComplete = arguments[2]; | ||
observer = { | ||
next: observer, | ||
error: arguments[1], | ||
complete: arguments[2] | ||
complete: () => { | ||
if (typeof onComplete === "function") { | ||
onComplete(); | ||
} | ||
return this.unsubscribe(observer); | ||
} | ||
}; | ||
@@ -402,2 +430,178 @@ } | ||
map(fn) { | ||
return new Selector(() => { | ||
var v; | ||
if ((v = obsv.value) === void 0) { | ||
return; | ||
} | ||
return ignore(() => { | ||
return fn(v); | ||
}); | ||
}, { | ||
notifyAlways: true | ||
}); | ||
} | ||
memo(mapFn) { | ||
var disposables, length, list, mapped, signals, trackIndex; | ||
mapped = []; | ||
list = []; | ||
disposables = []; | ||
length = 0; | ||
if ((trackIndex = mapFn.length > 1)) { | ||
signals = []; | ||
} | ||
Core$1.context.disposables.push(function() { | ||
var d, k, len; | ||
for (k = 0, len = disposables.length; k < len; k++) { | ||
d = disposables[k]; | ||
d(); | ||
} | ||
return disposables = mapped = list = signals = null; | ||
}); | ||
return this.map((newList) => { | ||
var d, end, i, indexedItems, item, itemIndex, j, k, l, len, len1, len2, m, mappedFn, newEnd, newLength, newListUnwrapped, newMapped, start, tempDisposables, tempSignals; | ||
// non-arrays | ||
newListUnwrapped = unwrap(newList, true); | ||
if (!Array.isArray(newListUnwrapped)) { | ||
if ((newListUnwrapped == null) || newListUnwrapped === false) { | ||
mapped = []; | ||
list = []; | ||
for (k = 0, len = disposables.length; k < len; k++) { | ||
d = disposables[k]; | ||
d(); | ||
} | ||
disposables = []; | ||
if (trackIndex) { | ||
signals = []; | ||
} | ||
return null; | ||
} | ||
if (list[0] === newListUnwrapped) { | ||
return mapped[0]; | ||
} | ||
for (l = 0, len1 = disposables.length; l < len1; l++) { | ||
d = disposables[l]; | ||
d(); | ||
} | ||
disposables = []; | ||
list[0] = newListUnwrapped; | ||
return mapped[0] = root(function(dispose) { | ||
disposables[0] = dispose; | ||
return mapFn(newList); | ||
}); | ||
} | ||
mappedFn = function(dispose) { | ||
disposables[j] = dispose; | ||
if (trackIndex) { | ||
return mapFn((typeof newList.peek === "function" ? newList.peek(j) : void 0) || newList[j], signals[j] = new Signal(j), newList); | ||
} | ||
return mapFn((typeof newList.peek === "function" ? newList.peek(j) : void 0) || newList[j]); | ||
}; | ||
newLength = newListUnwrapped.length; | ||
if (newLength === 0) { | ||
if (length !== 0) { | ||
list = []; | ||
mapped = []; | ||
length = 0; | ||
for (m = 0, len2 = disposables.length; m < len2; m++) { | ||
d = disposables[m]; | ||
d(); | ||
} | ||
disposables = []; | ||
if (trackIndex) { | ||
signals = []; | ||
} | ||
} | ||
} else if (length === 0) { | ||
j = 0; | ||
while (j < newLength) { | ||
list[j] = newListUnwrapped[j]; | ||
mapped[j] = root(mappedFn); | ||
j++; | ||
} | ||
length = newLength; | ||
} else { | ||
newMapped = new Array(newLength); | ||
tempDisposables = new Array(newLength); | ||
indexedItems = new Map(); | ||
if (trackIndex) { | ||
tempSignals = new Array(newLength); | ||
} | ||
end = Math.min(length, newLength); | ||
// reduce from both ends | ||
start = 0; | ||
while (start < end && newListUnwrapped[start] === list[start]) { | ||
start++; | ||
} | ||
end = length - 1; | ||
newEnd = newLength - 1; | ||
while (end >= 0 && newEnd >= 0 && newListUnwrapped[newEnd] === list[end]) { | ||
newMapped[newEnd] = mapped[end]; | ||
tempDisposables[newEnd] = disposables[end]; | ||
if (trackIndex) { | ||
tempSignals[newEnd] = signals[end]; | ||
} | ||
end--; | ||
newEnd--; | ||
} | ||
// create indices | ||
j = newEnd; | ||
while (j >= start) { | ||
item = newListUnwrapped[j]; | ||
itemIndex = indexedItems.get(item); | ||
if (itemIndex != null) { | ||
itemIndex.push(j); | ||
} else { | ||
indexedItems.set(item, [j]); | ||
} | ||
j--; | ||
} | ||
// find old items | ||
i = start; | ||
while (i <= end) { | ||
item = list[i]; | ||
itemIndex = indexedItems.get(item); | ||
if ((itemIndex != null) && itemIndex.length > 0) { | ||
j = itemIndex.pop(); | ||
newMapped[j] = mapped[i]; | ||
tempDisposables[j] = disposables[i]; | ||
if (trackIndex) { | ||
tempSignals[j] = signals[i]; | ||
} | ||
} else { | ||
disposables[i](); | ||
} | ||
i++; | ||
} | ||
// set all new values | ||
j = start; | ||
while (j < newLength) { | ||
if (newMapped.hasOwnProperty(j)) { | ||
mapped[j] = newMapped[j]; | ||
disposables[j] = tempDisposables[j]; | ||
if (trackIndex) { | ||
signals[j] = tempSignals[j]; | ||
if (signals[j].peek() !== j) { | ||
signals[j].next(j); | ||
} | ||
} | ||
} else { | ||
mapped[j] = root(mappedFn); | ||
} | ||
j++; | ||
} | ||
// truncate extra length | ||
length = mapped.length = disposables.length = newLength; | ||
if (trackIndex) { | ||
signals.length = newLength; | ||
} | ||
// save list for next iteration | ||
list = newListUnwrapped.slice(0); | ||
} | ||
return mapped; | ||
}); | ||
} | ||
// RxJS compatibility | ||
lift(op) { | ||
@@ -414,5 +618,5 @@ return rxCompat(this, op); | ||
Stream = class Stream extends Signal { | ||
constructor(provider) { | ||
constructor(provider, {value}) { | ||
var ref; | ||
super(); | ||
super(value); | ||
this.provider = provider; | ||
@@ -429,3 +633,3 @@ if ((ref = Core$1.context) != null) { | ||
if (!oldSize && this._subscriptions.size && !this.initialized) { | ||
this.disposable = this.provider(this); | ||
this.provider.start(this); | ||
this.initialized = true; | ||
@@ -441,6 +645,3 @@ } | ||
if (!this._subscriptions.size) { | ||
if (typeof this.disposable === "function") { | ||
this.disposable(); | ||
} | ||
delete this.disposable; | ||
this.provider.stop(this); | ||
return delete this.initialized; | ||
@@ -455,5 +656,21 @@ } | ||
error() {} | ||
complete() {} | ||
_next(value) { | ||
return super.next(value); | ||
} | ||
_error(value) { | ||
return super.error(value); | ||
} | ||
_complete() { | ||
return super.complete(); | ||
} | ||
peek() { | ||
if (!this.initialized) { | ||
this.disposable = this.provider(this); | ||
this.provider.start(this); | ||
this.initialized = true; | ||
@@ -468,5 +685,3 @@ } | ||
} | ||
if (typeof this.disposable === "function") { | ||
this.disposable(); | ||
} | ||
this.provider.stop(this); | ||
return delete this.initialized; | ||
@@ -478,5 +693,5 @@ } | ||
Selector = class Selector extends Signal { | ||
constructor(handler1, {defer, notifyAlways} = {}) { | ||
constructor(handler1, {defer, notifyAlways, value} = {}) { | ||
var ref; | ||
super(); | ||
super(value); | ||
this.handler = handler1; | ||
@@ -517,2 +732,6 @@ this.notifyAlways = notifyAlways; | ||
error() {} | ||
complete() {} | ||
peek() { | ||
@@ -547,6 +766,6 @@ if (!this.disposables.length) { | ||
clean() { | ||
var disposable, j, len, ref; | ||
var disposable, k, len, ref; | ||
ref = this.disposables; | ||
for (j = 0, len = ref.length; j < len; j++) { | ||
disposable = ref[j]; | ||
for (k = 0, len = ref.length; k < len; k++) { | ||
disposable = ref[k]; | ||
disposable(); | ||
@@ -579,10 +798,25 @@ } | ||
if ($$observable in payload) { | ||
return new Stream(observableProvider(payload[$$observable]())); | ||
return new Stream(fromObservable(payload[$$observable]()), options); | ||
} | ||
if ('then' in payload) { | ||
return new Stream(promiseProvider(payload)); | ||
return new Stream(fromPromise(payload), options); | ||
} | ||
if ('start' in payload && 'stop' in payload) { | ||
return new Stream(payload, options); | ||
} | ||
return new Signal(payload); | ||
}; | ||
var map = function(fn) { | ||
return function(obsv) { | ||
return S(obsv).map(fn); | ||
}; | ||
}; | ||
var memo = function(fn) { | ||
return function(obsv) { | ||
return S(obsv).memo(fn); | ||
}; | ||
}; | ||
var pipe = function(...fns) { | ||
@@ -1473,3 +1707,3 @@ if (!fns) { | ||
exports.Sync = Sync$1; | ||
exports.ignore = ignore; | ||
exports.ignore = ignore$1; | ||
exports.root = root; | ||
@@ -1480,2 +1714,4 @@ exports.unwrap = unwrap; | ||
exports.S = Signal$1; | ||
exports.map = map; | ||
exports.memo = memo; | ||
exports.pipe = pipe; |
{ | ||
"name": "solid-js", | ||
"description": "A declarative JavaScript library for building user interfaces.", | ||
"version": "0.0.9-beta.8", | ||
"version": "0.0.9-beta.9", | ||
"author": "Ryan Carniato", | ||
@@ -6,0 +6,0 @@ "license": "MIT", |
@@ -134,3 +134,2 @@ # Solid.js | ||
* [Observables](../master/documentation/observables.md) | ||
* [Operators](../master/documentation/operators.md) | ||
@@ -137,0 +136,0 @@ ## Related Projects |
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
117422
13
3198
151