-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Expand file tree
/
Copy pathstructured_clone_test.ts
More file actions
133 lines (120 loc) · 4.03 KB
/
structured_clone_test.ts
File metadata and controls
133 lines (120 loc) · 4.03 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2018-2026 the Deno authors. MIT license.
import { assert, assertEquals, assertThrows } from "./test_util.ts";
// Basic tests for the structured clone algorithm. Mainly tests TypeScript
// typings. Actual functionality is tested in WPT.
Deno.test("self.structuredClone", async () => {
const arrayOriginal = ["hello world"];
const channelOriginal = new MessageChannel();
const [arrayCloned, portTransferred] = self
.structuredClone(
[arrayOriginal, channelOriginal.port2] as [string[], MessagePort],
{
transfer: [channelOriginal.port2],
},
);
assert(arrayOriginal !== arrayCloned); // not the same identity
assertEquals(arrayCloned, arrayOriginal); // but same value
channelOriginal.port1.postMessage("1");
await new Promise((resolve) => portTransferred.onmessage = () => resolve(1));
channelOriginal.port1.close();
portTransferred.close();
});
Deno.test("correct DataCloneError message", () => {
assertThrows(
() => {
const sab = new SharedArrayBuffer(1024);
structuredClone(sab, {
// @ts-expect-error cannot assign SharedArrayBuffer because it's not tranferable
transfer: [sab],
});
},
DOMException,
"Value not transferable",
);
const ab = new ArrayBuffer(1);
// detach ArrayBuffer
structuredClone(ab, { transfer: [ab] });
assertThrows(
() => {
structuredClone(ab, { transfer: [ab] });
},
DOMException,
"ArrayBuffer at index 0 is already detached",
);
const ab2 = new ArrayBuffer(0);
assertThrows(
() => {
structuredClone([ab2, ab], { transfer: [ab2, ab] });
},
DOMException,
"ArrayBuffer at index 1 is already detached",
);
// ab2 should not be detached after above failure
structuredClone(ab2, { transfer: [ab2] });
});
Deno.test("structuredClone CryptoKey", async () => {
// AES key
const aesKey = await crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"],
);
const aesClone = structuredClone(aesKey);
assert(aesKey !== aesClone);
assertEquals(aesClone.type, aesKey.type);
assertEquals(aesClone.extractable, aesKey.extractable);
assertEquals(aesClone.algorithm, aesKey.algorithm);
assertEquals([...aesClone.usages], [...aesKey.usages]);
// Verify the cloned key actually works
const data = new TextEncoder().encode("hello");
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
aesClone,
data,
);
const decrypted = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv },
aesKey,
encrypted,
);
assertEquals(new Uint8Array(decrypted), data);
// Non-extractable key can be cloned
const nonExtractable = await crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
false,
["encrypt", "decrypt"],
);
const nonExtractableClone = structuredClone(nonExtractable);
assertEquals(nonExtractableClone.extractable, false);
assertEquals(nonExtractableClone.algorithm, nonExtractable.algorithm);
// HMAC key
const hmacKey = await crypto.subtle.generateKey(
{ name: "HMAC", hash: "SHA-256" },
true,
["sign", "verify"],
);
const hmacClone = structuredClone(hmacKey);
assertEquals(hmacClone.type, hmacKey.type);
assertEquals(hmacClone.algorithm, hmacKey.algorithm);
assertEquals([...hmacClone.usages], [...hmacKey.usages]);
// EC key pair
const ecKeyPair = await crypto.subtle.generateKey(
{ name: "ECDSA", namedCurve: "P-256" },
true,
["sign", "verify"],
) as CryptoKeyPair;
const ecPrivateClone = structuredClone(ecKeyPair.privateKey);
const ecPublicClone = structuredClone(ecKeyPair.publicKey);
assertEquals(ecPrivateClone.type, "private");
assertEquals(ecPublicClone.type, "public");
// Ed25519 key pair
const edKeyPair = await crypto.subtle.generateKey(
"Ed25519",
true,
["sign", "verify"],
) as CryptoKeyPair;
const edClone = structuredClone(edKeyPair.privateKey);
assertEquals(edClone.type, "private");
assertEquals(edClone.algorithm.name, "Ed25519");
});