solid-js 1.3.17 → 1.4.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/solid.js CHANGED
@@ -127,6 +127,7 @@ function nextHydrateContext() {
127
127
 
128
128
  const equalFn = (a, b) => a === b;
129
129
  const $PROXY = Symbol("solid-proxy");
130
+ const $TRACK = Symbol("solid-track");
130
131
  const $DEVCOMP = Symbol("solid-dev-component");
131
132
  const signalOptions = {
132
133
  equals: equalFn
@@ -201,7 +202,7 @@ function createEffect(fn, value, options) {
201
202
  s = SuspenseContext && lookup(Owner, SuspenseContext.id);
202
203
  if (s) c.suspense = s;
203
204
  c.user = true;
204
- Effects ? Effects.push(c) : queueMicrotask(() => updateComputation(c));
205
+ Effects ? Effects.push(c) : updateComputation(c);
205
206
  }
206
207
  function createReaction(onInvalidate, options) {
207
208
  let fn;
@@ -242,13 +243,8 @@ function createResource(source, fetcher, options) {
242
243
  source = true;
243
244
  }
244
245
  options || (options = {});
245
- if (options.globalRefetch !== false) {
246
- Resources || (Resources = new Set());
247
- Resources.add(load);
248
- Owner && onCleanup(() => Resources.delete(load));
249
- }
250
246
  const contexts = new Set(),
251
- [s, set] = createSignal(options.initialValue),
247
+ [value, setValue] = createSignal(options.initialValue),
252
248
  [track, trigger] = createSignal(undefined, {
253
249
  equals: false
254
250
  }),
@@ -260,7 +256,8 @@ function createResource(source, fetcher, options) {
260
256
  id = null,
261
257
  loadedUnderTransition = false,
262
258
  scheduled = false,
263
- dynamic = typeof source === "function";
259
+ resolved = ("initialValue" in options),
260
+ dynamic = typeof source === "function" && createMemo(source);
264
261
  if (sharedConfig.context) {
265
262
  id = `${sharedConfig.context.id}${sharedConfig.context.count++}`;
266
263
  if (sharedConfig.load) initP = sharedConfig.load(id);
@@ -268,6 +265,7 @@ function createResource(source, fetcher, options) {
268
265
  function loadEnd(p, v, e, key) {
269
266
  if (pr === p) {
270
267
  pr = null;
268
+ resolved = true;
271
269
  if (initP && p === initP && options.onHydrated) options.onHydrated(key, {
272
270
  value: v
273
271
  });
@@ -290,7 +288,7 @@ function createResource(source, fetcher, options) {
290
288
  }
291
289
  function completeLoad(v) {
292
290
  batch(() => {
293
- set(() => v);
291
+ setValue(() => v);
294
292
  setLoading(false);
295
293
  for (const c of contexts.keys()) c.decrement();
296
294
  contexts.clear();
@@ -298,7 +296,7 @@ function createResource(source, fetcher, options) {
298
296
  }
299
297
  function read() {
300
298
  const c = SuspenseContext && lookup(Owner, SuspenseContext.id),
301
- v = s();
299
+ v = value();
302
300
  if (err) throw err;
303
301
  if (Listener && !Listener.user && c) {
304
302
  createComputed(() => {
@@ -317,15 +315,15 @@ function createResource(source, fetcher, options) {
317
315
  if (refetching && scheduled) return;
318
316
  scheduled = false;
319
317
  setError(err = undefined);
320
- const lookup = dynamic ? source() : source;
318
+ const lookup = dynamic ? dynamic() : source;
321
319
  loadedUnderTransition = Transition && Transition.running;
322
320
  if (lookup == null || lookup === false) {
323
- loadEnd(pr, untrack(s));
321
+ loadEnd(pr, untrack(value));
324
322
  return;
325
323
  }
326
324
  if (Transition && pr) Transition.promises.delete(pr);
327
325
  const p = initP || untrack(() => fetcher(lookup, {
328
- value: s(),
326
+ value: value(),
329
327
  refetching
330
328
  }));
331
329
  if (typeof p !== "object" || !("then" in p)) {
@@ -351,18 +349,21 @@ function createResource(source, fetcher, options) {
351
349
  get() {
352
350
  return error();
353
351
  }
352
+ },
353
+ latest: {
354
+ get() {
355
+ if (!resolved) return read();
356
+ if (err) throw err;
357
+ return value();
358
+ }
354
359
  }
355
360
  });
356
361
  if (dynamic) createComputed(() => load(false));else load(false);
357
362
  return [read, {
358
363
  refetch: load,
359
- mutate: set
364
+ mutate: setValue
360
365
  }];
361
366
  }
362
- let Resources;
363
- function refetchResources(info) {
364
- return Resources && Promise.all([...Resources].map(fn => fn(info)));
365
- }
366
367
  function createDeferred(source, options) {
367
368
  let t,
368
369
  timeout = options ? options.timeoutMs : undefined;
@@ -736,11 +737,14 @@ function runUpdates(fn, init) {
736
737
  if (Effects) wait = true;else Effects = [];
737
738
  ExecCount++;
738
739
  try {
739
- return fn();
740
+ const res = fn();
741
+ completeUpdates(wait);
742
+ return res;
740
743
  } catch (err) {
741
744
  handleError(err);
742
745
  } finally {
743
- completeUpdates(wait);
746
+ Updates = null;
747
+ if (!wait) Effects = null;
744
748
  }
745
749
  }
746
750
  function completeUpdates(wait) {
@@ -981,6 +985,7 @@ function mapArray(list, mapFn, options = {}) {
981
985
  let newItems = list() || [],
982
986
  i,
983
987
  j;
988
+ newItems[$TRACK];
984
989
  return untrack(() => {
985
990
  let newLen = newItems.length,
986
991
  newIndices,
@@ -1082,6 +1087,7 @@ function indexArray(list, mapFn, options = {}) {
1082
1087
  onCleanup(() => dispose(disposers));
1083
1088
  return () => {
1084
1089
  const newItems = list() || [];
1090
+ newItems[$TRACK];
1085
1091
  return untrack(() => {
1086
1092
  if (newItems.length === 0) {
1087
1093
  if (len !== 0) {
@@ -1141,12 +1147,12 @@ function createComponent(Comp, props) {
1141
1147
  if (sharedConfig.context) {
1142
1148
  const c = sharedConfig.context;
1143
1149
  setHydrateContext(nextHydrateContext());
1144
- const r = untrack(() => Comp(props));
1150
+ const r = untrack(() => Comp(props || {}));
1145
1151
  setHydrateContext(c);
1146
1152
  return r;
1147
1153
  }
1148
1154
  }
1149
- return untrack(() => Comp(props));
1155
+ return untrack(() => Comp(props || {}));
1150
1156
  }
1151
1157
  function trueFn() {
1152
1158
  return true;
@@ -1177,7 +1183,7 @@ const propTraps = {
1177
1183
  }
1178
1184
  };
1179
1185
  function resolveSource(s) {
1180
- return typeof s === "function" ? s() : s;
1186
+ return (s = typeof s === "function" ? s() : s) == null ? {} : s;
1181
1187
  }
1182
1188
  function mergeProps(...sources) {
1183
1189
  return new Proxy({
@@ -1245,9 +1251,7 @@ function lazy(fn) {
1245
1251
  });
1246
1252
  comp = s;
1247
1253
  } else if (!comp) {
1248
- const [s] = createResource(() => (p || (p = fn())).then(mod => mod.default), {
1249
- globalRefetch: false
1250
- });
1254
+ const [s] = createResource(() => (p || (p = fn())).then(mod => mod.default));
1251
1255
  comp = s;
1252
1256
  } else {
1253
1257
  const c = comp();
@@ -1499,4 +1503,4 @@ function Suspense(props) {
1499
1503
 
1500
1504
  let DEV;
1501
1505
 
1502
- export { $DEVCOMP, $PROXY, DEV, ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, batch, cancelCallback, children, createComponent, createComputed, createContext, createDeferred, createEffect, createMemo, createReaction, createRenderEffect, createResource, createRoot, createSelector, createSignal, createUniqueId, enableExternalSource, enableHydration, enableScheduling, equalFn, from, getListener, getOwner, indexArray, lazy, mapArray, mergeProps, observable, on, onCleanup, onError, onMount, refetchResources, requestCallback, resetErrorBoundaries, runWithOwner, sharedConfig, splitProps, startTransition, untrack, useContext, useTransition };
1506
+ export { $DEVCOMP, $PROXY, $TRACK, DEV, ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, batch, cancelCallback, children, createComponent, createComputed, createContext, createDeferred, createEffect, createMemo, createReaction, createRenderEffect, createResource, createRoot, createSelector, createSignal, createUniqueId, enableExternalSource, enableHydration, enableScheduling, equalFn, from, getListener, getOwner, indexArray, lazy, mapArray, mergeProps, observable, on, onCleanup, onError, onMount, requestCallback, resetErrorBoundaries, runWithOwner, sharedConfig, splitProps, startTransition, untrack, useContext, useTransition };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "solid-js",
3
3
  "description": "A declarative JavaScript library for building user interfaces.",
4
- "version": "1.3.17",
4
+ "version": "1.4.0-beta.2",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "homepage": "https://solidjs.com",
@@ -144,5 +144,5 @@
144
144
  "compiler",
145
145
  "performance"
146
146
  ],
147
- "gitHead": "88ce357264a4966d38d143143a3efe8a394e57c0"
147
+ "gitHead": "40902779866f8006cc5460c6ff82dbadf85d3f0f"
148
148
  }
@@ -71,11 +71,14 @@ function proxyDescriptor(target, property) {
71
71
  desc.get = () => target[solidJs.$PROXY][property];
72
72
  return desc;
73
73
  }
74
- function ownKeys(target) {
74
+ function trackSelf(target) {
75
75
  if (solidJs.getListener()) {
76
76
  const nodes = getDataNodes(target);
77
77
  (nodes._ || (nodes._ = createDataNode()))();
78
78
  }
79
+ }
80
+ function ownKeys(target) {
81
+ trackSelf(target);
79
82
  return Reflect.ownKeys(target);
80
83
  }
81
84
  function createDataNode() {
@@ -92,18 +95,12 @@ const proxyTraps$1 = {
92
95
  if (property === solidJs.$PROXY) return receiver;
93
96
  const value = target[property];
94
97
  if (property === $NODE || property === "__proto__") return value;
95
- const wrappable = isWrappable(value);
98
+ if (property === solidJs.$TRACK) return trackSelf(target);
96
99
  if (solidJs.getListener() && (typeof value !== "function" || target.hasOwnProperty(property))) {
97
- let nodes, node;
98
- if (wrappable && (nodes = getDataNodes(value))) {
99
- node = nodes._ || (nodes._ = createDataNode());
100
- node();
101
- }
102
- nodes = getDataNodes(target);
103
- node = nodes[property] || (nodes[property] = createDataNode());
104
- node();
100
+ const nodes = getDataNodes(target);
101
+ (nodes[property] || (nodes[property] = createDataNode()))();
105
102
  }
106
- return wrappable ? wrap$1(value, target[$NAME] && `${target[$NAME]}:${property.toString()}`) : value;
103
+ return isWrappable(value) ? wrap$1(value, target[$NAME] && `${target[$NAME]}:${property.toString()}`) : value;
107
104
  },
108
105
  set() {
109
106
  console.warn("Cannot mutate a Store directly");
@@ -120,16 +117,14 @@ function setProperty(state, property, value) {
120
117
  if (state[property] === value) return;
121
118
  const array = Array.isArray(state);
122
119
  const len = state.length;
123
- const isUndefined = value === undefined;
124
- const notify = array || isUndefined === property in state;
125
- if (isUndefined) {
120
+ if (value === undefined) {
126
121
  delete state[property];
127
122
  } else state[property] = value;
128
123
  let nodes = getDataNodes(state),
129
124
  node;
130
125
  (node = nodes[property]) && node.$();
131
126
  if (array && state.length !== len) (node = nodes.length) && node.$();
132
- notify && (node = nodes._) && node.$();
127
+ (node = nodes._) && node.$();
133
128
  }
134
129
  function mergeStoreNode(state, value) {
135
130
  const keys = Object.keys(value);
@@ -138,6 +133,18 @@ function mergeStoreNode(state, value) {
138
133
  setProperty(state, key, value[key]);
139
134
  }
140
135
  }
136
+ function updateArray(current, next) {
137
+ if (typeof next === "function") next = next(current);
138
+ next = unwrap(next);
139
+ if (current === next) return;
140
+ let i = 0,
141
+ len = next.length;
142
+ for (; i < len; i++) {
143
+ const value = next[i];
144
+ if (current[i] !== value) setProperty(current, i, value);
145
+ }
146
+ setProperty(current, "length", len);
147
+ }
141
148
  function updatePath(current, path, traversed = []) {
142
149
  let part,
143
150
  prev = current;
@@ -185,6 +192,7 @@ function updatePath(current, path, traversed = []) {
185
192
  }
186
193
  function createStore(store, options) {
187
194
  const unwrappedStore = unwrap(store || {});
195
+ const isArray = Array.isArray(unwrappedStore);
188
196
  if (typeof unwrappedStore !== "object" && typeof unwrappedStore !== "function") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createStore'. Expected an object.`);
189
197
  const wrappedStore = wrap$1(unwrappedStore, (options && options.name || solidJs.DEV.hashValue(unwrappedStore)));
190
198
  {
@@ -194,7 +202,9 @@ function createStore(store, options) {
194
202
  });
195
203
  }
196
204
  function setStore(...args) {
197
- solidJs.batch(() => updatePath(unwrappedStore, args));
205
+ solidJs.batch(() => {
206
+ isArray && args.length === 1 ? updateArray(unwrappedStore, args[0]) : updatePath(unwrappedStore, args);
207
+ });
198
208
  }
199
209
  return [wrappedStore, setStore];
200
210
  }
@@ -205,18 +215,14 @@ const proxyTraps = {
205
215
  if (property === solidJs.$PROXY) return receiver;
206
216
  const value = target[property];
207
217
  if (property === $NODE || property === "__proto__") return value;
208
- const wrappable = isWrappable(value);
218
+ if (property === solidJs.$TRACK) return trackSelf(target);
209
219
  if (solidJs.getListener() && (typeof value !== "function" || target.hasOwnProperty(property))) {
210
- let nodes, node;
211
- if (wrappable && (nodes = getDataNodes(value))) {
212
- node = nodes._ || (nodes._ = createDataNode());
213
- node();
214
- }
215
- nodes = getDataNodes(target);
216
- node = nodes[property] || (nodes[property] = createDataNode());
217
- node();
220
+ const nodes = getDataNodes(target);
221
+ (nodes[property] || (nodes[property] = createDataNode()))();
222
+ } else if (value != null && typeof value === "function" && value === Array.prototype[property]) {
223
+ return (...args) => solidJs.batch(() => Array.prototype[property].apply(receiver, args));
218
224
  }
219
- return wrappable ? wrap(value, target[$NAME] && `${target[$NAME]}:${property.toString()}`) : value;
225
+ return isWrappable(value) ? wrap(value, target[$NAME] && `${target[$NAME]}:${property.toString()}`) : value;
220
226
  },
221
227
  set(target, property, value) {
222
228
  setProperty(target, property, unwrap(value));
@@ -271,6 +277,9 @@ function createMutable(state, options) {
271
277
  }
272
278
  return wrappedStore;
273
279
  }
280
+ function modifyMutable(state, modifier) {
281
+ solidJs.batch(() => modifier(unwrap(state)));
282
+ }
274
283
 
275
284
  function applyState(target, parent, property, merge, key) {
276
285
  const previous = parent[property];
@@ -348,9 +357,9 @@ function reconcile(value, options = {}) {
348
357
  v = unwrap(value);
349
358
  return state => {
350
359
  if (!isWrappable(state) || !isWrappable(v)) return v;
351
- applyState(v, {
360
+ solidJs.batch(() => applyState(v, {
352
361
  state
353
- }, "state", merge, key);
362
+ }, "state", merge, key));
354
363
  return state;
355
364
  };
356
365
  }
@@ -379,6 +388,7 @@ function produce(fn) {
379
388
  exports.$RAW = $RAW;
380
389
  exports.createMutable = createMutable;
381
390
  exports.createStore = createStore;
391
+ exports.modifyMutable = modifyMutable;
382
392
  exports.produce = produce;
383
393
  exports.reconcile = reconcile;
384
394
  exports.unwrap = unwrap;
package/store/dist/dev.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $PROXY, DEV, getListener, batch, createSignal } from 'solid-js';
1
+ import { $PROXY, DEV, $TRACK, getListener, batch, createSignal } from 'solid-js';
2
2
 
3
3
  const $RAW = Symbol("store-raw"),
4
4
  $NODE = Symbol("store-node"),
@@ -67,11 +67,14 @@ function proxyDescriptor(target, property) {
67
67
  desc.get = () => target[$PROXY][property];
68
68
  return desc;
69
69
  }
70
- function ownKeys(target) {
70
+ function trackSelf(target) {
71
71
  if (getListener()) {
72
72
  const nodes = getDataNodes(target);
73
73
  (nodes._ || (nodes._ = createDataNode()))();
74
74
  }
75
+ }
76
+ function ownKeys(target) {
77
+ trackSelf(target);
75
78
  return Reflect.ownKeys(target);
76
79
  }
77
80
  function createDataNode() {
@@ -88,18 +91,12 @@ const proxyTraps$1 = {
88
91
  if (property === $PROXY) return receiver;
89
92
  const value = target[property];
90
93
  if (property === $NODE || property === "__proto__") return value;
91
- const wrappable = isWrappable(value);
94
+ if (property === $TRACK) return trackSelf(target);
92
95
  if (getListener() && (typeof value !== "function" || target.hasOwnProperty(property))) {
93
- let nodes, node;
94
- if (wrappable && (nodes = getDataNodes(value))) {
95
- node = nodes._ || (nodes._ = createDataNode());
96
- node();
97
- }
98
- nodes = getDataNodes(target);
99
- node = nodes[property] || (nodes[property] = createDataNode());
100
- node();
96
+ const nodes = getDataNodes(target);
97
+ (nodes[property] || (nodes[property] = createDataNode()))();
101
98
  }
102
- return wrappable ? wrap$1(value, target[$NAME] && `${target[$NAME]}:${property.toString()}`) : value;
99
+ return isWrappable(value) ? wrap$1(value, target[$NAME] && `${target[$NAME]}:${property.toString()}`) : value;
103
100
  },
104
101
  set() {
105
102
  console.warn("Cannot mutate a Store directly");
@@ -116,16 +113,14 @@ function setProperty(state, property, value) {
116
113
  if (state[property] === value) return;
117
114
  const array = Array.isArray(state);
118
115
  const len = state.length;
119
- const isUndefined = value === undefined;
120
- const notify = array || isUndefined === property in state;
121
- if (isUndefined) {
116
+ if (value === undefined) {
122
117
  delete state[property];
123
118
  } else state[property] = value;
124
119
  let nodes = getDataNodes(state),
125
120
  node;
126
121
  (node = nodes[property]) && node.$();
127
122
  if (array && state.length !== len) (node = nodes.length) && node.$();
128
- notify && (node = nodes._) && node.$();
123
+ (node = nodes._) && node.$();
129
124
  }
130
125
  function mergeStoreNode(state, value) {
131
126
  const keys = Object.keys(value);
@@ -134,6 +129,18 @@ function mergeStoreNode(state, value) {
134
129
  setProperty(state, key, value[key]);
135
130
  }
136
131
  }
132
+ function updateArray(current, next) {
133
+ if (typeof next === "function") next = next(current);
134
+ next = unwrap(next);
135
+ if (current === next) return;
136
+ let i = 0,
137
+ len = next.length;
138
+ for (; i < len; i++) {
139
+ const value = next[i];
140
+ if (current[i] !== value) setProperty(current, i, value);
141
+ }
142
+ setProperty(current, "length", len);
143
+ }
137
144
  function updatePath(current, path, traversed = []) {
138
145
  let part,
139
146
  prev = current;
@@ -181,6 +188,7 @@ function updatePath(current, path, traversed = []) {
181
188
  }
182
189
  function createStore(store, options) {
183
190
  const unwrappedStore = unwrap(store || {});
191
+ const isArray = Array.isArray(unwrappedStore);
184
192
  if (typeof unwrappedStore !== "object" && typeof unwrappedStore !== "function") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createStore'. Expected an object.`);
185
193
  const wrappedStore = wrap$1(unwrappedStore, (options && options.name || DEV.hashValue(unwrappedStore)));
186
194
  {
@@ -190,7 +198,9 @@ function createStore(store, options) {
190
198
  });
191
199
  }
192
200
  function setStore(...args) {
193
- batch(() => updatePath(unwrappedStore, args));
201
+ batch(() => {
202
+ isArray && args.length === 1 ? updateArray(unwrappedStore, args[0]) : updatePath(unwrappedStore, args);
203
+ });
194
204
  }
195
205
  return [wrappedStore, setStore];
196
206
  }
@@ -201,18 +211,14 @@ const proxyTraps = {
201
211
  if (property === $PROXY) return receiver;
202
212
  const value = target[property];
203
213
  if (property === $NODE || property === "__proto__") return value;
204
- const wrappable = isWrappable(value);
214
+ if (property === $TRACK) return trackSelf(target);
205
215
  if (getListener() && (typeof value !== "function" || target.hasOwnProperty(property))) {
206
- let nodes, node;
207
- if (wrappable && (nodes = getDataNodes(value))) {
208
- node = nodes._ || (nodes._ = createDataNode());
209
- node();
210
- }
211
- nodes = getDataNodes(target);
212
- node = nodes[property] || (nodes[property] = createDataNode());
213
- node();
216
+ const nodes = getDataNodes(target);
217
+ (nodes[property] || (nodes[property] = createDataNode()))();
218
+ } else if (value != null && typeof value === "function" && value === Array.prototype[property]) {
219
+ return (...args) => batch(() => Array.prototype[property].apply(receiver, args));
214
220
  }
215
- return wrappable ? wrap(value, target[$NAME] && `${target[$NAME]}:${property.toString()}`) : value;
221
+ return isWrappable(value) ? wrap(value, target[$NAME] && `${target[$NAME]}:${property.toString()}`) : value;
216
222
  },
217
223
  set(target, property, value) {
218
224
  setProperty(target, property, unwrap(value));
@@ -267,6 +273,9 @@ function createMutable(state, options) {
267
273
  }
268
274
  return wrappedStore;
269
275
  }
276
+ function modifyMutable(state, modifier) {
277
+ batch(() => modifier(unwrap(state)));
278
+ }
270
279
 
271
280
  function applyState(target, parent, property, merge, key) {
272
281
  const previous = parent[property];
@@ -344,9 +353,9 @@ function reconcile(value, options = {}) {
344
353
  v = unwrap(value);
345
354
  return state => {
346
355
  if (!isWrappable(state) || !isWrappable(v)) return v;
347
- applyState(v, {
356
+ batch(() => applyState(v, {
348
357
  state
349
- }, "state", merge, key);
358
+ }, "state", merge, key));
350
359
  return state;
351
360
  };
352
361
  }
@@ -372,4 +381,4 @@ function produce(fn) {
372
381
  };
373
382
  }
374
383
 
375
- export { $RAW, createMutable, createStore, produce, reconcile, unwrap };
384
+ export { $RAW, createMutable, createStore, modifyMutable, produce, reconcile, unwrap };
@@ -68,11 +68,14 @@ function proxyDescriptor(target, property) {
68
68
  desc.get = () => target[solidJs.$PROXY][property];
69
69
  return desc;
70
70
  }
71
- function ownKeys(target) {
71
+ function trackSelf(target) {
72
72
  if (solidJs.getListener()) {
73
73
  const nodes = getDataNodes(target);
74
74
  (nodes._ || (nodes._ = createDataNode()))();
75
75
  }
76
+ }
77
+ function ownKeys(target) {
78
+ trackSelf(target);
76
79
  return Reflect.ownKeys(target);
77
80
  }
78
81
  function createDataNode() {
@@ -89,18 +92,12 @@ const proxyTraps$1 = {
89
92
  if (property === solidJs.$PROXY) return receiver;
90
93
  const value = target[property];
91
94
  if (property === $NODE || property === "__proto__") return value;
92
- const wrappable = isWrappable(value);
95
+ if (property === solidJs.$TRACK) return trackSelf(target);
93
96
  if (solidJs.getListener() && (typeof value !== "function" || target.hasOwnProperty(property))) {
94
- let nodes, node;
95
- if (wrappable && (nodes = getDataNodes(value))) {
96
- node = nodes._ || (nodes._ = createDataNode());
97
- node();
98
- }
99
- nodes = getDataNodes(target);
100
- node = nodes[property] || (nodes[property] = createDataNode());
101
- node();
97
+ const nodes = getDataNodes(target);
98
+ (nodes[property] || (nodes[property] = createDataNode()))();
102
99
  }
103
- return wrappable ? wrap$1(value) : value;
100
+ return isWrappable(value) ? wrap$1(value) : value;
104
101
  },
105
102
  set() {
106
103
  return true;
@@ -115,16 +112,14 @@ function setProperty(state, property, value) {
115
112
  if (state[property] === value) return;
116
113
  const array = Array.isArray(state);
117
114
  const len = state.length;
118
- const isUndefined = value === undefined;
119
- const notify = array || isUndefined === property in state;
120
- if (isUndefined) {
115
+ if (value === undefined) {
121
116
  delete state[property];
122
117
  } else state[property] = value;
123
118
  let nodes = getDataNodes(state),
124
119
  node;
125
120
  (node = nodes[property]) && node.$();
126
121
  if (array && state.length !== len) (node = nodes.length) && node.$();
127
- notify && (node = nodes._) && node.$();
122
+ (node = nodes._) && node.$();
128
123
  }
129
124
  function mergeStoreNode(state, value) {
130
125
  const keys = Object.keys(value);
@@ -133,6 +128,18 @@ function mergeStoreNode(state, value) {
133
128
  setProperty(state, key, value[key]);
134
129
  }
135
130
  }
131
+ function updateArray(current, next) {
132
+ if (typeof next === "function") next = next(current);
133
+ next = unwrap(next);
134
+ if (current === next) return;
135
+ let i = 0,
136
+ len = next.length;
137
+ for (; i < len; i++) {
138
+ const value = next[i];
139
+ if (current[i] !== value) setProperty(current, i, value);
140
+ }
141
+ setProperty(current, "length", len);
142
+ }
136
143
  function updatePath(current, path, traversed = []) {
137
144
  let part,
138
145
  prev = current;
@@ -180,9 +187,12 @@ function updatePath(current, path, traversed = []) {
180
187
  }
181
188
  function createStore(store, options) {
182
189
  const unwrappedStore = unwrap(store || {});
190
+ const isArray = Array.isArray(unwrappedStore);
183
191
  const wrappedStore = wrap$1(unwrappedStore);
184
192
  function setStore(...args) {
185
- solidJs.batch(() => updatePath(unwrappedStore, args));
193
+ solidJs.batch(() => {
194
+ isArray && args.length === 1 ? updateArray(unwrappedStore, args[0]) : updatePath(unwrappedStore, args);
195
+ });
186
196
  }
187
197
  return [wrappedStore, setStore];
188
198
  }
@@ -193,18 +203,14 @@ const proxyTraps = {
193
203
  if (property === solidJs.$PROXY) return receiver;
194
204
  const value = target[property];
195
205
  if (property === $NODE || property === "__proto__") return value;
196
- const wrappable = isWrappable(value);
206
+ if (property === solidJs.$TRACK) return trackSelf(target);
197
207
  if (solidJs.getListener() && (typeof value !== "function" || target.hasOwnProperty(property))) {
198
- let nodes, node;
199
- if (wrappable && (nodes = getDataNodes(value))) {
200
- node = nodes._ || (nodes._ = createDataNode());
201
- node();
202
- }
203
- nodes = getDataNodes(target);
204
- node = nodes[property] || (nodes[property] = createDataNode());
205
- node();
208
+ const nodes = getDataNodes(target);
209
+ (nodes[property] || (nodes[property] = createDataNode()))();
210
+ } else if (value != null && typeof value === "function" && value === Array.prototype[property]) {
211
+ return (...args) => solidJs.batch(() => Array.prototype[property].apply(receiver, args));
206
212
  }
207
- return wrappable ? wrap(value) : value;
213
+ return isWrappable(value) ? wrap(value) : value;
208
214
  },
209
215
  set(target, property, value) {
210
216
  setProperty(target, property, unwrap(value));
@@ -249,6 +255,9 @@ function createMutable(state, options) {
249
255
  const wrappedStore = wrap(unwrappedStore);
250
256
  return wrappedStore;
251
257
  }
258
+ function modifyMutable(state, modifier) {
259
+ solidJs.batch(() => modifier(unwrap(state)));
260
+ }
252
261
 
253
262
  function applyState(target, parent, property, merge, key) {
254
263
  const previous = parent[property];
@@ -326,9 +335,9 @@ function reconcile(value, options = {}) {
326
335
  v = unwrap(value);
327
336
  return state => {
328
337
  if (!isWrappable(state) || !isWrappable(v)) return v;
329
- applyState(v, {
338
+ solidJs.batch(() => applyState(v, {
330
339
  state
331
- }, "state", merge, key);
340
+ }, "state", merge, key));
332
341
  return state;
333
342
  };
334
343
  }
@@ -357,6 +366,7 @@ function produce(fn) {
357
366
  exports.$RAW = $RAW;
358
367
  exports.createMutable = createMutable;
359
368
  exports.createStore = createStore;
369
+ exports.modifyMutable = modifyMutable;
360
370
  exports.produce = produce;
361
371
  exports.reconcile = reconcile;
362
372
  exports.unwrap = unwrap;