solid-js 1.4.2 → 1.4.5

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.cjs CHANGED
@@ -160,16 +160,18 @@ let ExecCount = 0;
160
160
  function createRoot(fn, detachedOwner) {
161
161
  const listener = Listener,
162
162
  owner = Owner,
163
- root = fn.length === 0 && !false ? UNOWNED : {
163
+ unowned = fn.length === 0,
164
+ root = unowned && !false ? UNOWNED : {
164
165
  owned: null,
165
166
  cleanups: null,
166
167
  context: null,
167
168
  owner: detachedOwner || owner
168
- };
169
+ },
170
+ updateFn = unowned ? fn : () => fn(() => cleanNode(root));
169
171
  Owner = root;
170
172
  Listener = null;
171
173
  try {
172
- return runUpdates(() => fn(() => cleanNode(root)), true);
174
+ return runUpdates(updateFn, true);
173
175
  } finally {
174
176
  Listener = listener;
175
177
  Owner = owner;
@@ -767,14 +769,16 @@ function completeUpdates(wait) {
767
769
  return;
768
770
  }
769
771
  const sources = Transition.sources;
772
+ const disposed = Transition.disposed;
770
773
  res = Transition.resolve;
771
- Effects.forEach(e => {
774
+ for (const e of Effects) {
772
775
  "tState" in e && (e.state = e.tState);
773
776
  delete e.tState;
774
- });
777
+ }
775
778
  Transition = null;
776
779
  batch(() => {
777
- sources.forEach(v => {
780
+ for (const d of disposed) cleanNode(d);
781
+ for (const v of sources) {
778
782
  v.value = v.tValue;
779
783
  if (v.owned) {
780
784
  for (let i = 0, len = v.owned.length; i < len; i++) cleanNode(v.owned[i]);
@@ -783,7 +787,7 @@ function completeUpdates(wait) {
783
787
  delete v.tValue;
784
788
  delete v.tOwned;
785
789
  v.tState = 0;
786
- });
790
+ }
787
791
  setTransPending(false);
788
792
  });
789
793
  }
@@ -901,7 +905,7 @@ function reset(node, top) {
901
905
  function handleError(err) {
902
906
  const fns = ERROR && lookup(Owner, ERROR);
903
907
  if (!fns) throw err;
904
- fns.forEach(f => f(err));
908
+ for (const f of fns) f(err);
905
909
  }
906
910
  function lookup(owner, key) {
907
911
  return owner ? owner.context && owner.context[key] !== undefined ? owner.context[key] : lookup(owner.owner, key) : undefined;
@@ -1331,23 +1335,24 @@ function Match(props) {
1331
1335
  return props;
1332
1336
  }
1333
1337
  let Errors;
1338
+ const NoErrors = {};
1334
1339
  function resetErrorBoundaries() {
1335
- Errors && [...Errors].forEach(fn => fn());
1340
+ Errors && [...Errors].forEach(fn => fn(NoErrors));
1336
1341
  }
1337
1342
  function ErrorBoundary(props) {
1338
- let err = undefined;
1343
+ let err = NoErrors;
1339
1344
  if (sharedConfig.context && sharedConfig.load) {
1340
- err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count);
1345
+ err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count) || NoErrors;
1341
1346
  }
1342
1347
  const [errored, setErrored] = createSignal(err);
1343
1348
  Errors || (Errors = new Set());
1344
1349
  Errors.add(setErrored);
1345
1350
  onCleanup(() => Errors.delete(setErrored));
1346
- let e;
1347
1351
  return createMemo(() => {
1348
- if ((e = errored()) != null) {
1352
+ let e;
1353
+ if ((e = errored()) !== NoErrors) {
1349
1354
  const f = props.fallback;
1350
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(null))) : f;
1355
+ return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(NoErrors))) : f;
1351
1356
  }
1352
1357
  onError(setErrored);
1353
1358
  return props.children;
@@ -1356,27 +1361,24 @@ function ErrorBoundary(props) {
1356
1361
 
1357
1362
  const SuspenseListContext = createContext();
1358
1363
  function SuspenseList(props) {
1359
- let index = 0,
1360
- suspenseSetter,
1361
- showContent,
1362
- showFallback;
1364
+ let suspenseSetter, showContent, showFallback;
1363
1365
  const listContext = useContext(SuspenseListContext);
1364
1366
  if (listContext) {
1365
1367
  const [inFallback, setFallback] = createSignal(false);
1366
1368
  suspenseSetter = setFallback;
1367
1369
  [showContent, showFallback] = listContext.register(inFallback);
1368
1370
  }
1369
- const registry = [],
1371
+ const [registry, setRegistry] = createSignal([]),
1370
1372
  comp = createComponent(SuspenseListContext.Provider, {
1371
1373
  value: {
1372
1374
  register: inFallback => {
1373
1375
  const [showingContent, showContent] = createSignal(false),
1374
1376
  [showingFallback, showFallback] = createSignal(false);
1375
- registry[index++] = {
1377
+ setRegistry(registry => [...registry, {
1376
1378
  inFallback,
1377
1379
  showContent,
1378
1380
  showFallback
1379
- };
1381
+ }]);
1380
1382
  return [showingContent, showingFallback];
1381
1383
  }
1382
1384
  },
@@ -1389,31 +1391,32 @@ function SuspenseList(props) {
1389
1391
  tail = props.tail,
1390
1392
  visibleContent = showContent ? showContent() : true,
1391
1393
  visibleFallback = showFallback ? showFallback() : true,
1394
+ reg = registry(),
1392
1395
  reverse = reveal === "backwards";
1393
1396
  if (reveal === "together") {
1394
- const all = registry.every(i => !i.inFallback());
1397
+ const all = reg.every(i => !i.inFallback());
1395
1398
  suspenseSetter && suspenseSetter(!all);
1396
- registry.forEach(i => {
1399
+ reg.forEach(i => {
1397
1400
  i.showContent(all && visibleContent);
1398
1401
  i.showFallback(visibleFallback);
1399
1402
  });
1400
1403
  return;
1401
1404
  }
1402
1405
  let stop = false;
1403
- for (let i = 0, len = registry.length; i < len; i++) {
1406
+ for (let i = 0, len = reg.length; i < len; i++) {
1404
1407
  const n = reverse ? len - i - 1 : i,
1405
- s = registry[n].inFallback();
1408
+ s = reg[n].inFallback();
1406
1409
  if (!stop && !s) {
1407
- registry[n].showContent(visibleContent);
1408
- registry[n].showFallback(visibleFallback);
1410
+ reg[n].showContent(visibleContent);
1411
+ reg[n].showFallback(visibleFallback);
1409
1412
  } else {
1410
1413
  const next = !stop;
1411
1414
  if (next && suspenseSetter) suspenseSetter(true);
1412
1415
  if (!tail || next && tail === "collapsed") {
1413
- registry[n].showFallback(visibleFallback);
1414
- } else registry[n].showFallback(false);
1416
+ reg[n].showFallback(visibleFallback);
1417
+ } else reg[n].showFallback(false);
1415
1418
  stop = true;
1416
- registry[n].showContent(next);
1419
+ reg[n].showContent(next);
1417
1420
  }
1418
1421
  }
1419
1422
  if (!stop && suspenseSetter) suspenseSetter(false);
@@ -1442,7 +1445,7 @@ function Suspense(props) {
1442
1445
  resolved: false
1443
1446
  },
1444
1447
  owner = getOwner();
1445
- if (sharedConfig.context) {
1448
+ if (sharedConfig.context && sharedConfig.load) {
1446
1449
  const key = sharedConfig.context.id + sharedConfig.context.count;
1447
1450
  p = sharedConfig.load(key);
1448
1451
  if (p) {
@@ -1475,7 +1478,7 @@ function Suspense(props) {
1475
1478
  return flicker = undefined;
1476
1479
  }
1477
1480
  if (ctx && p === undefined) setHydrateContext();
1478
- const rendered = untrack(() => props.children);
1481
+ const rendered = createMemo(() => props.children);
1479
1482
  return createMemo(() => {
1480
1483
  const inFallback = store.inFallback(),
1481
1484
  visibleContent = showContent ? showContent() : true,
@@ -1485,7 +1488,7 @@ function Suspense(props) {
1485
1488
  store.resolved = true;
1486
1489
  ctx = p = undefined;
1487
1490
  resumeEffects(store.effects);
1488
- return rendered;
1491
+ return rendered();
1489
1492
  }
1490
1493
  if (!visibleFallback) return;
1491
1494
  return createRoot(disposer => {
package/dist/solid.js CHANGED
@@ -156,16 +156,18 @@ let ExecCount = 0;
156
156
  function createRoot(fn, detachedOwner) {
157
157
  const listener = Listener,
158
158
  owner = Owner,
159
- root = fn.length === 0 && !false ? UNOWNED : {
159
+ unowned = fn.length === 0,
160
+ root = unowned && !false ? UNOWNED : {
160
161
  owned: null,
161
162
  cleanups: null,
162
163
  context: null,
163
164
  owner: detachedOwner || owner
164
- };
165
+ },
166
+ updateFn = unowned ? fn : () => fn(() => cleanNode(root));
165
167
  Owner = root;
166
168
  Listener = null;
167
169
  try {
168
- return runUpdates(() => fn(() => cleanNode(root)), true);
170
+ return runUpdates(updateFn, true);
169
171
  } finally {
170
172
  Listener = listener;
171
173
  Owner = owner;
@@ -763,14 +765,16 @@ function completeUpdates(wait) {
763
765
  return;
764
766
  }
765
767
  const sources = Transition.sources;
768
+ const disposed = Transition.disposed;
766
769
  res = Transition.resolve;
767
- Effects.forEach(e => {
770
+ for (const e of Effects) {
768
771
  "tState" in e && (e.state = e.tState);
769
772
  delete e.tState;
770
- });
773
+ }
771
774
  Transition = null;
772
775
  batch(() => {
773
- sources.forEach(v => {
776
+ for (const d of disposed) cleanNode(d);
777
+ for (const v of sources) {
774
778
  v.value = v.tValue;
775
779
  if (v.owned) {
776
780
  for (let i = 0, len = v.owned.length; i < len; i++) cleanNode(v.owned[i]);
@@ -779,7 +783,7 @@ function completeUpdates(wait) {
779
783
  delete v.tValue;
780
784
  delete v.tOwned;
781
785
  v.tState = 0;
782
- });
786
+ }
783
787
  setTransPending(false);
784
788
  });
785
789
  }
@@ -897,7 +901,7 @@ function reset(node, top) {
897
901
  function handleError(err) {
898
902
  const fns = ERROR && lookup(Owner, ERROR);
899
903
  if (!fns) throw err;
900
- fns.forEach(f => f(err));
904
+ for (const f of fns) f(err);
901
905
  }
902
906
  function lookup(owner, key) {
903
907
  return owner ? owner.context && owner.context[key] !== undefined ? owner.context[key] : lookup(owner.owner, key) : undefined;
@@ -1327,23 +1331,24 @@ function Match(props) {
1327
1331
  return props;
1328
1332
  }
1329
1333
  let Errors;
1334
+ const NoErrors = {};
1330
1335
  function resetErrorBoundaries() {
1331
- Errors && [...Errors].forEach(fn => fn());
1336
+ Errors && [...Errors].forEach(fn => fn(NoErrors));
1332
1337
  }
1333
1338
  function ErrorBoundary(props) {
1334
- let err = undefined;
1339
+ let err = NoErrors;
1335
1340
  if (sharedConfig.context && sharedConfig.load) {
1336
- err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count);
1341
+ err = sharedConfig.load(sharedConfig.context.id + sharedConfig.context.count) || NoErrors;
1337
1342
  }
1338
1343
  const [errored, setErrored] = createSignal(err);
1339
1344
  Errors || (Errors = new Set());
1340
1345
  Errors.add(setErrored);
1341
1346
  onCleanup(() => Errors.delete(setErrored));
1342
- let e;
1343
1347
  return createMemo(() => {
1344
- if ((e = errored()) != null) {
1348
+ let e;
1349
+ if ((e = errored()) !== NoErrors) {
1345
1350
  const f = props.fallback;
1346
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(null))) : f;
1351
+ return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored(NoErrors))) : f;
1347
1352
  }
1348
1353
  onError(setErrored);
1349
1354
  return props.children;
@@ -1352,27 +1357,24 @@ function ErrorBoundary(props) {
1352
1357
 
1353
1358
  const SuspenseListContext = createContext();
1354
1359
  function SuspenseList(props) {
1355
- let index = 0,
1356
- suspenseSetter,
1357
- showContent,
1358
- showFallback;
1360
+ let suspenseSetter, showContent, showFallback;
1359
1361
  const listContext = useContext(SuspenseListContext);
1360
1362
  if (listContext) {
1361
1363
  const [inFallback, setFallback] = createSignal(false);
1362
1364
  suspenseSetter = setFallback;
1363
1365
  [showContent, showFallback] = listContext.register(inFallback);
1364
1366
  }
1365
- const registry = [],
1367
+ const [registry, setRegistry] = createSignal([]),
1366
1368
  comp = createComponent(SuspenseListContext.Provider, {
1367
1369
  value: {
1368
1370
  register: inFallback => {
1369
1371
  const [showingContent, showContent] = createSignal(false),
1370
1372
  [showingFallback, showFallback] = createSignal(false);
1371
- registry[index++] = {
1373
+ setRegistry(registry => [...registry, {
1372
1374
  inFallback,
1373
1375
  showContent,
1374
1376
  showFallback
1375
- };
1377
+ }]);
1376
1378
  return [showingContent, showingFallback];
1377
1379
  }
1378
1380
  },
@@ -1385,31 +1387,32 @@ function SuspenseList(props) {
1385
1387
  tail = props.tail,
1386
1388
  visibleContent = showContent ? showContent() : true,
1387
1389
  visibleFallback = showFallback ? showFallback() : true,
1390
+ reg = registry(),
1388
1391
  reverse = reveal === "backwards";
1389
1392
  if (reveal === "together") {
1390
- const all = registry.every(i => !i.inFallback());
1393
+ const all = reg.every(i => !i.inFallback());
1391
1394
  suspenseSetter && suspenseSetter(!all);
1392
- registry.forEach(i => {
1395
+ reg.forEach(i => {
1393
1396
  i.showContent(all && visibleContent);
1394
1397
  i.showFallback(visibleFallback);
1395
1398
  });
1396
1399
  return;
1397
1400
  }
1398
1401
  let stop = false;
1399
- for (let i = 0, len = registry.length; i < len; i++) {
1402
+ for (let i = 0, len = reg.length; i < len; i++) {
1400
1403
  const n = reverse ? len - i - 1 : i,
1401
- s = registry[n].inFallback();
1404
+ s = reg[n].inFallback();
1402
1405
  if (!stop && !s) {
1403
- registry[n].showContent(visibleContent);
1404
- registry[n].showFallback(visibleFallback);
1406
+ reg[n].showContent(visibleContent);
1407
+ reg[n].showFallback(visibleFallback);
1405
1408
  } else {
1406
1409
  const next = !stop;
1407
1410
  if (next && suspenseSetter) suspenseSetter(true);
1408
1411
  if (!tail || next && tail === "collapsed") {
1409
- registry[n].showFallback(visibleFallback);
1410
- } else registry[n].showFallback(false);
1412
+ reg[n].showFallback(visibleFallback);
1413
+ } else reg[n].showFallback(false);
1411
1414
  stop = true;
1412
- registry[n].showContent(next);
1415
+ reg[n].showContent(next);
1413
1416
  }
1414
1417
  }
1415
1418
  if (!stop && suspenseSetter) suspenseSetter(false);
@@ -1438,7 +1441,7 @@ function Suspense(props) {
1438
1441
  resolved: false
1439
1442
  },
1440
1443
  owner = getOwner();
1441
- if (sharedConfig.context) {
1444
+ if (sharedConfig.context && sharedConfig.load) {
1442
1445
  const key = sharedConfig.context.id + sharedConfig.context.count;
1443
1446
  p = sharedConfig.load(key);
1444
1447
  if (p) {
@@ -1471,7 +1474,7 @@ function Suspense(props) {
1471
1474
  return flicker = undefined;
1472
1475
  }
1473
1476
  if (ctx && p === undefined) setHydrateContext();
1474
- const rendered = untrack(() => props.children);
1477
+ const rendered = createMemo(() => props.children);
1475
1478
  return createMemo(() => {
1476
1479
  const inFallback = store.inFallback(),
1477
1480
  visibleContent = showContent ? showContent() : true,
@@ -1481,7 +1484,7 @@ function Suspense(props) {
1481
1484
  store.resolved = true;
1482
1485
  ctx = p = undefined;
1483
1486
  resumeEffects(store.effects);
1484
- return rendered;
1487
+ return rendered();
1485
1488
  }
1486
1489
  if (!visibleFallback) return;
1487
1490
  return createRoot(disposer => {
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.4.2",
4
+ "version": "1.4.5",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "homepage": "https://solidjs.com",
@@ -151,5 +151,5 @@
151
151
  "compiler",
152
152
  "performance"
153
153
  ],
154
- "gitHead": "f17df5c7042425aa8d363be261bd9a9e5345c188"
154
+ "gitHead": "2c2252d6e4bd0d59f9164da32d6b6afc65dd4220"
155
155
  }
package/store/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This submodules contains the means for handling deeps nested reactivity. It provides 2 main primitives `createStore` and `createMutable` which leverage proxies to create dynamic nested reactive structures.
4
4
 
5
- This also contains helper methods `produce` and `reconcile` which augment the behavior of the store setter method to allow for localized mutationa and data diffing.
5
+ This also contains helper methods `produce` and `reconcile` which augment the behavior of the store setter method to allow for localized mutation and data diffing.
6
6
 
7
7
  For full documentation, check out the [website](https://www.solidjs.com/docs/latest/api).
8
8
 
@@ -20,4 +20,4 @@ const [store, setStore] = createStore({
20
20
 
21
21
  // update store.user.firstName
22
22
  setStore("user", "firstName", "Will");
23
- ```
23
+ ```
@@ -31,7 +31,8 @@ function wrap$1(value, name) {
31
31
  return p;
32
32
  }
33
33
  function isWrappable(obj) {
34
- return obj != null && typeof obj === "object" && (obj[solidJs.$PROXY] || !obj.__proto__ || obj.__proto__ === Object.prototype || Array.isArray(obj));
34
+ let proto;
35
+ return obj != null && typeof obj === "object" && (obj[solidJs.$PROXY] || !(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype || Array.isArray(obj));
35
36
  }
36
37
  function unwrap(item, set = new Set()) {
37
38
  let result, unwrapped, v, prop;
@@ -143,14 +144,16 @@ function mergeStoreNode(state, value) {
143
144
  function updateArray(current, next) {
144
145
  if (typeof next === "function") next = next(current);
145
146
  next = unwrap(next);
146
- if (current === next) return;
147
- let i = 0,
148
- len = next.length;
149
- for (; i < len; i++) {
150
- const value = next[i];
151
- if (current[i] !== value) setProperty(current, i, value);
152
- }
153
- setProperty(current, "length", len);
147
+ if (Array.isArray(next)) {
148
+ if (current === next) return;
149
+ let i = 0,
150
+ len = next.length;
151
+ for (; i < len; i++) {
152
+ const value = next[i];
153
+ if (current[i] !== value) setProperty(current, i, value);
154
+ }
155
+ setProperty(current, "length", len);
156
+ } else mergeStoreNode(current, next);
154
157
  }
155
158
  function updatePath(current, path, traversed = []) {
156
159
  let part,
@@ -197,7 +200,7 @@ function updatePath(current, path, traversed = []) {
197
200
  mergeStoreNode(prev, value);
198
201
  } else setProperty(current, part, value);
199
202
  }
200
- function createStore(store, options) {
203
+ function createStore(...[store, options]) {
201
204
  const unwrappedStore = unwrap(store || {});
202
205
  const isArray = Array.isArray(unwrappedStore);
203
206
  if (typeof unwrappedStore !== "object" && typeof unwrappedStore !== "function") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createStore'. Expected an object.`);
@@ -291,11 +294,15 @@ function modifyMutable(state, modifier) {
291
294
  solidJs.batch(() => modifier(unwrap(state)));
292
295
  }
293
296
 
297
+ const $ROOT = Symbol("store-root");
294
298
  function applyState(target, parent, property, merge, key) {
295
299
  const previous = parent[property];
296
300
  if (target === previous) return;
297
301
  if (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key]) {
298
- target !== previous && setProperty(parent, property, target);
302
+ if (target !== previous) {
303
+ if (property === $ROOT) return target;
304
+ setProperty(parent, property, target);
305
+ }
299
306
  return;
300
307
  }
301
308
  if (Array.isArray(target)) {
@@ -367,17 +374,19 @@ function reconcile(value, options = {}) {
367
374
  v = unwrap(value);
368
375
  return state => {
369
376
  if (!isWrappable(state) || !isWrappable(v)) return v;
370
- solidJs.batch(() => applyState(v, {
371
- state
372
- }, "state", merge, key));
373
- return state;
377
+ const res = applyState(v, {
378
+ [$ROOT]: state
379
+ }, $ROOT, merge, key);
380
+ return res === undefined ? state : res;
374
381
  };
375
382
  }
383
+ const producers = new WeakMap();
376
384
  const setterTraps = {
377
385
  get(target, property) {
378
386
  if (property === $RAW) return target;
379
387
  const value = target[property];
380
- return isWrappable(value) ? new Proxy(value, setterTraps) : value;
388
+ let proxy;
389
+ return isWrappable(value) ? producers.get(value) || (producers.set(value, proxy = new Proxy(value, setterTraps)), proxy) : value;
381
390
  },
382
391
  set(target, property, value) {
383
392
  setProperty(target, property, unwrap(value));
@@ -390,7 +399,13 @@ const setterTraps = {
390
399
  };
391
400
  function produce(fn) {
392
401
  return state => {
393
- if (isWrappable(state)) fn(new Proxy(state, setterTraps));
402
+ if (isWrappable(state)) {
403
+ let proxy;
404
+ if (!(proxy = producers.get(state))) {
405
+ producers.set(state, proxy = new Proxy(state, setterTraps));
406
+ }
407
+ fn(proxy);
408
+ }
394
409
  return state;
395
410
  };
396
411
  }
package/store/dist/dev.js CHANGED
@@ -27,7 +27,8 @@ function wrap$1(value, name) {
27
27
  return p;
28
28
  }
29
29
  function isWrappable(obj) {
30
- return obj != null && typeof obj === "object" && (obj[$PROXY] || !obj.__proto__ || obj.__proto__ === Object.prototype || Array.isArray(obj));
30
+ let proto;
31
+ return obj != null && typeof obj === "object" && (obj[$PROXY] || !(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype || Array.isArray(obj));
31
32
  }
32
33
  function unwrap(item, set = new Set()) {
33
34
  let result, unwrapped, v, prop;
@@ -139,14 +140,16 @@ function mergeStoreNode(state, value) {
139
140
  function updateArray(current, next) {
140
141
  if (typeof next === "function") next = next(current);
141
142
  next = unwrap(next);
142
- if (current === next) return;
143
- let i = 0,
144
- len = next.length;
145
- for (; i < len; i++) {
146
- const value = next[i];
147
- if (current[i] !== value) setProperty(current, i, value);
148
- }
149
- setProperty(current, "length", len);
143
+ if (Array.isArray(next)) {
144
+ if (current === next) return;
145
+ let i = 0,
146
+ len = next.length;
147
+ for (; i < len; i++) {
148
+ const value = next[i];
149
+ if (current[i] !== value) setProperty(current, i, value);
150
+ }
151
+ setProperty(current, "length", len);
152
+ } else mergeStoreNode(current, next);
150
153
  }
151
154
  function updatePath(current, path, traversed = []) {
152
155
  let part,
@@ -193,7 +196,7 @@ function updatePath(current, path, traversed = []) {
193
196
  mergeStoreNode(prev, value);
194
197
  } else setProperty(current, part, value);
195
198
  }
196
- function createStore(store, options) {
199
+ function createStore(...[store, options]) {
197
200
  const unwrappedStore = unwrap(store || {});
198
201
  const isArray = Array.isArray(unwrappedStore);
199
202
  if (typeof unwrappedStore !== "object" && typeof unwrappedStore !== "function") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createStore'. Expected an object.`);
@@ -287,11 +290,15 @@ function modifyMutable(state, modifier) {
287
290
  batch(() => modifier(unwrap(state)));
288
291
  }
289
292
 
293
+ const $ROOT = Symbol("store-root");
290
294
  function applyState(target, parent, property, merge, key) {
291
295
  const previous = parent[property];
292
296
  if (target === previous) return;
293
297
  if (!isWrappable(target) || !isWrappable(previous) || key && target[key] !== previous[key]) {
294
- target !== previous && setProperty(parent, property, target);
298
+ if (target !== previous) {
299
+ if (property === $ROOT) return target;
300
+ setProperty(parent, property, target);
301
+ }
295
302
  return;
296
303
  }
297
304
  if (Array.isArray(target)) {
@@ -363,17 +370,19 @@ function reconcile(value, options = {}) {
363
370
  v = unwrap(value);
364
371
  return state => {
365
372
  if (!isWrappable(state) || !isWrappable(v)) return v;
366
- batch(() => applyState(v, {
367
- state
368
- }, "state", merge, key));
369
- return state;
373
+ const res = applyState(v, {
374
+ [$ROOT]: state
375
+ }, $ROOT, merge, key);
376
+ return res === undefined ? state : res;
370
377
  };
371
378
  }
379
+ const producers = new WeakMap();
372
380
  const setterTraps = {
373
381
  get(target, property) {
374
382
  if (property === $RAW) return target;
375
383
  const value = target[property];
376
- return isWrappable(value) ? new Proxy(value, setterTraps) : value;
384
+ let proxy;
385
+ return isWrappable(value) ? producers.get(value) || (producers.set(value, proxy = new Proxy(value, setterTraps)), proxy) : value;
377
386
  },
378
387
  set(target, property, value) {
379
388
  setProperty(target, property, unwrap(value));
@@ -386,7 +395,13 @@ const setterTraps = {
386
395
  };
387
396
  function produce(fn) {
388
397
  return state => {
389
- if (isWrappable(state)) fn(new Proxy(state, setterTraps));
398
+ if (isWrappable(state)) {
399
+ let proxy;
400
+ if (!(proxy = producers.get(state))) {
401
+ producers.set(state, proxy = new Proxy(state, setterTraps));
402
+ }
403
+ fn(proxy);
404
+ }
390
405
  return state;
391
406
  };
392
407
  }
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const $RAW = Symbol("state-raw");
6
6
  function isWrappable(obj) {
7
- return obj != null && typeof obj === "object" && (obj.__proto__ === Object.prototype || Array.isArray(obj));
7
+ return obj != null && typeof obj === "object" && (Object.getPrototypeOf(obj) === Object.prototype || Array.isArray(obj));
8
8
  }
9
9
  function unwrap(item) {
10
10
  return item;
@@ -22,6 +22,19 @@ function mergeStoreNode(state, value, force) {
22
22
  setProperty(state, key, value[key], force);
23
23
  }
24
24
  }
25
+ function updateArray(current, next) {
26
+ if (typeof next === "function") next = next(current);
27
+ if (Array.isArray(next)) {
28
+ if (current === next) return;
29
+ let i = 0,
30
+ len = next.length;
31
+ for (; i < len; i++) {
32
+ const value = next[i];
33
+ if (current[i] !== value) setProperty(current, i, value);
34
+ }
35
+ setProperty(current, "length", len);
36
+ } else mergeStoreNode(current, next);
37
+ }
25
38
  function updatePath(current, path, traversed = []) {
26
39
  let part,
27
40
  next = current;
@@ -67,8 +80,9 @@ function updatePath(current, path, traversed = []) {
67
80
  } else setProperty(current, part, value);
68
81
  }
69
82
  function createStore(state) {
83
+ const isArray = Array.isArray(state);
70
84
  function setStore(...args) {
71
- updatePath(state, args);
85
+ isArray && args.length === 1 ? updateArray(state, args[0]) : updatePath(state, args);
72
86
  }
73
87
  return [state, setStore];
74
88
  }