|
1 | 1 | // Copyright 2018-2026 the Deno authors. MIT license. |
2 | | -import { assertArrayEquals, assertEquals, test } from "checkin:testing"; |
| 2 | +import { |
| 3 | + assert, |
| 4 | + assertArrayEquals, |
| 5 | + assertEquals, |
| 6 | + assertThrows, |
| 7 | + test, |
| 8 | +} from "checkin:testing"; |
3 | 9 |
|
4 | 10 | test(function testIssue20727() { |
5 | 11 | // https://github.com/denoland/deno/issues/20727 |
@@ -109,3 +115,103 @@ test(function structuredClone() { |
109 | 115 | assertEquals(cloned.test2, circularObject.test2); |
110 | 116 | assertEquals(cloned.test3, circularObject.test3); |
111 | 117 | }); |
| 118 | + |
| 119 | +test(function cloneableResourceStructuredClone() { |
| 120 | + // Create a class that supports structured cloning via hostObjectBrand |
| 121 | + class MyCloneable { |
| 122 | + value: string; |
| 123 | + constructor(value: string) { |
| 124 | + this.value = value; |
| 125 | + // deno-lint-ignore no-this-alias |
| 126 | + const self = this; |
| 127 | + this[Deno.core.hostObjectBrand] = () => ({ |
| 128 | + type: "MyCloneable", |
| 129 | + value: self.value, |
| 130 | + }); |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + Deno.core.registerCloneableResource( |
| 135 | + "MyCloneable", |
| 136 | + (data: { value: string }) => new MyCloneable(data.value), |
| 137 | + ); |
| 138 | + |
| 139 | + const original = new MyCloneable("hello"); |
| 140 | + const cloned = Deno.core.structuredClone(original); |
| 141 | + |
| 142 | + assert(cloned instanceof MyCloneable); |
| 143 | + assertEquals(cloned.value, "hello"); |
| 144 | + assert(cloned !== original); |
| 145 | +}); |
| 146 | + |
| 147 | +test(function cloneableResourceSerializeDeserialize() { |
| 148 | + // Use a different name to avoid duplicate registration |
| 149 | + class AnotherCloneable { |
| 150 | + data: number; |
| 151 | + constructor(data: number) { |
| 152 | + this.data = data; |
| 153 | + // deno-lint-ignore no-this-alias |
| 154 | + const self = this; |
| 155 | + this[Deno.core.hostObjectBrand] = () => ({ |
| 156 | + type: "AnotherCloneable", |
| 157 | + data: self.data, |
| 158 | + }); |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + Deno.core.registerCloneableResource( |
| 163 | + "AnotherCloneable", |
| 164 | + (d: { data: number }) => new AnotherCloneable(d.data), |
| 165 | + ); |
| 166 | + |
| 167 | + const original = new AnotherCloneable(42); |
| 168 | + const serialized = Deno.core.serialize(original); |
| 169 | + const deserialized = Deno.core.deserialize(serialized, { |
| 170 | + deserializers: Deno.core.getCloneableDeserializers(), |
| 171 | + }); |
| 172 | + |
| 173 | + assert(deserialized instanceof AnotherCloneable); |
| 174 | + assertEquals(deserialized.data, 42); |
| 175 | +}); |
| 176 | + |
| 177 | +test(function cloneableResourceNestedInObject() { |
| 178 | + class NestedCloneable { |
| 179 | + name: string; |
| 180 | + constructor(name: string) { |
| 181 | + this.name = name; |
| 182 | + // deno-lint-ignore no-this-alias |
| 183 | + const self = this; |
| 184 | + this[Deno.core.hostObjectBrand] = () => ({ |
| 185 | + type: "NestedCloneable", |
| 186 | + name: self.name, |
| 187 | + }); |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + Deno.core.registerCloneableResource( |
| 192 | + "NestedCloneable", |
| 193 | + (d: { name: string }) => new NestedCloneable(d.name), |
| 194 | + ); |
| 195 | + |
| 196 | + const obj = { |
| 197 | + foo: "bar", |
| 198 | + nested: new NestedCloneable("test"), |
| 199 | + num: 123, |
| 200 | + }; |
| 201 | + |
| 202 | + const cloned = Deno.core.structuredClone(obj); |
| 203 | + |
| 204 | + assertEquals(cloned.foo, "bar"); |
| 205 | + assertEquals(cloned.num, 123); |
| 206 | + assert(cloned.nested instanceof NestedCloneable); |
| 207 | + assertEquals(cloned.nested.name, "test"); |
| 208 | +}); |
| 209 | + |
| 210 | +test(function cloneableResourceDuplicateRegistrationThrows() { |
| 211 | + Deno.core.registerCloneableResource("DuplicateTest", () => {}); |
| 212 | + assertThrows( |
| 213 | + () => Deno.core.registerCloneableResource("DuplicateTest", () => {}), |
| 214 | + Error, |
| 215 | + "already registered", |
| 216 | + ); |
| 217 | +}); |
0 commit comments