Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / fast / js / structured-clone.html
blob5262d1f4d4ab196c91dc5ca59dcd30d0a3b97f14
1 <!DOCTYPE HTML>
2 <script src="../../resources/testharness.js"></script>
3 <script src="../../resources/testharnessreport.js"></script>
4 <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);
19 });
22 promise_test(function() {
23 var inner = {};
24 var orig = { inner: inner };
25 inner.outer = orig;
26 return structuredClone(orig).then(function(clone) {
27 assert_equals(clone.inner.outer, clone, 'Cycles should be preserved');
28 });
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) {
34 var simple = {};
35 var blob = new Blob(['content']);
36 var orig = {
37 s1: simple, s2: simple,
38 b1: blob, b2: blob,
39 k1: key, k2: key
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');
45 });
46 });
47 }, 'Verify: "This algorithm preserves... the identity of duplicate objects in graphs."');
49 promise_test(function() {
50 var name = 'this is a setter';
52 var orig = {};
53 orig[name] = 'value';
55 var setter_called = false;
56 Object.defineProperty(Object.prototype, name, {
57 set: function(a) {
58 setter_called = true;
60 });
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');
69 });
70 }, 'Verify: "Add a new property..." (objects)');
72 promise_test(function() {
73 var name = '123456';
75 var orig = [];
76 orig[name] = 'value';
78 var setter_called = false;
79 Object.defineProperty(Object.prototype, name, {
80 set: function(a) {
81 setter_called = true;
83 });
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');
92 });
93 }, 'Verify: "Add a new property..." (arrays)');
95 promise_test(function() {
96 var name = '256';
98 var orig = [];
99 for (var i = 0; i < 256; ++i) {
100 orig[i] = i;
103 orig[name] = 'value';
105 var setter_called = false;
106 Object.defineProperty(Object.prototype, name, {
107 set: function(a) {
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() {
123 var orig = {
124 emptySet: new Set,
125 set: new Set([1, 2, 3]),
126 emptyMap: new Map,
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() {
144 var set = new Set;
145 set.add(set);
146 var map = new Map;
147 map.set(map, map);
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() {
159 var set = new Set;
160 var map = new Map;
161 var setMutator = {
162 get val() {
163 set.add('mutated');
164 return 'setMutator';
167 var mapMutator = {
168 get val() {
169 map.set('mutated', true);
170 return 'mapMutator';
173 set.add(setMutator);
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');
192 }, function(ex) {
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');
202 }, function(ex) {
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');
211 }, function(ex) {
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');
217 </script>