@@ -12,8 +12,10 @@ import { filename } from '../../../state.js';
12
12
import { render_stylesheet } from '../css/index.js' ;
13
13
import { AssignmentExpression } from './visitors/javascript/AssignmentExpression.js' ;
14
14
import { CallExpression } from './visitors/javascript/CallExpression.js' ;
15
+ import { ClassBodyRunes } from './visitors/javascript/ClassBody.js' ;
15
16
import { Identifier } from './visitors/javascript/Identifier.js' ;
16
17
import { UpdateExpression } from './visitors/javascript/UpdateExpression.js' ;
18
+ import { PropertyDefinitionRunes } from './visitors/javascript/PropertyDefinition.js' ;
17
19
import { AwaitBlock } from './visitors/template/AwaitBlock.js' ;
18
20
import { Component } from './visitors/template/Component.js' ;
19
21
import { ConstTag } from './visitors/template/ConstTag.js' ;
@@ -68,138 +70,8 @@ const global_visitors = {
68
70
69
71
/** @type {Visitors } */
70
72
const javascript_visitors_runes = {
71
- ClassBody ( node , { state, visit } ) {
72
- /** @type {Map<string, StateField> } */
73
- const public_derived = new Map ( ) ;
74
-
75
- /** @type {Map<string, StateField> } */
76
- const private_derived = new Map ( ) ;
77
-
78
- /** @type {string[] } */
79
- const private_ids = [ ] ;
80
-
81
- for ( const definition of node . body ) {
82
- if (
83
- definition . type === 'PropertyDefinition' &&
84
- ( definition . key . type === 'Identifier' || definition . key . type === 'PrivateIdentifier' )
85
- ) {
86
- const { type, name } = definition . key ;
87
-
88
- const is_private = type === 'PrivateIdentifier' ;
89
- if ( is_private ) private_ids . push ( name ) ;
90
-
91
- if ( definition . value ?. type === 'CallExpression' ) {
92
- const rune = get_rune ( definition . value , state . scope ) ;
93
- if ( rune === '$derived' || rune === '$derived.by' ) {
94
- /** @type {StateField } */
95
- const field = {
96
- kind : rune === '$derived.by' ? 'derived_call' : 'derived' ,
97
- // @ts -expect-error this is set in the next pass
98
- id : is_private ? definition . key : null
99
- } ;
100
-
101
- if ( is_private ) {
102
- private_derived . set ( name , field ) ;
103
- } else {
104
- public_derived . set ( name , field ) ;
105
- }
106
- }
107
- }
108
- }
109
- }
110
-
111
- // each `foo = $derived()` needs a backing `#foo` field
112
- for ( const [ name , field ] of public_derived ) {
113
- let deconflicted = name ;
114
- while ( private_ids . includes ( deconflicted ) ) {
115
- deconflicted = '_' + deconflicted ;
116
- }
117
-
118
- private_ids . push ( deconflicted ) ;
119
- field . id = b . private_id ( deconflicted ) ;
120
- }
121
-
122
- /** @type {Array<MethodDefinition | PropertyDefinition> } */
123
- const body = [ ] ;
124
-
125
- const child_state = { ...state , private_derived } ;
126
-
127
- // Replace parts of the class body
128
- for ( const definition of node . body ) {
129
- if (
130
- definition . type === 'PropertyDefinition' &&
131
- ( definition . key . type === 'Identifier' || definition . key . type === 'PrivateIdentifier' )
132
- ) {
133
- const name = definition . key . name ;
134
-
135
- const is_private = definition . key . type === 'PrivateIdentifier' ;
136
- const field = ( is_private ? private_derived : public_derived ) . get ( name ) ;
137
-
138
- if ( definition . value ?. type === 'CallExpression' && field !== undefined ) {
139
- const init = /** @type {Expression } **/ (
140
- visit ( definition . value . arguments [ 0 ] , child_state )
141
- ) ;
142
- const value =
143
- field . kind === 'derived_call'
144
- ? b . call ( '$.once' , init )
145
- : b . call ( '$.once' , b . thunk ( init ) ) ;
146
-
147
- if ( is_private ) {
148
- body . push ( b . prop_def ( field . id , value ) ) ;
149
- } else {
150
- // #foo;
151
- const member = b . member ( b . this , field . id ) ;
152
- body . push ( b . prop_def ( field . id , value ) ) ;
153
-
154
- // get foo() { return this.#foo; }
155
- body . push ( b . method ( 'get' , definition . key , [ ] , [ b . return ( b . call ( member ) ) ] ) ) ;
156
-
157
- if ( ( field . kind === 'derived' || field . kind === 'derived_call' ) && state . options . dev ) {
158
- body . push (
159
- b . method (
160
- 'set' ,
161
- definition . key ,
162
- [ b . id ( '_' ) ] ,
163
- [ b . throw_error ( `Cannot update a derived property ('${ name } ')` ) ]
164
- )
165
- ) ;
166
- }
167
- }
168
-
169
- continue ;
170
- }
171
- }
172
-
173
- body . push ( /** @type {MethodDefinition } **/ ( visit ( definition , child_state ) ) ) ;
174
- }
175
-
176
- return { ...node , body } ;
177
- } ,
178
- PropertyDefinition ( node , { state, next, visit } ) {
179
- if ( node . value != null && node . value . type === 'CallExpression' ) {
180
- const rune = get_rune ( node . value , state . scope ) ;
181
-
182
- if ( rune === '$state' || rune === '$state.frozen' || rune === '$derived' ) {
183
- return {
184
- ...node ,
185
- value :
186
- node . value . arguments . length === 0
187
- ? null
188
- : /** @type {Expression } */ ( visit ( node . value . arguments [ 0 ] ) )
189
- } ;
190
- }
191
- if ( rune === '$derived.by' ) {
192
- return {
193
- ...node ,
194
- value :
195
- node . value . arguments . length === 0
196
- ? null
197
- : b . call ( /** @type {Expression } */ ( visit ( node . value . arguments [ 0 ] ) ) )
198
- } ;
199
- }
200
- }
201
- next ( ) ;
202
- } ,
73
+ ClassBody : ClassBodyRunes ,
74
+ PropertyDefinition : PropertyDefinitionRunes ,
203
75
VariableDeclaration ( node , { state, visit } ) {
204
76
const declarations = [ ] ;
205
77
0 commit comments