1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
#lang scribble/doc
@(require "mz.rkt")
@title[#:tag "modprotect"]{Code Inspectors}
In the same way that inspectors control access to structure fields
(see @secref["inspectors"]), inspectors also control access to
@tech{module bindings}. Inspectors used this way are @deftech{code
inspectors}. The default code inspector for @tech{module
bindings} is determined by the @racket[current-code-inspector]
parameter, instead of the @racket[current-inspector] parameter.
When a @racket[module] declaration is evaluated, the value of the
@racket[current-code-inspector] parameter is associated with the
module declaration. When the module is invoked via @racket[require] or
@racket[dynamic-require], a sub-inspector of the module's
declaration-time inspector is created, and this sub-inspector is
associated with the module invocation. Any inspector that controls the
sub-inspector (including the declaration-time inspector and its
superior) controls the module invocation. In particular, if the value
of @racket[current-code-inspector] never changes, then no control is
lost for any module invocation, since the module's invocation is
associated with a sub-inspector of @racket[current-code-inspector].
When an inspector that controls a module invocation is installed with
@racket[current-code-inspector], it enables using
@racket[module->namespace] on the module, and it enables access to the
module's protected exports (i.e., those identifiers exported from the
module with @racket[protect-out]) via @racket[dynamic-require]. A
module cannot @racket[require] a module that has a weaker
declaration-time code inspector.
When a @racket[module] form is expanded or a @tech{namespace} is
created, the value of @racket[current-code-inspector] is associated
with the module or namespace's top-level @tech{lexical information}.
Syntax objects with that @tech{lexical information} gain access to the
protected and unexported bindings of any module that the inspector
controls. In the case of a @racket[module], the inspector sticks with
such syntax objects even the syntax object is used in the expansion of
code in a less powerful context; furthermore, if the syntax object is
an identifier that is compiled as a variable reference, the inspector
sticks with the variable reference even if it appears in a module form
that is evaluated (i.e., declared) with a weaker inspector. When a
syntax object or variable reference is within compiled code that is
printed (see @secref["print-compiled"]), the associated inspector is
not preserved.
When compiled code in printed form is @racket[read] back in, no
inspectors are associated with the code. When the code is
@racket[eval]uated, the instantiated syntax-object literals and
module-variable references acquire value of
@racket[current-code-inspector] as their inspector.
When a module instantiation is attached to multiple @tech{namespaces},
each with its own @tech{module registry}, the inspector for the module
invocation can be registry-specific. The invocation inspector in a
particular module registry can be changed via
@racket[namespace-unprotect-module] (but changing the inspector
requires control over the old one).
@history[#:changed "8.1.0.8" @elem{Added constraint against
@racket[require] of a module with
a weaker code inspector.}]
@defparam[current-code-inspector insp inspector?]{
A @tech{parameter} that determines an inspector to control access to
module bindings and redefinitions.
If the code inspector is changed from its original value, then
bytecode loaded by the default @tech{compiled-load handler} is marked
as non-runnable.}
|