mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 01:55:44 +00:00
805 lines
41 KiB
HTML
805 lines
41 KiB
HTML
<!--
|
|
- The contents of this file are subject to the Netscape Public
|
|
- License Version 1.1 (the "License"); you may not use this file
|
|
- except in compliance with the License. You may obtain a copy of
|
|
- the License at http://www.mozilla.org/NPL/
|
|
-
|
|
- Software distributed under the License is distributed on an "AS
|
|
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
- implied. See the License for the specific language governing
|
|
- rights and limitations under the License.
|
|
-
|
|
- The Original Code is Mozilla Communicator client code, released
|
|
- March 31, 1998.
|
|
-
|
|
- The Initial Developer of the Original Code is Netscape
|
|
- Communications Corporation. Portions created by Netscape are
|
|
- Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
|
- Rights Reserved.
|
|
-
|
|
- Contributor(s):
|
|
-
|
|
- Alternatively, the contents of this file may be used under the
|
|
- terms of the GNU Public License (the "GPL"), in which case the
|
|
- provisions of the GPL are applicable instead of those above.
|
|
- If you wish to allow use of your version of this file only
|
|
- under the terms of the GPL and not to allow others to use your
|
|
- version of this file under the NPL, indicate your decision by
|
|
- deleting the provisions above and replace them with the notice
|
|
- and other provisions required by the GPL. If you do not delete
|
|
- the provisions above, a recipient may use your version of this
|
|
- file under either the NPL or the GPL.
|
|
-->
|
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<meta name="GENERATOR" content="Mozilla/4.5 [en] (WinNT; I) [Netscape]">
|
|
<title>JavaScript Reference Implementation (JSRef) README</title>
|
|
</head>
|
|
<body>
|
|
|
|
<h2>
|
|
Table of Contents</h2>
|
|
|
|
<ul>
|
|
<li>
|
|
<a href="#Introduction">Introduction</a></li>
|
|
|
|
<li>
|
|
<a href="#Build">Build conventions (standalone JS engine and shell)</a></li>
|
|
|
|
<li>
|
|
<a href="#Debugging">Debugging notes</a></li>
|
|
|
|
<li>
|
|
<a href="#Conventions">Naming and coding conventions</a></li>
|
|
|
|
<li>
|
|
<a href="#JSAPI">Using the JS API</a></li>
|
|
|
|
<li>
|
|
<a href="#Design">Design walk-through</a></li>
|
|
|
|
<li>
|
|
<a href="#Resources">Additional Resources (links, API docs, and newsgroups)</a></li>
|
|
|
|
</ul>
|
|
|
|
<h2>
|
|
<a NAME="Introduction"></a>Introduction</h2>
|
|
This is the README file for the <span CLASS=LXRSHORTDESC>JavaScript
|
|
Reference (JSRef) implementation.</span> It consists of build conventions
|
|
and instructions, source code conventions, a design walk-through, and a
|
|
brief file-by-file description of the source.
|
|
<p><span CLASS=LXRLONGDESC>JSRef builds a library or DLL containing the
|
|
JavaScript runtime (compiler, interpreter, decompiler, garbage collector,
|
|
atom manager, standard classes). It then compiles a small "shell" program
|
|
and links that with the library to make an interpreter that can be used
|
|
interactively and with test .js files to run scripts. The code has
|
|
no dependencies on the Navigator code.</span>
|
|
<p><i>Quick start tip</i>: skip to "Using the JS API" below, build the
|
|
js shell, and play with the object named "it" (start by setting 'it.noisy
|
|
= true').
|
|
<h2>
|
|
<a NAME="Build"></a>Build conventions (standalone JS engine and shell)</h2>
|
|
These build directions refer only to building the standalone JavaScript
|
|
engine and shell. To build within the browser, refer to the <a href="http://www.mozilla.org/docs/">build
|
|
directions</a> on the mozilla.org website.
|
|
<p>By default, all platforms build a version of the JS engine that is <i>not</i>
|
|
threadsafe. If you require thread-safety, you must also populate
|
|
the <tt>mozilla/dist</tt> directory with <a href="http://www.mozilla.org/docs/tplist/catCode/nsprdesc.htm">NSPR</a>
|
|
headers and libraries. (NSPR implements a portable threading library,
|
|
among other things. The source is downloadable via <a href="http://www.mozilla.org/cvs.html">CVS</a>
|
|
from <tt><a href="http://lxr.mozilla.org/mozilla/source/nsprpub">mozilla/nsprpub</a></tt>.)
|
|
Next, you must define <tt>JS_THREADSAFE</tt> when building the JS engine,
|
|
either on the command-line (gmake/nmake) or in a universal header file.
|
|
<h3>
|
|
Windows</h3>
|
|
|
|
<ul>
|
|
<li>
|
|
Use MSVC 4.2 or 5.0.</li>
|
|
|
|
<li>
|
|
For building from the IDE use <tt>js/src/js.mdp</tt>. (<tt>js.mdp</tt>
|
|
is an MSVC4.2 project file, but if you load it into MSVC5, it will be converted
|
|
to the newer project file format.) <font color="#CC0000">NOTE: makefile.win
|
|
is an nmake file used only for building the JS-engine in the Mozilla browser.
|
|
Don't attempt to use it to build the standalone JS-engine.</font></li>
|
|
|
|
<li>
|
|
If you prefer to build from the command-line, use '<tt>nmake -f js.mak</tt>'</li>
|
|
|
|
<li>
|
|
Executable shell <tt>js.exe</tt> and runtime library <tt>js32.dll</tt>
|
|
are created in either <tt>js/src/Debug</tt> or <tt>js/src/Release</tt>.</li>
|
|
</ul>
|
|
|
|
<h3>
|
|
Macintosh</h3>
|
|
|
|
<ul>
|
|
<li>
|
|
Use CodeWarrior 3.x</li>
|
|
|
|
<li>
|
|
Load the project file <tt>js:src:macbuild:JSRef.mcp </tt>and select "Make"
|
|
from the menu.</li>
|
|
</ul>
|
|
|
|
<h3>
|
|
Unix</h3>
|
|
|
|
<ul>
|
|
<li>
|
|
Use '<tt>gmake -f Makefile.ref</tt>' to build. To compile optimized code,
|
|
pass <tt>BUILD_OPT=1</tt> on the gmake command line or preset it in the
|
|
environment or <tt>Makefile.ref</tt>. <font color="#CC0000">NOTE:
|
|
Do not attempt to use Makefile to build the standalone JavaScript engine.
|
|
This file is used only for building the JS-engine in the Mozilla browser.</font></li>
|
|
|
|
<li>
|
|
<font color="#000000">Each platform on which JS is built must have a <tt>*.mk</tt>
|
|
configuration file in the <tt>js/src/config</tt> directory. The configuration
|
|
file specifies the compiler/linker to be used and allows for customization
|
|
of command-line options. To date, the build system has been tested
|
|
on Solaris, AIX, HP/UX, OSF, IRIX, x86 Linux and Windows NT.</font></li>
|
|
|
|
<li>
|
|
<font color="#000000">Most platforms will work with either the vendor compiler
|
|
</font>or
|
|
<a href="ftp://prep.ai.mit.edu/pub/gnu">gcc</a>.
|
|
(Except that HP builds only work using the native compiler. gcc won't
|
|
link correctly with shared libraries on that platform. If someone
|
|
knows a way to fix this, <a href="mailto:wynholds@netscape.com">let us
|
|
know</a>.)</li>
|
|
|
|
<li>
|
|
<font color="#000000">If you define <tt>JS_LIVECONNECT</tt>, gmake will
|
|
descend into the liveconnect directory and build
|
|
<a href="http://lxr.mozilla.org/mozilla/source/js/src/liveconnect/README.html">LiveConnect</a>
|
|
after building the JS engine.</font></li>
|
|
|
|
<li>
|
|
To build a binary drop (a zip'ed up file of headers, libraries, binaries),
|
|
check out <tt>mozilla/config</tt> and <tt>mozilla/nsprpub/config</tt>.
|
|
Use '<tt>gmake -f Makefile.ref nsinstall-target all export ship</tt>'</li>
|
|
</ul>
|
|
|
|
<h2>
|
|
<a NAME="Debugging"></a>Debugging notes</h2>
|
|
|
|
<ul>
|
|
<li>
|
|
To turn on GC instrumentation, define <tt>JS_GCMETER</tt>.</li>
|
|
|
|
<li>
|
|
To turn on the arena package's instrumentation, define <tt>JS_ARENAMETER</tt>.</li>
|
|
|
|
<li>
|
|
To turn on the hash table package's metering, define <tt>JS_HASHMETER</tt>.</li>
|
|
</ul>
|
|
|
|
<h2>
|
|
<a NAME="Conventions"></a>Naming and coding conventions</h2>
|
|
|
|
<ul>
|
|
<li>
|
|
Public function names begin with <tt>JS_</tt> followed by capitalized "intercaps",
|
|
e.g. <tt>JS_NewObject</tt>.</li>
|
|
|
|
<li>
|
|
Extern but library-private function names use a <tt>js_</tt> prefix and
|
|
mixed case, e.g. <tt>js_LookupSymbol</tt>.</li>
|
|
|
|
<li>
|
|
Most static function names have unprefixed, mixed-case names: <tt>GetChar</tt>.</li>
|
|
|
|
<li>
|
|
But static native methods of JS objects have lowercase, underscore-separated
|
|
or intercaps names, e.g., <tt>str_indexOf</tt>.</li>
|
|
|
|
<li>
|
|
And library-private and static data use underscores, not intercaps (but
|
|
library-private data do use a <tt>js_</tt> prefix).</li>
|
|
|
|
<li>
|
|
Scalar type names are lowercase and js-prefixed: <tt>jsdouble</tt>.</li>
|
|
|
|
<li>
|
|
Aggregate type names are JS-prefixed and mixed-case: <tt>JSObject.</tt></li>
|
|
|
|
<li>
|
|
Macros are generally <tt>ALL_CAPS </tt>and underscored, to call out potential
|
|
side effects, multiple uses of a formal argument, etc. - Four spaces of
|
|
indentation per statement nesting level.</li>
|
|
|
|
<li>
|
|
Tabs are taken to be eight spaces, and an Emacs magic comment at the top
|
|
of each file tries to help. If you're using MSVC or similar, you'll want
|
|
to set tab width to 8, or convert these files to be space-filled.</li>
|
|
|
|
<li>
|
|
DLL entry points have their return type expanded within a <tt>JS_PUBLIC_API()</tt>
|
|
macro call, to get the right Windows secret type qualifiers in the right
|
|
places for both 16- and 32-bit builds.</li>
|
|
|
|
<li>
|
|
Callback functions that might be called from a DLL are similarly macroized
|
|
with <tt>JS_STATIC_DLL_CALLBACK</tt> (if the function otherwise would be
|
|
static to hide its name) or <tt>JS_DLL_CALLBACK</tt> (this macro takes
|
|
no type argument; it should be used after the return type and before the
|
|
function name).</li>
|
|
</ul>
|
|
|
|
<h2>
|
|
<a NAME="JSAPI"></a>Using the JS API</h2>
|
|
|
|
<h4>
|
|
Starting up</h4>
|
|
|
|
<pre><tt> /*
|
|
* Tune this to avoid wasting space for shallow stacks, while saving on
|
|
* malloc overhead/fragmentation for deep or highly-variable stacks.
|
|
*/
|
|
#define STACK_CHUNK_SIZE 8192
|
|
|
|
JSRuntime *rt;
|
|
JSContext *cx;
|
|
|
|
/* You need a runtime and one or more contexts to do anything with JS. */
|
|
rt = JS_Init(1000000L);
|
|
if (!rt)
|
|
fail("can't create JavaScript runtime");
|
|
cx = JS_NewContext(rt, STACK_CHUNK_SIZE);
|
|
if (!cx)
|
|
fail("can't create JavaScript context");
|
|
|
|
/*
|
|
* The context definitely wants a global object, in order to have standard
|
|
* classes and functions like Date and parseInt. See below for details on
|
|
* JS_NewObject.
|
|
*/
|
|
JSObject *globalObj;
|
|
|
|
globalObj = JS_NewObject(cx, &my_global_class, 0, 0);
|
|
JS_InitStandardClasses(cx, globalObj);</tt></pre>
|
|
|
|
<h4>
|
|
Defining objects and properties</h4>
|
|
|
|
<pre><tt> /* Statically initialize a class to make "one-off" objects. */
|
|
JSClass my_class = {
|
|
"MyClass",
|
|
|
|
/* All of these can be replaced with the corresponding JS_*Stub
|
|
function pointers. */
|
|
my_addProperty, my_delProperty, my_getProperty, my_setProperty,
|
|
my_enumerate, my_resolve, my_convert, my_finalize
|
|
};
|
|
|
|
JSObject *obj;
|
|
|
|
/*
|
|
* Define an object named in the global scope that can be enumerated by
|
|
* for/in loops. The parent object is passed as the second argument, as
|
|
* with all other API calls that take an object/name pair. The prototype
|
|
* passed in is null, so the default object prototype will be used.
|
|
*/
|
|
obj = JS_DefineObject(cx, globalObj, "myObject", &my_class, 0,
|
|
JSPROP_ENUMERATE);
|
|
|
|
/*
|
|
* Define a bunch of properties with a JSPropertySpec array statically
|
|
* initialized and terminated with a null-name entry. Besides its name,
|
|
* each property has a "tiny" identifier (MY_COLOR, e.g.) that can be used
|
|
* in switch statements (in a common my_getProperty function, for example).
|
|
*/
|
|
enum my_tinyid {
|
|
MY_COLOR, MY_HEIGHT, MY_WIDTH, MY_FUNNY, MY_ARRAY, MY_RDONLY
|
|
};
|
|
|
|
static JSPropertySpec my_props[] = {
|
|
{"color", MY_COLOR, JSPROP_ENUMERATE},
|
|
{"height", MY_HEIGHT, JSPROP_ENUMERATE},
|
|
{"width", MY_WIDTH, JSPROP_ENUMERATE},
|
|
{"funny", MY_FUNNY, JSPROP_ENUMERATE},
|
|
{"array", MY_ARRAY, JSPROP_ENUMERATE},
|
|
{"rdonly", MY_RDONLY, JSPROP_READONLY},
|
|
{0}
|
|
};
|
|
|
|
JS_DefineProperties(cx, obj, my_props);
|
|
|
|
/*
|
|
* Given the above definitions and call to JS_DefineProperties, obj will
|
|
* need this sort of "getter" method in its class (my_class, above). See
|
|
* the example for the "It" class in js.c.
|
|
*/
|
|
static JSBool
|
|
my_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|
{
|
|
if (JSVAL_IS_INT(id)) {
|
|
switch (JSVAL_TO_INT(id)) {
|
|
case MY_COLOR: *vp = . . .; break;
|
|
case MY_HEIGHT: *vp = . . .; break;
|
|
case MY_WIDTH: *vp = . . .; break;
|
|
case MY_FUNNY: *vp = . . .; break;
|
|
case MY_ARRAY: *vp = . . .; break;
|
|
case MY_RDONLY: *vp = . . .; break;
|
|
}
|
|
}
|
|
return JS_TRUE;
|
|
}</tt></pre>
|
|
|
|
<h4>
|
|
Defining functions</h4>
|
|
|
|
<pre><tt> /* Define a bunch of native functions first: */
|
|
static JSBool
|
|
my_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|
{
|
|
jsdouble x, z;
|
|
|
|
if (!JS_ValueToNumber(cx, argv[0], &x))
|
|
return JS_FALSE;
|
|
z = (x < 0) ? -x : x;
|
|
return JS_NewDoubleValue(cx, z, rval);
|
|
}
|
|
|
|
. . .
|
|
|
|
/*
|
|
* Use a JSFunctionSpec array terminated with a null name to define a
|
|
* bunch of native functions.
|
|
*/
|
|
static JSFunctionSpec my_functions[] = {
|
|
/* name native nargs */
|
|
{"abs", my_abs, 1},
|
|
{"acos", my_acos, 1},
|
|
{"asin", my_asin, 1},
|
|
. . .
|
|
{0}
|
|
};
|
|
|
|
/*
|
|
* Pass a particular object to define methods for it alone. If you pass
|
|
* a prototype object, the methods will apply to all instances past and
|
|
* future of the prototype's class (see below for classes).
|
|
*/
|
|
JS_DefineFunctions(cx, globalObj, my_functions);</tt></pre>
|
|
|
|
<h4>
|
|
Defining classes</h4>
|
|
|
|
<pre><tt> /*
|
|
* This pulls together the above API elements by defining a constructor
|
|
* function, a prototype object, and properties of the prototype and of
|
|
* the constructor, all with one API call.
|
|
*
|
|
* Initialize a class by defining its constructor function, prototype, and
|
|
* per-instance and per-class properties. The latter are called "static"
|
|
* below by analogy to Java. They are defined in the constructor object's
|
|
* scope, so that 'MyClass.myStaticProp' works along with 'new MyClass()'.
|
|
*
|
|
* JS_InitClass takes a lot of arguments, but you can pass null for any of
|
|
* the last four if there are no such properties or methods.
|
|
*
|
|
* Note that you do not need to call JS_InitClass to make a new instance of
|
|
* that class -- otherwise there would be a chicken-and-egg problem making
|
|
* the global object -- but you should call JS_InitClass if you require a
|
|
* constructor function for script authors to call via new, and/or a class
|
|
* prototype object ('MyClass.prototype') for authors to extend with new
|
|
* properties at run-time.
|
|
*/
|
|
protoObj = JS_InitClass(cx, globalObj, NULL, &my_class,
|
|
|
|
/* native constructor function and min arg count */
|
|
MyClass, 0,
|
|
|
|
/* prototype object properties and methods -- these
|
|
will be "inherited" by all instances through
|
|
delegation up the instance's prototype link. */
|
|
my_props, my_methods,
|
|
|
|
/* class constructor properties and methods */
|
|
my_static_props, my_static_methods);</tt></pre>
|
|
|
|
<h4>
|
|
Running scripts</h4>
|
|
|
|
<pre><tt> /* These should indicate source location for diagnostics. */
|
|
char *filename;
|
|
uintN lineno;
|
|
|
|
/*
|
|
* The return value comes back here -- if it could be a GC thing, you must
|
|
* add it to the GC's "root set" with JS_AddRoot(cx, &thing) where thing
|
|
* is a JSString *, JSObject *, or jsdouble *, and remove the root before
|
|
* rval goes out of scope, or when rval is no longer needed.
|
|
*/
|
|
jsval rval;
|
|
JSBool ok;
|
|
|
|
/*
|
|
* Some example source in a C string. Larger, non-null-terminated buffers
|
|
* can be used, if you pass the buffer length to JS_EvaluateScript.
|
|
*/
|
|
char *source = "x * f(y)";
|
|
|
|
ok = JS_EvaluateScript(cx, globalObj, source, strlen(source),
|
|
filename, lineno, &rval);
|
|
|
|
if (ok) {
|
|
/* Should get a number back from the example source. */
|
|
jsdouble d;
|
|
|
|
ok = JS_ValueToNumber(cx, rval, &d);
|
|
. . .
|
|
}</tt></pre>
|
|
|
|
<h4>
|
|
Calling functions</h4>
|
|
|
|
<pre><tt> /* Call a global function named "foo" that takes no arguments. */
|
|
ok = JS_CallFunctionName(cx, globalObj, "foo", 0, 0, &rval);
|
|
|
|
jsval argv[2];
|
|
|
|
/* Call a function in obj's scope named "method", passing two arguments. */
|
|
argv[0] = . . .;
|
|
argv[1] = . . .;
|
|
ok = JS_CallFunctionName(cx, obj, "method", 2, argv, &rval);</tt></pre>
|
|
|
|
<h4>
|
|
Shutting down</h4>
|
|
|
|
<pre><tt> /* For each context you've created: */
|
|
JS_DestroyContext(cx);
|
|
|
|
/* And finally: */
|
|
JS_Finish(rt);</tt></pre>
|
|
|
|
<h4>
|
|
Debugging API</h4>
|
|
See the<tt> trap, untrap, watch, unwatch, line2pc</tt>, and <tt>pc2line</tt>
|
|
commands in <tt>js.c</tt>. Also the (scant) comments in <i>jsdbgapi.h</i>.
|
|
<h2>
|
|
<a NAME="Design"></a>Design walk-through</h2>
|
|
This section must be brief for now -- it could easily turn into a book.
|
|
<h4>
|
|
JS "JavaScript Proper"</h4>
|
|
JS modules declare and implement the JavaScript compiler, interpreter,
|
|
decompiler, GC and atom manager, and standard classes.
|
|
<p>JavaScript uses untyped bytecode and runtime type tagging of data values.
|
|
The <tt>jsval</tt> type is a signed machine word that contains either a
|
|
signed integer value (if the low bit is set), or a type-tagged pointer
|
|
or boolean value (if the low bit is clear). Tagged pointers all refer to
|
|
8-byte-aligned things in the GC heap.
|
|
<p>Objects consist of a possibly shared structural description, called
|
|
the map or scope; and unshared property values in a vector, called the
|
|
slots. Object properties are associated with nonnegative integers stored
|
|
in <tt>jsval</tt>'s, or with atoms (unique string descriptors) if named
|
|
by an identifier or a non-integral index expression.
|
|
<p>Scripts contain bytecode, source annotations, and a pool of string,
|
|
number, and identifier literals. Functions are objects that extend scripts
|
|
or native functions with formal parameters, a literal syntax, and a distinct
|
|
primitive type ("function").
|
|
<p>The compiler consists of a recursive-descent parser and a random-logic
|
|
rather than table-driven lexical scanner. Semantic and lexical feedback
|
|
are used to disambiguate hard cases such as missing semicolons, assignable
|
|
expressions ("lvalues" in C parlance), etc. The parser generates bytecode
|
|
as it parses, using fixup lists for downward branches and code buffering
|
|
and rewriting for exceptional cases such as for loops. It attempts no error
|
|
recovery. The interpreter executes the bytecode of top-level scripts, and
|
|
calls itself indirectly to interpret function bodies (which are also scripts).
|
|
All state associated with an interpreter instance is passed through formal
|
|
parameters to the interpreter entry point; most implicit state is collected
|
|
in a type named JSContext. Therefore, all API and almost all other functions
|
|
in JSRef take a JSContext pointer as their first argument.
|
|
<p>The decompiler translates postfix bytecode into infix source by consulting
|
|
a separate byte-sized code, called source notes, to disambiguate bytecodes
|
|
that result from more than one grammatical production.
|
|
<p>The GC is a mark-and-sweep, non-conservative (perfect) collector. It
|
|
can allocate only fixed-sized things -- the current size is two machine
|
|
words. It is used to hold JS object and string descriptors (but not property
|
|
lists or string bytes), and double-precision floating point numbers. It
|
|
runs automatically only when maxbytes (as passed to <tt>JS_Init()</tt>)
|
|
bytes of GC things have been allocated and another thing-allocation request
|
|
is made. JS API users should call <tt>JS_GC()</tt> or <tt>JS_MaybeGC()</tt>
|
|
between script executions or from the branch callback, as often as necessary.
|
|
<p>An important point about the GC's "perfection": you must add roots for
|
|
new objects created by your native methods if you store references to them
|
|
into a non-JS structure in the malloc heap or in static data. Also, if
|
|
you make a new object in a native method, but do not store it through the
|
|
<tt>rval</tt>
|
|
result parameter (see math_abs in the "Using the JS API" section above)
|
|
so that it is in a known root, the object is guaranteed to survive only
|
|
until another new object is created. Either lock the first new object when
|
|
making two in a row, or store it in a root you've added, or store it via
|
|
rval.
|
|
<p>The atom manager consists of a hash table associating strings uniquely
|
|
with scanner/parser information such as keyword type, index in script or
|
|
function literal pool, etc. Atoms play three roles in JSRef: as literals
|
|
referred to by unaligned 16-bit immediate bytecode operands, as unique
|
|
string descriptors for efficient property name hashing, and as members
|
|
of the root GC set for perfect GC. This design therefore requires atoms
|
|
to be manually reference counted, from script literal pools (<tt>JSAtomMap</tt>)
|
|
and object symbol (<tt>JSSymbol</tt>) entry keys.
|
|
<p>Native objects and methods for arrays, booleans, dates, functions, numbers,
|
|
and strings are implemented using the JS API and certain internal interfaces
|
|
used as "fast paths".
|
|
<p>In general, errors are signaled by false or unoverloaded-null return
|
|
values, and are reported using <tt>JS_ReportError()</tt> or one of its
|
|
variants by the lowest level in order to provide the most detail. Client
|
|
code can substitute its own error reporting function and suppress errors,
|
|
or reflect them into Java or some other runtime system as exceptions, GUI
|
|
dialogs, etc..
|
|
<h2>
|
|
File walk-through (BADLY OUT OF DATE!)</h2>
|
|
|
|
<h4>
|
|
jsapi.c, jsapi.h</h4>
|
|
The public API to be used by almost all client code. If your client
|
|
code can't make do with <tt>jsapi.h</tt>, and must reach into a friend
|
|
or private js* file, please let us know so we can extend <tt>jsapi.h</tt>
|
|
to include what you need in a fashion that we can support over the long
|
|
run.
|
|
<h4>
|
|
jspubtd.h, jsprvtd.h</h4>
|
|
These files exist to group struct and scalar typedefs so they can be used
|
|
everywhere without dragging in struct definitions from N different files.
|
|
The <tt>jspubtd.h</tt> file contains public typedefs, and is included by
|
|
<tt>jsapi.h</tt>.
|
|
The <tt>jsprvtd.h</tt> file contains private typedefs and is included by
|
|
various .h files that need type names, but not type sizes or declarations.
|
|
<h4>
|
|
jsdbgapi.c, jsdbgapi.h</h4>
|
|
The Debugging API, still very much under development. Provided so far:
|
|
<ul>
|
|
<li>
|
|
Traps, with which breakpoints, single-stepping, step over, step out, and
|
|
so on can be implemented. The debugger will have to consult jsopcode.def
|
|
on its own to figure out where to plant trap instructions to implement
|
|
functions like step out, but a future jsdbgapi.h will provide convenience
|
|
interfaces to do these things. At most one trap per bytecode can be set.
|
|
When a script (<tt>JSScript</tt>) is destroyed, all traps set in its bytecode
|
|
are cleared.</li>
|
|
|
|
<li>
|
|
Watchpoints, for intercepting set operations on properties and running
|
|
a debugger-supplied function that receives the old value and a pointer
|
|
to the new one, which it can use to modify the new value being set.</li>
|
|
|
|
<li>
|
|
Line number to PC and back mapping functions. The line-to-PC direction
|
|
"rounds" toward the next bytecode generated from a line greater than or
|
|
equal to the input line, and may return the PC of a for-loop update part,
|
|
if given the line number of the loop body's closing brace. Any line after
|
|
the last one in a script or function maps to a PC one byte beyond the last
|
|
bytecode in the script. An example, from perfect.js:</li>
|
|
|
|
<pre><tt>14 function perfect(n)
|
|
15 {
|
|
16 print("The perfect numbers up to " + n + " are:");
|
|
17
|
|
18 // We build sumOfDivisors[i] to hold a string expression for
|
|
19 // the sum of the divisors of i, excluding i itself.
|
|
20 var sumOfDivisors = new ExprArray(n+1,1);
|
|
21 for (var divisor = 2; divisor <= n; divisor++) {
|
|
22 for (var j = divisor + divisor; j <= n; j += divisor) {
|
|
23 sumOfDivisors[j] += " + " + divisor;
|
|
24 }
|
|
25 // At this point everything up to 'divisor' has its sumOfDivisors
|
|
26 // expression calculated, so we can determine whether it's perfect
|
|
27 // already by evaluating.
|
|
28 if (eval(sumOfDivisors[divisor]) == divisor) {
|
|
29 print("" + divisor + " = " + sumOfDivisors[divisor]);
|
|
30 }
|
|
31 }
|
|
32 delete sumOfDivisors;
|
|
33 print("That's all.");
|
|
34 }</tt></pre>
|
|
The line number to PC and back mappings can be tested using the js program
|
|
with the following script:
|
|
<pre><tt> load("perfect.js")
|
|
print(perfect)
|
|
dis(perfect)
|
|
|
|
print()
|
|
for (var ln = 0; ln <= 40; ln++) {
|
|
var pc = line2pc(perfect,ln)
|
|
var ln2 = pc2line(perfect,pc)
|
|
print("\tline " + ln + " => pc " + pc + " => line " + ln2)
|
|
}</tt></pre>
|
|
The result of the for loop over lines 0 to 40 inclusive is:
|
|
<pre><tt> line 0 => pc 0 => line 16
|
|
line 1 => pc 0 => line 16
|
|
line 2 => pc 0 => line 16
|
|
line 3 => pc 0 => line 16
|
|
line 4 => pc 0 => line 16
|
|
line 5 => pc 0 => line 16
|
|
line 6 => pc 0 => line 16
|
|
line 7 => pc 0 => line 16
|
|
line 8 => pc 0 => line 16
|
|
line 9 => pc 0 => line 16
|
|
line 10 => pc 0 => line 16
|
|
line 11 => pc 0 => line 16
|
|
line 12 => pc 0 => line 16
|
|
line 13 => pc 0 => line 16
|
|
line 14 => pc 0 => line 16
|
|
line 15 => pc 0 => line 16
|
|
line 16 => pc 0 => line 16
|
|
line 17 => pc 19 => line 20
|
|
line 18 => pc 19 => line 20
|
|
line 19 => pc 19 => line 20
|
|
line 20 => pc 19 => line 20
|
|
line 21 => pc 36 => line 21
|
|
line 22 => pc 53 => line 22
|
|
line 23 => pc 74 => line 23
|
|
line 24 => pc 92 => line 22
|
|
line 25 => pc 106 => line 28
|
|
line 26 => pc 106 => line 28
|
|
line 27 => pc 106 => line 28
|
|
line 28 => pc 106 => line 28
|
|
line 29 => pc 127 => line 29
|
|
line 30 => pc 154 => line 21
|
|
line 31 => pc 154 => line 21
|
|
line 32 => pc 161 => line 32
|
|
line 33 => pc 172 => line 33
|
|
line 34 => pc 172 => line 33
|
|
line 35 => pc 172 => line 33
|
|
line 36 => pc 172 => line 33
|
|
line 37 => pc 172 => line 33
|
|
line 38 => pc 172 => line 33
|
|
line 39 => pc 172 => line 33
|
|
line 40 => pc 172 => line 33</tt></pre>
|
|
</ul>
|
|
|
|
<h4>
|
|
jsconfig.h</h4>
|
|
Various configuration macros defined as 0 or 1 depending on how <tt>JS_VERSION</tt>
|
|
is defined (as 10 for JavaScript 1.0, 11 for JavaScript 1.1, etc.). Not
|
|
all macros are tested around related code yet. In particular, JS 1.0 support
|
|
is missing from JSRef. JS 1.2 support will appear in a future JSRef release.
|
|
<br>
|
|
<h4>
|
|
js.c</h4>
|
|
The "JS shell", a simple interpreter program that uses the JS API and more
|
|
than a few internal interfaces (some of these internal interfaces could
|
|
be replaced by <tt>jsapi.h</tt> calls). The js program built from this
|
|
source provides a test vehicle for evaluating scripts and calling functions,
|
|
trying out new debugger primitives, etc.
|
|
<h4>
|
|
jsarray.*, jsbool.*, jdsdate.*, jsfun.*, jsmath.*, jsnum.*, jsstr.*</h4>
|
|
These file pairs implement the standard classes and (where they exist)
|
|
their underlying primitive types. They have similar structure, generally
|
|
starting with class definitions and continuing with internal constructors,
|
|
finalizers, and helper functions.
|
|
<h4>
|
|
jsobj.*, jsscope.*</h4>
|
|
These two pairs declare and implement the JS object system. All of the
|
|
following happen here:
|
|
<ul>
|
|
<li>
|
|
creating objects by class and prototype, and finalizing objects;</li>
|
|
|
|
<li>
|
|
defining, looking up, getting, setting, and deleting properties;</li>
|
|
|
|
<li>
|
|
creating and destroying properties and binding names to them.</li>
|
|
</ul>
|
|
The details of an object map (scope) are mostly hidden in <tt>jsscope.[ch]</tt>,
|
|
where scopes start out as linked lists of symbols, and grow after some
|
|
threshold into PR hash tables.
|
|
<h4>
|
|
jsatom.c, jsatom.h</h4>
|
|
The atom manager. Contains well-known string constants, their atoms, the
|
|
global atom hash table and related state, the js_Atomize() function that
|
|
turns a counted string of bytes into an atom, and literal pool (<tt>JSAtomMap</tt>)
|
|
methods.
|
|
<h4>
|
|
jsgc.c, jsgc.h</h4>
|
|
[TBD]
|
|
<h4>
|
|
jsinterp.*, jscntxt.*</h4>
|
|
The bytecode interpreter, and related functions such as Call and AllocStack,
|
|
live in <i>jsinterp.c</i>. The JSContext constructor and destructor are
|
|
factored out into <i>jscntxt.c</i> for minimal linking when the compiler
|
|
part of JS is split from the interpreter part into a separate program.
|
|
<h4>
|
|
jsemit.*, jsopcode.tbl, jsopcode.*, jsparse.*, jsscan.*, jsscript.*</h4>
|
|
Compiler and decompiler modules. The <i>jsopcode.tbl</i> file is a C preprocessor
|
|
source that defines almost everything there is to know about JS bytecodes.
|
|
See its major comment for how to use it. For now, a debugger will use it
|
|
and its dependents such as <i>jsopcode.h</i> directly, but over time we
|
|
intend to extend <i>jsdbgapi.h</i> to hide uninteresting details and provide
|
|
conveniences. The code generator is split across paragraphs of code in
|
|
<i>jsparse.c</i>,
|
|
and the utility methods called on <tt>JSCodeGenerator</tt> appear in <i>jsemit.c</i>.
|
|
Source notes generated by <i>jsparse.c</i> and
|
|
<i>jsemit.c</i> are used
|
|
in <i>jsscript.c</i> to map line number to program counter and back.
|
|
<h4>
|
|
jstypes.h, jslog2.c</h4>
|
|
Fundamental representation types and utility macros. This file alone among
|
|
all .h files in JSRef must be included first by .c files. It is not nested
|
|
in .h files, as other prerequisite .h files generally are, since it is
|
|
also a direct dependency of most .c files and would be over-included if
|
|
nested in addition to being directly included. The one "not-quite-a-macro
|
|
macro" is the <tt>JS_CeilingLog2()</tt> function in <i>jslog2.c</i>.
|
|
<h4>
|
|
jsarena.c, jsarena.h</h4>
|
|
Last-In-First-Out allocation macros that amortize malloc costs and allow
|
|
for en-masse freeing. See the paper mentioned in prarena.h's major comment.
|
|
<h4>
|
|
jsutil.c, jsutil.h</h4>
|
|
The <tt>JS_ASSERT</tt> macro is used throughout JSRef source as a proof
|
|
device to make invariants and preconditions clear to the reader, and to
|
|
hold the line during maintenance and evolution against regressions or violations
|
|
of assumptions that it would be too expensive to test unconditionally at
|
|
run-time. Certain assertions are followed by run-time tests that cope with
|
|
assertion failure, but only where I'm too smart or paranoid to believe
|
|
the assertion will never fail...
|
|
<h4>
|
|
jsclist.h</h4>
|
|
Doubly-linked circular list struct and macros.
|
|
<h4>
|
|
jscpucfg.c</h4>
|
|
This standalone program generates <i>jscpucfg.h</i>, a header file containing
|
|
bytes per word and other constants that depend on CPU architecture and
|
|
C compiler type model. It tries to discover most of these constants by
|
|
running its own experiments on the build host, so if you are cross-compiling,
|
|
beware.
|
|
<h4>
|
|
prdtoa.c, prdtoa.h</h4>
|
|
David Gay's portable double-precision floating point to string conversion
|
|
code, with Permission To Use notice included.
|
|
<h4>
|
|
prhash.c, prhash.h</h4>
|
|
Portable, extensible hash tables. These use multiplicative hash for strength
|
|
reduction over division hash, yet with very good key distribution over
|
|
power of two table sizes. Collisions resolve via chaining, so each entry
|
|
burns a malloc and can fragment the heap.
|
|
<h4>
|
|
prlong.c, prlong.h</h4>
|
|
64-bit integer emulation, and compatible macros that use C's long long
|
|
type where it exists (my last company mapped long long to a 128-bit type,
|
|
but no real architecture does 128-bit ints yet).
|
|
<h4>
|
|
jsosdep.h</h4>
|
|
Annoying OS dependencies rationalized into a few "feature-test" macros
|
|
such as <tt>JS_HAVE_LONG_LONG</tt>.
|
|
<h4>
|
|
jsprf.*</h4>
|
|
Portable, buffer-overrun-resistant sprintf and friends. For no good reason
|
|
save lack of time, the %e, %f, and %g formats cause your system's native
|
|
sprintf, rather than <tt>JS_dtoa()</tt>, to be used. This bug doesn't affect
|
|
JSRef, because it uses its own <tt>JS_dtoa()</tt> call in <i>jsnum.c</i>
|
|
to convert from double to string, but it's a bug that we'll fix later,
|
|
and one you should be aware of if you intend to use a <tt>JS_*printf()</tt>
|
|
function with your own floating type arguments - various vendor sprintf's
|
|
mishandle NaN, +/-Inf, and some even print normal floating values inaccurately.
|
|
<h4>
|
|
prmjtime.c, prmjtime.h</h4>
|
|
Time functions. These interfaces are named in a way that makes local vs.
|
|
universal time confusion likely. Caveat emptor, and we're working on it.
|
|
To make matters worse, Java (and therefore JavaScript) uses "local" time
|
|
numbers (offsets from the epoch) in its Date class.
|
|
|
|
|
|
<h2>
|
|
<a NAME="Resources"></a>Additional Resources (links, API docs, and newsgroups)</h2>
|
|
<ul>
|
|
<li><a href ="http://www.mozilla.org/js/">http://www.mozilla.org/js/</a>
|
|
<li><a href ="http://www.mozilla.org/js/spidermonkey/">http://www.mozilla.org/js/spidermonkey/</a>
|
|
<li><a href ="news://news.mozilla.org/netscape.public.mozilla.jseng">news://news.mozilla.org/netscape.public.mozilla.jseng</a>
|
|
</ul>
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|