11
11
class JavaStreamManager {
12
12
constructor ( ) {
13
13
// Stream buffers
14
- this . stdout = "" ; // Output buffer
15
- this . stderr = "" ; // Error buffer
14
+ this . stdout = "" ; // Standard output buffer
15
+ this . stderr = "" ; // Standard error buffer
16
+ this . stdin = "" ; // Standard input buffer
16
17
17
18
// Event listeners
18
- this . inputListeners = [ ] ; // Listeners for input requests
19
+ this . inputListeners = [ ] ; // Listeners for input requests
19
20
this . outputListeners = [ ] ; // Listeners for output events
20
21
this . errorListeners = [ ] ; // Listeners for error events
21
22
@@ -24,194 +25,154 @@ class JavaStreamManager {
24
25
this . inputResolver = null ;
25
26
this . inputPrompt = "" ;
26
27
27
- // Flags
28
+ // Stream state
28
29
this . isInitialized = false ;
30
+ this . isClosed = false ;
29
31
}
30
-
31
- /**
32
- * Initialize the stream manager and register event handlers
33
- * @param {Object } options Configuration options
34
- */
32
+
33
+ // Initialize stream manager
35
34
initialize ( options = { } ) {
36
35
if ( this . isInitialized ) return this ;
37
36
38
- // Register event handlers if provided
39
- if ( options . onInputRequest && typeof options . onInputRequest === 'function' ) {
40
- this . addInputListener ( options . onInputRequest ) ;
41
- }
42
-
43
- if ( options . onOutput && typeof options . onOutput === 'function' ) {
44
- this . addOutputListener ( options . onOutput ) ;
45
- }
46
-
47
- if ( options . onError && typeof options . onError === 'function' ) {
48
- this . addErrorListener ( options . onError ) ;
49
- }
37
+ // Register handlers
38
+ if ( options . onInputRequest ) this . addInputListener ( options . onInputRequest ) ;
39
+ if ( options . onOutput ) this . addOutputListener ( options . onOutput ) ;
40
+ if ( options . onError ) this . addErrorListener ( options . onError ) ;
50
41
51
42
this . isInitialized = true ;
52
43
return this ;
53
44
}
54
-
55
- /**
56
- * Add a listener for input requests (when Java code needs user input)
57
- * @param {Function } listener Callback function that handles input requests
58
- */
45
+
46
+ // Add input request listener
59
47
addInputListener ( listener ) {
60
48
if ( typeof listener === 'function' ) {
61
49
this . inputListeners . push ( listener ) ;
62
50
}
63
51
return this ;
64
52
}
65
-
66
- /**
67
- * Add a listener for output events (when Java code writes to stdout)
68
- * @param {Function } listener Callback function that handles output
69
- */
53
+
54
+ // Add output listener
70
55
addOutputListener ( listener ) {
71
56
if ( typeof listener === 'function' ) {
72
57
this . outputListeners . push ( listener ) ;
73
58
}
74
59
return this ;
75
60
}
76
-
77
- /**
78
- * Add a listener for error events (when Java code writes to stderr)
79
- * @param {Function } listener Callback function that handles errors
80
- */
61
+
62
+ // Add error listener
81
63
addErrorListener ( listener ) {
82
64
if ( typeof listener === 'function' ) {
83
65
this . errorListeners . push ( listener ) ;
84
66
}
85
67
return this ;
86
68
}
87
-
88
- /**
89
- * Write to the standard output stream (simulates System.out.print in Java)
90
- * @param {string } text Text to write to stdout
91
- */
69
+
70
+ // Write to stdout
92
71
writeOutput ( text ) {
93
- this . stdout += text ;
94
-
95
- // Notify all output listeners
96
- for ( const listener of this . outputListeners ) {
97
- listener ( text ) ;
98
- }
72
+ if ( this . isClosed ) return this ;
99
73
74
+ this . stdout += text ;
75
+ // Notify listeners
76
+ this . outputListeners . forEach ( listener => listener ( text ) ) ;
100
77
return this ;
101
78
}
102
-
103
- /**
104
- * Write to the error output stream (simulates System.err.print in Java)
105
- * @param {string } text Text to write to stderr
106
- */
79
+
80
+ // Write to stderr
107
81
writeError ( text ) {
108
- this . stderr += text ;
109
-
110
- // Notify all error listeners
111
- for ( const listener of this . errorListeners ) {
112
- listener ( text ) ;
113
- }
82
+ if ( this . isClosed ) return this ;
114
83
84
+ this . stderr += text ;
85
+ // Notify listeners
86
+ this . errorListeners . forEach ( listener => listener ( text ) ) ;
115
87
return this ;
116
88
}
117
-
118
- /**
119
- * Request input from the user (simulates Scanner.nextLine() in Java)
120
- * @param {string } prompt Prompt to display to the user
121
- * @returns {Promise<string> } Promise that resolves with user input
122
- */
123
- requestInput ( prompt = "" ) {
89
+
90
+ // Request user input
91
+ async requestInput ( prompt = "" ) {
92
+ if ( this . isClosed ) throw new Error ( "Stream is closed" ) ;
93
+
124
94
this . inputRequested = true ;
125
95
this . inputPrompt = prompt ;
126
96
127
- return new Promise ( ( resolve ) => {
128
- this . inputResolver = resolve ;
129
-
130
- // Notify all input request listeners
131
- const promises = this . inputListeners . map ( listener => listener ( prompt ) ) ;
97
+ try {
98
+ // Get input from listeners or global handler
99
+ if ( this . inputListeners . length > 0 ) {
100
+ const promises = this . inputListeners . map ( listener => listener ( prompt ) ) ;
101
+ const results = await Promise . all ( promises ) ;
102
+ const input = results . find ( result => result !== undefined ) ;
103
+
104
+ if ( input !== undefined ) {
105
+ this . inputRequested = false ;
106
+ this . inputResolver = null ;
107
+ return input ;
108
+ }
109
+ }
132
110
133
- // If we have listeners, use their response
134
- if ( promises . length > 0 ) {
135
- Promise . all ( promises )
136
- . then ( results => {
137
- // Use the first non-undefined result
138
- const input = results . find ( result => result !== undefined ) ;
139
- if ( input !== undefined ) {
140
- this . inputRequested = false ;
141
- this . inputResolver = null ;
142
- resolve ( input ) ;
143
- }
144
- } ) ;
145
- } else if ( window . requestJavaInput ) {
146
- // Fallback to global requestJavaInput if available
147
- window . requestJavaInput ( prompt )
148
- . then ( input => {
149
- this . inputRequested = false ;
150
- this . inputResolver = null ;
151
- resolve ( input ) ;
152
- } ) ;
153
- } else {
154
- // If no input handlers are available, log an error and return a default
155
- console . error ( "No input handlers registered and no global requestJavaInput function found" ) ;
111
+ // Fallback to global handler
112
+ if ( window . requestJavaInput ) {
113
+ const input = await window . requestJavaInput ( prompt ) ;
156
114
this . inputRequested = false ;
157
115
this . inputResolver = null ;
158
- resolve ( "default\n" ) ;
116
+ return input ;
159
117
}
160
- } ) ;
161
- }
162
-
163
- /**
164
- * Provide input to resolve a pending input request
165
- * @param {string } input Input text from the user
166
- */
167
- provideInput ( input ) {
168
- if ( this . inputRequested && this . inputResolver ) {
169
- const resolver = this . inputResolver ;
118
+
119
+ throw new Error ( "No input handler available" ) ;
120
+ } catch ( error ) {
170
121
this . inputRequested = false ;
171
122
this . inputResolver = null ;
172
- resolver ( input ) ;
123
+ throw error ;
173
124
}
125
+ }
126
+
127
+ // Provide input directly
128
+ provideInput ( input ) {
129
+ if ( ! this . inputRequested || ! this . inputResolver ) return this ;
130
+
131
+ const resolver = this . inputResolver ;
132
+ this . inputRequested = false ;
133
+ this . inputResolver = null ;
134
+ resolver ( input ) ;
174
135
return this ;
175
136
}
176
-
177
- /**
178
- * Get the current contents of the standard output buffer
179
- * @returns {string } Current stdout content
180
- */
137
+
138
+ // Get stdout contents
181
139
getOutput ( ) {
182
140
return this . stdout ;
183
141
}
184
-
185
- /**
186
- * Get the current contents of the error output buffer
187
- * @returns {string } Current stderr content
188
- */
142
+
143
+ // Get stderr contents
189
144
getError ( ) {
190
145
return this . stderr ;
191
146
}
192
-
193
- /**
194
- * Clear all stream buffers
195
- */
147
+
148
+ // Clear all buffers
196
149
clearBuffers ( ) {
197
150
this . stdout = "" ;
198
151
this . stderr = "" ;
152
+ this . stdin = "" ;
199
153
return this ;
200
154
}
201
-
202
- /**
203
- * Reset the stream manager to its initial state
204
- */
155
+
156
+ // Reset to initial state
205
157
reset ( ) {
206
158
this . clearBuffers ( ) ;
207
159
this . inputRequested = false ;
208
160
this . inputResolver = null ;
209
161
this . inputPrompt = "" ;
162
+ this . isClosed = false ;
163
+ return this ;
164
+ }
165
+
166
+ // Close streams
167
+ close ( ) {
168
+ this . isClosed = true ;
169
+ this . inputRequested = false ;
170
+ this . inputResolver = null ;
210
171
return this ;
211
172
}
212
173
}
213
174
214
- // Create a singleton instance
175
+ // Create singleton instance
215
176
const javaStreams = new JavaStreamManager ( ) ;
216
177
217
178
export { javaStreams } ;
0 commit comments