Skip to content

Commit c6214ce

Browse files
committed
implement inheritance
1 parent 6dd301d commit c6214ce

File tree

7 files changed

+98
-5
lines changed

7 files changed

+98
-5
lines changed

packages/svelte/src/internal/client/dev/ownership.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,28 @@ function add_owner_to_object(object, owner) {
105105
}
106106
}
107107

108+
/**
109+
* @param {any} object
110+
*/
111+
export function strip_owner(object) {
112+
untrack(() => {
113+
strip_owner_from_object(object);
114+
});
115+
}
116+
117+
/**
118+
* @param {any} object
119+
*/
120+
function strip_owner_from_object(object) {
121+
if (object?.[STATE_SYMBOL]?.o) {
122+
object[STATE_SYMBOL].o = null;
123+
124+
for (const key in object) {
125+
strip_owner(object[key]);
126+
}
127+
}
128+
}
129+
108130
/**
109131
* @param {Set<Function>} owners
110132
*/

packages/svelte/src/internal/client/proxy.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
is_frozen,
2222
object_prototype
2323
} from './utils.js';
24-
import { check_ownership } from './dev/ownership.js';
24+
import { add_owner, check_ownership, strip_owner } from './dev/ownership.js';
2525

2626
export const STATE_SYMBOL = Symbol('$state');
2727

@@ -39,7 +39,20 @@ export function proxy(value, immutable = true, owners) {
3939
const metadata = /** @type {import('./types.js').ProxyMetadata<T>} */ (value[STATE_SYMBOL]);
4040
// ...unless the proxy belonged to a different object, because
4141
// someone copied the state symbol using `Reflect.ownKeys(...)`
42-
if (metadata.t === value || metadata.p === value) return metadata.p;
42+
if (metadata.t === value || metadata.p === value) {
43+
if (DEV) {
44+
// update ownership
45+
if (owners) {
46+
for (const owner of owners) {
47+
add_owner(value, owner);
48+
}
49+
} else {
50+
strip_owner(value);
51+
}
52+
}
53+
54+
return metadata.p;
55+
}
4356
}
4457

4558
const prototype = get_prototype_of(value);
@@ -249,8 +262,6 @@ const state_proxy_handler = {
249262
const s = metadata.s.get(prop);
250263
if (s !== undefined) {
251264
set(s, proxy(value, metadata.i, metadata.o));
252-
} else if (DEV) {
253-
// TODO transfer ownership, in case it differs
254265
}
255266
const is_array = metadata.a;
256267
const not_has = !(prop in target);

packages/svelte/tests/helpers.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ export async function compile_directory(
8181
if (file.endsWith('.js')) {
8282
const out = `${output_dir}/${file}`;
8383
if (file.endsWith('.svelte.js')) {
84-
const compiled = compileModule(text, opts);
84+
const compiled = compileModule(text, {
85+
filename: opts.filename,
86+
generate: opts.generate,
87+
dev: opts.dev
88+
});
8589
write(out, compiled.js.code);
8690
} else {
8791
// for non-runes tests, just re-export from the original source file — this
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
import { global } from './state.svelte.js';
3+
</script>
4+
5+
<button onclick={() => global.object.count += 1}>
6+
clicks: {global.object.count}
7+
</button>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { test } from '../../test';
2+
3+
/** @type {typeof console.warn} */
4+
let warn;
5+
6+
/** @type {any[]} */
7+
let warnings = [];
8+
9+
export default test({
10+
html: `<button>clicks: 0</button>`,
11+
12+
compileOptions: {
13+
dev: true
14+
},
15+
16+
before_test: () => {
17+
warn = console.warn;
18+
19+
console.warn = (...args) => {
20+
warnings.push(...args);
21+
};
22+
},
23+
24+
after_test: () => {
25+
console.warn = warn;
26+
warnings = [];
27+
},
28+
29+
async test({ assert, target }) {
30+
const btn = target.querySelector('button');
31+
await btn?.click();
32+
33+
assert.htmlEqual(target.innerHTML, `<button>clicks: 1</button>`);
34+
35+
assert.deepEqual(warnings, []);
36+
}
37+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script>
2+
import Counter from './Counter.svelte';
3+
import { global } from './state.svelte.js';
4+
5+
let object = $state({ count: 0 });
6+
global.object = object;
7+
</script>
8+
9+
<Counter />
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export let global = $state({
2+
object: { count: -1 }
3+
});

0 commit comments

Comments
 (0)