Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

structuredClone #984

Merged
merged 73 commits into from Dec 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
d220907
add structured-clone entry points
BasixKOR Sep 13, 2021
ebc8a32
add cloning of primitives, wrappers, Date, RegExp, Map, Set
BasixKOR Sep 14, 2021
3bb20f1
add cloning of array and object
BasixKOR Sep 14, 2021
d807b2e
cache cloned value in a weakmap
BasixKOR Sep 14, 2021
235e6f7
export structuredCloneInternal directly
BasixKOR Sep 15, 2021
5d7c03c
refactor structuredCloneInternal using classof
BasixKOR Sep 15, 2021
25476cc
treat array as object
BasixKOR Sep 15, 2021
8fae5ef
add tests
BasixKOR Sep 15, 2021
3c5342a
implement Error cloning
BasixKOR Sep 15, 2021
0ebccea
apply suggestions from review
BasixKOR Sep 16, 2021
14b3a78
implement arraybuffer cloning
BasixKOR Sep 25, 2021
3cb770d
implement SharedArrayBuffer cloning
BasixKOR Sep 25, 2021
5381fac
implement Blob cloning
BasixKOR Sep 25, 2021
50a1827
implement DataView cloning
BasixKOR Sep 25, 2021
40eccb7
update compat data
BasixKOR Oct 2, 2021
da59491
implement TypedArray cloning
BasixKOR Oct 18, 2021
071ffae
use map for caching
BasixKOR Oct 18, 2021
e6d0a27
rename has
BasixKOR Oct 18, 2021
5800aea
some fixes
zloirock Oct 29, 2021
e149ca8
clone `File` and `ImageData`
zloirock Oct 29, 2021
34b6f80
improve tests
zloirock Oct 29, 2021
ae44dee
clone `DOMException`, fix some specific `Error` cases
zloirock Oct 29, 2021
8977c69
some improvements
zloirock Oct 29, 2021
9284911
clone geometry types
zloirock Oct 29, 2021
300491e
add clone of `AudioData` and `VideoFrame`
zloirock Oct 29, 2021
53d7619
add pure version tests
zloirock Oct 29, 2021
4707b73
forced usage of polyfill in the pure version since native `structured…
zloirock Oct 30, 2021
2040a05
return original `SharedArrayBuffer`, unify `ArrayBufferView` logic
zloirock Oct 31, 2021
bbaddce
don't create `Map` cache on cloning primitives
zloirock Oct 31, 2021
1b81767
fix FF implementation
zloirock Oct 31, 2021
f4bb633
use native structured clone from `PerformanceMark.detail`
zloirock Nov 1, 2021
fddef17
some stylistic changes
zloirock Nov 1, 2021
1675881
make tests pass in Edge (some builtins are functions, but not constru…
zloirock Nov 1, 2021
104a7b5
use `PerformanceMark` instead of `performance.mark`
zloirock Nov 1, 2021
48981fd
fix tests: some engines have `DOMQuad`, but haven't `DOMPoint.fromPoint`
zloirock Nov 1, 2021
fc14c99
use constructors as fallbacks for some geometry types to make them cl…
zloirock Nov 1, 2021
44ae9b1
fix tests for `DOMRect` in FF30-
zloirock Nov 1, 2021
eb03549
drop some dead code from tests
zloirock Nov 1, 2021
d354dd3
clone `FileList`
zloirock Nov 2, 2021
92755dc
Chrome 82- swaps `.name` and `.message` of cloned `DOMException`
zloirock Nov 2, 2021
5341988
move `internals/structured-clone` content to `modules/web.structured-…
zloirock Nov 3, 2021
68e1f60
simplify `ArrayBuffer` case, update entries dependencies
zloirock Nov 3, 2021
488c1fe
fix the order of variables definition
zloirock Nov 3, 2021
e46a9ea
use `nativeRestrictedStructuredClone` where it's possible, throw `Dat…
zloirock Nov 4, 2021
166cc3f
clone`Error#stack`
zloirock Nov 4, 2021
0a84f77
drop extra `case`
zloirock Nov 4, 2021
f64a562
implement new errors cloning semantic
zloirock Nov 4, 2021
904ede6
update compat test
zloirock Nov 4, 2021
7beae95
improve reusage of native implementations
zloirock Nov 5, 2021
5d170d8
improve `transfer` handling
zloirock Nov 6, 2021
a14201d
handle a case with existent native structuredClone, structuredCloneFr…
zloirock Nov 6, 2021
b925e5a
avoid extra feature detection
zloirock Nov 6, 2021
017a374
fix `.sham` flag
zloirock Nov 6, 2021
047e8ac
polyfill transferring of some platform objects
zloirock Nov 6, 2021
00f0d0c
some stylistic changes
zloirock Nov 6, 2021
4c32695
use `CreateDataProperty`
zloirock Nov 6, 2021
1fdfd14
throw 'Cloning of %TYPE% cannot be properly polyfilled' where it's us…
zloirock Nov 6, 2021
9fbedfb
some comments
zloirock Nov 6, 2021
31d5712
`.transfer` option should be convertible to a sequence
zloirock Nov 6, 2021
95663bf
some more related errors on unpolyfillable transferable behavior
zloirock Nov 7, 2021
be7be95
Update packages/core-js/modules/web.structured-clone.js
zloirock Nov 7, 2021
bba0457
drop `USE_STRUCTURED_CLONE_FROM_MARK` fast case
zloirock Nov 7, 2021
e9f74db
update docs
zloirock Nov 10, 2021
f80540d
don't test the native source on node
zloirock Nov 17, 2021
2fbece8
fix linting
zloirock Nov 17, 2021
a9298a7
native NodeJS `structuredClone` throws a `TypeError` on transferable …
zloirock Nov 17, 2021
5826451
NodeJS events are simple objects
zloirock Nov 17, 2021
6475af3
add a workaround for `node-qunit` bug
zloirock Nov 17, 2021
205a8b6
drop reusage of structured cloning from `performance.mark` on NodeJS
zloirock Nov 17, 2021
6414360
add some comments
zloirock Nov 17, 2021
64be468
refactor tests
zloirock Nov 22, 2021
27182a3
use polyfilled `DOMException`
zloirock Dec 9, 2021
e0d475e
improve description of some tests
zloirock Dec 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions .eslintrc.js
Expand Up @@ -108,7 +108,7 @@ const base = {
// disallow unnecessary labels
'no-extra-label': ERROR,
// disallow fallthrough of case statements
'no-fallthrough': ERROR,
'no-fallthrough': [ERROR, { commentPattern: 'break omitted' }],
// disallow the use of leading or trailing decimal points in numeric literals
'no-floating-decimal': ERROR,
// disallow reassignments of native objects
Expand Down Expand Up @@ -1119,11 +1119,12 @@ module.exports = {
'tests/compat/**',
],
globals: {
compositeKey: READONLY,
compositeSymbol: READONLY,
AsyncIterator: READONLY,
Iterator: READONLY,
Observable: READONLY,
compositeKey: READONLY,
compositeSymbol: READONLY,
structuredClone: READONLY,
},
},
{
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,9 @@
## Changelog
##### Unreleased
- Added `structuredClone` method [from the HTML spec](https://html.spec.whatwg.org/multipage/structured-data.html#dom-structuredclone), [see MDN](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone)
- Includes all cases of cloning and transferring of required ECMAScript and platform types that can be polyfilled, for the details see [the caveats](https://github.com/zloirock/core-js#caveats-when-using-structuredclone-polyfill)
- Uses native structured cloning algorithm implementations where it's possible
- Includes the new semantic of errors cloning from [`html/5749`](https://github.com/whatwg/html/pull/5749)
- Added `DOMException` polyfill, [the Web IDL spec](https://webidl.spec.whatwg.org/#idl-DOMException), [see MDN](https://developer.mozilla.org/en-US/docs/Web/API/DOMException)
- Includes `DOMException` and its attributes polyfills with fixes of many different engines bugs
- Includes `DOMException#stack` property polyfill in engines that should have it
Expand Down
46 changes: 46 additions & 0 deletions README.md
Expand Up @@ -130,6 +130,7 @@ Promise.resolve(32).then(x => console.log(x)); // => 32
- [Pre-stage 0 proposals](#pre-stage-0-proposals)
- [`Reflect` metadata](#reflect-metadata)
- [Web standards](#web-standards)
- [`structuredClone`](#structuredclone)
- [`setTimeout` and `setInterval`](#settimeout-and-setinterval)
- [`setImmediate`](#setimmediate)
- [`queueMicrotask`](#queuemicrotask)
Expand Down Expand Up @@ -2865,6 +2866,51 @@ Reflect.getOwnMetadata('foo', object); // => 'bar'
```js
core-js(-pure)/web
```
#### `structuredClone`[⬆](#index)
[Spec](https://html.spec.whatwg.org/multipage/structured-data.html#dom-structuredclone), module [`web.structured-clone`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.structured-clone.js)
```js
function structuredClone(value: Serializable, { transfer?: Sequence<Transferable> }): any;
```
[*CommonJS entry points:*](#commonjs-api)
```js
core-js/web/structured-clone
core-js(-pure)/stable|features/structured-clone
```
[*Examples*](t.ly/dBEC):
```js
const structured = [{ a: 42 }];
const sclone = structuredClone(structured);
console.log(sclone); // => [{ a: 42 }]
console.log(structured !== sclone); // => true
console.log(structured[0] !== sclone[0]); // => true

const circular = {};
circular.circular = circular;
const cclone = structuredClone(circular);
console.log(cclone.circular === cclone); // => true

structuredClone(42); // => 42
structuredClone({ x: 42 }); // => { x: 42 }
structuredClone([1, 2, 3]); // => [1, 2, 3]
structuredClone(new Set([1, 2, 3])); // => Set{ 1, 2, 3 }
structuredClone(new Map([['a', 1], ['b', 2]])); // => Map{ a: 1, b: 2 }
structuredClone(new Int8Array([1, 2, 3])); // => new Int8Array([1, 2, 3])
structuredClone(new AggregateError([1, 2, 3], 'message')); // => new AggregateError([1, 2, 3], 'message'))
structuredClone(new TypeError('message', { cause: 42 })); // => new TypeError('message', { cause: 42 })
structuredClone(new DOMException('message', 'DataCloneError')); // => new DOMException('message', 'DataCloneError')
structuredClone(document.getElementById('myfileinput')); // => new FileList
structuredClone(new DOMPoint(1, 2, 3, 4)); // => new DOMPoint(1, 2, 3, 4)
structuredClone(new Blob(['test'])); // => new Blob(['test'])
structuredClone(new ImageData(8, 8)); // => new ImageData(8, 8)
// etc.

structuredClone(new WeakMap()); // => DataCloneError on non-serializable types
```
##### Caveats when using `structuredClone` polyfill:[⬆](#index)

* `ArrayBuffer` instances and many platform types cannot be transferred in most engines since we have no way to polyfill this behavior, however `.transfer` option works for some platform types. I recommend avoiding this option.
* Some specific platform types can't be cloned in old engines. Mainly it's very specific types or very old engines, but here are some exceptions. For example, we have no sync way to clone `ImageBitmap` in Safari 14.0- or Firefox 83-, so it's recommended to look to the [polyfill source](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.structured-clone.js) if you wanna clone something specific.

#### `setTimeout` and `setInterval`[⬆](#index)
Module [`web.timers`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/web.timers.js). Additional arguments fix for IE9-.
```js
Expand Down
7 changes: 7 additions & 0 deletions packages/core-js-compat/src/data.mjs
Expand Up @@ -1850,6 +1850,13 @@ export const data = {
node: '12.0', // '11.0',
safari: '12.1',
},
'web.structured-clone': {
BasixKOR marked this conversation as resolved.
Show resolved Hide resolved
// https://github.com/whatwg/html/pull/5749
// deno: '1.14',
// current FF implementation can't clone errors
// firefox: '94',
// node: '17.0',
},
'web.timers': {
android: '1.5',
chrome: '1',
Expand Down
1 change: 1 addition & 0 deletions packages/core-js-compat/src/modules-by-versions.mjs
Expand Up @@ -133,5 +133,6 @@ export default {
'web.dom-exception.constructor',
'web.dom-exception.stack',
'web.dom-exception.to-string-tag',
'web.structured-clone',
],
};
1 change: 1 addition & 0 deletions packages/core-js/es/array-buffer/constructor.js
@@ -1,4 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.object.to-string');
var path = require('../../internals/path');

Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/data-view/index.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.data-view');
require('../../modules/es.object.to-string');
var path = require('../../internals/path');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/float32-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.float32-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/float64-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.float64-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/int16-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.int16-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/int32-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.int32-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/int8-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.int8-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/uint16-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.uint16-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/uint32-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.uint32-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/uint8-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.uint8-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/es/typed-array/uint8-clamped-array.js
@@ -1,3 +1,5 @@
require('../../modules/es.array-buffer.constructor');
require('../../modules/es.array-buffer.slice');
require('../../modules/es.typed-array.uint8-clamped-array');
require('./methods');
var global = require('../../internals/global');
Expand Down
3 changes: 3 additions & 0 deletions packages/core-js/features/structured-clone.js
@@ -0,0 +1,3 @@
var parent = require('../stable/structured-clone');

module.exports = parent;