Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions python/pythonmonkey/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
require("base64")
require("timers")
require("url")
require("structured-clone")
require("XMLHttpRequest")
15 changes: 15 additions & 0 deletions python/pythonmonkey/builtin_modules/structured-clone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @file structured-clone.js
* Polyfill the structuredClone() global
*
* @author Dan Desjardins <dan@distributive.network>
* @date November 2026
*
* @copyright Copyright (c) 2026 Distributive Corp.
*/

// Apply polyfill from core-js
require('./dom-exception');
require('core-js/actual/structured-clone');

exports.structuredClone = globalThis.structuredClone;
3 changes: 3 additions & 0 deletions python/pythonmonkey/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ declare var clearInterval: typeof import("timers").clearInterval;
declare var URL: typeof import("url").URL;
declare var URLSearchParams: typeof import("url").URLSearchParams;

// Expose `structuredClone`
declare function structuredClone<T = any>(value: T, options?: { transfer?: any[] }): T;

// Expose `XMLHttpRequest` (XHR) API
declare var XMLHttpRequest: typeof import("XMLHttpRequest").XMLHttpRequest;

Expand Down
28 changes: 28 additions & 0 deletions tests/js/structured-clone.simple
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @file structured-clone.simple
* Simple test for the structuredClone() global
* @author Dan Desjardins <dan@distributive.network>
* @date November 2026
*/

function assert(cond, message)
{
if (!cond) throw new Error(message);
}

assert(typeof structuredClone === 'function', 'structuredClone is not a global function');

const source = { list: ['a'], nested: { map: new Map([[1, { x: 2 }]]), date: new Date(0), bytes: new Uint8Array([1, 2, 3]) } };
source.self = source;
const copy = structuredClone(source);

copy.list.push('b');
assert(source.list.length === 1, 'clone shares an array with its source');
assert(copy.nested.map.get(1).x === 2, 'Map entries were not cloned');
assert(copy.nested.date instanceof Date && copy.nested.date.getTime() === 0, 'Date was not cloned');
assert(copy.nested.bytes.join() === '1,2,3' && copy.nested.bytes !== source.nested.bytes, 'Uint8Array was not cloned');
assert(copy.self === copy, 'cycle was not preserved');

let error;
try { structuredClone(function f() {}); } catch (e) { error = e; }
assert(error && error.name === 'DataCloneError', 'cloning a function did not throw DataCloneError');
Loading