|
JavaScript 2.0
Core Language
Definitions
|
Thursday, November 11, 1999
Any definition can have a Visibility prefix. That prefix specifies the following:
A Visibility prefix can be one of the prefixes in the table below, or it can be user-defined. User-defined Visibility prefixes allow the author of a package P to control definition visibility based on the version by which a client package imports P. User-defined Visibility prefixes also allow definition access to be controlled by the manner in which a client attempts to reference the definition.
The following are the predefined Visibility prefixes. The access privileges they provide are
described in more detail in the next section. Unless overridden, the default Visibility is box.
| Visibility | Access allowed from |
|---|---|
local |
only within current block |
box |
only within current package (when applied to a class member), function, or box |
private |
only within current class |
package |
only within current package |
public |
within any package that imports this package |
To understand the scope to which a definition applies we need to define a few terms. In the definitions below D represents a variable, function, member, or class definition.
box Block lexically
enclosing D. If there is no such block, then the containing box of D is the package scope.box Block,
or visibility-specifying block lexically enclosing D. If there
is no such block, then the containing visibility specifier of D is the package scope.box.To determine the scope S to which a definition D applies, we look up the definition's Visibility prefix in the table below. A definition without a Visibility prefix uses its visibility default prefix.
| Visibility | Scope where entity is declared |
|---|---|
local |
D's containing block |
box |
D's containing box |
private |
D's containing class |
package |
D's containing class |
public |
D's containing class |
| User-defined | D's containing class |
The scope S is not the scope in which the definition is accessible; rather, it is the scope into which the declared entity is inserted.
If S is a class and Visibility is not local,
then the declared entity will appear as a member of class S. If S is a class and Visibility
is local, then the declared entity will only be created inside class S's block
without becoming a member of class S; it is an error if this case arises for a method or field definition.
Once the scope S is known, the accessibility of definition D is determined by the table below. P is the lexically enclosing package.
| Visibility prefix |
Scope S is ... | ||||
|---|---|---|---|---|---|
| a package P | a class C | a function F | a box B | a block B | |
local |
Package P | Class C | Function F | Box B | Block B |
box |
Package P | Package P | Function F | Box B | |
private |
Package P | Class C | |||
package |
Package P | Package P | |||
public |
Any package | Any package | |||
| User-defined | User-defined | User-defined | |||
All of these definitions share several common scoping rules:
Rules 3 and 4 state that once an identifier is resolved to a variable or function in a scope, that resolution cannot be changed. This permits efficient compilation and avoids confusion with programs such as:
const b:integer = 7;
function f():integer {
function g():integer {return b}
var a = g();
const b:integer = 8;
return g() - a;
}
Definitions at the top level of a Program or at the top level of a ClassDefinition's
Block may omit Visibility, in which case they are treated as if
they had package visibility. When used outside a ClassDefinition's
Block, private is equivalent to package.
does not apply to the current Block. Instead, it declares either an entity at the top level of the current package (if outside a ClassDefinition's Block) or a member of the current class (if inside a ClassDefinition's Block). In addition to lifting the definition out of the current scope in this way, Visibility also specifies the definition's visibility from other packages or classes. Visibility can take one of the following forms:
Most lexical scopes are established by Block productions in the grammar. Lexical scopes nest, and a definition in an inner scope can shadow definitions in outer ones.
In the example below the comments indicate the scope and visibility of each definition:
var a0; // Package-visible global variable
private var a1 = true; // Package-visible global variable
package var a2; // Package-visible global variable
public var a3; // Public global variable
if (a1) {
var b0; // Local to this block
private var b1; // Package-visible global variable
package var b2; // Package-visible global variable
public var b3; // Public global variable
}
public function F() { // Public global function
var c0; // Local to this function
private var c1; // Package-visible global variable
package var c2; // Package-visible global variable
public var c3; // Public global variable
}
function G() { // Package-visible global function
var d0; // Never defined because G isn't called
private var d1; // Never defined because G isn't called
package var d2; // Never defined because G isn't called
public var d3; // Never defined because G isn't called
}
class C { // Package-visible global class
var e0; // Package-visible class variable
private var e1; // Class-visible class variable
package var e2; // Package-visible class variable
public var e3; // Public class variable
field e4; // Package-visible instance variable
private field e5; // Class-visible instance variable
package field e6; // Package-visible instance variable
public field e7; // Public instance variable
function H() { // Package-visible class function
var f0; // Local to this function
private var f1; // Class-visible class variable
package var f2; // Package-visible class variable
public var f3; // Public class variable
private field f4; // Class-visible instance variable
package field f5; // Package-visible instance variable
public field f6; // Public instance variable
}
public method I() {} // Public class method
H();
}
F();
A public definition's identifier is exported to other packages. To help avoid accidental collisions between
identifiers declared in different packages, identifiers can be selectively exported depending on the version requested by
an importing package. An identifier definition with a version number newer than that requested by the importer will not be
seen by that importer. The versioning facilities also include additional facilities that allow
robust removal and renaming of identifiers.
VersionsAndRenames describes the set of versions in which an identifier is exported, together with a possible alias for the identifier:
: Identifier] , ... , VersionRange [: Identifier]].. [Version]Suppose a client package C imports version V of package P that exports identifier N with some VersionsAndRenames. If the VersionsAndRenames's VersionRange includes version V, then package C can use the corresponding Identifier alias to access package P's N. If the Identifier alias is omitted, then package C can use N to access package P's N. Multiple VersionRanges operate independently.
In most cases VersionsAndRenames is just a Version name (a string):
public "1.2" const z = 3;
If VersionsAndRenames is omitted, the default version "" is assumed.
Do we want to collapse all block scopes into one inside functions? On one hand this complicates the language conceptually and surprises Java and C++ programmers. On the other hand, this would match JavaScript 1.5 better and simplify closure creation when a closure is created nested inside several blocks in a function.
Should we make private illegal outside a class rather than making it
equivalent to package?
Should we introduce a local Visibility prefix
that explicitly means that the definition is visible locally? This wouldn't provide any additional functionality but it
would provide a convenient name for talking about the four kinds of visibility prefixes.
What should the default visibilities be? The current defaults are loosely modeled after Java:
| Definition Location | Default visibility |
|---|---|
| Package top level | package (equivalent to local in this case) |
| Inside a statement outside a function or class | local |
| Function or method code's top level | local |
| Inside a statement inside a function or method | local |
| Class definition block's top level | package |
| Inside a statement inside a class definition block | local |
Should we have a protected Visibility? It has been omitted
for now to keep the language simple, but there does not appear to be any fundamental reason why it could not be supported.
If we do support it, should we choose the C++ protected concept (visible only in class and subclasses) or the
Java protected concept (visible in class, subclasses, and the original class's package)?
|
Waldemar Horwat Last modified Thursday, November 11, 1999 |