chunks
4 days ago
vendor
10 months ago
admin.build.js
2 months ago
admin.js
4 months ago
analytics-tracker.js
2 months ago
analytics.build.js
4 days ago
blocks.build.js
4 days ago
carousel.js
1 year ago
custom-player.build.js
2 months ago
documents-viewer-script.js
4 months ago
editor-popover-guard.js
2 weeks ago
ep-gr-elementor-control.js
1 month ago
ep-pdf-lightbox.js
4 months ago
ep-view-count.js
2 months ago
ep-yt-queue.js
2 months ago
feature-notices.js
9 months ago
feature-preview-modal.js
1 month ago
front.js
1 month ago
frontend.build.js
4 months ago
gallery-justify.js
2 months ago
google-reviews.build.js
4 weeks ago
google-reviews.js
4 weeks ago
gutneberg-script.js
3 months ago
index.html
7 years ago
initCarousel.js
2 years ago
initplyr.js
3 months ago
instafeed.js
2 months ago
instagram-shortcode-generator.js
3 months ago
lazy-load.js
8 months ago
license.js
5 months ago
meetup-timezone.js
4 months ago
onboarding.build.js
4 days ago
pdf-gallery-elementor-editor.js
4 months ago
pdf-gallery.js
4 months ago
preview.js
1 month ago
settings.js
4 months ago
sponsored.js
11 months ago
editor-popover-guard.js
110 lines
| 1 | /** |
| 2 | * Editor popover guard — prevents the block editor from crashing when the |
| 3 | * iframed canvas is torn down while a Floating UI popover is still mounted. |
| 4 | * |
| 5 | * THE BUG (FB #84254) |
| 6 | * ------------------- |
| 7 | * WordPress only iframes the editor canvas when EVERY block in the post is |
| 8 | * `apiVersion >= 3` (see `useShouldIframe()` in wp-includes/js/dist/edit-post.js). |
| 9 | * EmbedPress blocks are `apiVersion: 2`, so inserting one into a post that was |
| 10 | * being edited in the iframed canvas flips that condition to false and core |
| 11 | * destroys the `editor-canvas` iframe mid-flight. |
| 12 | * |
| 13 | * The block toolbar / between-blocks insertion-point popovers are still mounted |
| 14 | * at that moment. Floating UI's `autoUpdate()` then runs: |
| 15 | * |
| 16 | * getOverflowAncestors(node) |
| 17 | * -> const win = getWindow(scrollableAncestor) |
| 18 | * -> getFrameElement(win) // returns null: the frame is gone |
| 19 | * -> getOverflowAncestors(null) // core recurses WITHOUT a null check |
| 20 | * -> getNearestOverflowAncestor(null) |
| 21 | * -> getComputedStyle(null) // TypeError -> React unmounts the editor |
| 22 | * |
| 23 | * Result: "The editor has encountered an unexpected error." |
| 24 | * |
| 25 | * WHY THE GUARD LIVES HERE |
| 26 | * ------------------------ |
| 27 | * `useShouldIframe()` exposes no filter, so the teardown itself cannot be |
| 28 | * prevented from a plugin. The throw is core passing `null` into a DOM API that |
| 29 | * requires an Element -- a call that is meaningless for a null argument in the |
| 30 | * first place. We make that single call non-fatal. |
| 31 | * |
| 32 | * Scope is deliberately minimal: |
| 33 | * - Only runs on block editor screens where EmbedPress is active. |
| 34 | * - Only intercepts non-Element arguments. Every real Element call goes |
| 35 | * straight through to the native implementation, untouched. |
| 36 | * - Returns an inert style-declaration-shaped stub, which is what the |
| 37 | * Floating UI ancestor walk reads (`overflow`, `overflowX`, `overflowY`, |
| 38 | * `display`, `position`) before discarding the branch. |
| 39 | * |
| 40 | * This mirrors what upstream Floating UI does today: newer versions null-check |
| 41 | * `frameElement` before recursing. The guard becomes a no-op once WordPress |
| 42 | * ships that version. |
| 43 | */ |
| 44 | (function () { |
| 45 | 'use strict'; |
| 46 | |
| 47 | if (typeof window === 'undefined' || !window.getComputedStyle) { |
| 48 | return; |
| 49 | } |
| 50 | |
| 51 | // Guard against double-installation (script enqueued twice, HMR, etc.). |
| 52 | if (window.__embedpressPopoverGuardInstalled) { |
| 53 | return; |
| 54 | } |
| 55 | window.__embedpressPopoverGuardInstalled = true; |
| 56 | |
| 57 | var native = window.getComputedStyle.bind(window); |
| 58 | |
| 59 | // Values the Floating UI overflow-ancestor walk reads. `visible`/`static` |
| 60 | // make it treat the node as a non-scrolling, non-positioned ancestor, so it |
| 61 | // stops walking that branch instead of throwing. |
| 62 | var INERT = { |
| 63 | overflow: 'visible', |
| 64 | overflowX: 'visible', |
| 65 | overflowY: 'visible', |
| 66 | display: 'block', |
| 67 | position: 'static', |
| 68 | getPropertyValue: function (prop) { |
| 69 | return Object.prototype.hasOwnProperty.call(INERT, prop) && |
| 70 | typeof INERT[prop] === 'string' |
| 71 | ? INERT[prop] |
| 72 | : ''; |
| 73 | }, |
| 74 | }; |
| 75 | |
| 76 | window.getComputedStyle = function (element, pseudoElement) { |
| 77 | // Anything that is a real Element keeps the exact native behaviour. |
| 78 | // |
| 79 | // The check is `nodeType`, NOT `instanceof Element`, and that matters: |
| 80 | // `instanceof` is realm-bound. The editor canvas is an IFRAME, so its |
| 81 | // elements come from a different realm and fail `instanceof Element` |
| 82 | // against this window even while they are perfectly real, attached |
| 83 | // elements. Using `instanceof` here handed every element inside the |
| 84 | // iframed canvas the inert stub below during NORMAL editing — the exact |
| 85 | // opposite of this guard's contract that real elements pass through |
| 86 | // untouched — so anything measuring layout in the canvas silently read |
| 87 | // `overflow: visible` / `position: static` instead of its true style. |
| 88 | // `nodeType === 1` (ELEMENT_NODE) is realm-agnostic and correct here. |
| 89 | if (element && element.nodeType === 1) { |
| 90 | // Resolve against the element's OWN view. An element inside the |
| 91 | // editor-canvas iframe must be measured by that iframe's window; |
| 92 | // passing it to the outer window's implementation resolves it |
| 93 | // against the wrong view. Fall back to the native outer |
| 94 | // implementation when the element has no defaultView (detached). |
| 95 | var view = |
| 96 | element.ownerDocument && element.ownerDocument.defaultView; |
| 97 | if (view && view !== window && |
| 98 | typeof view.getComputedStyle === 'function') { |
| 99 | return view.getComputedStyle(element, pseudoElement); |
| 100 | } |
| 101 | return native(element, pseudoElement); |
| 102 | } |
| 103 | |
| 104 | // Non-Element (null/undefined/window/document/text node): core is walking |
| 105 | // past a torn-down canvas. Returning an inert declaration ends the walk |
| 106 | // quietly instead of taking the whole editor down. |
| 107 | return INERT; |
| 108 | }; |
| 109 | })(); |
| 110 |