@@ -6,7 +6,7 @@ import { escape_html, get_depth } from '../../../utils.js';
6
6
import { ready } from '../common/index.js' ;
7
7
8
8
/**
9
- * @typedef {import("../../../../routes/tutorial/[slug]/state.js").CompilerWarning } CompilerWarning
9
+ * @typedef {import("../../../../routes/tutorial/[slug]/state.svelte. js").CompilerWarning } CompilerWarning
10
10
*/
11
11
12
12
const converter = new AnsiToHtml ( {
@@ -17,15 +17,11 @@ const converter = new AnsiToHtml({
17
17
let vm ;
18
18
19
19
/**
20
- * @param {import('svelte/store').Writable<string | null> } base
21
- * @param {import('svelte/store').Writable<Error | null> } error
22
- * @param {import('svelte/store').Writable<{ value: number, text: string }> } progress
23
- * @param {import('svelte/store').Writable<string[]> } logs
24
- * @param {import('svelte/store').Writable<Record<string, CompilerWarning[]>> } warnings
20
+ * @param {typeof import('../../../../routes/tutorial/[slug]/adapter.svelte.js').a } state
25
21
* @returns {Promise<import('$lib/types').Adapter> }
26
22
*/
27
- export async function create ( base , error , progress , logs , warnings ) {
28
- progress . set ( { value : 0 , text : 'loading files' } ) ;
23
+ export async function create ( state ) {
24
+ state . progress = { value : 0 , text : 'loading files' } ;
29
25
30
26
const q = yootils . queue ( 1 ) ;
31
27
/** @type {Map<string, Array<import('$lib/types').FileStub>> } */
@@ -34,10 +30,10 @@ export async function create(base, error, progress, logs, warnings) {
34
30
/** Paths and contents of the currently loaded file stubs */
35
31
let current_stubs = stubs_to_map ( [ ] ) ;
36
32
37
- progress . set ( { value : 1 / 5 , text : 'booting webcontainer' } ) ;
33
+ state . progress = { value : 1 / 5 , text : 'booting webcontainer' } ;
38
34
vm = await WebContainer . boot ( ) ;
39
35
40
- progress . set ( { value : 2 / 5 , text : 'writing virtual files' } ) ;
36
+ state . progress = { value : 2 / 5 , text : 'writing virtual files' } ;
41
37
const common = await ready ;
42
38
await vm . mount ( {
43
39
'common.zip' : {
@@ -48,48 +44,31 @@ export async function create(base, error, progress, logs, warnings) {
48
44
}
49
45
} ) ;
50
46
51
- /** @type {Record<string, CompilerWarning[]> } */
52
- let $warnings ;
53
- warnings . subscribe ( ( value ) => $warnings = value ) ;
54
-
55
- /** @type {any } */
56
- let timeout ;
57
-
58
- /** @param {number } msec */
59
- function schedule_to_update_warning ( msec ) {
60
- clearTimeout ( timeout ) ;
61
- timeout = setTimeout ( ( ) => warnings . set ( $warnings ) , msec ) ;
62
- }
63
-
64
47
const log_stream = ( ) =>
65
48
new WritableStream ( {
66
49
write ( chunk ) {
67
50
if ( chunk === '\x1B[1;1H' ) {
68
51
// clear screen
69
- logs . set ( [ ] ) ;
70
-
52
+ state . logs = [ ] ;
71
53
} else if ( chunk ?. startsWith ( 'svelte:warnings:' ) ) {
72
54
/** @type {CompilerWarning } */
73
55
const warn = JSON . parse ( chunk . slice ( 16 ) ) ;
74
- const current = $ warnings[ warn . filename ] ;
56
+ const current = state . warnings [ warn . filename ] ;
75
57
76
58
if ( ! current ) {
77
- $ warnings[ warn . filename ] = [ warn ] ;
78
- // the exact same warning may be given multiple times in a row
79
- } else if ( ! current . some ( ( s ) => ( s . code === warn . code && s . pos === warn . pos ) ) ) {
59
+ state . warnings [ warn . filename ] = [ warn ] ;
60
+ // the exact same warning may be given multiple times in a row
61
+ } else if ( ! current . some ( ( s ) => s . code === warn . code && s . pos === warn . pos ) ) {
80
62
current . push ( warn ) ;
81
63
}
82
-
83
- schedule_to_update_warning ( 100 ) ;
84
-
85
64
} else {
86
65
const log = converter . toHtml ( escape_html ( chunk ) ) . replace ( / \n / g, '<br>' ) ;
87
- logs . update ( ( $ logs) => [ ...$ logs, log ] ) ;
66
+ state . logs = [ ...state . logs , log ] ;
88
67
}
89
68
}
90
69
} ) ;
91
70
92
- progress . set ( { value : 3 / 5 , text : 'unzipping files' } ) ;
71
+ state . progress = { value : 3 / 5 , text : 'unzipping files' } ;
93
72
const unzip = await vm . spawn ( 'node' , [ 'unzip.cjs' ] ) ;
94
73
unzip . output . pipeTo ( log_stream ( ) ) ;
95
74
const code = await unzip . exit ;
@@ -101,11 +80,11 @@ export async function create(base, error, progress, logs, warnings) {
101
80
await vm . spawn ( 'chmod' , [ 'a+x' , 'node_modules/vite/bin/vite.js' ] ) ;
102
81
103
82
vm . on ( 'server-ready' , ( _port , url ) => {
104
- base . set ( url ) ;
83
+ state . base = url ;
105
84
} ) ;
106
85
107
86
vm . on ( 'error' , ( { message } ) => {
108
- error . set ( new Error ( message ) ) ;
87
+ state . error = new Error ( message ) ;
109
88
} ) ;
110
89
111
90
let launched = false ;
@@ -114,7 +93,7 @@ export async function create(base, error, progress, logs, warnings) {
114
93
if ( launched ) return ;
115
94
launched = true ;
116
95
117
- progress . set ( { value : 4 / 5 , text : 'starting dev server' } ) ;
96
+ state . progress = { value : 4 / 5 , text : 'starting dev server' } ;
118
97
119
98
await new Promise ( async ( fulfil , reject ) => {
120
99
const error_unsub = vm . on ( 'error' , ( error ) => {
@@ -124,7 +103,7 @@ export async function create(base, error, progress, logs, warnings) {
124
103
125
104
const ready_unsub = vm . on ( 'server-ready' , ( _port , base ) => {
126
105
ready_unsub ( ) ;
127
- progress . set ( { value : 5 / 5 , text : 'ready' } ) ;
106
+ state . progress = { value : 5 / 5 , text : 'ready' } ;
128
107
fulfil ( base ) ; // this will be the last thing that happens if everything goes well
129
108
} ) ;
130
109
@@ -179,30 +158,26 @@ export async function create(base, error, progress, logs, warnings) {
179
158
// Don't delete the node_modules folder when switching from one exercise to another
180
159
// where, as this crashes the dev server.
181
160
const to_delete = [
182
- ...Array . from ( current_stubs . keys ( ) ) . filter (
183
- ( s ) => ! s . startsWith ( '/node_modules' )
184
- ) ,
161
+ ...Array . from ( current_stubs . keys ( ) ) . filter ( ( s ) => ! s . startsWith ( '/node_modules' ) ) ,
185
162
...force_delete
186
163
] ;
187
164
188
165
// initialize warnings of written files
189
166
to_write
190
- . filter ( ( stub ) => stub . type === 'file' && $ warnings[ stub . name ] )
191
- . forEach ( ( stub ) => $ warnings[ stub . name ] = [ ] ) ;
167
+ . filter ( ( stub ) => stub . type === 'file' && state . warnings [ stub . name ] )
168
+ . forEach ( ( stub ) => ( state . warnings [ stub . name ] = [ ] ) ) ;
192
169
// remove warnings of deleted files
193
170
to_delete
194
- . filter ( ( stubname ) => $warnings [ stubname ] )
195
- . forEach ( ( stubname ) => delete $warnings [ stubname ] ) ;
196
-
197
- warnings . set ( $warnings ) ;
171
+ . filter ( ( stubname ) => state . warnings [ stubname ] )
172
+ . forEach ( ( stubname ) => delete state . warnings [ stubname ] ) ;
198
173
199
174
current_stubs = stubs_to_map ( stubs ) ;
200
175
201
176
// For some reason, server-ready is fired again when the vite dev server is restarted.
202
177
// We need to wait for it to finish before we can continue, else we might
203
178
// request files from Vite before it's ready, leading to a timeout.
204
- const will_restart = launched &&
205
- ( to_write . some ( is_config ) || to_delete . some ( is_config_path ) ) ;
179
+ const will_restart =
180
+ launched && ( to_write . some ( is_config ) || to_delete . some ( is_config_path ) ) ;
206
181
const promise = will_restart ? wait_for_restart_vite ( ) : Promise . resolve ( ) ;
207
182
208
183
for ( const file of to_delete ) {
@@ -223,14 +198,13 @@ export async function create(base, error, progress, logs, warnings) {
223
198
} ) ;
224
199
} ,
225
200
update : ( file ) => {
226
-
227
201
let queue = q_per_file . get ( file . name ) ;
228
202
if ( queue ) {
229
203
queue . push ( file ) ;
230
204
return Promise . resolve ( false ) ;
231
205
}
232
206
233
- q_per_file . set ( file . name , queue = [ file ] ) ;
207
+ q_per_file . set ( file . name , ( queue = [ file ] ) ) ;
234
208
235
209
return q . add ( async ( ) => {
236
210
/** @type {import('@webcontainer/api').FileSystemTree } */
@@ -257,16 +231,14 @@ export async function create(base, error, progress, logs, warnings) {
257
231
const will_restart = is_config ( file ) ;
258
232
259
233
while ( queue && queue . length > 0 ) {
260
-
261
234
// if the file is updated many times rapidly, get the most recently updated one
262
235
const file = /** @type {import('$lib/types').FileStub } */ ( queue . pop ( ) ) ;
263
- queue . length = 0
236
+ queue . length = 0 ;
264
237
265
238
tree [ basename ] = to_file ( file ) ;
266
239
267
240
// initialize warnings of this file
268
- $warnings [ file . name ] = [ ] ;
269
- schedule_to_update_warning ( 100 ) ;
241
+ state . warnings [ file . name ] = [ ] ;
270
242
271
243
await vm . mount ( root ) ;
272
244
@@ -280,7 +252,7 @@ export async function create(base, error, progress, logs, warnings) {
280
252
await new Promise ( ( f ) => setTimeout ( f , 50 ) ) ;
281
253
}
282
254
283
- q_per_file . delete ( file . name )
255
+ q_per_file . delete ( file . name ) ;
284
256
285
257
return will_restart ;
286
258
} ) ;
0 commit comments