# structuredClone

The `structuredClone()` global function of Azion Runtime returns a deep copy of a value with the structured clone algorithm, the JavaScript mechanism that duplicates complex objects. In browsers, the same algorithm also copies data that `postMessage()` passes between workers and objects that IndexedDB stores. The algorithm walks the input recursively and records each object it visits, so a circular reference does not make it loop forever. For more information, refer to [Structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) on MDN Web Docs.

> **Note**
>
> Under `azion dev`, the `transfer` option copies the buffer and leaves the source attached, with its full `byteLength`. A cloned `Map` is not an instance of `Map`, a cloned `RangeError` is not an instance of `RangeError`, and a `DataCloneError` is not an instance of `DOMException`, although its constructor name is `DOMException`.

---

## Syntax

```javascript
structuredClone(value, options)
```

| Parameter          | Type   | Description                                                                                                                                                                    |
| ------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `value`            | Any    | Value to copy.                                                                                                                                                                 |
| `options`          | Object | Optional. Holds the `transfer` option.                                                                                                                                         |
| `options.transfer` | Array  | Transferable objects, such as an `ArrayBuffer`, that move into the copy instead of being copied. After the call, a transferred buffer in the source has a `byteLength` of `0`. |

The function returns the copy. The copy is a new object, and the objects nested in it are copies too.

---

## Cloned values

The deployed runtime clones each value in the source into this value in the copy:

| Value in the source              | Value in the copy                                                                                                                                                     |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Nested objects and arrays        | A copy at every level, with the same values.                                                                                                                          |
| An object that references itself | A new object that references itself: the cycle is kept.                                                                                                               |
| `Map`                            | A `Map` with the same entries.                                                                                                                                        |
| `Set`                            | A `Set` with the same values.                                                                                                                                         |
| `BigInt`                         | A `BigInt`.                                                                                                                                                           |
| `Uint8Array`                     | A `Uint8Array`.                                                                                                                                                       |
| `RangeError`                     | A `RangeError` with the same `name`.                                                                                                                                  |
| `Date`                           | A value that is not an instance of `Date`.                                                                                                                            |
| `RegExp`                         | A `RegExp` with the same `source` and `flags`. `lastIndex` resets to `0`.                                                                                             |
| An instance of a class           | A plain object with the own properties of the instance. The prototype chain is not copied, so the methods of the class are absent and `constructor.name` is `Object`. |
| `Request`                        | An empty object, `{}`. The call does not throw.                                                                                                                       |

The copy does not keep property descriptors, getters, setters, or similar metadata:

- A getter becomes a data property that holds the value the getter returned.
- A property marked read-only with a property descriptor is writable in the copy, because writable is the default.

---

## Errors

A value the algorithm cannot copy makes `structuredClone()` throw a `DOMException` whose `name` is `DataCloneError`. The deployed runtime refuses these values with these errors, shown as `name: message`:

| Value                                          | Error                                                   |
| ---------------------------------------------- | ------------------------------------------------------- |
| A function, such as the method in `{ f() {} }` | `DataCloneError: f(){} could not be cloned.`            |
| `Symbol('s')`                                  | `DataCloneError: Symbol(s) could not be cloned.`        |
| `new WeakMap()`                                | `DataCloneError: [object WeakMap] could not be cloned.` |
| `Promise.resolve(1)`                           | `DataCloneError: [object Promise] could not be cloned.` |

---

## Example

This handler clones an object that holds a `Date`, a `Map`, a `Set`, a `BigInt`, a `Uint8Array`, a `RangeError`, and nested data, then returns what it read from the copy:

```javascript
export default {
  async fetch(request, env, ctx) {
    const source = {
      d: new Date(0),
      m: new Map([[1, 'a']]),
      s: new Set([1]),
      big: 10n,
      ab: new Uint8Array([1, 2]),
      err: new RangeError('r'),
      nested: { a: [1, { b: 2 }] },
    };
    const copy = structuredClone(source);
    return Response.json({
      date: copy.d instanceof Date,
      map: copy.m instanceof Map && copy.m.get(1),
      set: copy.s.has(1),
      bigint: typeof copy.big,
      typedArray: copy.ab.constructor.name,
      errorName: copy.err?.name,
      errorIsRangeError: copy.err instanceof RangeError,
      deepCopy: copy.nested !== source.nested && copy.nested.a[1].b === 2,
    });
  },
};
```

A deployed function returns these values from the copy. `map` is the entry read from the cloned `Map`, and `date` is `false` because the cloned `Date` is not an instance of `Date`:

```json
{
 "date": false,
 "map": "a",
 "set": true,
 "bigint": "bigint",
 "typedArray": "Uint8Array",
 "errorName": "RangeError",
 "errorIsRangeError": true,
 "deepCopy": true
}
```

---

## Related resources

- [Globals](/en/documentation/devtools/runtime/api-reference/azion-runtime-globals.md): The other global objects and functions that a function can call.
- [Request](/en/documentation/devtools/runtime/api-reference/request.md): The incoming request, which carries its own `clone()` method.
- [Response](/en/documentation/devtools/runtime/api-reference/response.md): How to build a response, and how `response.clone()` copies one.
- [Web APIs](/en/documentation/devtools/runtime/api-reference/javascript.md): The other Web APIs that Azion Runtime supports.
