@b9g/crank 0.7.4 → 0.7.6

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/crank.cjs CHANGED
@@ -251,9 +251,15 @@ function getValue(ret, isNested = false, index) {
251
251
  function getChildValues(ret, startIndex) {
252
252
  const values = [];
253
253
  const lingerers = ret.lingerers;
254
- const children = _utils.wrap(ret.children);
254
+ const rawChildren = ret.children;
255
+ const isChildrenArray = Array.isArray(rawChildren);
256
+ const childrenLength = rawChildren === undefined
257
+ ? 0
258
+ : isChildrenArray
259
+ ? rawChildren.length
260
+ : 1;
255
261
  let currentIndex = startIndex;
256
- for (let i = 0; i < children.length; i++) {
262
+ for (let i = 0; i < childrenLength; i++) {
257
263
  if (lingerers != null && lingerers[i] != null) {
258
264
  const rets = lingerers[i];
259
265
  for (const ret of rets) {
@@ -274,7 +280,9 @@ function getChildValues(ret, startIndex) {
274
280
  }
275
281
  }
276
282
  }
277
- const child = children[i];
283
+ const child = isChildrenArray
284
+ ? rawChildren[i]
285
+ : rawChildren;
278
286
  if (child) {
279
287
  const value = getValue(child, true, currentIndex);
280
288
  if (Array.isArray(value)) {
@@ -293,8 +301,8 @@ function getChildValues(ret, startIndex) {
293
301
  }
294
302
  }
295
303
  }
296
- if (lingerers != null && lingerers.length > children.length) {
297
- for (let i = children.length; i < lingerers.length; i++) {
304
+ if (lingerers != null && lingerers.length > childrenLength) {
305
+ for (let i = childrenLength; i < lingerers.length; i++) {
298
306
  const rets = lingerers[i];
299
307
  if (rets != null) {
300
308
  for (const ret of rets) {
@@ -453,7 +461,155 @@ function renderRoot(adapter, root, ret, children) {
453
461
  }
454
462
  return adapter.read(_utils.unwrap(getChildValues(ret)));
455
463
  }
464
+ function diffChild(adapter, root, host, ctx, scope, parent, newChildren) {
465
+ let child = narrow(newChildren);
466
+ let ret = parent.children;
467
+ let graveyard;
468
+ let diff;
469
+ if (typeof child === "object") {
470
+ let childCopied = false;
471
+ // Check key match
472
+ const oldKey = typeof ret === "object" ? ret.el.props.key : undefined;
473
+ const newKey = child.props.key;
474
+ if (oldKey !== newKey) {
475
+ if (typeof ret === "object") {
476
+ (graveyard = graveyard || []).push(ret);
477
+ }
478
+ ret = undefined;
479
+ }
480
+ if (child.tag === Copy) {
481
+ childCopied = true;
482
+ }
483
+ else if (typeof ret === "object" &&
484
+ ret.el === child &&
485
+ getFlag(ret, DidCommit)) {
486
+ childCopied = true;
487
+ }
488
+ else {
489
+ if (ret && ret.el.tag === child.tag) {
490
+ ret.el = child;
491
+ if (child.props.copy && typeof child.props.copy !== "string") {
492
+ childCopied = true;
493
+ }
494
+ }
495
+ else if (ret) {
496
+ let candidateFound = false;
497
+ for (let predecessor = ret, candidate = ret.fallback; candidate; predecessor = candidate, candidate = candidate.fallback) {
498
+ if (candidate.el.tag === child.tag) {
499
+ const clone = cloneRetainer(candidate);
500
+ setFlag(clone, IsResurrecting);
501
+ predecessor.fallback = clone;
502
+ const fallback = ret;
503
+ ret = candidate;
504
+ ret.el = child;
505
+ ret.fallback = fallback;
506
+ setFlag(ret, DidDiff, false);
507
+ candidateFound = true;
508
+ break;
509
+ }
510
+ }
511
+ if (!candidateFound) {
512
+ const fallback = ret;
513
+ ret = new Retainer(child);
514
+ ret.fallback = fallback;
515
+ }
516
+ }
517
+ else {
518
+ ret = new Retainer(child);
519
+ }
520
+ if (childCopied && getFlag(ret, DidCommit)) ;
521
+ else if (child.tag === Raw || child.tag === Text) ;
522
+ else if (child.tag === Fragment) {
523
+ diff = diffChildren(adapter, root, host, ctx, scope, ret, ret.el.props.children);
524
+ }
525
+ else if (typeof child.tag === "function") {
526
+ diff = diffComponent(adapter, root, host, ctx, scope, ret);
527
+ }
528
+ else {
529
+ diff = diffHost(adapter, root, ctx, scope, ret);
530
+ }
531
+ }
532
+ if (typeof ret === "object") {
533
+ if (childCopied) {
534
+ setFlag(ret, IsCopied);
535
+ diff = getInflightDiff(ret);
536
+ }
537
+ else {
538
+ setFlag(ret, IsCopied, false);
539
+ }
540
+ }
541
+ }
542
+ else if (typeof child === "string") {
543
+ if (typeof ret === "object" && ret.el.tag === Text) {
544
+ ret.el.props.value = child;
545
+ }
546
+ else {
547
+ if (typeof ret === "object") {
548
+ (graveyard = graveyard || []).push(ret);
549
+ }
550
+ ret = new Retainer(createElement(Text, { value: child }));
551
+ }
552
+ }
553
+ else {
554
+ if (typeof ret === "object") {
555
+ (graveyard = graveyard || []).push(ret);
556
+ }
557
+ ret = undefined;
558
+ }
559
+ parent.children = ret;
560
+ if (_utils.isPromiseLike(diff)) {
561
+ const diff1 = diff.finally(() => {
562
+ setFlag(parent, DidDiff);
563
+ if (graveyard) {
564
+ if (parent.graveyard) {
565
+ for (let i = 0; i < graveyard.length; i++) {
566
+ parent.graveyard.push(graveyard[i]);
567
+ }
568
+ }
569
+ else {
570
+ parent.graveyard = graveyard;
571
+ }
572
+ }
573
+ });
574
+ let onNextDiffs;
575
+ const diff2 = (parent.pendingDiff = _utils.safeRace([
576
+ diff1,
577
+ new Promise((resolve) => (onNextDiffs = resolve)),
578
+ ]));
579
+ if (parent.onNextDiff) {
580
+ parent.onNextDiff(diff2);
581
+ }
582
+ parent.onNextDiff = onNextDiffs;
583
+ return diff2;
584
+ }
585
+ else {
586
+ setFlag(parent, DidDiff);
587
+ if (graveyard) {
588
+ if (parent.graveyard) {
589
+ for (let i = 0; i < graveyard.length; i++) {
590
+ parent.graveyard.push(graveyard[i]);
591
+ }
592
+ }
593
+ else {
594
+ parent.graveyard = graveyard;
595
+ }
596
+ }
597
+ if (parent.onNextDiff) {
598
+ parent.onNextDiff(diff);
599
+ parent.onNextDiff = undefined;
600
+ }
601
+ parent.pendingDiff = undefined;
602
+ }
603
+ }
456
604
  function diffChildren(adapter, root, host, ctx, scope, parent, newChildren) {
605
+ // Fast path for the common single non-keyed child case
606
+ if (!Array.isArray(newChildren) &&
607
+ (typeof newChildren !== "object" ||
608
+ newChildren === null ||
609
+ typeof newChildren[Symbol.iterator] !== "function") &&
610
+ !Array.isArray(parent.children)) {
611
+ return diffChild(adapter, root, host, ctx, scope, parent, newChildren);
612
+ }
457
613
  const oldRetained = _utils.wrap(parent.children);
458
614
  const newRetained = [];
459
615
  const newChildren1 = _utils.arrayify(newChildren);
@@ -754,7 +910,7 @@ function commit(adapter, host, ret, ctx, scope, root, index, schedulePromises, h
754
910
  }
755
911
  }
756
912
  if (skippedHydrationNodes) {
757
- skippedHydrationNodes.splice(0, _utils.wrap(value).length);
913
+ skippedHydrationNodes.splice(0, value == null ? 0 : Array.isArray(value) ? value.length : 1);
758
914
  }
759
915
  if (!getFlag(ret, DidCommit)) {
760
916
  setFlag(ret, DidCommit);
@@ -769,8 +925,17 @@ function commit(adapter, host, ret, ctx, scope, root, index, schedulePromises, h
769
925
  }
770
926
  function commitChildren(adapter, host, ctx, scope, root, parent, index, schedulePromises, hydrationNodes) {
771
927
  let values = [];
772
- for (let i = 0, children = _utils.wrap(parent.children); i < children.length; i++) {
773
- let child = children[i];
928
+ const rawChildren = parent.children;
929
+ const isChildrenArray = Array.isArray(rawChildren);
930
+ const childrenLength = rawChildren === undefined
931
+ ? 0
932
+ : isChildrenArray
933
+ ? rawChildren.length
934
+ : 1;
935
+ for (let i = 0; i < childrenLength; i++) {
936
+ let child = isChildrenArray
937
+ ? rawChildren[i]
938
+ : rawChildren;
774
939
  let schedulePromises1;
775
940
  let isSchedulingFallback = false;
776
941
  while (child &&
@@ -1055,6 +1220,7 @@ function commitHost(adapter, ret, ctx, root, schedulePromises, hydrationNodes) {
1055
1220
  props,
1056
1221
  children,
1057
1222
  oldProps,
1223
+ scope,
1058
1224
  root,
1059
1225
  });
1060
1226
  }
@@ -1212,12 +1378,18 @@ function unmountChildren(adapter, host, ctx, root, ret, isNested) {
1212
1378
  }
1213
1379
  ret.graveyard = undefined;
1214
1380
  }
1215
- for (let i = 0, children = _utils.wrap(ret.children); i < children.length; i++) {
1216
- const child = children[i];
1217
- if (typeof child === "object") {
1218
- unmount(adapter, host, ctx, root, child, isNested);
1381
+ const rawChildren = ret.children;
1382
+ if (Array.isArray(rawChildren)) {
1383
+ for (let i = 0; i < rawChildren.length; i++) {
1384
+ const child = rawChildren[i];
1385
+ if (typeof child === "object") {
1386
+ unmount(adapter, host, ctx, root, child, isNested);
1387
+ }
1219
1388
  }
1220
1389
  }
1390
+ else if (rawChildren !== undefined) {
1391
+ unmount(adapter, host, ctx, root, rawChildren, isNested);
1392
+ }
1221
1393
  }
1222
1394
  const provisionMaps = new WeakMap();
1223
1395
  const scheduleMap = new WeakMap();
@@ -2087,12 +2259,16 @@ function isRetainerActive(target, host) {
2087
2259
  ((typeof current.el.tag === "string" && current.el.tag !== Fragment) ||
2088
2260
  current.el.tag === Portal);
2089
2261
  if (current.children && !isHostBoundary) {
2090
- const children = _utils.wrap(current.children);
2091
- for (const child of children) {
2092
- if (child) {
2093
- stack.push(child);
2262
+ if (Array.isArray(current.children)) {
2263
+ for (const child of current.children) {
2264
+ if (child) {
2265
+ stack.push(child);
2266
+ }
2094
2267
  }
2095
2268
  }
2269
+ else {
2270
+ stack.push(current.children);
2271
+ }
2096
2272
  }
2097
2273
  // Add fallback chains (only if current retainer is using fallback)
2098
2274
  if (current.fallback && !getFlag(current, DidDiff)) {
@@ -2116,6 +2292,11 @@ function propagateComponent(ctx) {
2116
2292
  if (!isRetainerActive(initiator, host)) {
2117
2293
  return;
2118
2294
  }
2295
+ // Check if host has been committed (has a node)
2296
+ // Fixes #334: refresh() called before component yields
2297
+ if (!getFlag(host, DidCommit)) {
2298
+ return;
2299
+ }
2119
2300
  const props = stripSpecialProps(host.el.props);
2120
2301
  const hostChildren = getChildValues(host, 0);
2121
2302
  ctx.adapter.arrange({
@@ -2125,6 +2306,7 @@ function propagateComponent(ctx) {
2125
2306
  props,
2126
2307
  oldProps: props,
2127
2308
  children: hostChildren,
2309
+ scope: host.scope,
2128
2310
  root: ctx.root,
2129
2311
  });
2130
2312
  flush(ctx.adapter, ctx.root, ctx);