Comparing version 0.3.4 to 0.3.5
@@ -1,49 +0,33 @@ | ||
import S$1 from 's-js'; | ||
import S from 's-js'; | ||
function comparer(v, k, b, isArray, path, r) { | ||
let index; | ||
const newPath = path.concat([k]); | ||
if (isArray && v != null && typeof v === 'object' | ||
&& k != (index = b.findIndex(i => i && (i === v || (v.id != null && i.id === v.id) || (v._id != null && i._id === v._id))))) { | ||
return r.push(newPath.concat([index > -1 ? b[index] : v])); | ||
} | ||
return r.push.apply(r, diff(v, b[k], newPath)); | ||
} | ||
const SNODE = Symbol('solid-node'), | ||
SPROXY = Symbol('solid-proxy'); | ||
function isWrappable(obj) { return obj !== null && typeof obj === 'object' && !(obj instanceof Element); } | ||
function diff(a, b, path = []) { | ||
let i, k, l, len, v; | ||
const r = []; | ||
if (!isWrappable(a) || (b == null)) { | ||
if (a !== b) { | ||
r.push(path.concat([a])); | ||
} | ||
} else if (Array.isArray(a)) { | ||
for (k = i = 0, len = a.length; i < len; k = ++i) { | ||
v = a[k]; | ||
if ((b != null ? b[k] : void 0) !== v) comparer(v, k, b, true, path, r); | ||
} | ||
if ((b != null ? b.length : void 0) > a.length) { | ||
l = a.length; | ||
while (l < b.length) { | ||
r.push(path.concat([l, void 0])); | ||
l++; | ||
const proxyTraps = { | ||
get(target, property) { | ||
if (property === '_state') return target; | ||
const value = target[property], | ||
wrappable = isWrappable(value); | ||
if (S.isListening() && typeof value !== 'function') { | ||
let nodes, node; | ||
if (wrappable && (nodes = getDataNodes(value))) { | ||
node = nodes._self || (nodes._self = S.makeDataNode()); | ||
node.current(); | ||
} | ||
nodes = getDataNodes(target); | ||
node = nodes[property] || (nodes[property] = S.makeDataNode()); | ||
node.current(); | ||
} | ||
} else { | ||
for (k in a) { | ||
v = a[k]; | ||
if ((b != null ? b[k] : void 0) !== v) | ||
comparer(v, k, b, false, path, r); | ||
} | ||
for (k in b) { | ||
v = b[k]; | ||
if (!(k in a)) | ||
r.push(path.concat([k, void 0])); | ||
} | ||
} | ||
return r; | ||
} | ||
return wrappable ? wrap(value) : value; | ||
}, | ||
set() { return true; }, | ||
deleteProperty() { return true; } | ||
}; | ||
function wrap(value) { return value[SPROXY] || (value[SPROXY] = new Proxy(value, proxyTraps)); } | ||
function isWrappable(obj) { return obj !== null && typeof obj === 'object' && !(obj instanceof Element); } | ||
function unwrap(item) { | ||
@@ -71,52 +55,2 @@ let result, unwrapped, v; | ||
// export observable | ||
function observable(input) { | ||
if (Symbol.observable in input) return input[Symbol.observable](); | ||
return { | ||
subscribe(observer) { | ||
if (!(observer instanceof Object) || observer == null) { | ||
throw new TypeError('Expected the observer to be an object.'); | ||
} | ||
observer = observer.next || observer; | ||
let complete = false; | ||
S.on(input, function next() { | ||
if (complete) return; | ||
observer(input()); | ||
}); | ||
return { | ||
unsubscribe() { complete = true; } | ||
}; | ||
}, | ||
[Symbol.observable]() { return this; } | ||
}; | ||
} | ||
const SNODE = Symbol('solid-node'), | ||
SPROXY = Symbol('solid-proxy'); | ||
const proxyTraps = { | ||
get(target, property) { | ||
if (property === '_state') return target; | ||
const value = target[property], | ||
wrappable = isWrappable(value); | ||
if (S$1.isListening() && typeof value !== 'function') { | ||
let nodes, node; | ||
if (wrappable && (nodes = getDataNodes(value))) { | ||
node = nodes._self || (nodes._self = S$1.makeDataNode()); | ||
node.current(); | ||
} | ||
nodes = getDataNodes(target); | ||
node = nodes[property] || (nodes[property] = S$1.makeDataNode()); | ||
node.current(); | ||
} | ||
return wrappable ? wrap(value) : value; | ||
}, | ||
set() { return true; }, | ||
deleteProperty() { return true; } | ||
}; | ||
function wrap(value) { return value[SPROXY] || (value[SPROXY] = new Proxy(value, proxyTraps)); } | ||
function getDataNodes(target) { | ||
@@ -128,11 +62,9 @@ let nodes = target[SNODE]; | ||
function setProperty(state, property, value) { | ||
function setProperty(state, property, value, force) { | ||
value = unwrap(value); | ||
if (state[property] === value) return; | ||
if (!force && state[property] === value) return; | ||
const notify = Array.isArray(state) || !(property in state); | ||
if (value === void 0) { | ||
delete state[property]; | ||
if (Array.isArray(state)) state.length -= 1; | ||
} | ||
else state[property] = value; | ||
} else state[property] = value; | ||
let nodes = getDataNodes(state), node; | ||
@@ -151,3 +83,3 @@ (node = nodes[property]) && node.next(); | ||
function updatePath(current, path, traversed = [], replace) { | ||
function updatePath(current, path, traversed = []) { | ||
if (path.length === 1) { | ||
@@ -157,8 +89,4 @@ let value = path[0]; | ||
value = value(wrap(current), traversed); | ||
// deep map | ||
if (Array.isArray(value)) { | ||
for (let i = 0; i < value.length; i += 1) | ||
updatePath(current, value[i], traversed, true); | ||
return; | ||
} | ||
// reconciled | ||
if (value === undefined) return; | ||
} | ||
@@ -175,7 +103,7 @@ return mergeState(current, value); | ||
for (let i = 0; i < part.length; i++) | ||
updatePath(current, [part[i]].concat(path), traversed.concat([part[i]]), replace); | ||
updatePath(current, [part[i]].concat(path), traversed.concat([part[i]])); | ||
} else if (isArray && partType === 'function') { | ||
// Ex. update('data', i => i.id === 42, 'label', l => l + ' !!!'); | ||
for (let i = 0; i < current.length; i++) | ||
if (part(current[i], i)) updatePath(current[i], path.slice(0), traversed.concat([i]), replace); | ||
if (part(current[i], i)) updatePath(current[i], path.slice(0), traversed.concat([i])); | ||
} else if (isArray && partType === 'object') { | ||
@@ -185,7 +113,7 @@ // Ex. update('data', { from: 3, to: 12, by: 2 }, 'label', l => l + ' !!!'); | ||
for (let i = from; i <= to; i += by) | ||
updatePath(current[i], path.slice(0), traversed.concat([i]), replace); | ||
updatePath(current[i], path.slice(0), traversed.concat([i])); | ||
} else if (isArray && part === '*') { | ||
// Ex. update('data', '*', 'label', l => l + ' !!!'); | ||
for (let i = 0; i < current.length; i++) | ||
updatePath(current, [i].concat(path), traversed.concat([i]), replace); | ||
updatePath(current, [i].concat(path), traversed.concat([i])); | ||
} else if (path.length === 1) { | ||
@@ -197,6 +125,6 @@ let value = path[0]; | ||
} | ||
if (!replace && isWrappable(current[part]) && isWrappable(value) && !Array.isArray(value)) | ||
if (isWrappable(current[part]) && isWrappable(value) && !Array.isArray(value)) | ||
return mergeState(current[part], value); | ||
return setProperty(current, part, value); | ||
} else updatePath(current[part], path, traversed.concat([part]), replace); | ||
} else updatePath(current[part], path, traversed.concat([part])); | ||
} | ||
@@ -211,3 +139,3 @@ | ||
const args = arguments; | ||
S$1.freeze(() => { | ||
S.freeze(() => { | ||
if (Array.isArray(args[0])) { | ||
@@ -221,9 +149,93 @@ for (let i = 0; i < args.length; i += 1) | ||
function reconcile() { | ||
const path = Array.prototype.slice.call(arguments, 0, -1), | ||
const DEFAULT = 'default', | ||
MERGE = 'merge', | ||
FORCE = 'force'; | ||
function applyState(target, parent, property, mode, key) { | ||
let previous = parent[property], force = mode === FORCE; | ||
if (!force && target === previous) return; | ||
if (!isWrappable(target) || (previous == null)) { | ||
return (force || target !== previous) && setProperty(parent, property, target, force); | ||
} | ||
if (Array.isArray(target)) { | ||
if (target.length && previous.length && (mode === DEFAULT | ||
|| (key && mode === MERGE && target[0][key] != null))) { | ||
// skip common prefix and suffix | ||
let i, j, start, end, newEnd, item, newIndicesNext, keyVal, | ||
temp = new Array(target.length), | ||
newIndices = new Map(); | ||
for (start = 0, end = Math.min(previous.length, target.length); start < end && (previous[start] === target[start] || key && previous[start][key] === target[start][key]); start++) | ||
applyState(target[start], previous, start, mode, key); | ||
for (end = previous.length - 1, newEnd = target.length - 1; end >= 0 && newEnd >= 0 && (previous[end] === target[newEnd] || key && previous[end][key] === target[newEnd][key]); end--, newEnd--) | ||
temp[newEnd] = previous[end]; | ||
// prepare a map of all indices in target | ||
newIndicesNext = new Array(newEnd + 1); | ||
for (j = newEnd; j >= start; j--) { | ||
item = target[j]; | ||
keyVal = key ? item[key] : item; | ||
i = newIndices.get(keyVal); | ||
newIndicesNext[j] = i === undefined ? -1 : i; | ||
newIndices.set(keyVal, j); | ||
} | ||
// step through all old items to check reuse | ||
for (i = start; i <= end; i++) { | ||
item = previous[i]; | ||
keyVal = key ? item[key] : item; | ||
j = newIndices.get(keyVal); | ||
if (j !== undefined && j !== -1) { | ||
temp[j] = mapped[i]; | ||
j = newIndicesNext[j]; | ||
newIndices.set(keyVal, j); | ||
} | ||
} | ||
// set all the new values | ||
for (j = start; j < target.length; j++) { | ||
if (temp.hasOwnProperty(j)) { | ||
setProperty(previous, j, temp[j]); | ||
applyState(target[j], previous, j, mode, key); | ||
} | ||
else setProperty(previous, j, target[j]); | ||
} | ||
} else { | ||
for (let i = 0, len = target.length; i < len; i++) { | ||
applyState(target[i], previous, i, mode, key); | ||
} | ||
} | ||
if (previous.length > target.length) setProperty(previous, 'length', target.length); | ||
return; | ||
} | ||
const targetKeys = Object.keys(target); | ||
for (let i = 0, len = targetKeys.length; i < len; i++) { | ||
applyState(target[targetKeys[i]], previous, targetKeys[i], mode, key); | ||
} | ||
const previousKeys = Object.keys(previous); | ||
for (let i = 0, len = previousKeys.length; i < len; i++) { | ||
if (target[previousKeys[i]] === undefined) setProperty(previous, previousKeys[i], undefined); | ||
} | ||
} | ||
// Diff method for setState | ||
function reconcile(path, options = {}) { | ||
let value; | ||
if (Array.isArray(path)) { | ||
value = path.pop(); | ||
} else if (typeof path === 'object') { | ||
value = path; | ||
path = undefined; | ||
} else { | ||
path = Array.prototype.slice.call(arguments, 0, -1), | ||
value = arguments[arguments.length - 1]; | ||
options = {}; | ||
} | ||
const mode = options.mode !== undefined ? options.mode : DEFAULT, | ||
key = options.key !== undefined ? options.key : 'id'; | ||
return state => { | ||
state = unwrap(state); | ||
for (let i = 0; i < path.length; i += 1) state = state[path[i]]; | ||
return diff(value, state, path); | ||
if (path) { | ||
for (let i = 0; i < path.length - 1; i += 1) state = state[path[i]]; | ||
applyState(value, state, path[path.length - 1], mode, key); | ||
} else applyState(value, { state }, 'state', mode, key); | ||
} | ||
@@ -233,3 +245,3 @@ } | ||
function useSignal(value, comparator) { | ||
const d = S$1.makeDataNode(value); | ||
const d = S.makeDataNode(value); | ||
let setter; | ||
@@ -252,11 +264,33 @@ if (comparator) { | ||
function useMemo(fn, seed) { return S$1(fn, seed); } | ||
function useMemo(fn, seed) { return S(fn, seed); } | ||
function useEffect(fn, deps, defer) { | ||
if (!deps) return S$1.makeComputationNode(fn); | ||
S$1.on(deps, fn, undefined, defer); | ||
if (!deps) return S.makeComputationNode(fn); | ||
S.on(deps, fn, undefined, defer); | ||
} | ||
const { root, cleanup: useCleanup, sample, freeze } = S$1; | ||
// export observable | ||
function observable(input) { | ||
if (Symbol.observable in input) return input[Symbol.observable](); | ||
return { | ||
subscribe(observer) { | ||
if (!(observer instanceof Object) || observer == null) { | ||
throw new TypeError('Expected the observer to be an object.'); | ||
} | ||
observer = observer.next || observer; | ||
let complete = false; | ||
S.on(input, function next() { | ||
if (complete) return; | ||
observer(input()); | ||
}); | ||
return { | ||
unsubscribe() { complete = true; } | ||
}; | ||
}, | ||
[Symbol.observable]() { return this; } | ||
}; | ||
} | ||
export { root, useCleanup, sample, freeze, unwrap, observable, useState, reconcile, useSignal, useMemo, useEffect }; | ||
const { root, cleanup: useCleanup, sample, freeze } = S; | ||
export { root, useCleanup, sample, freeze, useState, unwrap, reconcile, useSignal, useMemo, useEffect, observable }; |
@@ -25,6 +25,22 @@ # State | ||
This can be used to do deep diffs by producing the list of changes to apply from a new State value. This is useful when pulling in immutable data trees from stores to ensure the least amount of mutations to your state. It can also be used to replace the all keys on the base state object if no path is provided as it does both positive and negative diff. | ||
This can be used to do deep diffs by applying the changes from a new State value. This is useful when pulling in immutable data trees from stores to ensure the least amount of mutations to your state. It can also be used to replace the all keys on the base state object if no path is provided as it does both positive and negative diff. | ||
```js | ||
setState(reconcile('users', store.get('users'))) | ||
``` | ||
``` | ||
If you pass as array you can configure the diff algorithm with an options object: | ||
```js | ||
setState(reconcile( | ||
['users', store.get('users')], | ||
{ | ||
mode: 'force' // type of comparison - default: 'default' | ||
key: '_id' // does a keyed comparison on arrays with key - default: 'id' | ||
} | ||
)) | ||
``` | ||
<b>Modes</b> | ||
* default: tries to detect array position changes by ref when not keyed | ||
* merge: overwrites rather than detects array position changes when not keyed | ||
* force: updates everything assuming 100% dirty |
280
lib/solid.js
@@ -7,50 +7,34 @@ 'use strict'; | ||
var S$1 = _interopDefault(require('s-js')); | ||
var S = _interopDefault(require('s-js')); | ||
function comparer(v, k, b, isArray, path, r) { | ||
let index; | ||
const newPath = path.concat([k]); | ||
if (isArray && v != null && typeof v === 'object' | ||
&& k != (index = b.findIndex(i => i && (i === v || (v.id != null && i.id === v.id) || (v._id != null && i._id === v._id))))) { | ||
return r.push(newPath.concat([index > -1 ? b[index] : v])); | ||
} | ||
return r.push.apply(r, diff(v, b[k], newPath)); | ||
} | ||
const SNODE = Symbol('solid-node'), | ||
SPROXY = Symbol('solid-proxy'); | ||
function isWrappable(obj) { return obj !== null && typeof obj === 'object' && !(obj instanceof Element); } | ||
function diff(a, b, path = []) { | ||
let i, k, l, len, v; | ||
const r = []; | ||
if (!isWrappable(a) || (b == null)) { | ||
if (a !== b) { | ||
r.push(path.concat([a])); | ||
} | ||
} else if (Array.isArray(a)) { | ||
for (k = i = 0, len = a.length; i < len; k = ++i) { | ||
v = a[k]; | ||
if ((b != null ? b[k] : void 0) !== v) comparer(v, k, b, true, path, r); | ||
} | ||
if ((b != null ? b.length : void 0) > a.length) { | ||
l = a.length; | ||
while (l < b.length) { | ||
r.push(path.concat([l, void 0])); | ||
l++; | ||
const proxyTraps = { | ||
get(target, property) { | ||
if (property === '_state') return target; | ||
const value = target[property], | ||
wrappable = isWrappable(value); | ||
if (S.isListening() && typeof value !== 'function') { | ||
let nodes, node; | ||
if (wrappable && (nodes = getDataNodes(value))) { | ||
node = nodes._self || (nodes._self = S.makeDataNode()); | ||
node.current(); | ||
} | ||
nodes = getDataNodes(target); | ||
node = nodes[property] || (nodes[property] = S.makeDataNode()); | ||
node.current(); | ||
} | ||
} else { | ||
for (k in a) { | ||
v = a[k]; | ||
if ((b != null ? b[k] : void 0) !== v) | ||
comparer(v, k, b, false, path, r); | ||
} | ||
for (k in b) { | ||
v = b[k]; | ||
if (!(k in a)) | ||
r.push(path.concat([k, void 0])); | ||
} | ||
} | ||
return r; | ||
} | ||
return wrappable ? wrap(value) : value; | ||
}, | ||
set() { return true; }, | ||
deleteProperty() { return true; } | ||
}; | ||
function wrap(value) { return value[SPROXY] || (value[SPROXY] = new Proxy(value, proxyTraps)); } | ||
function isWrappable(obj) { return obj !== null && typeof obj === 'object' && !(obj instanceof Element); } | ||
function unwrap(item) { | ||
@@ -78,52 +62,2 @@ let result, unwrapped, v; | ||
// export observable | ||
function observable(input) { | ||
if (Symbol.observable in input) return input[Symbol.observable](); | ||
return { | ||
subscribe(observer) { | ||
if (!(observer instanceof Object) || observer == null) { | ||
throw new TypeError('Expected the observer to be an object.'); | ||
} | ||
observer = observer.next || observer; | ||
let complete = false; | ||
S.on(input, function next() { | ||
if (complete) return; | ||
observer(input()); | ||
}); | ||
return { | ||
unsubscribe() { complete = true; } | ||
}; | ||
}, | ||
[Symbol.observable]() { return this; } | ||
}; | ||
} | ||
const SNODE = Symbol('solid-node'), | ||
SPROXY = Symbol('solid-proxy'); | ||
const proxyTraps = { | ||
get(target, property) { | ||
if (property === '_state') return target; | ||
const value = target[property], | ||
wrappable = isWrappable(value); | ||
if (S$1.isListening() && typeof value !== 'function') { | ||
let nodes, node; | ||
if (wrappable && (nodes = getDataNodes(value))) { | ||
node = nodes._self || (nodes._self = S$1.makeDataNode()); | ||
node.current(); | ||
} | ||
nodes = getDataNodes(target); | ||
node = nodes[property] || (nodes[property] = S$1.makeDataNode()); | ||
node.current(); | ||
} | ||
return wrappable ? wrap(value) : value; | ||
}, | ||
set() { return true; }, | ||
deleteProperty() { return true; } | ||
}; | ||
function wrap(value) { return value[SPROXY] || (value[SPROXY] = new Proxy(value, proxyTraps)); } | ||
function getDataNodes(target) { | ||
@@ -135,11 +69,9 @@ let nodes = target[SNODE]; | ||
function setProperty(state, property, value) { | ||
function setProperty(state, property, value, force) { | ||
value = unwrap(value); | ||
if (state[property] === value) return; | ||
if (!force && state[property] === value) return; | ||
const notify = Array.isArray(state) || !(property in state); | ||
if (value === void 0) { | ||
delete state[property]; | ||
if (Array.isArray(state)) state.length -= 1; | ||
} | ||
else state[property] = value; | ||
} else state[property] = value; | ||
let nodes = getDataNodes(state), node; | ||
@@ -158,3 +90,3 @@ (node = nodes[property]) && node.next(); | ||
function updatePath(current, path, traversed = [], replace) { | ||
function updatePath(current, path, traversed = []) { | ||
if (path.length === 1) { | ||
@@ -164,8 +96,4 @@ let value = path[0]; | ||
value = value(wrap(current), traversed); | ||
// deep map | ||
if (Array.isArray(value)) { | ||
for (let i = 0; i < value.length; i += 1) | ||
updatePath(current, value[i], traversed, true); | ||
return; | ||
} | ||
// reconciled | ||
if (value === undefined) return; | ||
} | ||
@@ -182,7 +110,7 @@ return mergeState(current, value); | ||
for (let i = 0; i < part.length; i++) | ||
updatePath(current, [part[i]].concat(path), traversed.concat([part[i]]), replace); | ||
updatePath(current, [part[i]].concat(path), traversed.concat([part[i]])); | ||
} else if (isArray && partType === 'function') { | ||
// Ex. update('data', i => i.id === 42, 'label', l => l + ' !!!'); | ||
for (let i = 0; i < current.length; i++) | ||
if (part(current[i], i)) updatePath(current[i], path.slice(0), traversed.concat([i]), replace); | ||
if (part(current[i], i)) updatePath(current[i], path.slice(0), traversed.concat([i])); | ||
} else if (isArray && partType === 'object') { | ||
@@ -192,7 +120,7 @@ // Ex. update('data', { from: 3, to: 12, by: 2 }, 'label', l => l + ' !!!'); | ||
for (let i = from; i <= to; i += by) | ||
updatePath(current[i], path.slice(0), traversed.concat([i]), replace); | ||
updatePath(current[i], path.slice(0), traversed.concat([i])); | ||
} else if (isArray && part === '*') { | ||
// Ex. update('data', '*', 'label', l => l + ' !!!'); | ||
for (let i = 0; i < current.length; i++) | ||
updatePath(current, [i].concat(path), traversed.concat([i]), replace); | ||
updatePath(current, [i].concat(path), traversed.concat([i])); | ||
} else if (path.length === 1) { | ||
@@ -204,6 +132,6 @@ let value = path[0]; | ||
} | ||
if (!replace && isWrappable(current[part]) && isWrappable(value) && !Array.isArray(value)) | ||
if (isWrappable(current[part]) && isWrappable(value) && !Array.isArray(value)) | ||
return mergeState(current[part], value); | ||
return setProperty(current, part, value); | ||
} else updatePath(current[part], path, traversed.concat([part]), replace); | ||
} else updatePath(current[part], path, traversed.concat([part])); | ||
} | ||
@@ -218,3 +146,3 @@ | ||
const args = arguments; | ||
S$1.freeze(() => { | ||
S.freeze(() => { | ||
if (Array.isArray(args[0])) { | ||
@@ -228,9 +156,93 @@ for (let i = 0; i < args.length; i += 1) | ||
function reconcile() { | ||
const path = Array.prototype.slice.call(arguments, 0, -1), | ||
const DEFAULT = 'default', | ||
MERGE = 'merge', | ||
FORCE = 'force'; | ||
function applyState(target, parent, property, mode, key) { | ||
let previous = parent[property], force = mode === FORCE; | ||
if (!force && target === previous) return; | ||
if (!isWrappable(target) || (previous == null)) { | ||
return (force || target !== previous) && setProperty(parent, property, target, force); | ||
} | ||
if (Array.isArray(target)) { | ||
if (target.length && previous.length && (mode === DEFAULT | ||
|| (key && mode === MERGE && target[0][key] != null))) { | ||
// skip common prefix and suffix | ||
let i, j, start, end, newEnd, item, newIndicesNext, keyVal, | ||
temp = new Array(target.length), | ||
newIndices = new Map(); | ||
for (start = 0, end = Math.min(previous.length, target.length); start < end && (previous[start] === target[start] || key && previous[start][key] === target[start][key]); start++) | ||
applyState(target[start], previous, start, mode, key); | ||
for (end = previous.length - 1, newEnd = target.length - 1; end >= 0 && newEnd >= 0 && (previous[end] === target[newEnd] || key && previous[end][key] === target[newEnd][key]); end--, newEnd--) | ||
temp[newEnd] = previous[end]; | ||
// prepare a map of all indices in target | ||
newIndicesNext = new Array(newEnd + 1); | ||
for (j = newEnd; j >= start; j--) { | ||
item = target[j]; | ||
keyVal = key ? item[key] : item; | ||
i = newIndices.get(keyVal); | ||
newIndicesNext[j] = i === undefined ? -1 : i; | ||
newIndices.set(keyVal, j); | ||
} | ||
// step through all old items to check reuse | ||
for (i = start; i <= end; i++) { | ||
item = previous[i]; | ||
keyVal = key ? item[key] : item; | ||
j = newIndices.get(keyVal); | ||
if (j !== undefined && j !== -1) { | ||
temp[j] = mapped[i]; | ||
j = newIndicesNext[j]; | ||
newIndices.set(keyVal, j); | ||
} | ||
} | ||
// set all the new values | ||
for (j = start; j < target.length; j++) { | ||
if (temp.hasOwnProperty(j)) { | ||
setProperty(previous, j, temp[j]); | ||
applyState(target[j], previous, j, mode, key); | ||
} | ||
else setProperty(previous, j, target[j]); | ||
} | ||
} else { | ||
for (let i = 0, len = target.length; i < len; i++) { | ||
applyState(target[i], previous, i, mode, key); | ||
} | ||
} | ||
if (previous.length > target.length) setProperty(previous, 'length', target.length); | ||
return; | ||
} | ||
const targetKeys = Object.keys(target); | ||
for (let i = 0, len = targetKeys.length; i < len; i++) { | ||
applyState(target[targetKeys[i]], previous, targetKeys[i], mode, key); | ||
} | ||
const previousKeys = Object.keys(previous); | ||
for (let i = 0, len = previousKeys.length; i < len; i++) { | ||
if (target[previousKeys[i]] === undefined) setProperty(previous, previousKeys[i], undefined); | ||
} | ||
} | ||
// Diff method for setState | ||
function reconcile(path, options = {}) { | ||
let value; | ||
if (Array.isArray(path)) { | ||
value = path.pop(); | ||
} else if (typeof path === 'object') { | ||
value = path; | ||
path = undefined; | ||
} else { | ||
path = Array.prototype.slice.call(arguments, 0, -1), | ||
value = arguments[arguments.length - 1]; | ||
options = {}; | ||
} | ||
const mode = options.mode !== undefined ? options.mode : DEFAULT, | ||
key = options.key !== undefined ? options.key : 'id'; | ||
return state => { | ||
state = unwrap(state); | ||
for (let i = 0; i < path.length; i += 1) state = state[path[i]]; | ||
return diff(value, state, path); | ||
if (path) { | ||
for (let i = 0; i < path.length - 1; i += 1) state = state[path[i]]; | ||
applyState(value, state, path[path.length - 1], mode, key); | ||
} else applyState(value, { state }, 'state', mode, key); | ||
} | ||
@@ -240,3 +252,3 @@ } | ||
function useSignal(value, comparator) { | ||
const d = S$1.makeDataNode(value); | ||
const d = S.makeDataNode(value); | ||
let setter; | ||
@@ -259,11 +271,33 @@ if (comparator) { | ||
function useMemo(fn, seed) { return S$1(fn, seed); } | ||
function useMemo(fn, seed) { return S(fn, seed); } | ||
function useEffect(fn, deps, defer) { | ||
if (!deps) return S$1.makeComputationNode(fn); | ||
S$1.on(deps, fn, undefined, defer); | ||
if (!deps) return S.makeComputationNode(fn); | ||
S.on(deps, fn, undefined, defer); | ||
} | ||
const { root, cleanup: useCleanup, sample, freeze } = S$1; | ||
// export observable | ||
function observable(input) { | ||
if (Symbol.observable in input) return input[Symbol.observable](); | ||
return { | ||
subscribe(observer) { | ||
if (!(observer instanceof Object) || observer == null) { | ||
throw new TypeError('Expected the observer to be an object.'); | ||
} | ||
observer = observer.next || observer; | ||
let complete = false; | ||
S.on(input, function next() { | ||
if (complete) return; | ||
observer(input()); | ||
}); | ||
return { | ||
unsubscribe() { complete = true; } | ||
}; | ||
}, | ||
[Symbol.observable]() { return this; } | ||
}; | ||
} | ||
const { root, cleanup: useCleanup, sample, freeze } = S; | ||
exports.root = root; | ||
@@ -273,5 +307,4 @@ exports.useCleanup = useCleanup; | ||
exports.freeze = freeze; | ||
exports.useState = useState; | ||
exports.unwrap = unwrap; | ||
exports.observable = observable; | ||
exports.useState = useState; | ||
exports.reconcile = reconcile; | ||
@@ -281,1 +314,2 @@ exports.useSignal = useSignal; | ||
exports.useEffect = useEffect; | ||
exports.observable = observable; |
{ | ||
"name": "solid-js", | ||
"description": "A declarative JavaScript library for building user interfaces.", | ||
"version": "0.3.4", | ||
"version": "0.3.5", | ||
"author": "Ryan Carniato", | ||
@@ -27,5 +27,5 @@ "license": "MIT", | ||
"jest": "~23.6.0", | ||
"rollup": "^1.0.0", | ||
"rollup": "^1.1.0", | ||
"rollup-plugin-node-resolve": "^4.0.0" | ||
} | ||
} |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
51493
706
1