justintadlock / block-pattern-builder

Build block patterns from the WordPress admin.
GNU General Public License v2.0
42 stars 9 forks source link

block-pattern-builder crashes the editor after a user selects multiple blocks #22

Open skorasaurus opened 3 years ago

skorasaurus commented 3 years ago

After creating a group block and a user attempts to select more blocks, the block-pattern-builder plugin causes the editor to crash.

To reproduce:

  1. Open the editor
  2. create several blocks, content doesn't matter
  3. While holding shift, select multiple blocks
  4. go to the block toolbar and group them together. This is successful.
  5. Begin selecting multiple blocks again to create a new group .
  6. the editor crashes.

I've been able to reproduce this across Gutenberg 9.1 and 9.4.1.

I've deactivated all other plugins except the block-pattern-builder. I'm unable to reproduce this if I deactivate the block-pattern-builder plugin.

I think what could be of note is the following line which is in the console.log

render/S<@https://local.wordpress.test/wp-content/plugins/block-pattern-builder/public/js/editor.js?id=0fa3860205cf6b634f29:1:2467

The full console log is below:

Uncaught Error: An error occurred while running 'mapSelect': block is null
The error may be correlated with this previous error:
serializeBlock@https://local.wordpress.test/wp-includes/js/dist/blocks.js?ver=94ae7f5a0fa088eb1cb5e8b7a601a5eb:9242:19
serialize/<@https://local.wordpress.test/wp-includes/js/dist/blocks.js?ver=94ae7f5a0fa088eb1cb5e8b7a601a5eb:9264:12
serialize@https://local.wordpress.test/wp-includes/js/dist/blocks.js?ver=94ae7f5a0fa088eb1cb5e8b7a601a5eb:9263:61
render/S<@https://local.wordpress.test/wp-content/plugins/block-pattern-builder/public/js/editor.js?id=0fa3860205cf6b634f29:1:2467
onStoreChange@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:3344:46
useSelect/</unsubscribe<@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:3371:9
globalListener/<@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:2418:14
globalListener@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:2417:15
createNamespace/subscribe</<@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:2024:9
dispatch@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:1101:7
createMiddleware/</</<@https://local.wordpress.test/wp-includes/js/dist/redux-routine.js?ver=9c464c6fba42fc0112f5feedb4939fa6:928:18
promiseMiddleware/</<@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:1560:14
createResolversCacheMiddleware/</</<@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:1619:16
multi/</<@https://local.wordpress.test/wp-includes/js/dist/block-editor.js?ver=a5482da84276f82419126932713bda2f:10411:77
middleware/</<@https://local.wordpress.test/wp-includes/js/dist/block-editor.js?ver=a5482da84276f82419126932713bda2f:5562:19
createBoundAction/<@https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:2134:36
onMouseDown@https://local.wordpress.test/wp-includes/js/dist/block-editor.js?ver=a5482da84276f82419126932713bda2f:26662:24
callCallback@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:341:14
invokeGuardedCallbackDev@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:391:16
invokeGuardedCallback@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:448:31
invokeGuardedCallbackAndCatchFirstError@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:462:25
executeDispatch@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:594:42
executeDispatchesInOrder@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:613:22
executeDispatchesAndRelease@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:719:29
executeDispatchesAndReleaseTopLevel@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:727:10
forEachAccumulated@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:701:8
runEventsInBatch@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:744:21
runExtractedPluginEventsInBatch@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:875:19
handleTopLevel@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:6026:36
batchedEventUpdates@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:2342:12
dispatchEventForPluginEventSystem@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:6121:24
dispatchEvent@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:6150:38
unstable_runWithPriority@https://local.wordpress.test/wp-includes/js/dist/vendor/react.js?ver=16.9.0:2820:12
runWithPriority$2@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:11443:10
discreteUpdates$1@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:21810:12
discreteUpdates@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:2357:12
dispatchDiscreteEvent@https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:6104:18

Original stack trace:
    useSelect https://local.wordpress.test/wp-includes/js/dist/data.js?ver=75f90354ddff4acd5b0b4026454037ca:3319
    render https://local.wordpress.test/wp-content/plugins/block-pattern-builder/public/js/editor.js?id=0fa3860205cf6b634f29:1
    renderWithHooks https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:15246
    updateFunctionComponent https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:17063
    beginWork$1 https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:18636
    callCallback https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:341
    invokeGuardedCallbackDev https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:391
    invokeGuardedCallback https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:448
    beginWork$$1 https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:23355
    performUnitOfWork https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:22346
    workLoopSync https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:22323
    renderRoot https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:22016
    runRootCallback https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:21692
    flushSyncCallbackQueueImpl https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:11491
    unstable_runWithPriority https://local.wordpress.test/wp-includes/js/dist/vendor/react.js?ver=16.9.0:2820
    runWithPriority$2 https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:11443
    flushSyncCallbackQueueImpl https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:11487
    flushSyncCallbackQueue https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:11476
    discreteUpdates$1 https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:21815
    discreteUpdates https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:2357
    dispatchDiscreteEvent https://local.wordpress.test/wp-includes/js/dist/vendor/react-dom.js?ver=16.9.0:6104

render/S<@https://local.wordpress.test/wp-content/plugins/block-pattern-builder/public/js/editor.js?id=0fa3860205cf6b634f29:1:2467

character 2467, expanded out is before u(l)

When I beautified, that out, the surrounding code is:

    var o = blockPatternBuilder.labels,
      u = (wp.i18n.__, wp.blocks.serialize),
      l = wp.components,
      i = l.Button,
      a = l.Modal,
      c = l.TextControl,
      s = wp.data,
      f = s.useSelect,
      p = s.useDispatch,
      d = wp.editPost.PluginBlockSettingsMenuItem,
      b = wp.element.useState;
    (0, wp.plugins.registerPlugin)("block-pattern-builder", {
      render: function () {
        var e = n(b(!1), 2),
          t = e[0],
          r = e[1],
          l = n(b(!1), 2),
          s = l[0],
          m = l[1],
          y = n(b(""), 2),
          g = y[0],
          v = y[1],
          S = f((function (e) {
            var t = e("core/block-editor"),
              n = t.getSelectedBlockCount,
              r = t.getSelectedBlock,
              o = t.getMultiSelectedBlocks,
              l = 1 === n() ? r() : o();
            return u(l)
          }), []),
mgetka commented 3 years ago

I've did some digging and have found out that just before the crash the getSelectedBlockCount returns 1, getMultiSelectedBlocks returns single element array with some block entity, but the getSelectedBlock for some reason returns null.

As a workaround i've changed the logic to use getMultiSelectedBlocks unconditionally near https://github.com/justintadlock/block-pattern-builder/blob/f14564dcce8166cc02810f238487eb3ab1e0751c/resources/js/editor.js#L34 and as for now it seems to work good, but I'm not familiar with gutenberg API to any extent, so I'm not really sure what are eventual side effects of such a change.