diff --git a/.changeset/olive-mangos-march.md b/.changeset/olive-mangos-march.md new file mode 100644 index 000000000000..28253eb49aa7 --- /dev/null +++ b/.changeset/olive-mangos-march.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: handle cross-realm Promises in `hydratable` diff --git a/packages/svelte/src/internal/server/hydratable.js b/packages/svelte/src/internal/server/hydratable.js index 59fa97da4c6d..5711885ed41c 100644 --- a/packages/svelte/src/internal/server/hydratable.js +++ b/packages/svelte/src/internal/server/hydratable.js @@ -56,7 +56,7 @@ function encode(key, value, unresolved) { let uid = 1; entry.serialized = devalue.uneval(entry.value, (value, uneval) => { - if (value instanceof Promise) { + if (is_promise(value)) { const p = value .then((v) => `r(${uneval(v)})`) .catch((devalue_error) => @@ -90,6 +90,16 @@ function encode(key, value, unresolved) { return entry; } +/** + * @param {any} value + * @returns {value is Promise} + */ +function is_promise(value) { + // we use this check rather than `instanceof Promise` + // because it works cross-realm + return Object.prototype.toString.call(value) === '[object Promise]'; +} + /** * @param {string} key * @param {HydratableLookupEntry} a