Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactivity API: Refactor internal proxy and signals system #62734

Merged
merged 91 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
181841a
WIP
DAreRodz Jun 28, 2024
e78df31
More WIP
DAreRodz Jun 28, 2024
80c1da9
Restore previous packages
DAreRodz Jun 28, 2024
852bc99
Fix current tests
DAreRodz Jun 28, 2024
0688cff
Add computation tests
DAreRodz Jun 28, 2024
4dec758
Fix getter call
DAreRodz Jun 28, 2024
dace302
Fix for..in on new properties
DAreRodz Jun 28, 2024
20923cb
Refactor code a little
DAreRodz Jun 28, 2024
38c4ca8
Add tests for getters with scope
DAreRodz Jun 28, 2024
98163be
Move namespaces to properties
DAreRodz Jun 28, 2024
55cca00
Fix a problem with object references
DAreRodz Jun 28, 2024
8711d38
Add store handlers
DAreRodz Jun 28, 2024
349a257
Add signals-core dependency
DAreRodz Jun 28, 2024
fc7a39b
Rename Property to PropSignal
DAreRodz Jun 28, 2024
0df6219
Move withScope inside PropSignal logic
DAreRodz Jun 28, 2024
61b1da5
Create proxies folder
DAreRodz Jun 28, 2024
3401a2b
Attempt to make the context work
DAreRodz Jun 28, 2024
5a546eb
Reorganize code
DAreRodz Jun 28, 2024
d375418
Make peek() return only the value inside signalValue
DAreRodz Jun 28, 2024
075c4f9
A bit of refactoring
DAreRodz Jun 28, 2024
b9f5ac8
Return the computed value with `peek()`
DAreRodz Jun 28, 2024
a9a5fb0
Rename DEFAULT_SCOPE to NO_SCOPE
DAreRodz Jun 28, 2024
c9a854c
Remove deepsignal
DAreRodz Jun 28, 2024
fc131dc
Handle functions inside state
DAreRodz Jun 28, 2024
fe0b6bb
Fix withScope in this PR
DAreRodz Jun 28, 2024
e371add
Fix context proxification
DAreRodz Jun 28, 2024
fe1920d
Move store root logic to store proxy handlers
DAreRodz Jun 28, 2024
b471609
Move store initialization inside init
DAreRodz Jun 28, 2024
164d92e
Add TODO comment inside `peek()`
DAreRodz Jun 28, 2024
c06f6bf
Fix store root assignments
DAreRodz Jun 28, 2024
747c822
Fix lint error
DAreRodz Jun 28, 2024
7938dd8
Enable skipped test for non-initialized getters
DAreRodz Jul 1, 2024
c238ede
Rename get(State|Store)Proxy to proxify(State|Store)
DAreRodz Jul 2, 2024
3cf82a1
Make `getContext` throw when there is no scope
DAreRodz Jul 3, 2024
99f6e87
Fix `proxifyState` types
DAreRodz Jul 3, 2024
821532e
Rename some variables in tests
DAreRodz Jul 3, 2024
2dc4548
Add test for object reference keeping
DAreRodz Jul 3, 2024
c720d0f
Rename test suite for state proxy
DAreRodz Jul 3, 2024
8de7b83
Add tests for getters and functions with scope
DAreRodz Jul 3, 2024
4bac1a8
Add tests for prop subscription inside functions
DAreRodz Jul 3, 2024
5e508c1
Allow functions to use `this`
DAreRodz Jul 3, 2024
a4840a0
Minor fixes
DAreRodz Jul 3, 2024
d17f4bd
Add tests to store proxies
DAreRodz Jul 3, 2024
d64eee3
Throw an error when an object cannot be proxified
DAreRodz Jul 4, 2024
22f5244
Change peek implementation
DAreRodz Jul 4, 2024
82622aa
Add tests for peek and unsupported structures
DAreRodz Jul 4, 2024
43dcfec
Test peeking getters that access scope or other namespaces
DAreRodz Jul 4, 2024
e2b2e61
Ignore well-known symbols
DAreRodz Jul 4, 2024
0bd1050
Minor comment format fix
DAreRodz Jul 4, 2024
53c3939
Move namespace arg to first position in proxify functions
DAreRodz Jul 4, 2024
e294bba
chore: Update jest.config.js to stop ignoring deepsignal because we r…
michalczaplinski Jul 9, 2024
c0c633e
Add comments to proxy registry
DAreRodz Jul 16, 2024
1e1aa6a
Remove namespace from PropSignal
DAreRodz Jul 16, 2024
5648754
Remove unused `peekValueSignal` method
DAreRodz Jul 16, 2024
d2f849f
Simplify PropSignal methods
DAreRodz Jul 17, 2024
573ce9d
Add TSDocs to PropSignal
DAreRodz Jul 17, 2024
0950fa8
Disable unused vars lint rule in state-proxy tests
DAreRodz Jul 17, 2024
236e389
Remove descriptor alias
DAreRodz Jul 17, 2024
8bcb576
Expand `getProxyNs` docs
DAreRodz Jul 19, 2024
1b7d2df
Add more comments in `state`
DAreRodz Jul 19, 2024
4554fb4
Refactor state functions and add tsdocs
DAreRodz Jul 23, 2024
5cce756
Fix some grammar issues
DAreRodz Jul 23, 2024
86a5b5a
Fix default namespace for setters
DAreRodz Jul 23, 2024
cebfd6e
Replace `isNotRoot` with `isRoot`
DAreRodz Jul 24, 2024
0e2b095
Update comments in store.ts
DAreRodz Jul 24, 2024
a12732c
Move `isPlainObject` to utils
DAreRodz Jul 24, 2024
0667028
Remove remaining deepSignal references
DAreRodz Jul 24, 2024
9a52b65
Delete unnecessary @ts-ignore-next-line
luisherranz Jul 26, 2024
b21a3ce
Use `isPlainObject` from utils inside store
DAreRodz Jul 29, 2024
e8c5458
Move scopes and namespaces to separate files
DAreRodz Jul 29, 2024
6d1d887
Call `init` outside `DOMContentLoaded`
DAreRodz Jul 29, 2024
4dccb45
Replace `signals-core` imports with `signals`
DAreRodz Jul 30, 2024
fee316d
Rename `proxiedStore` to `proxifiedStore`
DAreRodz Jul 30, 2024
52373b1
Remove unnecessary `peek()` call
DAreRodz Jul 31, 2024
55a9d01
Throw more descriptive errors from getContext and getElement
DAreRodz Jul 31, 2024
ff9c901
Use more descriptive name for proxy functions
DAreRodz Jul 31, 2024
68de3b6
Use destructured `get` inside `setGetter` call
DAreRodz Jul 31, 2024
1009a4f
Add comment to explain `objToIterable` signals subscription
DAreRodz Jul 31, 2024
2e5c926
Change line comment to block comment
DAreRodz Jul 31, 2024
2aaf909
Replace `?` with `!` operator
DAreRodz Jul 31, 2024
1ff465d
Wrap Interactivity API tests with appropriate `describe`
DAreRodz Jul 31, 2024
b470cc2
Remove unnecessary `setNamespace` calls in tests
DAreRodz Jul 31, 2024
65dfdf8
Remove duplicated test
DAreRodz Jul 31, 2024
e0272f8
Fix typo
DAreRodz Jul 31, 2024
4db4bff
Add extra tests for getter modification
DAreRodz Jul 31, 2024
80e9ff5
Test the right namespace is used inside getters
DAreRodz Jul 31, 2024
80cf598
Fix test name
DAreRodz Jul 31, 2024
28d329b
Check if length's PropSignal exists before updating its value
DAreRodz Jul 31, 2024
0efe2c2
Add deepMerge tests and prevent server overwritting
luisherranz Aug 6, 2024
31ad6a9
Make sure context inheritance is shallow and server props don't overw…
luisherranz Aug 6, 2024
185ec72
Refactor wp-each to use new proxifyContext structure
luisherranz Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
More WIP
  • Loading branch information
