Make `enter!' go into a module even if there was an error when it was instantiated.

Previously, when trying to `enter!' into a module, an exception would
abort the whole thing, leaving the repl where it was.  This behavior can
be very confusing:

  > (module foo racket/base (define x 123) (error "bleh!"))
  > (enter! 'foo)
  bleh!
  > x
  reference to undefined identifier: x
  > (enter! 'foo)
  > x
  123

Things are a little better with xrepl, since the prompt always indicates
the module that you're in.  Still, it's unfortunate that a module with
an error is more likely to be something you'd want to debug -- and most
people are likely to miss the fact that entering a second time will work.

So make `enter!' catch exceptions when requiring the module, change the
namespace, and then re-raise the exception so the user sees it and is
left in the expected namespace.
This commit is contained in:
Eli Barzilay 2011-09-16 11:31:41 -04:00
parent 16cd1ad78d
commit c5b3317daf
2 changed files with 15 additions and 5 deletions

View File

@ -33,11 +33,15 @@
(define (do-enter! mod flags)
(let ([flags (check-flags flags)])
(if mod
(begin (enter-require mod flags)
(let ([ns (module->namespace mod)])
(current-namespace ns)
(unless (memq '#:dont-re-require-enter flags)
(namespace-require 'racket/enter))))
(let* ([none "none"]
[exn (with-handlers ([void values])
(enter-require mod flags)
none)]
[ns (module->namespace mod)])
(current-namespace ns)
(unless (memq '#:dont-re-require-enter flags)
(namespace-require 'racket/enter))
(unless (eq? none exn) (raise exn)))
(current-namespace orig-namespace))))
(struct mod (name timestamp depends))

View File

@ -147,5 +147,11 @@
; located at scribble/html.rkt
; imports: racket/base.rkt, scribble/html/main.rkt.
; no direct exports.
-> «(module broken racket/base (define foo 123) (error "bleh!"))»
-> «,en broken»
bleh! threw an error...
'broken> «foo»
123 ...but we still got in
'broken> «,top»
-> «,ex»
@||})