@@ -13,47 +13,24 @@ import {
1313import { useEmbedContext } from "../embedContext" ;
1414import { ReplOutput } from "../repl" ;
1515import { RuntimeContext } from "../runtime" ;
16- import dynamic from "next/dynamic" ;
1716
1817export const compilerOptions : CompilerOptions = { } ;
1918
20- type TSModules = {
21- ts : typeof import ( "typescript" ) ;
22- vfs : typeof import ( "@typescript/vfs" ) ;
23- } ;
24- interface ITypeScriptContext {
25- modules : TSModules | null ;
26- setModules : ( modules : TSModules ) => void ;
27- tsEnv : VirtualTypeScriptEnvironment | null ;
28- }
29- const TypeScriptContext = createContext < ITypeScriptContext > ( {
30- modules : null ,
31- setModules : ( ) => { } ,
32- tsEnv : null ,
33- } ) ;
34- const LazyInitTypeScript = dynamic (
35- async ( ) => {
36- const ts = await import ( "typescript" ) ;
37- const vfs = await import ( "@typescript/vfs" ) ;
38- return function LazyInitTypeScript ( ) {
39- const { setModules } = useContext ( TypeScriptContext ) ;
40- useEffect ( ( ) => {
41- setModules ( { ts, vfs } ) ;
42- } , [ setModules ] ) ;
43- return null ;
44- } ;
45- } ,
46- { ssr : false }
19+ const TypeScriptContext = createContext < VirtualTypeScriptEnvironment | null > (
20+ null
4721) ;
4822export function TypeScriptProvider ( { children } : { children : ReactNode } ) {
4923 const [ tsEnv , setTSEnv ] = useState < VirtualTypeScriptEnvironment | null > ( null ) ;
50- const [ modules , setModules ] = useState < TSModules | null > ( null ) ;
5124
5225 useEffect ( ( ) => {
53- if ( modules !== null && tsEnv === null ) {
54- const { ts, vfs } = modules ;
26+ // useEffectはサーバーサイドでは実行されないが、
27+ // typeof window !== "undefined" でガードしないとなぜかesbuildが"typescript"を
28+ // サーバーサイドでのインポート対象とみなしてしまう。
29+ if ( tsEnv === null && typeof window !== "undefined" ) {
5530 const abortController = new AbortController ( ) ;
5631 ( async ( ) => {
32+ const ts = await import ( "typescript" ) ;
33+ const vfs = await import ( "@typescript/vfs" ) ;
5734 const system = vfs . createSystem ( new Map ( ) ) ;
5835 const libFiles = vfs . knownLibFilesForCompilerOptions (
5936 compilerOptions ,
@@ -90,81 +67,76 @@ export function TypeScriptProvider({ children }: { children: ReactNode }) {
9067 abortController . abort ( ) ;
9168 } ;
9269 }
93- } , [ tsEnv , setTSEnv , modules ] ) ;
70+ } , [ tsEnv , setTSEnv ] ) ;
9471 return (
95- < TypeScriptContext . Provider value = { { tsEnv, modules, setModules } } >
96- < LazyInitTypeScript />
72+ < TypeScriptContext . Provider value = { tsEnv } >
9773 { children }
9874 </ TypeScriptContext . Provider >
9975 ) ;
10076}
10177
10278export function useTypeScript ( jsEval : RuntimeContext ) : RuntimeContext {
103- const { modules , tsEnv } = useContext ( TypeScriptContext ) ;
79+ const tsEnv = useContext ( TypeScriptContext ) ;
10480
10581 const { writeFile } = useEmbedContext ( ) ;
10682 const runFiles = useCallback (
10783 async ( filenames : string [ ] , files : Record < string , string > ) => {
108- if ( tsEnv === null || modules === null ) {
84+ if ( tsEnv === null || typeof window === "undefined" ) {
10985 return [
11086 { type : "error" as const , message : "TypeScript is not ready yet." } ,
11187 ] ;
112- }
88+ } else {
89+ for ( const [ filename , content ] of Object . entries ( files ) ) {
90+ tsEnv . createFile ( filename , content ) ;
91+ }
11392
114- for ( const [ filename , content ] of Object . entries ( files ) ) {
115- tsEnv . createFile ( filename , content ) ;
116- }
93+ const outputs : ReplOutput [ ] = [ ] ;
11794
118- const outputs : ReplOutput [ ] = [ ] ;
95+ const ts = await import ( "typescript" ) ;
11996
120- for ( const diagnostic of tsEnv . languageService . getSyntacticDiagnostics (
121- filenames [ 0 ]
122- ) ) {
123- outputs . push ( {
124- type : "error" ,
125- message : modules . ts . formatDiagnosticsWithColorAndContext (
126- [ diagnostic ] ,
127- {
97+ for ( const diagnostic of tsEnv . languageService . getSyntacticDiagnostics (
98+ filenames [ 0 ]
99+ ) ) {
100+ outputs . push ( {
101+ type : "error" ,
102+ message : ts . formatDiagnosticsWithColorAndContext ( [ diagnostic ] , {
128103 getCurrentDirectory : ( ) => "" ,
129104 getCanonicalFileName : ( f ) => f ,
130105 getNewLine : ( ) => "\n" ,
131- }
132- ) ,
133- } ) ;
134- }
106+ } ) ,
107+ } ) ;
108+ }
135109
136- for ( const diagnostic of tsEnv . languageService . getSemanticDiagnostics (
137- filenames [ 0 ]
138- ) ) {
139- outputs . push ( {
140- type : "error" ,
141- message : modules . ts . formatDiagnosticsWithColorAndContext (
142- [ diagnostic ] ,
143- {
110+ for ( const diagnostic of tsEnv . languageService . getSemanticDiagnostics (
111+ filenames [ 0 ]
112+ ) ) {
113+ outputs . push ( {
114+ type : "error" ,
115+ message : ts . formatDiagnosticsWithColorAndContext ( [ diagnostic ] , {
144116 getCurrentDirectory : ( ) => "" ,
145117 getCanonicalFileName : ( f ) => f ,
146118 getNewLine : ( ) => "\n" ,
147- }
148- ) ,
149- } ) ;
150- }
119+ } ) ,
120+ } ) ;
121+ }
151122
152- const emitOutput = tsEnv . languageService . getEmitOutput ( filenames [ 0 ] ) ;
153- files = await writeFile (
154- Object . fromEntries (
155- emitOutput . outputFiles . map ( ( of ) => [ of . name , of . text ] )
156- )
157- ) ;
123+ const emitOutput = tsEnv . languageService . getEmitOutput ( filenames [ 0 ] ) ;
124+ files = await writeFile (
125+ Object . fromEntries (
126+ emitOutput . outputFiles . map ( ( of ) => [ of . name , of . text ] )
127+ )
128+ ) ;
158129
159- console . log ( emitOutput ) ;
160- const jsOutputs = jsEval . runFiles (
161- [ emitOutput . outputFiles [ 0 ] . name ] ,
162- files
163- ) ;
130+ console . log ( emitOutput ) ;
131+ const jsOutputs = jsEval . runFiles (
132+ [ emitOutput . outputFiles [ 0 ] . name ] ,
133+ files
134+ ) ;
164135
165- return outputs . concat ( await jsOutputs ) ;
136+ return outputs . concat ( await jsOutputs ) ;
137+ }
166138 } ,
167- [ modules , tsEnv , writeFile , jsEval ]
139+ [ tsEnv , writeFile , jsEval ]
168140 ) ;
169141 return {
170142 ready : tsEnv !== null ,
0 commit comments