Propagating numerous fixes from js/ref
and development branches, including but not limited to: - Preliminary exception handling per ECMA proposal; try, multiple catchblocks, and finally. Catchblocks are of the form catch (v) or catch(v:<guard>), where guard is an optional boolean expression that is evaluated to determine whether the exception is to be caught by that block. - ECMA-proposed 'in' operator; "'foo' in o" or "4 in o" asks if o has property foo or element 4. - Added a new set of defines in jsconfig.h for js 1.4 features-in-progress. (in, instanceof, exception handling.) Default build version is now 1.4. Fixed a few conditional features that had become broken. - Progress towards porting to FreeBSD and Alpha; casts of NaN and friends to int are a little more localized. Not there yet... - New config files to compile on more OSes; various fixes to improve portability. git-svn-id: svn://10.0.0.236/trunk@6907 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
8eb80556d6
commit
b32b6c20e8
@ -46,6 +46,10 @@
|
||||
#include "jsscope.h"
|
||||
#include "jsscript.h"
|
||||
|
||||
#ifdef PERLCONNECT
|
||||
#include "jsperl.h"
|
||||
#endif
|
||||
|
||||
#ifdef LIVECONNECT
|
||||
#include "jsjava.h"
|
||||
#endif
|
||||
@ -55,6 +59,9 @@
|
||||
#ifdef JSDEBUGGER_JAVA_UI
|
||||
#include "jsdjava.h"
|
||||
#endif /* JSDEBUGGER_JAVA_UI */
|
||||
#ifdef JSDEBUGGER_C_UI
|
||||
#include "jsdb.h"
|
||||
#endif /* JSDEBUGGER_C_UI */
|
||||
#endif /* JSDEBUGGER */
|
||||
|
||||
#ifdef XP_UNIX
|
||||
@ -66,6 +73,28 @@
|
||||
|
||||
#ifdef XP_MAC
|
||||
#define isatty(f) 1
|
||||
|
||||
#include <SIOUX.h>
|
||||
#include <MacTypes.h>
|
||||
|
||||
static char* mac_argv[] = { "js", NULL };
|
||||
|
||||
static void initConsole(StringPtr consoleName, const char* startupMessage, int *argc, char** *argv)
|
||||
{
|
||||
SIOUXSettings.autocloseonquit = true;
|
||||
SIOUXSettings.asktosaveonclose = false;
|
||||
/* SIOUXSettings.initializeTB = false;
|
||||
SIOUXSettings.showstatusline = true;*/
|
||||
puts(startupMessage);
|
||||
SIOUXSetTitle(consoleName);
|
||||
|
||||
/* set up a buffer for stderr (otherwise it's a pig). */
|
||||
setvbuf(stderr, malloc(BUFSIZ), _IOLBF, BUFSIZ);
|
||||
|
||||
*argc = 1;
|
||||
*argv = mac_argv;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef JSFILE
|
||||
@ -109,7 +138,7 @@ Process(JSContext *cx, JSObject *obj, char *filename)
|
||||
while((ch = fgetc(ts->file)) != EOF) {
|
||||
if(ch == '\n' || ch == '\r')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ungetc(ch, ts->file);
|
||||
}
|
||||
@ -151,6 +180,82 @@ out:
|
||||
PR_FreeArenaPool(&cx->tempPool);
|
||||
}
|
||||
|
||||
static int
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "%s\n", JS_GetImplementationVersion());
|
||||
fprintf(stderr, "usage: js [-v version] [-f scriptfile] [scriptfile] [scriptarg...]\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int
|
||||
ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
|
||||
{
|
||||
int i;
|
||||
char *filename = NULL;
|
||||
jsint length;
|
||||
jsval *vector;
|
||||
jsval *p;
|
||||
JSObject *argsObj;
|
||||
|
||||
for (i=0; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
switch (argv[i][1]) {
|
||||
case 'v':
|
||||
if (i+1 == argc) {
|
||||
return usage();
|
||||
}
|
||||
JS_SetVersion(cx, atoi(argv[i+1]));
|
||||
i++;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (i+1 == argc) {
|
||||
return usage();
|
||||
}
|
||||
filename = argv[i+1];
|
||||
/* "-f -" means read from stdin */
|
||||
if (filename[0] == '-' && filename[1] == '\0')
|
||||
filename = NULL;
|
||||
Process(cx, obj, filename);
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
return usage();
|
||||
}
|
||||
} else {
|
||||
filename = argv[i++];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
length = argc - i;
|
||||
vector = JS_malloc(cx, length * sizeof(jsval));
|
||||
p = vector;
|
||||
|
||||
if (vector == NULL)
|
||||
return 1;
|
||||
|
||||
while (i < argc) {
|
||||
JSString *str = JS_NewStringCopyZ(cx, argv[i]);
|
||||
if (str == NULL)
|
||||
return 1;
|
||||
*p++ = STRING_TO_JSVAL(str);
|
||||
i++;
|
||||
}
|
||||
argsObj = JS_NewArrayObject(cx, length, vector);
|
||||
if (argsObj == NULL)
|
||||
return 1;
|
||||
|
||||
if (!JS_DefineProperty(cx, obj, "arguments",
|
||||
OBJECT_TO_JSVAL(argsObj), NULL, NULL, 0))
|
||||
return 1;
|
||||
|
||||
Process(cx, obj, filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static JSBool
|
||||
Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
@ -161,6 +266,9 @@ Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
|
||||
|
||||
static JSBool
|
||||
Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
@ -179,13 +287,8 @@ Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
filename = JS_GetStringBytes(str);
|
||||
errno = 0;
|
||||
script = JS_CompileFile(cx, obj, filename);
|
||||
if (!script) {
|
||||
fprintf(stderr, "js: cannot load %s", filename);
|
||||
if (errno)
|
||||
fprintf(stderr, ": %s", strerror(errno));
|
||||
putc('\n', stderr);
|
||||
if (!script)
|
||||
continue;
|
||||
}
|
||||
ok = JS_ExecuteScript(cx, obj, script, &result);
|
||||
JS_DestroyScript(cx, script);
|
||||
if (!ok)
|
||||
@ -391,7 +494,7 @@ PCToLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
#ifdef DEBUG
|
||||
|
||||
static void
|
||||
SingleNote(JSContext *cx, JSFunction *fun )
|
||||
SrcNotes(JSContext *cx, JSFunction *fun )
|
||||
{
|
||||
uintN offset, delta;
|
||||
jssrcnote *notes, *sn;
|
||||
@ -432,6 +535,11 @@ SingleNote(JSContext *cx, JSFunction *fun )
|
||||
atom = js_GetAtom(cx, &fun->script->atomMap, atomIndex);
|
||||
printf(" atom %u (%s)", (uintN)atomIndex, ATOM_BYTES(atom));
|
||||
break;
|
||||
case SRC_CATCH:
|
||||
delta = (uintN) js_GetSrcNoteOffset(sn, 0);
|
||||
if (delta)
|
||||
printf(" guard size %u", delta);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
putchar('\n');
|
||||
@ -450,23 +558,23 @@ Notes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
|
||||
SingleNote(cx, fun);
|
||||
SrcNotes(cx, fun);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ExceptionTable(JSContext *cx, JSFunction *fun)
|
||||
TryNotes(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
JSTryNote *iter = fun->script->trynotes;
|
||||
JSTryNote *tn = fun->script->trynotes;
|
||||
|
||||
if (!iter)
|
||||
if (!tn)
|
||||
return JS_TRUE;
|
||||
printf("\nException table:\nstart\tend\tcatch\tfinally\n");
|
||||
while (iter->start && iter->end) {
|
||||
printf(" %d\t%d\t%d\t%d\n",
|
||||
iter->start, iter->end, iter->catch, iter->finally);
|
||||
iter++;
|
||||
printf("\nException table:\nstart\tend\tcatch\n");
|
||||
while (tn->start && tn->catchStart) {
|
||||
printf(" %d\t%d\t%d\n",
|
||||
tn->start, tn->length, tn->catchStart);
|
||||
tn++;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -492,8 +600,8 @@ Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return JS_FALSE;
|
||||
|
||||
js_Disassemble(cx, fun->script, lines, stdout);
|
||||
SingleNote(cx, fun);
|
||||
ExceptionTable(cx, fun);
|
||||
SrcNotes(cx, fun);
|
||||
TryNotes(cx, fun);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -857,6 +965,7 @@ Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
JSString *str;
|
||||
const char *bytes;
|
||||
|
||||
printf("%s\n", JS_GetImplementationVersion());
|
||||
if (argc == 0) {
|
||||
ShowHelpHeader();
|
||||
for (i = 0; shell_functions[i].name; i++)
|
||||
@ -1046,7 +1155,7 @@ my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
|
||||
fputs("^\n", stderr);
|
||||
}
|
||||
|
||||
#if defined DEBUG && defined XP_UNIX
|
||||
#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
|
||||
static JSBool
|
||||
Exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
@ -1099,7 +1208,7 @@ Exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool
|
||||
global_resolve(JSContext *cx, JSObject *obj, jsval id)
|
||||
{
|
||||
#if defined DEBUG && defined XP_UNIX
|
||||
#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
|
||||
/*
|
||||
* Do this expensive hack only for unoptimized Unix builds, which are not
|
||||
* used for benchmarking.
|
||||
@ -1155,11 +1264,11 @@ static JSClass global_class = {
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int c, i;
|
||||
JSVersion version;
|
||||
JSRuntime *rt;
|
||||
JSContext *cx;
|
||||
JSObject *glob, *it;
|
||||
int result;
|
||||
|
||||
#ifdef XP_OS2
|
||||
/* these streams are normally line buffered on OS/2 and need a \n, *
|
||||
@ -1168,26 +1277,15 @@ main(int argc, char **argv)
|
||||
setbuf(stderr,0);
|
||||
#endif
|
||||
|
||||
#ifdef XP_MAC
|
||||
initConsole("\pJavaScript Shell", "Welcome to js shell.", &argc, &argv);
|
||||
#endif
|
||||
|
||||
version = JSVERSION_DEFAULT;
|
||||
#ifdef XP_UNIX
|
||||
while ((c = getopt(argc, argv, "v:")) != -1) {
|
||||
switch (c) {
|
||||
case 'v':
|
||||
version = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: js [-v version]\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
#else
|
||||
c = -1;
|
||||
#ifndef LIVECONNECT
|
||||
argc--;
|
||||
argv++;
|
||||
#endif
|
||||
|
||||
rt = JS_NewRuntime(8L * 1024L * 1024L);
|
||||
if (!rt)
|
||||
return 1;
|
||||
@ -1214,6 +1312,11 @@ main(int argc, char **argv)
|
||||
if (!JS_DefineProperties(cx, it, its_props))
|
||||
return 1;
|
||||
|
||||
#ifdef PERLCONNECT
|
||||
if (!js_InitPerlClass(cx, glob))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#ifdef LIVECONNECT
|
||||
if (!JSJ_SimpleInit(cx, glob, NULL, getenv("CLASSPATH")))
|
||||
return 1;
|
||||
@ -1240,14 +1343,12 @@ main(int argc, char **argv)
|
||||
* is passed on the cmd line.
|
||||
*/
|
||||
#endif /* JSDEBUGGER_JAVA_UI */
|
||||
#ifdef JSDEBUGGER_C_UI
|
||||
JSDB_InitDebugger(rt, _jsdc, 0);
|
||||
#endif /* JSDEBUGGER_C_UI */
|
||||
#endif /* JSDEBUGGER */
|
||||
|
||||
if (argc > 0) {
|
||||
for (i = 0; i < argc; i++)
|
||||
Process(cx, glob, argv[i]);
|
||||
} else {
|
||||
Process(cx, glob, NULL);
|
||||
}
|
||||
result = ProcessArgs(cx, glob, argv, argc);
|
||||
|
||||
#ifdef JSDEBUGGER
|
||||
if (_jsdc)
|
||||
@ -1257,5 +1358,5 @@ main(int argc, char **argv)
|
||||
JS_DestroyContext(cx);
|
||||
JS_DestroyRuntime(rt);
|
||||
JS_ShutDown();
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -326,6 +326,8 @@ JS_TypeOfValue(JSContext *cx, jsval v)
|
||||
{
|
||||
JSType type;
|
||||
JSObject *obj;
|
||||
JSObjectOps *ops;
|
||||
JSClass *clasp;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
if (JSVAL_IS_VOID(v)) {
|
||||
@ -333,9 +335,11 @@ JS_TypeOfValue(JSContext *cx, jsval v)
|
||||
} else if (JSVAL_IS_OBJECT(v)) {
|
||||
obj = JSVAL_TO_OBJECT(v);
|
||||
if (obj &&
|
||||
(OBJ_IS_NATIVE(obj)
|
||||
? OBJ_GET_CLASS(cx, obj)->call || OBJ_GET_CLASS(cx, obj) == &js_FunctionClass
|
||||
: obj->map->ops->call != 0)) {
|
||||
(ops = obj->map->ops,
|
||||
ops == &js_ObjectOps
|
||||
? (clasp = OBJ_GET_CLASS(cx, obj),
|
||||
clasp->call || clasp == &js_FunctionClass)
|
||||
: ops->call != 0)) {
|
||||
type = JSTYPE_FUNCTION;
|
||||
} else {
|
||||
type = JSTYPE_OBJECT;
|
||||
@ -436,7 +440,7 @@ JS_BeginRequest(JSContext *cx)
|
||||
JS_LOCK_GC(rt);
|
||||
while (rt->gcLevel > 0)
|
||||
JS_AWAIT_GC_DONE(rt);
|
||||
|
||||
|
||||
/* Indicate that a request is running. */
|
||||
rt->requestCount++;
|
||||
JS_UNLOCK_GC(rt);
|
||||
@ -466,7 +470,7 @@ JS_PUBLIC_API(void)
|
||||
JS_YieldRequest(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
PR_ASSERT(rt->requestCount > 0);
|
||||
@ -506,7 +510,7 @@ JS_ResumeRequest(JSContext *cx)
|
||||
JS_LOCK_GC(rt);
|
||||
while (rt->gcLevel > 0)
|
||||
JS_AWAIT_GC_DONE(rt);
|
||||
|
||||
|
||||
/* Indicate that a request is running. */
|
||||
rt->requestCount++;
|
||||
JS_UNLOCK_GC(rt);
|
||||
@ -543,13 +547,13 @@ JS_DestroyContext(JSContext *cx)
|
||||
JS_PUBLIC_API(void*)
|
||||
JS_GetContextPrivate(JSContext *cx)
|
||||
{
|
||||
return cx->pvt;
|
||||
return cx->data;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetContextPrivate(JSContext *cx, void *pvt)
|
||||
JS_SetContextPrivate(JSContext *cx, void *data)
|
||||
{
|
||||
cx->pvt = pvt;
|
||||
cx->data = data;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSRuntime *)
|
||||
@ -597,6 +601,13 @@ JS_SetVersion(JSContext *cx, JSVersion version)
|
||||
return oldVersion;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(const char *)
|
||||
JS_GetImplementationVersion(void)
|
||||
{
|
||||
return "JavaScript-C 1.3 1998 06 30";
|
||||
}
|
||||
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetGlobalObject(JSContext *cx)
|
||||
{
|
||||
@ -672,8 +683,8 @@ JS_malloc(JSContext *cx, size_t nbytes)
|
||||
{
|
||||
void *p;
|
||||
|
||||
#ifdef XP_OS2
|
||||
if (nbytes == 0) /*DSR072897 - Windows allows this, OS/2 doesn't*/
|
||||
#if defined(XP_OS2) || defined(XP_MAC)
|
||||
if (nbytes == 0) /*DSR072897 - Windows allows this, OS/2 & Mac don't*/
|
||||
nbytes = 1;
|
||||
#endif
|
||||
p = malloc(nbytes);
|
||||
@ -962,7 +973,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
/* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
|
||||
if (OBJ_GET_CLASS(cx, ctor) == clasp) {
|
||||
/* XXXMLM - this fails in framesets that are writing over
|
||||
* themselves!
|
||||
* themselves!
|
||||
* PR_ASSERT(!OBJ_GET_PROTO(cx, ctor));
|
||||
*/
|
||||
OBJ_SET_PROTO(cx, ctor, proto);
|
||||
@ -1198,19 +1209,11 @@ JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
|
||||
* so we don't need to GC-alloc constant doubles.
|
||||
*/
|
||||
jsdouble d = cds->dval;
|
||||
jsint i;
|
||||
|
||||
/* We can't do a (jsint) cast to check against JSDOUBLE_IS_INT until we
|
||||
* know that d is not NaN, or we risk a FPE on some platforms.
|
||||
*/
|
||||
if (JSDOUBLE_IS_NaN(d)) {
|
||||
value = DOUBLE_TO_JSVAL(&cds->dval);
|
||||
} else {
|
||||
jsint i = (jsint)d;
|
||||
|
||||
value = (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
|
||||
? INT_TO_JSVAL(i)
|
||||
: DOUBLE_TO_JSVAL(&cds->dval);
|
||||
}
|
||||
value = (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
|
||||
? INT_TO_JSVAL(i)
|
||||
: DOUBLE_TO_JSVAL(&cds->dval);
|
||||
#else
|
||||
ok = js_NewNumberValue(cx, cds->dval, &value);
|
||||
if (!ok)
|
||||
@ -1754,7 +1757,7 @@ JS_Enumerate(JSContext *cx, JSObject *obj)
|
||||
vector[i++] = id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ida;
|
||||
|
||||
error:
|
||||
@ -1780,9 +1783,13 @@ JS_NewFunction(JSContext *cx, JSNative call, uintN nargs, uintN flags,
|
||||
JSAtom *atom;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
atom = js_Atomize(cx, name, strlen(name), 0);
|
||||
if (!atom)
|
||||
return NULL;
|
||||
|
||||
atom = NULL;
|
||||
if (name) {
|
||||
atom = js_Atomize(cx, name, strlen(name), 0);
|
||||
if (!atom)
|
||||
return NULL;
|
||||
}
|
||||
return js_NewFunction(cx, NULL, call, nargs, flags, parent, atom);
|
||||
}
|
||||
|
||||
@ -2529,7 +2536,7 @@ JS_IsExceptionPending(JSContext *cx)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
return (JSBool) cx->fp->exceptPending;
|
||||
return (JSBool) cx->fp->throwing;
|
||||
#else
|
||||
return JS_FALSE;
|
||||
#endif
|
||||
@ -2540,7 +2547,7 @@ JS_GetPendingException(JSContext *cx, jsval *vp)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
if (!cx->fp->exceptPending)
|
||||
if (!cx->fp->throwing)
|
||||
return JS_FALSE;
|
||||
*vp = cx->fp->exception;
|
||||
return JS_TRUE;
|
||||
@ -2554,7 +2561,7 @@ JS_SetPendingException(JSContext *cx, jsval v)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
cx->fp->exceptPending = JS_TRUE;
|
||||
cx->fp->throwing = JS_TRUE;
|
||||
cx->fp->exception = v;
|
||||
#endif
|
||||
}
|
||||
@ -2564,7 +2571,7 @@ JS_ClearPendingException(JSContext *cx)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
#if JS_HAS_EXCEPTIONS
|
||||
cx->fp->exceptPending = JS_FALSE;
|
||||
cx->fp->throwing = JS_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2591,7 +2598,6 @@ JS_ClearContextThread(JSContext *cx)
|
||||
return old;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
@ -2649,3 +2655,4 @@ BOOL CALLBACK __loadds WEP(BOOL fSystemExit)
|
||||
#endif /* !_WIN32 */
|
||||
#endif /* XP_OS2 */
|
||||
#endif /* XP_PC */
|
||||
| ||||