DAreRodz committed Jul 31, 2024
commit e78df315f1d7c1f491b66ab9fe76232cf03bb73b
32 changes: 32 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/interactivity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"dependencies": {
"@preact/signals": "^1.2.2",
"@preact/signals-core": "1.6.1",
"deepsignal": "1.5.0",
"preact": "^10.19.3"
},
"publishConfig": {
Expand Down
31 changes: 14 additions & 17 deletions packages/interactivity/src/store/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ export const stateHandlers: ProxyHandler< object > = {
*/
const getter = descriptor( target, key )?.get;
if ( getter && ns ) {
prop.updateGetter( getter );
prop.update( { get: getter } );
setNamespace( ns );
const result = prop.accessor( withScope ).value;
const value = prop.get( withScope ).value;
resetNamespace();
return result;
return value;
}

/*
Expand All @@ -43,13 +43,14 @@ export const stateHandlers: ProxyHandler< object > = {
* is updated, which only triggers a re-render when the value changes.
*/
const value = Reflect.get( target, key, receiver );
prop.updateSignal(
shouldProxy( value ) && ns
? proxify( value, stateHandlers, ns )
: value
);

return prop.accessor().value;
prop.update( {
value:
shouldProxy( value ) && ns
? proxify( value, stateHandlers, ns )
: value,
} );

return prop.get().value;
},

set(
Expand Down Expand Up @@ -78,7 +79,7 @@ export const stateHandlers: ProxyHandler< object > = {

if ( Array.isArray( target ) ) {
const length = getProperty( target, 'length' );
length.updateSignal( target.length );
length.update( { value: target.length } );
}
}

Expand All @@ -94,11 +95,7 @@ export const stateHandlers: ProxyHandler< object > = {
const result = Reflect.defineProperty( target, key, desc );

if ( result ) {
if ( desc.get ) {
prop.updateGetter( desc.get );
} else if ( desc.value ) {
prop.updateSignal( desc.value );
}
prop.update( desc );
}
return result;
},
Expand All @@ -108,7 +105,7 @@ export const stateHandlers: ProxyHandler< object > = {

if ( result ) {
const prop = getProperty( target, key );
prop.updateSignal( undefined );
prop.update( {} );

if ( objToIterable.has( target ) ) {
objToIterable.get( target ).value++;
Expand Down
36 changes: 16 additions & 20 deletions packages/interactivity/src/store/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { getProxy } from './proxies';
import { getScope } from '../hooks';

const DEFAULT_SCOPE = {};
const DEFAULT_SCOPE = Symbol();
const objToProps: WeakMap< object, Map< string, Property > > = new WeakMap();

export const getProperty = ( target: object, key: string ) => {
Expand All @@ -40,33 +40,28 @@ class Property {
this.accessors = new WeakMap();
}

updateSignal( value: unknown | undefined ) {
public update( {
get,
value,
}: {
get?: () => any;
value?: unknown;
} ): void {
if ( ! this.signal ) {
this.signal = signal( value );
this.getter = signal( undefined );
} else if ( value !== this.signal.peek() ) {
this.getter = signal( get );
} else if (
value !== this.signal.peek() ||
get !== this.getter?.peek()
) {
batch( () => {
this.signal!.value = value;
this.getter!.value = undefined;
this.getter!.value = get;
} );
}
}

updateGetter( getter: () => any | undefined ) {
if ( ! this.getter ) {
this.signal = signal( undefined );
this.getter = signal( getter );
} else if ( getter !== this.getter.peek() ) {
batch( () => {
this.signal!.value = undefined;
this.getter!.value = getter;
} );
}
}

accessor(
wrapper?: < G extends () => any >( getter: G ) => G
): ReadonlySignal {
get( wrapper?: < G extends () => any >( getter: G ) => G ): ReadonlySignal {
const scope = getScope() || DEFAULT_SCOPE;

if ( ! this.accessors.has( scope ) ) {
Expand All @@ -85,6 +80,7 @@ class Property {
} )
);
}

return this.accessors.get( scope )!;
}
}