Releases: Shopify/remote-dom
@remote-dom/signals@2.1.1
Patch Changes
-
#611
f20f6e7Thanks @eddiechan! - Guard receivers against late mutations on detached nodesRemoteReceiverandSignalRemoteReceivernow dropinsertChild,removeChild,updateProperty, andupdateTextmutations whose target node is no longer in the receiver'sattachedmap, instead of throwing aTypeErrorwhile dereferencing the missing node.This race surfaces in production as unhandled promise rejections such as
TypeError: undefined is not an object (evaluating 'x.properties')(Safari) /TypeError: Cannot read properties of undefined (reading 'properties')(V8) when a remote sender dispatches a mutation for a node whose host-side state has just been removed (for example, aremoveChildfor an ancestor was processed earlier in the same batch, or arrived first from a separate batched payload).PR #533 previously added a similar guard to
removeChildfor the case where the child slot at a given index was empty, but did not handle the case where the parent itself was missing, and did not touchupdatePropertyorupdateText. This change applies the same defensive pattern uniformly to every connection callback that dereferencesattached.get(id).Late mutations targeting a detached subtree are by definition no-ops — there is nothing left to mutate.
-
Updated dependencies [
f20f6e7]:- @remote-dom/core@1.11.1
@remote-dom/core@1.11.1
Patch Changes
-
#611
f20f6e7Thanks @eddiechan! - Guard receivers against late mutations on detached nodesRemoteReceiverandSignalRemoteReceivernow dropinsertChild,removeChild,updateProperty, andupdateTextmutations whose target node is no longer in the receiver'sattachedmap, instead of throwing aTypeErrorwhile dereferencing the missing node.This race surfaces in production as unhandled promise rejections such as
TypeError: undefined is not an object (evaluating 'x.properties')(Safari) /TypeError: Cannot read properties of undefined (reading 'properties')(V8) when a remote sender dispatches a mutation for a node whose host-side state has just been removed (for example, aremoveChildfor an ancestor was processed earlier in the same batch, or arrived first from a separate batched payload).PR #533 previously added a similar guard to
removeChildfor the case where the child slot at a given index was empty, but did not handle the case where the parent itself was missing, and did not touchupdatePropertyorupdateText. This change applies the same defensive pattern uniformly to every connection callback that dereferencesattached.get(id).Late mutations targeting a detached subtree are by definition no-ops — there is nothing left to mutate.
@remote-dom/core@1.11.0
Minor Changes
-
#604
7177edbThanks @justinhenricks! - FlushBatchingRemoteConnectionmutations on a microtask by defaultThe default
batchfunction used byBatchingRemoteConnectionnow schedules flushes on a microtask (viaqueueMicrotask, falling back toPromise.resolve().then(...)) instead of a macrotask viaMessageChannel/setTimeout.This ensures that DOM mutations made in the remote environment are delivered to the host before any
awaited RPC response resolves, avoiding a class of bugs where the host sees an RPC result before the element updates that produced it (for example, aperform()callback setting an error on a field, only to have the host run its post-awaitlogic before that error mutation arrives).If you were relying on the previous macrotask behavior, you can restore it by passing a custom
batchoption, e.g.:new BatchingRemoteConnection(connection, { batch: (flush) => { const channel = new MessageChannel(); channel.port1.onmessage = () => flush(); channel.port2.postMessage(null); }, });
@remote-dom/polyfill@1.5.1
Patch Changes
- #600
d9b4dabThanks @henrytao-me! - Fix document fragment owner document
@remote-dom/core@1.10.1
Patch Changes
-
#600
d9b4dabThanks @henrytao-me! - Fix document fragment owner document -
Updated dependencies [
d9b4dab]:- @remote-dom/polyfill@1.5.1
@remote-dom/core@1.10.0
@remote-dom/polyfill@1.5.0
Minor Changes
- #593
61f5cbaThanks @developit! - Add support fornotin query-selectors
@remote-dom/polyfill@1.4.7
Patch Changes
- #594
789a7c7Thanks @robin-drexler! - addFocusEvent,ClipboardEventandToggleEventto polyfill
@remote-dom/polyfill@1.4.6
Patch Changes
- #590
8994a49Thanks @robin-drexler! - fix error events not working
@remote-dom/core@1.9.0
Minor Changes
-
#583
a7be991Thanks @lemonmade! - ImprovedRemoteMutationObserverto support automatic emptying and observing multiple nodesIf you are observing a multi-node list — such as a
DocumentFragmentor<template>element — you can now provide a customidoption when observing each node. This allows you to treat the observer as a kind of "virtual root" for a list of nodes, similar to the role theDocumentFragmentplays in the DOM. You are responsible for giving each node a unique ID, and this class will take care of correctly attaching that node to the root of the remote tree.const observer = new RemoteMutationObserver(connection); let id = 0; for (const child of documentFragment.childNodes) { observer.observe(child, { id: `DocumentFragment:${id++}`, }); }
You can also now provide an
emptyoption toRemoteMutationObserver.disconnect()in order to clear out children in remote environment:const observer = new RemoteMutationObserver(connection); observer.observe(container); observer.disconnect({empty: true});
-
#583
a7be991Thanks @lemonmade! - ExposeremoteId()andsetRemoteId()for getting and setting a Node's remote ID