'use strict'; var solidJs = require('solid-js'); const $RAW = Symbol("store-raw"), $NODE = Symbol("store-node"), $HAS = Symbol("store-has"), $SELF = Symbol("store-self"); const DevHooks = { onStoreNodeUpdate: null }; function wrap$1(value) { let p = value[solidJs.$PROXY]; if (!p) { Object.defineProperty(value, solidJs.$PROXY, { value: p = new Proxy(value, proxyTraps$1) }); if (!Array.isArray(value)) { const keys = Object.keys(value), desc = Object.getOwnPropertyDescriptors(value); for (let i = 0, l = keys.length; i < l; i++) { const prop = keys[i]; if (desc[prop].get) { Object.defineProperty(value, prop, { enumerable: desc[prop].enumerable, get: desc[prop].get.bind(p) }); } } } } return p; } function isWrappable(obj) { let proto; return obj != null && typeof obj === "object" && (obj[solidJs.$PROXY] || !(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype || Array.isArray(obj)); } function unwrap(item, set = new Set()) { let result, unwrapped, v, prop; if (result = item != null && item[$RAW]) return result; if (!isWrappable(item) || set.has(item)) return item; if (Array.isArray(item)) { if (Object.isFrozen(item)) item = item.slice(0);else set.add(item); for (let i = 0, l = item.length; i < l; i++) { v = item[i]; if ((unwrapped = unwrap(v, set)) !== v) item[i] = unwrapped; } } else { if (Object.isFrozen(item)) item = Object.assign({}, item);else set.add(item); const keys = Object.keys(item), desc = Object.getOwnPropertyDescriptors(item); for (let i = 0, l = keys.length; i < l; i++) { prop = keys[i]; if (desc[prop].get) continue; v = item[prop]; if ((unwrapped = unwrap(v, set)) !== v) item[prop] = unwrapped; } } return item; } function getNodes(target, symbol) { let nodes = target[symbol]; if (!nodes) Object.defineProperty(target, symbol, { value: nodes = Object.create(null) }); return nodes; } function getNode(nodes, property, value) { if (nodes[property]) return nodes[property]; const [s, set] = solidJs.createSignal(value, { equals: false, internal: true }); s.$ = set; return nodes[property] = s; } function proxyDescriptor$1(target, property) { const desc = Reflect.getOwnPropertyDescriptor(target, property); if (!desc || desc.get || !desc.configurable || property === solidJs.$PROXY || property === $NODE) return desc; delete desc.value; delete desc.writable; desc.get = () => target[solidJs.$PROXY][property]; return desc; } function trackSelf(target) { solidJs.getListener() && getNode(getNodes(target, $NODE), $SELF)(); } function ownKeys(target) { trackSelf(target); return Reflect.ownKeys(target); } const proxyTraps$1 = { get(target, property, receiver) { if (property === $RAW) return target; if (property === solidJs.$PROXY) return receiver; if (property === solidJs.$TRACK) { trackSelf(target); return receiver; } const nodes = getNodes(target, $NODE); const tracked = nodes[property]; let value = tracked ? tracked() : target[property]; if (property === $NODE || property === $HAS || property === "__proto__") return value; if (!tracked) { const desc = Object.getOwnPropertyDescriptor(target, property); if (solidJs.getListener() && (typeof value !== "function" || target.hasOwnProperty(property)) && !(desc && desc.get)) value = getNode(nodes, property, value)(); } return isWrappable(value) ? wrap$1(value) : value; }, has(target, property) { if (property === $RAW || property === solidJs.$PROXY || property === solidJs.$TRACK || property === $NODE || property === $HAS || property === "__proto__") return true; solidJs.getListener() && getNode(getNodes(target, $HAS), property)(); return property in target; }, set() { console.warn("Cannot mutate a Store directly"); return true; }, deleteProperty() { console.warn("Cannot mutate a Store directly"); return true; }, ownKeys: ownKeys, getOwnPropertyDescriptor: proxyDescriptor$1 }; function setProperty(state, property, value, deleting = false) { if (!deleting && state[property] === value) return; const prev = state[property], len = state.length; DevHooks.onStoreNodeUpdate && DevHooks.onStoreNodeUpdate(state, property, value, prev); if (value === undefined) { delete state[property]; if (state[$HAS] && state[$HAS][property] && prev !== undefined) state[$HAS][property].$(); } else { state[property] = value; if (state[$HAS] && state[$HAS][property] && prev === undefined) state[$HAS][property].$(); } let nodes = getNodes(state, $NODE), node; if (node = getNode(nodes, property, prev)) node.$(() => value); if (Array.isArray(state) && state.length !== len) { for (let i = state.length; i < len; i++) (node = nodes[i]) && node.$(); (node = getNode(nodes, "length", len)) && node.$(state.length); } (node = nodes[$SELF]) && node.$(); } function mergeStoreNode(state, value) { const keys = Object.keys(value); for (let i = 0; i < keys.length; i += 1) { const key = keys[i]; setProperty(state, key, value[key]); } } function updateArray(current, next) { if (typeof next === "function") next = next(current); next = unwrap(next); if (Array.isArray(next)) { if (current === next) return; let i = 0, len = next.length; for (; i < len; i++) { const value = next[i]; if (current[i] !== value) setProperty(current, i, value); } setProperty(current, "length", len); } else mergeStoreNode(current, next); } function updatePath(current, path, traversed = []) { let part, prev = current; if (path.length > 1) { part = path.shift(); const partType = typeof part, isArray = Array.isArray(current); if (Array.isArray(part)) { for (let i = 0; i < part.length; i++) { updatePath(current, [part[i]].concat(path), traversed); } return; } else if (isArray && partType === "function") { for (let i = 0; i < current.length; i++) { if (part(current[i], i)) updatePath(current, [i].concat(path), traversed); } return; } else if (isArray && partType === "object") { const { from = 0, to = current.length - 1, by = 1 } = part; for (let i = from; i <= to; i += by) { updatePath(current, [i].concat(path), traversed); } return; } else if (path.length > 1) { updatePath(current[part], path, [part].concat(traversed)); return; } prev = current[part]; traversed = [part].concat(traversed); } let value = path[0]; if (typeof value === "function") { value = value(prev, traversed); if (value === prev) return; } if (part === undefined && value == undefined) return; value = unwrap(value); if (part === undefined || isWrappable(prev) && isWrappable(value) && !Array.isArray(value)) { mergeStoreNode(prev, value); } else setProperty(current, part, value); } function createStore(...[store, options]) { const unwrappedStore = unwrap(store || {}); const isArray = Array.isArray(unwrappedStore); if (typeof unwrappedStore !== "object" && typeof unwrappedStore !== "function") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createStore'. Expected an object.`); const wrappedStore = wrap$1(unwrappedStore); solidJs.DEV.registerGraph({ value: unwrappedStore, name: options && options.name }); function setStore(...args) { solidJs.batch(() => { isArray && args.length === 1 ? updateArray(unwrappedStore, args[0]) : updatePath(unwrappedStore, args); }); } return [wrappedStore, setStore]; } function proxyDescriptor(target, property) { const desc = Reflect.getOwnPropertyDescriptor(target, property); if (!desc || desc.get || desc.set || !desc.configurable || property === solidJs.$PROXY || property === $NODE) return desc; delete desc.value; delete desc.writable; desc.get = () => target[solidJs.$PROXY][property]; desc.set = v => target[solidJs.$PROXY][property] = v; return desc; } const proxyTraps = { get(target, property, receiver) { if (property === $RAW) return target; if (property === solidJs.$PROXY) return receiver; if (property === solidJs.$TRACK) { trackSelf(target); return receiver; } const nodes = getNodes(target, $NODE); const tracked = nodes[property]; let value = tracked ? tracked() : target[property]; if (property === $NODE || property === $HAS || property === "__proto__") return value; if (!tracked) { const desc = Object.getOwnPropertyDescriptor(target, property); const isFunction = typeof value === "function"; if (solidJs.getListener() && (!isFunction || target.hasOwnProperty(property)) && !(desc && desc.get)) value = getNode(nodes, property, value)();else if (value != null && isFunction && value === Array.prototype[property]) { return (...args) => solidJs.batch(() => Array.prototype[property].apply(receiver, args)); } } return isWrappable(value) ? wrap(value) : value; }, has(target, property) { if (property === $RAW || property === solidJs.$PROXY || property === solidJs.$TRACK || property === $NODE || property === $HAS || property === "__proto__") return true; solidJs.getListener() && getNode(getNodes(target, $HAS), property)(); return property in target; }, set(target, property, value) { solidJs.batch(() => setProperty(target, property, unwrap(value))); return true; }, deleteProperty(target, property) { solidJs.batch(() => setProperty(target, property, undefined, true)); return true; }, ownKeys: ownKeys, getOwnPropertyDescriptor: proxyDescriptor }; function wrap(value) { let p = value[solidJs.$PROXY]; if (!p) { Object.defineProperty(value, solidJs.$PROXY, { value: p = new Proxy(value, proxyTraps) }); const keys = Object.keys(value), desc = Object.getOwnPropertyDescriptors(value); const proto = Object.getPrototypeOf(value); const isClass = value !== null && typeof value === "object" && !Array.isArray(value) && proto !== Object.prototype; if (isClass) { const descriptors = Object.getOwnPropertyDescriptors(proto); keys.push(...Object.keys(descriptors)); Object.assign(desc, descriptors); } for (let i = 0, l = keys.length; i < l; i++) { const prop = keys[i]; if (isClass && prop === "constructor") continue; if (desc[prop].get) { const get = desc[prop].get.bind(p); Object.defineProperty(value, prop, { get, configurable: true }); } if (desc[prop].set) { const og = desc[prop].set, set = v => solidJs.batch(() => og.call(p, v)); Object.defineProperty(value, prop, { set, configurable: true }); } } } return p; } function createMutable(state, options) { const unwrappedStore = unwrap(state || {}); if (typeof unwrappedStore !== "object" && typeof unwrappedStore !== "function") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createMutable'. Expected an object.`); const wrappedStore = wrap(unwrappedStore); solidJs.DEV.registerGraph({ value: unwrappedStore, name: options && options.name }); return wrappedStore; } function modifyMutable(state, modifier) { solidJs.batch(() => modifier(unwrap(state))); } const $ROOT = Symbol("store-root"); function applyState(target, parent, property, merge, key) { const previous = parent[property]; if (target === previous) return; const isArray = Array.isArray(target); if (property !== $ROOT && (!isWrappable(target) || !isWrappable(previous) || isArray !== Array.isArray(previous) || key && target[key] !== previous[key])) { setProperty(parent, property, target); return; } if (isArray) { if (target.length && previous.length && (!merge || key && target[0] && target[0][key] != null)) { let i, j, start, end, newEnd, item, newIndicesNext, keyVal; for (start = 0, end = Math.min(previous.length, target.length); start < end && (previous[start] === target[start] || key && previous[start] && target[start] && previous[start][key] === target[start][key]); start++) { applyState(target[start], previous, start, merge, key); } const temp = new Array(target.length), newIndices = new Map(); for (end = previous.length - 1, newEnd = target.length - 1; end >= start && newEnd >= start && (previous[end] === target[newEnd] || key && previous[start] && target[start] && previous[end][key] === target[newEnd][key]); end--, newEnd--) { temp[newEnd] = previous[end]; } if (start > newEnd || start > end) { for (j = start; j <= newEnd; j++) setProperty(previous, j, target[j]); for (; j < target.length; j++) { setProperty(previous, j, temp[j]); applyState(target[j], previous, j, merge, key); } if (previous.length > target.length) setProperty(previous, "length", target.length); return; } newIndicesNext = new Array(newEnd + 1); for (j = newEnd; j >= start; j--) { item = target[j]; keyVal = key && item ? item[key] : item; i = newIndices.get(keyVal); newIndicesNext[j] = i === undefined ? -1 : i; newIndices.set(keyVal, j); } for (i = start; i <= end; i++) { item = previous[i]; keyVal = key && item ? item[key] : item; j = newIndices.get(keyVal); if (j !== undefined && j !== -1) { temp[j] = previous[i]; j = newIndicesNext[j]; newIndices.set(keyVal, j); } } for (j = start; j < target.length; j++) { if (j in temp) { setProperty(previous, j, temp[j]); applyState(target[j], previous, j, merge, key); } else setProperty(previous, j, target[j]); } } else { for (let i = 0, len = target.length; i < len; i++) { applyState(target[i], previous, i, merge, 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], merge, 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); } } function reconcile(value, options = {}) { const { merge, key = "id" } = options, v = unwrap(value); return state => { if (!isWrappable(state) || !isWrappable(v)) return v; const res = applyState(v, { [$ROOT]: state }, $ROOT, merge, key); return res === undefined ? state : res; }; } const producers = new WeakMap(); const setterTraps = { get(target, property) { if (property === $RAW) return target; const value = target[property]; let proxy; return isWrappable(value) ? producers.get(value) || (producers.set(value, proxy = new Proxy(value, setterTraps)), proxy) : value; }, set(target, property, value) { setProperty(target, property, unwrap(value)); return true; }, deleteProperty(target, property) { setProperty(target, property, undefined, true); return true; } }; function produce(fn) { return state => { if (isWrappable(state)) { let proxy; if (!(proxy = producers.get(state))) { producers.set(state, proxy = new Proxy(state, setterTraps)); } fn(proxy); } return state; }; } const DEV = { $NODE, isWrappable, hooks: DevHooks } ; exports.$RAW = $RAW; exports.DEV = DEV; exports.createMutable = createMutable; exports.createStore = createStore; exports.modifyMutable = modifyMutable; exports.produce = produce; exports.reconcile = reconcile; exports.unwrap = unwrap;