2 <script src=
"../../resources/testharness.js"></script>
3 <script src=
"../../resources/testharnessreport.js"></script>
5 function promise_test(func
, name
, properties
) {
6 properties
= properties
|| {};
7 var test
= async_test(name
, properties
);
8 Promise
.resolve(test
.step(func
, test
, test
))
9 .then(function() { test
.done(); })
10 .catch(test
.step_func(function(value
) { throw value
; }));
13 function structuredClone(o
)
15 return new Promise(function(resolve
, reject
) {
16 var mc
= new MessageChannel();
17 mc
.port2
.onmessage = function(e
) { resolve(e
.data
); };
18 mc
.port1
.postMessage(o
);
22 promise_test(function() {
24 var orig
= { inner
: inner
};
26 return structuredClone(orig
).then(function(clone
) {
27 assert_equals(clone
.inner
.outer
, clone
, 'Cycles should be preserved');
29 }, 'Verify: "This algorithm preserves cycles..."');
31 promise_test(function() {
32 var gen
= {name
: 'AES-CBC', length
: 128};
33 return crypto
.subtle
.generateKey(gen
, false, ['encrypt']).then(function(key
) {
35 var blob
= new Blob(['content']);
37 s1
: simple
, s2
: simple
,
41 return structuredClone(orig
).then(function(clone
) {
42 assert_equals(clone
.s1
, clone
.s2
, 'JS object identity should be preserved');
43 assert_equals(clone
.b1
, clone
.b2
, 'Core object identity should be preserved');
44 assert_equals(clone
.k1
, clone
.k2
, 'Module object identity should be preserved');
47 }, 'Verify: "This algorithm preserves... the identity of duplicate objects in graphs."');
49 promise_test(function() {
50 var name
= 'this is a setter';
55 var setter_called
= false;
56 Object
.defineProperty(Object
.prototype, name
, {
62 assert_true(orig
.hasOwnProperty(name
));
64 return structuredClone(orig
).then(function(clone
) {
65 assert_equals(typeof clone
, 'object', 'Clone should be an object');
66 assert_false(setter_called
, 'Setter should not be called by cloning algorithm.');
67 assert_true(clone
.hasOwnProperty(name
), 'Cloning algorithm should add an own property.')
68 assert_equals(clone
[name
], orig
[name
], 'Property value should match');
70 }, 'Verify: "Add a new property..." (objects)');
72 promise_test(function() {
78 var setter_called
= false;
79 Object
.defineProperty(Object
.prototype, name
, {
85 assert_true(orig
.hasOwnProperty(name
));
87 return structuredClone(orig
).then(function(clone
) {
88 assert_true(Array
.isArray(clone
), 'Clone should be an Array');
89 assert_false(setter_called
, 'Setter should not be called by cloning algorithm.');
90 assert_true(clone
.hasOwnProperty(name
), 'Cloning algorithm should add an own property.')
91 assert_equals(clone
[name
], orig
[name
], 'Property value should match');
93 }, 'Verify: "Add a new property..." (arrays)');
95 promise_test(function() {
99 for (var i
= 0; i
< 256; ++i
) {
103 orig
[name
] = 'value';
105 var setter_called
= false;
106 Object
.defineProperty(Object
.prototype, name
, {
108 setter_called
= true;
112 assert_true(orig
.hasOwnProperty(name
));
114 return structuredClone(orig
).then(function(clone
) {
115 assert_true(Array
.isArray(clone
), 'Clone should be an Array');
116 assert_false(setter_called
, 'Setter should not be called by cloning algorithm.');
117 assert_true(clone
.hasOwnProperty(name
), 'Cloning algorithm should add an own property.')
118 assert_equals(clone
[name
], orig
[name
], 'Property value should match');
120 }, 'Verify: "Add a new property..." (dense arrays)');
122 promise_test(function() {
125 set: new Set([1, 2, 3]),
127 map
: new Map([[1, 2], [3, 4]]),
129 return structuredClone(orig
).then(function(clone
) {
130 assert_true(clone
.emptySet
instanceof Set
, 'Clone should be a Set');
131 assert_true(clone
.emptyMap
instanceof Map
, 'Clone should be a Map');
132 assert_true(clone
.set instanceof Set
, 'Clone should be a Set');
133 assert_true(clone
.map
instanceof Map
, 'Clone should be a Map');
134 assert_equals(clone
.emptySet
.size
, 0, 'Clone should be the same size');
135 assert_equals(clone
.emptyMap
.size
, 0, 'Clone should be the same size');
136 assert_equals(clone
.set.size
, orig
.set.size
, 'Clone should be the same size');
137 assert_equals(clone
.map
.size
, orig
.map
.size
, 'Clone should be the same size');
138 assert_true(clone
.set.has(1) && clone
.set.has(2) && clone
.set.has(3), 'Cloned set should have the same keys');
139 assert_true(clone
.map
.get(1) == 2 && clone
.map
.get(3) == 4, 'Cloned map should have the same keys and values');
141 }, 'Maps and Sets are cloned');
143 promise_test(function() {
148 var orig
= { map
: map
, set: set };
149 return structuredClone(orig
).then(function(clone
) {
150 assert_true(clone
.set instanceof Set
, 'Clone should be a Set');
151 assert_true(clone
.map
instanceof Map
, 'Clone should be a Map');
152 assert_equals(clone
.set, Array
.from(clone
.set)[0], 'Recursive sets should preserve identity');
153 assert_equals(clone
.map
, Array
.from(clone
.map
)[0][0], 'Recursive maps should preserve identity');
154 assert_equals(clone
.map
, Array
.from(clone
.map
)[0][1], 'Recursive maps should preserve identity');
156 }, 'Cloning Maps and Sets preserve cycles');
158 promise_test(function() {
169 map
.set('mutated', true);
174 map
.set('mapMutator', mapMutator
);
175 var orig
= { map
: map
, set: set };
176 return structuredClone(orig
).then(function(clone
) {
177 assert_true(clone
.set instanceof Set
, 'Clone should be a Set');
178 assert_true(clone
.map
instanceof Map
, 'Clone should be a Map');
179 assert_equals(orig
.set.size
, 2, 'Original set should have been mutated');
180 assert_equals(orig
.map
.size
, 2, 'Original map should have been mutated');
181 assert_equals(clone
.set.size
, 1, 'Cloned set should not reflect mutation');
182 assert_equals(clone
.map
.size
, 1, 'Cloned map should not reflect mutation');
183 assert_equals(Array
.from(clone
.set)[0].val
, 'setMutator', 'Cloned set should contain getter return value');
184 assert_equals(clone
.map
.get('mapMutator').val
, 'mapMutator', 'Cloned map should contain getter return value');
186 }, 'Cloned Maps and Sets do not reflect mutations that occur during cloning');
188 promise_test(function() {
189 var map
= new Map([['key', function(){}]]);
190 return structuredClone(map
).then(function(clone
) {
191 assert_unreached('Should have thrown an exception');
193 assert_true(ex
instanceof DOMException
, 'Should throw a DOMException');
194 assert_equals(ex
.code
, DOMException
.DATA_CLONE_ERR
, 'Should be a DataCloneError');
196 }, 'Cloning Maps should fail if they contain non-cloneable things');
198 promise_test(function() {
199 var set = new Set([function(){}]);
200 return structuredClone(set).then(function(clone
) {
201 assert_unreached('Should have thrown an exception');
203 assert_true(ex
instanceof DOMException
, 'Should throw a DOMException');
204 assert_equals(ex
.code
, DOMException
.DATA_CLONE_ERR
, 'Should be a DataCloneError');
206 }, 'Cloning Sets should fail if they contain non-cloneable things');
208 promise_test(function() {
209 return structuredClone(Symbol('foo')).then(function(clone
) {
210 assert_unreached('Should have thrown an exception');
212 assert_true(ex
instanceof DOMException
, 'Should throw a DOMException');
213 assert_equals(ex
.code
, DOMException
.DATA_CLONE_ERR
, 'Should be a DataCloneError');
215 }, 'Cloning Symbols should fail');