11"use client" ;
22
3- import { Context , ReactNode , useCallback , useRef , useState } from "react" ;
3+ import {
4+ Context ,
5+ ReactNode ,
6+ useCallback ,
7+ useEffect ,
8+ useMemo ,
9+ useRef ,
10+ useState ,
11+ } from "react" ;
412import { RuntimeContext , RuntimeLang } from "../runtime" ;
513import { ReplOutput , SyntaxStatus } from "../repl" ;
614import { Mutex , MutexInterface } from "async-mutex" ;
@@ -62,7 +70,7 @@ export function WorkerProvider({
6270} ) {
6371 const workerRef = useRef < Worker | null > ( null ) ;
6472 const [ ready , setReady ] = useState < boolean > ( false ) ;
65- const mutex = useRef < MutexInterface > ( new Mutex ( ) ) ;
73+ const mutex = useMemo < MutexInterface > ( ( ) => new Mutex ( ) , [ ] ) ;
6674 const { writeFile } = useEmbedContext ( ) ;
6775
6876 const messageCallbacks = useRef <
@@ -89,7 +97,7 @@ export function WorkerProvider({
8997 }
9098
9199 const initializeWorker = useCallback ( async ( ) => {
92- if ( ! mutex . current . isLocked ( ) ) {
100+ if ( ! mutex . isLocked ( ) ) {
93101 throw new Error ( `mutex of context must be locked for initializeWorker` ) ;
94102 }
95103 if ( workerRef . current ) {
@@ -135,15 +143,26 @@ export function WorkerProvider({
135143 } ) . then ( ( payload ) => {
136144 capabilities . current = payload . capabilities ;
137145 } ) ;
138- } , [ lang ] ) ;
146+ } , [ lang , mutex ] ) ;
139147
140- // First initialization
141- const init = useCallback ( ( ) => {
142- // すでに初期化済みだった場合initializeWorker()がreturnしなにもしない
143- void mutex . current . runExclusive ( ( ) =>
144- initializeWorker ( ) . then ( ( ) => setReady ( true ) )
145- ) ;
146- } , [ initializeWorker ] ) ;
148+ const [ doInit , setDoInit ] = useState ( false ) ;
149+ const init = useCallback ( ( ) => setDoInit ( true ) , [ ] ) ;
150+
151+ // Initialization effect
152+ useEffect ( ( ) => {
153+ if ( doInit ) {
154+ void mutex . runExclusive ( async ( ) => {
155+ await initializeWorker ( ) ;
156+ setReady ( true ) ;
157+ } ) ;
158+ return ( ) => {
159+ void mutex . runExclusive ( async ( ) => {
160+ workerRef . current ?. terminate ( ) ;
161+ workerRef . current = null ;
162+ } ) ;
163+ } ;
164+ }
165+ } , [ doInit , initializeWorker , mutex ] ) ;
147166
148167 const interrupt = useCallback ( ( ) => {
149168 if ( ! capabilities . current ) return ;
@@ -164,7 +183,7 @@ export function WorkerProvider({
164183 workerRef . current = null ;
165184 setReady ( false ) ;
166185
167- void mutex . current . runExclusive ( async ( ) => {
186+ void mutex . runExclusive ( async ( ) => {
168187 await initializeWorker ( ) ;
169188 if ( commandHistory . current . length > 0 ) {
170189 await postMessage ( "restoreState" , {
@@ -179,11 +198,11 @@ export function WorkerProvider({
179198 capabilities . current ?. interrupt satisfies never ;
180199 break ;
181200 }
182- } , [ initializeWorker ] ) ;
201+ } , [ initializeWorker , mutex ] ) ;
183202
184203 const runCommand = useCallback (
185204 async ( code : string ) : Promise < ReplOutput [ ] > => {
186- if ( ! mutex . current . isLocked ( ) ) {
205+ if ( ! mutex . isLocked ( ) ) {
187206 throw new Error ( `mutex of context must be locked for runCommand` ) ;
188207 }
189208 if ( ! workerRef . current || ! ready ) {
@@ -223,18 +242,18 @@ export function WorkerProvider({
223242 return [ { type : "error" , message : String ( error ) } ] ;
224243 }
225244 } ,
226- [ ready , writeFile ]
245+ [ ready , writeFile , mutex ]
227246 ) ;
228247
229248 const checkSyntax = useCallback (
230249 async ( code : string ) : Promise < SyntaxStatus > => {
231250 if ( ! workerRef . current || ! ready ) return "invalid" ;
232- const { status } = await mutex . current . runExclusive ( ( ) =>
251+ const { status } = await mutex . runExclusive ( ( ) =>
233252 postMessage ( "checkSyntax" , { code } )
234253 ) ;
235254 return status ;
236255 } ,
237- [ ready ]
256+ [ ready , mutex ]
238257 ) ;
239258
240259 const runFiles = useCallback (
@@ -264,7 +283,7 @@ export function WorkerProvider({
264283 ) {
265284 interruptBuffer . current [ 0 ] = 0 ;
266285 }
267- return mutex . current . runExclusive ( async ( ) => {
286+ return mutex . runExclusive ( async ( ) => {
268287 const { output, updatedFiles } = await postMessage ( "runFile" , {
269288 name : filenames [ 0 ] ,
270289 files,
@@ -273,7 +292,7 @@ export function WorkerProvider({
273292 return output ;
274293 } ) ;
275294 } ,
276- [ ready , writeFile ]
295+ [ ready , writeFile , mutex ]
277296 ) ;
278297
279298 return (
@@ -283,7 +302,7 @@ export function WorkerProvider({
283302 ready,
284303 runCommand,
285304 checkSyntax,
286- mutex : mutex . current ,
305+ mutex,
287306 runFiles,
288307 interrupt,
289308 } }
0 commit comments