@@ -90,7 +90,7 @@ export class RubyVM {
9090 const component = await initComponent ( {
9191 ...vm . getImports ( ) ,
9292 throwProhibitRewindException : ( message : string ) => {
93- throw new RbFatalError ( message ) ;
93+ vm . throwProhibitRewindException ( message ) ;
9494 } ,
9595 JsAbiValue : Object ,
9696 } ) ;
@@ -141,25 +141,29 @@ export class RubyVM {
141141 const str = new TextDecoder ( ) . decode (
142142 new Uint8Array ( memory . buffer , messagePtr , messageLen ) ,
143143 ) ;
144- let message = "Ruby APIs that may rewind the VM stack are prohibited under nested VM operation " +
145- `(${ str } )\n` +
146- "Nested VM operation means that the call stack has sandwitched JS frames like JS -> Ruby -> JS -> Ruby " +
147- "caused by something like `window.rubyVM.eval(\"JS.global[:rubyVM].eval('Fiber.yield')\")`\n" +
148- "\n" +
149- "Please check your call stack and make sure that you are **not** doing any of the following inside the nested Ruby frame:\n" +
150- " 1. Switching fibers (e.g. Fiber#resume, Fiber.yield, and Fiber#transfer)\n" +
151- " Note that `evalAsync` JS API switches fibers internally\n" +
152- " 2. Raising uncaught exceptions\n" +
153- " Please catch all exceptions inside the nested operation\n" +
154- " 3. Calling Continuation APIs\n" ;
155-
156- const error = new RbValue ( this . guest . rbErrinfo ( ) , this , this . privateObject ( ) ) ;
157- if ( error . call ( "nil?" ) . toString ( ) === "false" ) {
158- message += "\n" + this . exceptionFormatter . format ( error , this , this . privateObject ( ) ) ;
159- }
160- throw new RbFatalError ( message ) ;
144+ this . throwProhibitRewindException ( str ) ;
161145 } ,
162146 } ;
147+ private throwProhibitRewindException ( str : string ) {
148+ let message = "Ruby APIs that may rewind the VM stack are prohibited under nested VM operation " +
149+ `(${ str } )\n` +
150+ "Nested VM operation means that the call stack has sandwitched JS frames like JS -> Ruby -> JS -> Ruby " +
151+ "caused by something like `window.rubyVM.eval(\"JS.global[:rubyVM].eval('Fiber.yield')\")`\n" +
152+ "\n" +
153+ "Please check your call stack and make sure that you are **not** doing any of the following inside the nested Ruby frame:\n" +
154+ " 1. Switching fibers (e.g. Fiber#resume, Fiber.yield, and Fiber#transfer)\n" +
155+ " Note that `evalAsync` JS API switches fibers internally\n" +
156+ " 2. Raising uncaught exceptions\n" +
157+ " Please catch all exceptions inside the nested operation\n" +
158+ " 3. Calling Continuation APIs\n" ;
159+
160+ const error = new RbValue ( this . guest . rbErrinfo ( ) , this , this . privateObject ( ) ) ;
161+ if ( error . call ( "nil?" ) . toString ( ) === "false" ) {
162+ message += "\n" + this . exceptionFormatter . format ( error , this , this . privateObject ( ) ) ;
163+ }
164+ throw new RbFatalError ( message ) ;
165+ }
166+
163167 // NOTE: The GC may collect objects that are still referenced by Wasm
164168 // locals because Asyncify cannot scan the Wasm stack above the JS frame.
165169 // So we need to keep track whether the JS frame is sandwitched by Ruby
0 commit comments