forked from dumbmatter/realistic-structured-clone
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
78 lines (65 loc) · 2.44 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
'use strict';
var util = require('util');
var isPlainObject = require('lodash.isplainobject');
function DataCloneError(message) {
this.name = this.constructor.name;
this.message = message;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, DataCloneError);
}
}
util.inherits(DataCloneError, Error);
// http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm
function structuredClone(input, memory) {
memory = memory !== undefined ? memory : [];
for (var i = 0; i < memory.length; i++) {
if (memory[i].source === input) {
return memory[i].destination;
}
}
var type = typeof input;
var output;
if (type === 'string' || type === 'number' || type === 'boolean' || type === 'undefined' || input === null) {
return input;
}
var deepClone = 'none';
if (input instanceof Boolean || input instanceof Number || input instanceof String || input instanceof Date) {
output = new input.constructor(input.valueOf());
} else if (input instanceof RegExp) {
output = new RegExp(input.source, "g".substr(0, Number(input.global)) + "i".substr(0, Number(input.ignoreCase)) + "m".substr(0, Number(input.multiline)));
// Supposed to also handle Blob, FileList, ImageData, ImageBitmap, ArrayBuffer, and "object with a [[DataView]] internal slot", but fuck it
} else if (Array.isArray(input)) {
output = new Array(input.length);
deepClone = 'own';
} else if (isPlainObject(input)) {
output = {};
deepClone = 'own';
} else if (input instanceof Map) {
output = new Map();
deepClone = 'map';
} else if (input instanceof Set) {
output = new Set();
deepClone = 'set';
} else {
throw new DataCloneError();
}
memory.push({
source: input,
destination: output
});
if (deepClone === 'map') {
throw new DataCloneError('Map support not implemented yet');
} else if (deepClone === 'set') {
throw new DataCloneError('Set support not implemented yet');
} else if (deepClone === 'own') {
for (var name in input) {
if (input.hasOwnProperty(name)) {
var sourceValue = input[name];
var clonedValue = structuredClone(sourceValue, memory);
output[name] = clonedValue;
}
}
}
return output;
}
module.exports = structuredClone;