96 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# structuredClone polyfill
 | 
						|
 | 
						|
[](https://www.npmjs.com/package/@ungap/structured-clone) [](https://github.com/ungap/structured-clone/actions) [](https://coveralls.io/github/ungap/structured-clone?branch=main)
 | 
						|
 | 
						|
An env agnostic serializer and deserializer with recursion ability and types beyond *JSON* from the *HTML* standard itself.
 | 
						|
 | 
						|
  * [Supported Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types)
 | 
						|
    * *not supported yet*: Blob, File, FileList, ImageBitmap, ImageData or others non *JS* types but typed arrays are supported without major issues, but u/int8, u/int16, and u/int32 are the only safely suppored (right now).
 | 
						|
    * *not possible to implement*: the `{transfer: []}` option can be passed but it's completely ignored.
 | 
						|
  * [MDN Documentation](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone)
 | 
						|
  * [Serializer](https://html.spec.whatwg.org/multipage/structured-data.html#structuredserializeinternal)
 | 
						|
  * [Deserializer](https://html.spec.whatwg.org/multipage/structured-data.html#structureddeserialize)
 | 
						|
 | 
						|
Serialized values can be safely stringified as *JSON* too, and deserialization resurrect all values, even recursive, or more complex than what *JSON* allows.
 | 
						|
 | 
						|
 | 
						|
### Examples
 | 
						|
 | 
						|
Check the [100% test coverage](./test/index.js) to know even more.
 | 
						|
 | 
						|
```js
 | 
						|
// as default export
 | 
						|
import structuredClone from '@ungap/structured-clone';
 | 
						|
const cloned = structuredClone({any: 'serializable'});
 | 
						|
 | 
						|
// as independent serializer/deserializer
 | 
						|
import {serialize, deserialize} from '@ungap/structured-clone';
 | 
						|
 | 
						|
// the result can be stringified as JSON without issues
 | 
						|
// even if there is recursive data, bigint values,
 | 
						|
// typed arrays, and so on
 | 
						|
const serialized = serialize({any: 'serializable'});
 | 
						|
 | 
						|
// the result will be a replica of the original object
 | 
						|
const deserialized = deserialize(serialized);
 | 
						|
```
 | 
						|
 | 
						|
#### Global Polyfill
 | 
						|
Note: Only monkey patch the global if needed. This polyfill works just fine as an explicit import: `import structuredClone from "@ungap/structured-clone"`
 | 
						|
```js
 | 
						|
// Attach the polyfill as a Global function
 | 
						|
import structuredClone from "@ungap/structured-clone";
 | 
						|
if (!("structuredClone" in globalThis)) {
 | 
						|
  globalThis.structuredClone = structuredClone;
 | 
						|
}
 | 
						|
 | 
						|
// Or don't monkey patch
 | 
						|
import structuredClone from "@ungap/structured-clone"
 | 
						|
// Just use it in the file
 | 
						|
structuredClone()
 | 
						|
```
 | 
						|
 | 
						|
**Note**: Do not attach this module's default export directly to the global scope, whithout a conditional guard to detect a native implementation. In environments where there is a native global implementation of `structuredClone()` already, assignment to the global object will result in an infinite loop when `globalThis.structuredClone()` is called. See the example above for a safe way to provide the polyfill globally in your project.
 | 
						|
 | 
						|
### Extra Features
 | 
						|
 | 
						|
There is no middle-ground between the structured clone algorithm and JSON:
 | 
						|
 | 
						|
  * JSON is more relaxed about incompatible values: it just ignores these
 | 
						|
  * Structured clone is inflexible regarding incompatible values, yet it makes specialized instances impossible to reconstruct, plus it doesn't offer any helper, such as `toJSON()`, to make serialization possible, or better, with specific cases
 | 
						|
 | 
						|
This module specialized `serialize` export offers, within the optional extra argument, a **lossy** property to avoid throwing when incompatible types are found down the road (function, symbol, ...), so that it is possible to send with less worrying about thrown errors.
 | 
						|
 | 
						|
```js
 | 
						|
// as default export
 | 
						|
import structuredClone from '@ungap/structured-clone';
 | 
						|
const cloned = structuredClone(
 | 
						|
  {
 | 
						|
    method() {
 | 
						|
      // ignored, won't be cloned
 | 
						|
    },
 | 
						|
    special: Symbol('also ignored')
 | 
						|
  },
 | 
						|
  {
 | 
						|
    // avoid throwing
 | 
						|
    lossy: true,
 | 
						|
    // avoid throwing *and* looks for toJSON
 | 
						|
    json: true
 | 
						|
  }
 | 
						|
);
 | 
						|
```
 | 
						|
 | 
						|
The behavior is the same found in *JSON* when it comes to *Array*, so that unsupported values will result as `null` placeholders instead.
 | 
						|
 | 
						|
#### toJSON
 | 
						|
 | 
						|
If `lossy` option is not enough, `json` will actually enforce `lossy` and also check for `toJSON` method when objects are parsed.
 | 
						|
 | 
						|
Alternative, the `json` exports combines all features:
 | 
						|
 | 
						|
```js
 | 
						|
import {stringify, parse} from '@ungap/structured-clone/json';
 | 
						|
 | 
						|
parse(stringify({any: 'serializable'}));
 | 
						|
```
 |