July 2000 Draft
JavaScript 2.0
Core Language
Packages
previousupnext

Friday, May 26, 2000

Defining Packages

Packages are an abstraction mechanism for grouping and distributing related code. Packages are designed to be linked at run time to allow a program to take advantage of packages written elsewhere or provided by the embedding environment. JavaScript 2.0 offers a number of facilities to make packages robust for dynamic linking:

A package is defined using the following syntax:

PackageDefinition  package [no line break] PackageName Block
PackageName 
   String
|  CompoundPackageName
CompoundPackageName 
   Identifier
|  CompoundPackageName . Identifier

A PackageName is either a literal string or a series of dot-separated identifiers (a CompoundPackageName). A CompoundPackageName is converted to a string by concatinating the names of the identifiers, separated by period (.) characters.

An earlier version of this proposal used URIs as package names, which simplified the process of finding packages and avoiding package name clashes.

The Block contains the body of a package P. The Block is evaluated at the time package P is loaded. Any public top-level properties are available to other packages that import package P. Any public class and interface properties are available to all other packages, regardless of whether they import package P. Top-level, class, and interface properties defined by P in another namespace N are available to other packages only if they use namespace N or qualify the access with namespace N.

A package is loaded (its body is evaluated) when the package is first imported or invoked directly (if, for example, the package is on an HTML web page). Some standard packages are loaded when the JavaScript engine first starts up. When a package is loaded, its statements are evaluated in order, which may cause other packages to be loaded along the way when import statements are encountered. Circularities are not allowed in the graph of package imports.

Two attempts to load the same package in the same environment result in sharing of that package. What constitutes an environment is necessarily application-dependent. However, if package P1 loads packages P2 and P3, both of which load package P4, then P4 is loaded only once and thereafter its code and data is shared by P2 and P3.

To create packages A and B that access each others' symbols, define instead a hidden package C that consists of all of the code that would have gone into A and B. Package A would then import C and reexport the symbols that should be visible in A. Similarly, package B would import C and reexport the symbols that should be visible in B.

Referencing Packages

A package P can reference another package Q via an import statement:

ImportStatement 
   import ImportList
|  use [no line break] import ImportList
ImportList 
   ImportBinding
|  ImportList , ImportBinding
ImportBinding 
   PackageName
|  Identifier = PackageName

An import statement does the following for each ImportBinding:

All definitions can be imported except for attribute definitions.

If package P defines a public top-level entity n and package Q imports P using import PkgP = P, then package Q can refer to n as either PkgP.n or PkgP::n. If package Q imports P using use import PkgP = P, then package Q can also refer to n as plain n as long as it does not conflict with any n defined in Q or some other package imported by Q.

If package P defines a top-level entity n in namespace N and package Q imports P using either import PkgP = P or use import PkgP = P, then package Q can refer to n as either PkgP.N::n or N::n. Package Q can execute use namespace N to be able to refer to n as plain n (barring name collisions).


Waldemar Horwat
Last modified Friday, May 26, 2000
previousupnext