Propagate lots 'o work from the development branch.

Including:

Preliminary work on internationalizing error messages

Preliminary work on exposing runtime errors as catchable exceptions

ECMA-proposed throw and try/catch/finally, with multiple catch clauses
and catchguards

ECMA-proposed in/instanceof operators

IEEE-conformant number to string conversion

Fixes and other good stuff.
This commit is contained in:
mccabe%netscape.com 1998-08-29 00:38:43 +00:00
Родитель 41997f8f65
Коммит 845c56005f
42 изменённых файлов: 4584 добавлений и 3359 удалений

Просмотреть файл

@ -26,8 +26,12 @@ OS_CPUARCH := $(shell uname -m)
ifeq ($(OS_CPUARCH),i86pc) ifeq ($(OS_CPUARCH),i86pc)
OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH) OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH)
else else
ifeq ($(OS_ARCH),AIX)
OS_RELEASE := $(shell uname -v).$(shell uname -r)
else
OS_RELEASE := $(shell uname -r) OS_RELEASE := $(shell uname -r)
endif endif
endif
# Virtually all Linux versions are identical. # Virtually all Linux versions are identical.
# Any distinctions are handled in linux.h # Any distinctions are handled in linux.h
@ -40,6 +44,8 @@ endif
ASFLAGS = ASFLAGS =
DEFINES = DEFINES =
#NS_USE_NATIVE = 1
include config/$(OS_CONFIG).mk include config/$(OS_CONFIG).mk
ifdef BUILD_OPT ifdef BUILD_OPT
@ -83,6 +89,20 @@ CFLAGS = $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \
-DJSFILE $(XCFLAGS) -DJSFILE $(XCFLAGS)
LDFLAGS = -lm $(XLDFLAGS) LDFLAGS = -lm $(XLDFLAGS)
#
# Ask perl what flags it was built with, so we can build js with similar flags
# and link properly. Viva gmake.
#
ifdef PERLCONNECT
DEFINES += -DPERLCONNECT
PERLCFLAGS := $(shell perl -MExtUtils::Embed -e ccopts)
PERLLDFLAGS := $(shell perl -MExtUtils::Embed -e ldopts)
CFLAGS += $(PERLCFLAGS)
LDFLAGS += $(PERLLDFLAGS)
endif
# For purify # For purify
PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \ PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \
$(INCLUDES) $(XCFLAGS) $(INCLUDES) $(XCFLAGS)
@ -114,6 +134,7 @@ JS_HFILES = \
jscntxt.h \ jscntxt.h \
jsdate.h \ jsdate.h \
jsemit.h \ jsemit.h \
jsexn.h \
jsfun.h \ jsfun.h \
jsgc.h \ jsgc.h \
jsinterp.h \ jsinterp.h \
@ -160,6 +181,7 @@ JS_CFILES = \
jsdate.c \ jsdate.c \
jsdbgapi.c \ jsdbgapi.c \
jsemit.c \ jsemit.c \
jsexn.c \
jsfun.c \ jsfun.c \
jsgc.c \ jsgc.c \
jsinterp.c \ jsinterp.c \
@ -177,6 +199,10 @@ JS_CFILES = \
jsxdrapi.c \ jsxdrapi.c \
$(NULL) $(NULL)
ifdef PERLCONNECT
JS_CFILES += jsperl.c
endif
LIB_CFILES = $(PR_CFILES) $(JS_CFILES) LIB_CFILES = $(PR_CFILES) $(JS_CFILES)
LIB_ASFILES := $(wildcard *_$(OS_ARCH).s) LIB_ASFILES := $(wildcard *_$(OS_ARCH).s)
PROG_CFILES = js.c PROG_CFILES = js.c

Просмотреть файл

@ -13,10 +13,12 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# #
# Config stuff for IRIX # Config stuff for IRIX
# #
CPU_ARCH = mips CPU_ARCH = mips
GFX_ARCH = x GFX_ARCH = x

Просмотреть файл

@ -13,8 +13,10 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# #
# Config stuff for IRIX5.3 # Config stuff for IRIX5.3
# #
include config/IRIX.mk include config/IRIX.mk

Просмотреть файл

@ -13,8 +13,10 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# #
# Config stuff for IRIX6.3 # Config stuff for IRIX6.3
# #
include config/IRIX.mk include config/IRIX.mk

Просмотреть файл

@ -13,8 +13,11 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
#
# Config for all versions of Linux # Config for all versions of Linux
#
CC = gcc -Wall -Wno-format CC = gcc -Wall -Wno-format
CCC = g++ -Wall -Wno-format CCC = g++ -Wall -Wno-format

Просмотреть файл

@ -13,6 +13,7 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# #
# Config stuff for SunOS4.1 # Config stuff for SunOS4.1

Просмотреть файл

@ -13,6 +13,7 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# #
# Config stuff for SunOS5.3 # Config stuff for SunOS5.3

Просмотреть файл

@ -13,6 +13,7 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# #
# Config stuff for SunOS5.4 # Config stuff for SunOS5.4

Просмотреть файл

@ -13,15 +13,21 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# #
# Config stuff for SunOS5.5 # Config stuff for SunOS5.5
# #
AS = as
CC = gcc -Wall -Wno-format
CCC = g++ -Wall -Wno-format
#CC = /opt/SUNWspro/SC3.0.1/bin/cc AS = as
ifndef NS_USE_NATIVE
CC = gcc -Wall -Wno-format
CCC = g++ -Wall
else
CC = cc
CCC = CC
endif
RANLIB = echo RANLIB = echo
#.c.o: #.c.o:

Просмотреть файл

@ -13,10 +13,12 @@
# Communications Corporation. Portions created by Netscape are # Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# #
# Config stuff for SunOS5.5 # Config stuff for SunOS5.5
# #
AS = as AS = as
CC = gcc -Wall -Wno-format CC = gcc -Wall -Wno-format
CCC = g++ -Wall -Wno-format CCC = g++ -Wall -Wno-format

Просмотреть файл

@ -14,7 +14,9 @@
# Copyright (C) 1998 Netscape Communications Corporation. All Rights # Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved. # Reserved.
#
# Config for Windows NT using MS Visual C++ (version?) # Config for Windows NT using MS Visual C++ (version?)
#
CC = cl CC = cl

Просмотреть файл

@ -104,6 +104,8 @@ static JSDJContext *_jsdjc;
#endif /* JSDEBUGGER_JAVA_UI */ #endif /* JSDEBUGGER_JAVA_UI */
#endif /* JSDEBUGGER */ #endif /* JSDEBUGGER */
static int reportWarnings;
static void static void
Process(JSContext *cx, JSObject *obj, char *filename) Process(JSContext *cx, JSObject *obj, char *filename)
{ {
@ -161,6 +163,31 @@ Process(JSContext *cx, JSObject *obj, char *filename)
if (str) if (str)
printf("%s\n", JS_GetStringBytes(str)); printf("%s\n", JS_GetStringBytes(str));
} }
if (JS_IsExceptionPending(cx) &&
JS_GetPendingException(cx, &result))
{
/*
* Calling JS_ValueToString could cause another error (and
* throw an associated exception) - so we disable the error
* reporter so nothing gets reported, and we always clear
* the pending exception... which might be different than
* the one we just got in &result.
*/
JSErrorReporter older;
older = JS_SetErrorReporter(cx, NULL);
str = JS_ValueToString(cx, result);
JS_SetErrorReporter(cx, older);
/* XXX non-i18nized strings... */
if (str) {
fprintf(stderr, "Uncaught javascript exception: %s\n",
JS_GetStringBytes(str));
} else {
fprintf(stderr, "Uncaught javascript exception\n");
}
JS_ClearPendingException(cx);
}
JS_DestroyScript(cx, script); JS_DestroyScript(cx, script);
} }
} }
@ -180,7 +207,7 @@ static int
usage(void) usage(void)
{ {
fprintf(stderr, "%s\n", JS_GetImplementationVersion()); fprintf(stderr, "%s\n", JS_GetImplementationVersion());
fprintf(stderr, "usage: js [-v version] [-f scriptfile] [scriptfile] [scriptarg...]\n"); fprintf(stderr, "usage: js [-w] [-v version] [-f scriptfile] [scriptfile] [scriptarg...]\n");
return 2; return 2;
} }
@ -204,6 +231,9 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
JS_SetVersion(cx, atoi(argv[i+1])); JS_SetVersion(cx, atoi(argv[i+1]));
i++; i++;
break; break;
case 'w':
reportWarnings++;
break;
case 'f': case 'f':
if (i+1 == argc) { if (i+1 == argc) {
@ -423,7 +453,7 @@ Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
int32 i; int32 i;
if (argc == 0) { if (argc == 0) {
JS_ReportError(cx, "usage: trap [fun] [pc] expr"); JS_ReportErrorNumber(cx, NULL, JSMSG_TRAP_USAGE);
return JS_FALSE; return JS_FALSE;
} }
argc--; argc--;
@ -457,7 +487,7 @@ LineToPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsbytecode *pc; jsbytecode *pc;
if (argc == 0) { if (argc == 0) {
JS_ReportError(cx, "usage: line2pc [fun] line"); JS_ReportErrorNumber(cx, NULL, JSMSG_LINE2PC_USAGE);
return JS_FALSE; return JS_FALSE;
} }
script = cx->fp->down->script; script = cx->fp->down->script;
@ -619,13 +649,14 @@ DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
return JS_FALSE; return JS_FALSE;
if (!fun->script || !fun->script->filename) { if (!fun->script || !fun->script->filename) {
JS_ReportError(cx, "only works on JS scripts read from files"); JS_ReportErrorNumber(cx, NULL, JSMSG_FILE_SCRIPTS_ONLY);
return JS_FALSE; return JS_FALSE;
} }
file = fopen(fun->script->filename, "r"); file = fopen(fun->script->filename, "r");
if (!file) { if (!file) {
JS_ReportError(cx, "can't open %s: %s", fun->script->filename, strerror(errno)); JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_OPEN,
fun->script->filename, strerror(errno));
return JS_FALSE; return JS_FALSE;
} }
@ -652,9 +683,9 @@ DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
bupline = 0; bupline = 0;
while (line1 < line2) { while (line1 < line2) {
if (!fgets(linebuf, LINE_BUF_LEN, file)) { if (!fgets(linebuf, LINE_BUF_LEN, file)) {
JS_ReportError(cx, "unexpected EOF in %s", JS_ReportErrorNumber(cx, NULL, JSMSG_UNEXPECTED_EOF,
fun->script->filename); fun->script->filename);
goto bail; goto bail;
} }
line1++; line1++;
printf("%s %3u: %s", sep, line1, linebuf); printf("%s %3u: %s", sep, line1, linebuf);
@ -826,7 +857,7 @@ DoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
uintN attrs; uintN attrs;
if (argc != 2) { if (argc != 2) {
JS_ReportError(cx, "usage: doexp obj id"); JS_ReportErrorNumber(cx, NULL, JSMSG_DOEXP_USAGE);
return JS_FALSE; return JS_FALSE;
} }
if (!JS_ValueToObject(cx, argv[0], &obj)) if (!JS_ValueToObject(cx, argv[0], &obj))
@ -1120,24 +1151,52 @@ static void
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{ {
int i, j, k, n; int i, j, k, n;
char *prefix = NULL, *tmp;
fputs("js: ", stderr);
if (!report) { if (!report) {
fprintf(stderr, "%s\n", message); fprintf(stderr, "%s\n", message);
return; return;
} }
if (report->filename) /*
fprintf(stderr, "%s, ", report->filename); * Conditionally ignore reported warnings, and ignore error reports for
if (report->lineno) * which a JavaScript exception has been thrown.
fprintf(stderr, "line %u: ", report->lineno); */
fputs(message, stderr); if ((JSREPORT_IS_WARNING(report->flags) && !reportWarnings) ||
if (!report->linebuf) { JSREPORT_IS_EXCEPTION(report->flags)) {
putc('\n', stderr); return;
return;
} }
fprintf(stderr, ":\n%s\n", report->linebuf); if (report->filename)
prefix = PR_smprintf("%s:", report->filename);
if (report->lineno) {
tmp = prefix;
prefix = PR_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
JS_free(cx, tmp);
}
if (JSREPORT_IS_WARNING(report->flags)) {
tmp = prefix;
prefix = PR_smprintf("%swarning: ", tmp ? tmp : "");
JS_free(cx, tmp);
}
/* embedded newlines -- argh! */
while ((tmp = strchr(message, '\n'))) {
tmp++;
fputs(prefix, stderr);
fwrite(message, 1, tmp - message, stderr);
message = tmp;
}
/* If there were no filename or lineno, the prefix might be empty */
if (prefix) fputs(prefix, stderr);
fputs(message, stderr);
if (!report->linebuf) {
putc('\n', stderr);
goto out;
}
fprintf(stderr, ":\n%s%s\n%s", prefix, report->linebuf, prefix);
n = report->tokenptr - report->linebuf; n = report->tokenptr - report->linebuf;
for (i = j = 0; i < n; i++) { for (i = j = 0; i < n; i++) {
if (report->linebuf[i] == '\t') { if (report->linebuf[i] == '\t') {
@ -1149,6 +1208,8 @@ my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
j++; j++;
} }
fputs("^\n", stderr); fputs("^\n", stderr);
out:
JS_free(cx, prefix);
} }
#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX) #if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
@ -1265,6 +1326,12 @@ main(int argc, char **argv)
JSContext *cx; JSContext *cx;
JSObject *glob, *it; JSObject *glob, *it;
int result; int result;
#ifdef LIVECONNECT
JavaVM *java_vm = NULL;
#endif
#ifdef JSDEBUGGER_JAVA_UI
JNIEnv *java_env;
#endif
#ifdef XP_OS2 #ifdef XP_OS2
/* these streams are normally line buffered on OS/2 and need a \n, * /* these streams are normally line buffered on OS/2 and need a \n, *
@ -1278,10 +1345,10 @@ main(int argc, char **argv)
#endif #endif
version = JSVERSION_DEFAULT; version = JSVERSION_DEFAULT;
#ifndef LIVECONNECT
argc--; argc--;
argv++; argv++;
#endif
rt = JS_NewRuntime(8L * 1024L * 1024L); rt = JS_NewRuntime(8L * 1024L * 1024L);
if (!rt) if (!rt)
return 1; return 1;
@ -1309,15 +1376,10 @@ main(int argc, char **argv)
return 1; return 1;
#ifdef PERLCONNECT #ifdef PERLCONNECT
if (!js_InitPerlClass(cx, glob)) if (!JS_InitPerlClass(cx, glob))
return 1; return 1;
#endif #endif
#ifdef LIVECONNECT
if (!JSJ_SimpleInit(cx, glob, NULL, getenv("CLASSPATH")))
return 1;
#endif
#ifdef JSDEBUGGER #ifdef JSDEBUGGER
/* /*
* XXX A command line option to enable debugging (or not) would be good * XXX A command line option to enable debugging (or not) would be good
@ -1332,7 +1394,9 @@ main(int argc, char **argv)
if (! _jsdjc) if (! _jsdjc)
return 1; return 1;
JSDJ_SetJSDContext(_jsdjc, _jsdc); JSDJ_SetJSDContext(_jsdjc, _jsdc);
JSDJ_CreateJavaVMAndStartDebugger(_jsdjc); java_env = JSDJ_CreateJavaVMAndStartDebugger(_jsdjc);
if (java_env)
(*java_env)->GetJavaVM(java_env, &java_vm);
/* /*
* XXX This would be the place to wait for the debugger to start. * XXX This would be the place to wait for the debugger to start.
* Waiting would be nice in general, but especially when a js file * Waiting would be nice in general, but especially when a js file
@ -1344,6 +1408,11 @@ main(int argc, char **argv)
#endif /* JSDEBUGGER_C_UI */ #endif /* JSDEBUGGER_C_UI */
#endif /* JSDEBUGGER */ #endif /* JSDEBUGGER */
#ifdef LIVECONNECT
if (!JSJ_SimpleInit(cx, glob, java_vm, getenv("CLASSPATH")))
return 1;
#endif
result = ProcessArgs(cx, glob, argv, argc); result = ProcessArgs(cx, glob, argv, argc);
#ifdef JSDEBUGGER #ifdef JSDEBUGGER

Просмотреть файл

@ -36,6 +36,7 @@
#include "jsconfig.h" #include "jsconfig.h"
#include "jsdate.h" #include "jsdate.h"
#include "jsemit.h" #include "jsemit.h"
#include "jsexn.h"
#include "jsfun.h" #include "jsfun.h"
#include "jsgc.h" #include "jsgc.h"
#include "jsinterp.h" #include "jsinterp.h"
@ -113,10 +114,12 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
if (required) { if (required) {
fun = js_ValueToFunction(cx, &argv[-2], JS_FALSE); fun = js_ValueToFunction(cx, &argv[-2], JS_FALSE);
if (fun) { if (fun) {
JS_ReportError(cx, char numBuf[12];
"%s requires more than %u argument%s", sprintf(numBuf, "%u", argc);
JS_GetFunctionName(fun), JS_ReportErrorNumber(cx, NULL, JSMSG_MORE_ARGS_NEEDED,
argc, (argc == 1) ? "" : "s"); JS_GetFunctionName(fun),
numBuf,
(argc == 1) ? "" : "s");
} }
return JS_FALSE; return JS_FALSE;
} }
@ -184,9 +187,12 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
break; break;
case '*': case '*':
break; break;
default: default: {
JS_ReportError(cx, "invalid format character %c", *cp); char charBuf[2] = " ";
charBuf[0] = *cp;
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_CHAR, charBuf);
return JS_FALSE; return JS_FALSE;
}
} }
i++; i++;
} }
@ -239,9 +245,12 @@ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
if (ok) if (ok)
*vp = BOOLEAN_TO_JSVAL(b); *vp = BOOLEAN_TO_JSVAL(b);
break; break;
default: default: {
JS_ReportError(cx, "unknown type %d", (int)type); char numBuf[12];
sprintf(numBuf, "%d", (int)type);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_TYPE, numBuf);
ok = JS_FALSE; ok = JS_FALSE;
}
break; break;
} }
return ok; return ok;
@ -366,6 +375,22 @@ JS_NewRuntime(uint32 maxbytes)
{ {
JSRuntime *rt; JSRuntime *rt;
#ifdef DEBUG
PR_BEGIN_MACRO
/*
* This code asserts that the numbers associated with the error names in
* jsmsg.def are monotonically increasing. It uses values for the error
* names enumerated in jscntxt.c. It's not a compiletime check, but it's
* better than nothing.
*/
int errorNumber = 0;
#define MSG_DEF(name, number, count, exception, format) \
PR_ASSERT(name == errorNumber++);
#include "jsmsg.def"
#undef MSG_DEF
PR_END_MACRO;
#endif /* DEBUG */
if (!js_InitStringGlobals()) if (!js_InitStringGlobals())
return NULL; return NULL;
rt = malloc(sizeof(JSRuntime)); rt = malloc(sizeof(JSRuntime));
@ -663,6 +688,9 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
#endif #endif
#if JS_HAS_SCRIPT_OBJECT #if JS_HAS_SCRIPT_OBJECT
js_InitScriptClass(cx, obj) && js_InitScriptClass(cx, obj) &&
#endif
#if JS_HAS_ERROR_EXCEPTIONS
js_InitExceptionClasses(cx, obj) &&
#endif #endif
js_InitDateClass(cx, obj); js_InitDateClass(cx, obj);
} }
@ -679,7 +707,7 @@ JS_malloc(JSContext *cx, size_t nbytes)
{ {
void *p; void *p;
#if defined(XP_OS2) || defined(XP_MAC) #if defined(XP_OS2) || defined(XP_MAC) || defined(AIX)
if (nbytes == 0) /*DSR072897 - Windows allows this, OS/2 & Mac don't*/ if (nbytes == 0) /*DSR072897 - Windows allows this, OS/2 & Mac don't*/
nbytes = 1; nbytes = 1;
#endif #endif
@ -797,7 +825,7 @@ JS_LockGCThing(JSContext *cx, void *thing)
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
ok = js_LockGCThing(cx, thing); ok = js_LockGCThing(cx, thing);
if (!ok) if (!ok)
JS_ReportError(cx, "can't lock memory"); JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_LOCK);
return ok; return ok;
} }
@ -809,7 +837,7 @@ JS_UnlockGCThing(JSContext *cx, void *thing)
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
ok = js_UnlockGCThing(cx, thing); ok = js_UnlockGCThing(cx, thing);
if (!ok) if (!ok)
JS_ReportError(cx, "can't unlock memory"); JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_UNLOCK);
return ok; return ok;
} }
@ -1015,7 +1043,7 @@ JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
if (argv) { if (argv) {
fun = js_ValueToFunction(cx, &argv[-2], JS_FALSE); fun = js_ValueToFunction(cx, &argv[-2], JS_FALSE);
if (fun) { if (fun) {
JS_ReportError(cx, "%s.prototype.%s called on incompatible %s", JS_ReportErrorNumber(cx, NULL, JSMSG_INCOMPATIBLE_PROTO,
clasp->name, JS_GetFunctionName(fun), clasp->name, JS_GetFunctionName(fun),
OBJ_GET_CLASS(cx, obj)->name); OBJ_GET_CLASS(cx, obj)->name);
} }
@ -1108,7 +1136,7 @@ JS_GetConstructor(JSContext *cx, JSObject *proto)
if (!ok) if (!ok)
return NULL; return NULL;
if (!JSVAL_IS_FUNCTION(cx, cval)) { if (!JSVAL_IS_FUNCTION(cx, cval)) {
JS_ReportError(cx, "%s has no constructor", JS_ReportErrorNumber(cx, NULL, JSMSG_NO_CONSTRUCTOR,
OBJ_GET_CLASS(cx, proto)->name); OBJ_GET_CLASS(cx, proto)->name);
return NULL; return NULL;
} }
@ -1323,7 +1351,7 @@ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
} }
if (obj2 != obj || !OBJ_IS_NATIVE(obj2)) { if (obj2 != obj || !OBJ_IS_NATIVE(obj2)) {
OBJ_DROP_PROPERTY(cx, obj2, prop); OBJ_DROP_PROPERTY(cx, obj2, prop);
JS_ReportError(cx, "can't alias %s to %s in class %s", JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_ALIAS,
alias, name, OBJ_GET_CLASS(cx, obj2)->name); alias, name, OBJ_GET_CLASS(cx, obj2)->name);
return JS_FALSE; return JS_FALSE;
} }
@ -1361,17 +1389,14 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
return rval; return rval;
} }
JS_PUBLIC_API(JSBool) static JSBool
JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name, GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
uintN *attrsp, JSBool *foundp) uintN *attrsp, JSBool *foundp)
{ {
JSAtom *atom;
JSObject *obj2; JSObject *obj2;
JSProperty *prop; JSProperty *prop;
JSBool ok; JSBool ok;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, name, strlen(name), 0);
if (!atom) if (!atom)
return JS_FALSE; return JS_FALSE;
if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop)) if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop))
@ -1389,17 +1414,14 @@ JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
return ok; return ok;
} }
JS_PUBLIC_API(JSBool) static JSBool
JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name, SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
uintN attrs, JSBool *foundp) uintN attrs, JSBool *foundp)
{ {
JSAtom *atom;
JSObject *obj2; JSObject *obj2;
JSProperty *prop; JSProperty *prop;
JSBool ok; JSBool ok;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, name, strlen(name), 0);
if (!atom) if (!atom)
return JS_FALSE; return JS_FALSE;
if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop)) if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &obj2, &prop))
@ -1417,6 +1439,27 @@ JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
return ok; return ok;
} }
JS_PUBLIC_API(JSBool)
JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
uintN *attrsp, JSBool *foundp)
{
CHECK_REQUEST(cx);
return GetPropertyAttributes(cx, obj,
js_Atomize(cx, name, strlen(name), 0),
attrsp, foundp);
}
JS_PUBLIC_API(JSBool)
JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
uintN attrs, JSBool *foundp)
{
CHECK_REQUEST(cx);
return SetPropertyAttributes(cx, obj,
js_Atomize(cx, name, strlen(name), 0),
attrs, foundp);
}
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp) JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
{ {
@ -1488,6 +1531,28 @@ JS_DefineUCProperty(JSContext *cx, JSObject *obj,
attrs, NULL); attrs, NULL);
} }
JS_PUBLIC_API(JSBool)
JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
uintN *attrsp, JSBool *foundp)
{
CHECK_REQUEST(cx);
return GetPropertyAttributes(cx, obj,
js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0),
attrsp, foundp);
}
JS_PUBLIC_API(JSBool)
JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
uintN attrs, JSBool *foundp)
{
CHECK_REQUEST(cx);
return SetPropertyAttributes(cx, obj,
js_AtomizeChars(cx, name, AUTO_NAMELEN(name,namelen), 0),
attrs, foundp);
}
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen, const jschar *name, size_t namelen,
@ -1633,9 +1698,11 @@ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
return JS_FALSE; return JS_FALSE;
} }
if (obj2 != obj || !OBJ_IS_NATIVE(obj2)) { if (obj2 != obj || !OBJ_IS_NATIVE(obj2)) {
char numBuf[12];
OBJ_DROP_PROPERTY(cx, obj2, prop); OBJ_DROP_PROPERTY(cx, obj2, prop);
JS_ReportError(cx, "can't alias %ld to %s in class %s", sprintf(numBuf, "%ld", (long)alias);
(long)alias, name, OBJ_GET_CLASS(cx, obj2)->name); JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_ALIAS,
numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
return JS_FALSE; return JS_FALSE;
} }
scope = (JSScope *) obj->map; scope = (JSScope *) obj->map;
@ -2423,7 +2490,30 @@ JS_ReportError(JSContext *cx, const char *format, ...)
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
va_start(ap, format); va_start(ap, format);
js_ReportErrorVA(cx, format, ap); js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
va_end(ap);
}
JS_PUBLIC_API(void)
JS_ReportErrorNumber(JSContext *cx, JSErrorCallBack errCallBack,
const uintN errorNumber, ...)
{
va_list ap;
CHECK_REQUEST(cx);
va_start(ap, errorNumber);
js_ReportErrorNumberVA(cx, JSREPORT_ERROR,
errCallBack, errorNumber, ap);
va_end(ap);
}
PR_PUBLIC_API(void)
JS_ReportWarning(JSContext *cx, const char *format, ...)
{
va_list ap;
va_start(ap, format);
js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
va_end(ap); va_end(ap);
} }
@ -2464,7 +2554,7 @@ JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
JS_free(cx, chars); JS_free(cx, chars);
return obj; return obj;
#else #else
JS_ReportError(cx, "sorry, regular expression are not supported"); JS_ReportErrorNumber(cx, NULL, JSMSG_NO_REG_EXPS);
return NULL; return NULL;
#endif #endif
} }
@ -2476,7 +2566,7 @@ JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
#if JS_HAS_REGEXPS #if JS_HAS_REGEXPS
return js_NewRegExpObject(cx, chars, length, flags); return js_NewRegExpObject(cx, chars, length, flags);
#else #else
JS_ReportError(cx, "sorry, regular expression are not supported"); JS_ReportErrorNumber(cx, NULL, JSMSG_NO_REG_EXPS);
return NULL; return NULL;
#endif #endif
} }
@ -2528,7 +2618,7 @@ JS_IsExceptionPending(JSContext *cx)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
#if JS_HAS_EXCEPTIONS #if JS_HAS_EXCEPTIONS
return (JSBool) cx->fp->throwing; return (JSBool) cx->throwing;
#else #else
return JS_FALSE; return JS_FALSE;
#endif #endif
@ -2539,9 +2629,9 @@ JS_GetPendingException(JSContext *cx, jsval *vp)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
#if JS_HAS_EXCEPTIONS #if JS_HAS_EXCEPTIONS
if (!cx->fp->throwing) if (!cx->throwing)
return JS_FALSE; return JS_FALSE;
*vp = cx->fp->exception; *vp = cx->exception;
return JS_TRUE; return JS_TRUE;
#else #else
return JS_FALSE; return JS_FALSE;
@ -2553,8 +2643,8 @@ JS_SetPendingException(JSContext *cx, jsval v)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
#if JS_HAS_EXCEPTIONS #if JS_HAS_EXCEPTIONS
cx->fp->throwing = JS_TRUE; cx->throwing = JS_TRUE;
cx->fp->exception = v; cx->exception = v;
#endif #endif
} }
@ -2563,7 +2653,7 @@ JS_ClearPendingException(JSContext *cx)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
#if JS_HAS_EXCEPTIONS #if JS_HAS_EXCEPTIONS
cx->fp->throwing = JS_FALSE; cx->throwing = JS_FALSE;
#endif #endif
} }

Просмотреть файл

@ -605,6 +605,29 @@ JS_DefineUCProperty(JSContext *cx, JSObject *obj,
JSPropertyOp getter, JSPropertyOp setter, JSPropertyOp getter, JSPropertyOp setter,
uintN attrs); uintN attrs);
/*
* Determine the attributes (JSPROP_* flags) of a property on a given object.
*
* If the object does not have a property by that name, *foundp will be
* JS_FALSE and the value of *attrsp is undefined.
*/
extern JS_PUBLIC_API(JSBool)
JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
uintN *attrsp, JSBool *foundp);
/*
* Set the attributes of a property on a given object.
*
* If the object does not have a property by that name, *foundp will be
* JS_FALSE and nothing will be altered.
*/
extern JS_PUBLIC_API(JSBool)
JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
uintN attrs, JSBool *foundp);
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen, const jschar *name, size_t namelen,
@ -904,6 +927,19 @@ JS_CompareStrings(JSString *str1, JSString *str2);
extern JS_PUBLIC_API(void) extern JS_PUBLIC_API(void)
JS_ReportError(JSContext *cx, const char *format, ...); JS_ReportError(JSContext *cx, const char *format, ...);
/*
* As above, but use an errorNumber for the format string
*/
extern JS_PUBLIC_API(void)
JS_ReportErrorNumber(JSContext *cx, JSErrorCallBack errCallBack,
const uintN errorNumber, ...);
/*
* As above, but report a warning instead (JSREPORT_IS_WARNING(report->flags)).
*/
extern PR_PUBLIC_API(void)
JS_ReportWarning(JSContext *cx, const char *format, ...);
/* /*
* Complain when out of memory. * Complain when out of memory.
*/ */
@ -917,8 +953,33 @@ struct JSErrorReport {
const char *tokenptr; /* pointer to error token in linebuf */ const char *tokenptr; /* pointer to error token in linebuf */
const jschar *uclinebuf; /* unicode (original) line buffer */ const jschar *uclinebuf; /* unicode (original) line buffer */
const jschar *uctokenptr;/* unicode (original) token pointer */ const jschar *uctokenptr;/* unicode (original) token pointer */
uintN flags; /* error/warning, etc. */
uintN errorNumber; /* the error number, e.g. see jsmsg.def */
JSString *ucmessage; /* the (default) error message */
JSString **messageArgs; /* arguments for the error message */
}; };
/*
* JSErrorReport flag values.
*/
/* XXX need better classification system */
#define JSREPORT_ERROR 0x0
#define JSREPORT_WARNING 0x1 /* reported via JS_ReportWarning */
/*
* If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
* has been thrown for this runtime error, and the host should ignore it.
* Exception-aware hosts should also check for JS_IsPendingException if
* JS_ExecuteScript returns failure, and signal or propagate the exception, as
* appropriate.
*/
#define JSREPORT_EXCEPTION 0x2
#define JSREPORT_IS_WARNING(flags) (flags & JSREPORT_WARNING)
#define JSREPORT_IS_EXCEPTION(flags) (flags & JSREPORT_EXCEPTION)
extern JS_PUBLIC_API(JSErrorReporter) extern JS_PUBLIC_API(JSErrorReporter)
JS_SetErrorReporter(JSContext *cx, JSErrorReporter er); JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);

Просмотреть файл

@ -495,8 +495,7 @@ array_join(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
static JSBool static JSBool
array_nyi(JSContext *cx, const char *what) array_nyi(JSContext *cx, const char *what)
{ {
JS_ReportError(cx, "sorry, Array.prototype.%s is not yet implemented", JS_ReportErrorNumber(cx, NULL, JSMSG_NO_PROTO, what);
what);
return JS_FALSE; return JS_FALSE;
} }
#endif #endif
@ -699,7 +698,7 @@ array_sort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (argc > 0) { if (argc > 0) {
if (JSVAL_IS_PRIMITIVE(argv[0])) { if (JSVAL_IS_PRIMITIVE(argv[0])) {
JS_ReportError(cx, "invalid Array.prototype.sort argument"); JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_PROTO_SORT);
return JS_FALSE; return JS_FALSE;
} }
fval = argv[0]; fval = argv[0];

Просмотреть файл

@ -605,7 +605,9 @@ js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i)
PR_ASSERT(map->vector && i < map->length); PR_ASSERT(map->vector && i < map->length);
if (!map->vector || i >= map->length) { if (!map->vector || i >= map->length) {
JS_ReportError(cx, "internal error: no index for atom %ld", (long)i); char numBuf[12];
sprintf(numBuf, "%s", (long)i);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_ATOMIC_NUMBER, numBuf);
return NULL; return NULL;
} }
atom = map->vector[i]; atom = map->vector[i];
@ -629,7 +631,7 @@ js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
count = al->count; count = al->count;
if (count >= ATOM_INDEX_LIMIT) { if (count >= ATOM_INDEX_LIMIT) {
JS_ReportError(cx, "too many literals"); JS_ReportErrorNumber(cx, NULL, JSMSG_TOO_MANY_LITERALS);
return JS_FALSE; return JS_FALSE;
} }
vector = JS_malloc(cx, (size_t) count * sizeof *vector); vector = JS_malloc(cx, (size_t) count * sizeof *vector);

Просмотреть файл

@ -32,6 +32,7 @@
#include "jscntxt.h" #include "jscntxt.h"
#include "jsconfig.h" #include "jsconfig.h"
#include "jsdbgapi.h" #include "jsdbgapi.h"
#include "jsexn.h"
#include "jsgc.h" #include "jsgc.h"
#include "jslock.h" #include "jslock.h"
#include "jsobj.h" #include "jsobj.h"
@ -168,7 +169,7 @@ js_ContextIterator(JSRuntime *rt, JSContext **iterp)
} }
void void
js_ReportErrorVA(JSContext *cx, const char *format, va_list ap) js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
{ {
JSStackFrame *fp; JSStackFrame *fp;
JSErrorReport report, *reportp; JSErrorReport report, *reportp;
@ -181,8 +182,10 @@ js_ReportErrorVA(JSContext *cx, const char *format, va_list ap)
/* XXX should fetch line somehow */ /* XXX should fetch line somehow */
report.linebuf = NULL; report.linebuf = NULL;
report.tokenptr = NULL; report.tokenptr = NULL;
report.flags = flags;
reportp = &report; reportp = &report;
} else { } else {
/* XXXshaver still fill out report here for flags? */
reportp = NULL; reportp = NULL;
} }
last = PR_vsmprintf(format, ap); last = PR_vsmprintf(format, ap);
@ -193,6 +196,161 @@ js_ReportErrorVA(JSContext *cx, const char *format, va_list ap)
free(last); free(last);
} }
JSBool
js_ExpandErrorArguments(JSContext *cx, JSErrorCallBack callback,
const uintN errorNumber, char **message,
JSErrorReport *reportp, va_list ap)
/*
The arguments from va_list need to be packaged up into an array and stored
into the report struct.
Then...
if JS_HAS_DFLT_MSG_STRINGS
The format string addressed by the error number may contain operands
identified by the format {N}, where N is a decimal digit. Each of these
is to be replaced by the Nth argument from the va_list. The complete
message is placed into reportp->ucmessage converted to a JSString.
else
reportp->ucmessage is left NULL, to indicate that the installed error
reporter is to use the errorNumber & arguments as it wishes
endif
returns true/false if the expansion succeeds
*/
{
/* make sure this is a legal error number */
if ((errorNumber > 0) && (errorNumber < JSErr_Limit)) {
const JSErrorFormatString *fmtData;
int i;
int argCount;
if (callback)
fmtData = (*callback)(errorNumber);
else
fmtData = &js_ErrorFormatString[errorNumber];
argCount = fmtData->argCount;
if (argCount > 0) {
/*
gather the arguments into a char * array, the
messageArgs field is supposed to be an array of
JSString's and we'll convert them later.
*/
reportp->messageArgs = (JSString **)malloc(sizeof(char *) * argCount);
if (!reportp->messageArgs) return JS_FALSE;
for (i = 0; i < argCount; i++)
reportp->messageArgs[i] = (JSString *) va_arg(ap, char *);
}
#if JS_HAS_DFLT_MSG_STRINGS
/*
parse the error format, substituting the argument X
for {X} in the format
*/
if (argCount > 0) {
const char *fmt;
char *out;
int expandedLength
= strlen(fmtData->format)
- (3 * argCount);
for (i = 0; i < argCount; i++)
expandedLength += strlen((char *)(reportp->messageArgs[i]));
*message = out = malloc(expandedLength + 1);
if (!out) {
if (reportp->messageArgs) free(reportp->messageArgs);
return JS_FALSE;
}
fmt = fmtData->format;
while (*fmt) {
if (*fmt == '{') {
if (isdigit(fmt[1])) {
strcpy(out, (char *)(reportp->messageArgs[JS7_UNDEC(fmt[1])]));
out += strlen((char *)(reportp->messageArgs[JS7_UNDEC(fmt[1])]));
fmt += 3;
}
else
*out++ = *fmt++;
}
else
*out++ = *fmt++;
}
*out = '\0';
/*
Now convert all the arguments to JSString's
*/
for (i = 0; i < argCount; i++) {
reportp->messageArgs[i]
= JS_NewStringCopyZ(cx, (char *)(reportp->messageArgs[i]));
}
}
else
*message = JS_strdup(cx, fmtData->format);
/*
And finally convert the message
*/
reportp->ucmessage = JS_NewStringCopyZ(cx, *message);
#else
/*
If we're not providing the error string we just pass
the arguments array but also need to pass some content
for 'message' though this should never be seen.
*/
*message = JS_strdup(cx, "No Error Message Available");
#endif
}
return JS_TRUE;
}
void
js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallBack callback,
const uintN errorNumber, va_list ap)
{
JSStackFrame *fp;
JSErrorReport report, *reportp;
char *message;
report.messageArgs = NULL;
report.ucmessage = NULL;
message = NULL;
fp = cx->fp;
if (fp && fp->script && fp->pc) {
report.filename = fp->script->filename;
report.lineno = js_PCToLineNumber(fp->script, fp->pc);
}
else {
report.filename = NULL;
report.lineno = 0;
}
/* XXX should fetch line somehow */
report.linebuf = NULL;
report.tokenptr = NULL;
report.flags = flags;
report.errorNumber = errorNumber;
reportp = &report;
if (!js_ExpandErrorArguments(cx, callback, errorNumber,
&message, reportp, ap))
return;
#if JS_HAS_ERROR_EXCEPTIONS
/*
* Check the error report, and set a JavaScript-catchable exception
* if the error is defined to have an associated exception. If an
* exception is thrown, then the JSREPORT_EXCEPTION flag will be set
* on the error report, and exception-aware hosts should ignore it.
*/
js_ErrorToException(cx, reportp);
#endif
js_ReportErrorAgain(cx, message, reportp);
if (message) free(message);
if (report.messageArgs) free(report.messageArgs);
}
JS_FRIEND_API(void) JS_FRIEND_API(void)
js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp) js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
{ {
@ -213,7 +371,7 @@ js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
void void
js_ReportIsNotDefined(JSContext *cx, const char *name) js_ReportIsNotDefined(JSContext *cx, const char *name)
{ {
JS_ReportError(cx, "%s is not defined", name); JS_ReportErrorNumber(cx, NULL, JSMSG_NOT_DEFINED, name);
} }
#if defined DEBUG && defined XP_UNIX #if defined DEBUG && defined XP_UNIX
@ -221,3 +379,14 @@ js_ReportIsNotDefined(JSContext *cx, const char *name)
void js_traceon(JSContext *cx) { cx->tracefp = stderr; } void js_traceon(JSContext *cx) { cx->tracefp = stderr; }
void js_traceoff(JSContext *cx) { cx->tracefp = NULL; } void js_traceoff(JSContext *cx) { cx->tracefp = NULL; }
#endif #endif
#if JS_HAS_DFLT_MSG_STRINGS
JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
#define MSG_DEF(name, number, count, exception, format) \
{ format, count } ,
#include "jsmsg.def"
#undef MSG_DEF
};
#endif

Просмотреть файл

@ -160,6 +160,8 @@ struct JSContext {
jsrefcount requestDepth; jsrefcount requestDepth;
#endif #endif
JSStackFrame *dormantFrameChain; /* dormant frame chains */ JSStackFrame *dormantFrameChain; /* dormant frame chains */
JSPackedBool throwing; /* is there a pending exception? */
jsval exception; /* most-recently-thrown exceptin */
}; };
typedef struct JSInterpreterHooks { typedef struct JSInterpreterHooks {
@ -188,7 +190,14 @@ js_ContextIterator(JSRuntime *rt, JSContext **iterp);
*/ */
#ifdef va_start #ifdef va_start
extern void extern void
js_ReportErrorVA(JSContext *cx, const char *format, va_list ap); js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
extern void
js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallBack callback,
const uintN errorNumber, va_list ap);
extern JS_PUBLIC_API(JSBool)
js_ExpandErrorArguments(JSContext *cx, JSErrorCallBack callback,
const uintN errorNumber, char **message,
JSErrorReport *reportp, va_list ap);
#endif #endif
/* /*
@ -200,6 +209,17 @@ js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
extern void extern void
js_ReportIsNotDefined(JSContext *cx, const char *name); js_ReportIsNotDefined(JSContext *cx, const char *name);
enum JSErrNum {
#define MSG_DEF(name, number, count, exception, format) \
name = number,
#include "jsmsg.def"
#undef MSG_DEF
JSErr_Limit
#undef MSGDEF
};
extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
PR_END_EXTERN_C PR_END_EXTERN_C
#endif /* jscntxt_h___ */ #endif /* jscntxt_h___ */

Просмотреть файл

@ -68,6 +68,7 @@
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */ #define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */ #define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */ #define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
#elif JS_VERSION == 110 #elif JS_VERSION == 110
@ -114,6 +115,7 @@
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */ #define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */ #define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */ #define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
#elif JS_VERSION == 120 #elif JS_VERSION == 120
@ -160,6 +162,7 @@
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */ #define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
#define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */ #define JS_HAS_ARGS_OBJECT 0 /* has minimal ECMA arguments object */
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */ #define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
#elif JS_VERSION == 130 #elif JS_VERSION == 130
@ -206,6 +209,7 @@
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */ #define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof Object */
#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */ #define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ #define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
#define JS_HAS_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
#elif JS_VERSION == 140 #elif JS_VERSION == 140
@ -252,6 +256,9 @@
#define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof Object */ #define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof Object */
#define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */ #define JS_HAS_ARGS_OBJECT 1 /* has minimal ECMA arguments object */
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */ #define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
#define JS_HAS_ERROR_EXCEPTIONS 1 /* rt errors reflected as exceptions */
#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */
#else #else

Просмотреть файл

@ -345,8 +345,8 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
JSWatchPoint *wp; JSWatchPoint *wp;
if (!OBJ_IS_NATIVE(obj)) { if (!OBJ_IS_NATIVE(obj)) {
JS_ReportError(cx, "can't watch non-native objects of class %s", JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_WATCH,
OBJ_GET_CLASS(cx, obj)->name); OBJ_GET_CLASS(cx, obj)->name);
return JS_FALSE; return JS_FALSE;
} }
@ -580,12 +580,36 @@ JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
return fp->fun && fp->fun->call; return fp->fun && fp->fun->call;
} }
/* this is deprecated, use JS_GetFrameScopeChain instead */
JS_PUBLIC_API(JSObject *) JS_PUBLIC_API(JSObject *)
JS_GetFrameObject(JSContext *cx, JSStackFrame *fp) JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
{ {
return fp->scopeChain; return fp->scopeChain;
} }
JS_PUBLIC_API(JSObject *)
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
{
/* Force creation of argument and call objects if not yet created */
JS_GetFrameCallObject(cx, fp);
return fp->scopeChain;
}
JS_PUBLIC_API(JSObject *)
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
{
if (! fp->fun)
return NULL;
/* Force creation of argument object if not yet created */
js_GetArgsObject(cx, fp);
#if JS_HAS_CALL_OBJECT
return js_GetCallObject(cx, fp, NULL, NULL);
#else
return NULL;
#endif /* JS_HAS_CALL_OBJECT */
}
JS_PUBLIC_API(JSObject *) JS_PUBLIC_API(JSObject *)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp) JS_GetFrameThis(JSContext *cx, JSStackFrame *fp)
{ {
@ -680,12 +704,22 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
sym = sprop->symbols; sym = sprop->symbols;
pd->id = sym ? js_IdToValue(sym_id(sym)) : JSVAL_VOID; pd->id = sym ? js_IdToValue(sym_id(sym)) : JSVAL_VOID;
pd->value = OBJ_GET_SLOT(cx, obj, sprop->slot); if (!sym || !js_GetProperty(cx, obj, sym_id(sym), &pd->value))
pd->value = OBJ_GET_SLOT(cx, obj, sprop->slot);
pd->flags = ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0) pd->flags = ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
| ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0) | ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0)
| ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0) | ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0)
#if JS_HAS_CALL_OBJECT
| ((sprop->getter == js_GetCallVariable) ? JSPD_VARIABLE : 0)
#endif /* JS_HAS_CALL_OBJECT */
| ((sprop->getter == js_GetArgument) ? JSPD_ARGUMENT : 0) | ((sprop->getter == js_GetArgument) ? JSPD_ARGUMENT : 0)
| ((sprop->getter == js_GetLocalVariable) ? JSPD_VARIABLE : 0); | ((sprop->getter == js_GetLocalVariable) ? JSPD_VARIABLE : 0);
#if JS_HAS_CALL_OBJECT
/* for Call Object 'real' getter isn't passed in to us */
if (OBJ_GET_CLASS(cx, obj) == &js_CallClass &&
OBJ_GET_CLASS(cx, obj)->getProperty == sprop->getter)
pd->flags |= JSPD_ARGUMENT;
#endif /* JS_HAS_CALL_OBJECT */
pd->spare = 0; pd->spare = 0;
pd->slot = (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE)) pd->slot = (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE))
? JSVAL_TO_INT(sprop->id) ? JSVAL_TO_INT(sprop->id)
@ -706,11 +740,16 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
uint32 i, n; uint32 i, n;
JSPropertyDesc *pd; JSPropertyDesc *pd;
JSScopeProperty *sprop; JSScopeProperty *sprop;
jsval state;
jsid num_prop;
if (!OBJ_GET_CLASS(cx, obj)->enumerate(cx, obj)) if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, &num_prop))
return JS_FALSE; return JS_FALSE;
scope = (JSScope *)obj->map; scope = (JSScope *)obj->map;
if (!scope->props) { /* have no props, or object's scope has not mutated from that of proto */
if (!scope->props ||
(OBJ_GET_PROTO(cx,obj) &&
scope == (JSScope *)(OBJ_GET_PROTO(cx,obj)->map))) {
pda->length = 0; pda->length = 0;
pda->array = NULL; pda->array = NULL;
return JS_TRUE; return JS_TRUE;

Просмотреть файл

@ -130,9 +130,16 @@ JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
extern JS_PUBLIC_API(void *) extern JS_PUBLIC_API(void *)
JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp); JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp);
/* this is deprecated, use JS_GetFrameScopeChain instead */
extern JS_PUBLIC_API(JSObject *) extern JS_PUBLIC_API(JSObject *)
JS_GetFrameObject(JSContext *cx, JSStackFrame *fp); JS_GetFrameObject(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSObject *)
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSObject *)
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(JSObject *) extern JS_PUBLIC_API(JSObject *)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp); JS_GetFrameThis(JSContext *cx, JSStackFrame *fp);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

212
js/ref/jsexn.c Normal file
Просмотреть файл

@ -0,0 +1,212 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* JS standard exception implementation.
*/
#include "jsstddef.h"
#include "prtypes.h"
#include "prassert.h"
#include "jsapi.h"
#include "jscntxt.h"
#include "jsconfig.h"
#include "jsexn.h"
#if JS_HAS_ERROR_EXCEPTIONS
#if !JS_HAS_EXCEPTIONS
# error "JS_HAS_EXCEPTIONS must be defined to use JS_HAS_ERROR_EXCEPTIONS"
#endif
/* Maybe #define RANDOM_CLASS(name, prototype) 4 here? */
struct JSExnSpec {
int protoIndex;
JSClass theclass;
};
/* This must be kept in synch with the exceptions array */
typedef enum JSExnType {
JSEXN_NONE = -1,
JSEXN_EXCEPTION,
JSEXN_ERR,
JSEXN_INTERNALERR,
JSEXN_SYNTAXERR,
JSEXN_REFERENCEERR,
JSEXN_CALLERR,
JSEXN_TARGETERR,
JSEXN_CONSTRUCTORERR,
JSEXN_CONVERSIONERR,
JSEXN_TOOBJECTERR,
JSEXN_TOPRIMITIVEERR,
JSEXN_DEFAULTVALUEERR,
JSEXN_ARRAYERR,
JSEXN_LIMIT
} JSExnType;
#define FLAGS JSCLASS_HAS_PRIVATE
static struct JSExnSpec exceptions[] = {
{ JSEXN_NONE, /* No proto? */ {
"Exception", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_EXCEPTION, {
"Error", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_ERR, {
"InternalError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_ERR, {
"SyntaxError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_ERR, {
"ReferenceError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_ERR, {
"CallError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_CALLERR, {
"TargetError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_ERR, {
"ConstructorError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_ERR, {
"ConversionError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_CONVERSIONERR, {
"ToObjectError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_CONVERSIONERR, {
"ToPrimitiveError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_CONVERSIONERR, {
"DefaultValueError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{ JSEXN_ERR, {
"ArrayError", FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
} },
{0}
};
static JSBool
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsval bval;
bval = JSVAL_FALSE;
if (!cx->fp->constructing) {
*rval = bval;
return JS_TRUE;
}
return JS_TRUE;
}
static JSFunctionSpec exception_methods[] = {
{0}
};
JSObject *
js_InitExceptionClasses(JSContext *cx, JSObject *obj)
{
JSObject *protos[JSEXN_LIMIT];
int i;
for (i = 0; exceptions[i].theclass.name != 0; i++) {
int protoidx = exceptions[i].protoIndex;
protos[i] = JS_InitClass(cx, obj,
((protoidx >= 0) ? protos[protoidx] : NULL),
&(exceptions[i].theclass),
Exception, 1,
NULL,
exception_methods,
NULL,
NULL);
}
/*
* JS_InitClass magically replaces a null prototype with Object.prototype,
* so we need to explicitly assign to the proto slot to get null.
*
* Temporarily disabled until I do toString for Exception.
*/
/* protos[0]->slots[JSSLOT_PROTO] = JSVAL_NULL; */
return protos[0];
}
static JSExnType errorToException[] = {
#define MSG_DEF(name, number, count, exception, format) \
exception,
#include "jsmsg.def"
#undef MSG_DEF
};
JSBool
js_ErrorToException(JSContext *cx, JSErrorReport *reportp) {
uintN errorNumber;
JSObject *errobj;
JSExnType exn;
PR_ASSERT(reportp);
errorNumber = reportp->errorNumber;
exn = errorToException[errorNumber];
PR_ASSERT(exn < JSEXN_LIMIT);
if (exn > JSEXN_NONE) {
errobj = js_ConstructObject(cx,
&(exceptions[exn].theclass),
NULL, NULL);
JS_SetPendingException(cx, OBJECT_TO_JSVAL(errobj));
reportp->flags |= JSREPORT_EXCEPTION;
return JS_TRUE;
}
return JS_FALSE;
}
#endif /* JS_HAS_ERROR_EXCEPTIONS */

47
js/ref/jsexn.h Normal file
Просмотреть файл

@ -0,0 +1,47 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* JS runtime exception classes.
*/
#ifndef jsexn_h___
#define jsexn_h___
PR_BEGIN_EXTERN_C
/*
* Initialize exception object hierarchy.
*/
extern JSObject *
js_InitExceptionClasses(JSContext *cx, JSObject *obj);
/*
* Given a JSErrorReport, check to see if there is an exception associated
* with the error number. If there is, then create an appropriate exception
* object, set it as the pending exception, and set the JSREPORT_EXCEPTION
* flag on the error report. Exception-aware host error reporters will
* know to ignore error reports so flagged. Returns JS_TRUE if an associated
* exception is found, JS_FALSE if none.
*/
extern JSBool
js_ErrorToException(JSContext *cx, JSErrorReport *reportp);
PR_END_EXTERN_C
#endif /* jsexn_h___ */

Просмотреть файл

@ -891,7 +891,7 @@ fun_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
_readonly: _readonly:
if (JSVERSION_IS_ECMA(cx->version)) if (JSVERSION_IS_ECMA(cx->version))
return fun_getProperty(cx, obj, id, vp); return fun_getProperty(cx, obj, id, vp);
JS_ReportError(cx, "%s is read-only", js_arguments_str); JS_ReportErrorNumber(cx, NULL, JSMSG_READ_ONLY, js_arguments_str);
return JS_FALSE; return JS_FALSE;
} }
@ -1130,21 +1130,36 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
#if JS_HAS_INSTANCEOF #if JS_HAS_INSTANCEOF
/*
* [[HasInstance]] internal method for Function objects - takes the .prototype
* property of its target, and walks the prototype chain of v (if v is an
* object,) returning true if .prototype is found.
*/
static JSBool static JSBool
fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp) fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
{ {
jsval pval; jsval pval;
JSString *str;
if (!OBJ_GET_PROPERTY(cx, obj, if (!OBJ_GET_PROPERTY(cx, obj,
(jsid)cx->runtime->atomState.classPrototypeAtom, (jsid)cx->runtime->atomState.classPrototypeAtom,
&pval)) { &pval)) {
return JS_FALSE; return JS_FALSE;
} }
if (JSVAL_IS_PRIMITIVE(pval)) { if (!JSVAL_IS_PRIMITIVE(pval))
*bp = JS_FALSE; return js_IsDelegate(cx, JSVAL_TO_OBJECT(pval), v, bp);
return JS_TRUE;
/*
* Throw a runtime error if instanceof is called on a function
* that has a non-Object as its .prototype value.
*/
str = js_DecompileValueGenerator(cx, OBJECT_TO_JSVAL(obj), NULL);
if (str) {
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_PROTOTYPE,
JS_GetStringBytes(str));
} }
return js_IsDelegate(cx, JSVAL_TO_OBJECT(pval), v, bp); return JS_FALSE;
} }
#else /* !JS_HAS_INSTANCEOF */ #else /* !JS_HAS_INSTANCEOF */
@ -1446,7 +1461,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
* TOK_ERROR. * TOK_ERROR.
*/ */
if (tt != TOK_NAME) { if (tt != TOK_NAME) {
JS_ReportError(cx, "missing formal parameter"); JS_ReportErrorNumber(cx, NULL, JSMSG_NO_FORMAL);
goto badargs; goto badargs;
} }
/* Get the atom corresponding to the name from the tokenstream; /* Get the atom corresponding to the name from the tokenstream;
@ -1461,8 +1476,8 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
#ifdef CHECK_ARGUMENT_HIDING #ifdef CHECK_ARGUMENT_HIDING
PR_ASSERT(sprop->getter == js_GetArgument); PR_ASSERT(sprop->getter == js_GetArgument);
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop); OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
JS_ReportError(cx, "duplicate formal argument %s", JS_ReportErrorNumber(cx, NULL, JSMSG_SAME_FORMAL,
ATOM_BYTES(atom)); ATOM_BYTES(atom));
goto badargs; goto badargs;
#else #else
/* A duplicate parameter name. We create a dummy symbol /* A duplicate parameter name. We create a dummy symbol
@ -1714,7 +1729,7 @@ js_ReportIsNotFunction(JSContext *cx, jsval *vp, JSBool constructing)
if (fp) if (fp)
fp->sp = sp; fp->sp = sp;
if (str) { if (str) {
JS_ReportError(cx, "%s is not a %s", JS_ReportErrorNumber(cx, NULL, JSMSG_DENY,
JS_GetStringBytes(str), JS_GetStringBytes(str),
constructing ? "constructor" : "function"); constructing ? "constructor" : "function");
} }

Просмотреть файл

@ -42,7 +42,8 @@ struct JSFunction {
extern JSClass js_ArgumentsClass; extern JSClass js_ArgumentsClass;
extern JSClass js_CallClass; extern JSClass js_CallClass;
extern JSClass js_ClosureClass; extern JSClass js_ClosureClass;
extern JSClass js_FunctionClass; /* JS_FRIEND_DATA so that JSVAL_IS_FUNCTION is callable from outside */
extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
/* /*
* NB: jsapi.h and jsobj.h must be included before any call to this macro. * NB: jsapi.h and jsobj.h must be included before any call to this macro.

Просмотреть файл

@ -583,8 +583,18 @@ gc_root_marker(PRHashEntry *he, intN i, void *arg)
{ {
void **rp = (void **)he->key; void **rp = (void **)he->key;
if (*rp) if (*rp) {
#ifdef DEBUG
PRArena *a;
JSRuntime *rt = (JSRuntime *)arg;
for (a = rt->gcArenaPool.first.next; a; a = a->next) {
PR_ASSERT(!rp ||
(*rp >= (void *)a->base && *rp <= (void *)a->avail));
}
#endif
GC_MARK(arg, *rp, he->value ? he->value : "root", NULL); GC_MARK(arg, *rp, he->value ? he->value : "root", NULL);
}
return HT_ENUMERATE_NEXT; return HT_ENUMERATE_NEXT;
} }

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -48,8 +48,6 @@ struct JSStackFrame {
JSPackedBool constructing; /* true if called via new operator */ JSPackedBool constructing; /* true if called via new operator */
uint8 overrides; /* bit-set of overridden Call properties */ uint8 overrides; /* bit-set of overridden Call properties */
JSPackedBool debugging; /* true if for JS_EvaluateInStackFrame */ JSPackedBool debugging; /* true if for JS_EvaluateInStackFrame */
JSPackedBool throwing; /* is there a pending exception? */
jsval exception; /* most-recently-thrown exceptin */
JSStackFrame *dormantNext; /* next dormant frame chain */ JSStackFrame *dormantNext; /* next dormant frame chain */
}; };

198
js/ref/jsmsg.def Normal file
Просмотреть файл

@ -0,0 +1,198 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
This is the JavaScript error message file.
The format for each JS error message is:
MSG_DEF(<SYMBOLIC_NAME>, <ERROR_NUMBER>, <ARGUMENT_COUNT>, <EXCEPTION_NAME>,
<FORMAT_STRING>)
where ;
<SYMBOLIC_NAME> is a legal C identifer that will be used in the
JS engine source.
<ERROR_NUMBER> is an unique integral value identifying this error.
<ARGUMENT_COUNT> is an integer literal specifying the total number of
replaceable arguments in the following format string.
<EXCEPTION_NAME> is an exception index from the enum in jsexn.c;
JSEXN_NONE for none. The given exception index will be raised by the
engine when the corresponding error occurs.
<FORMAT_STRING> is a string literal, optionally containing sequences
{X} where X is an integer representing the argument number that will
be replaced with a string value when the error is reported.
e.g.
MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 73, JSEXN_NONE, 2,
"{0} is not a member of the {1} family")
can be used :
JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
to report :
"Rhino is not a member of the Monkey family"
*/
MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
MSG_DEF(JSMSG_NOT_DEFINED, 1, 1, JSEXN_NONE, "{0} is not defined")
MSG_DEF(JSMSG_NOT_A_FUNCTION, 2, 1, JSEXN_NONE, "{0} is not a function")
MSG_DEF(JSMSG_NO_REG_EXPS, 3, 1, JSEXN_NONE, "sorry, regular expression are not supported")
MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 4, 3, JSEXN_NONE, "{0} requires more than {1} argument{2}")
MSG_DEF(JSMSG_BAD_CHAR, 5, 1, JSEXN_NONE, "invalid format character {0}")
MSG_DEF(JSMSG_BAD_TYPE, 6, 1, JSEXN_NONE, "unknown type {0}")
MSG_DEF(JSMSG_CANT_LOCK, 7, 0, JSEXN_NONE, "can't lock memory")
MSG_DEF(JSMSG_CANT_UNLOCK, 8, 0, JSEXN_NONE, "can't unlock memory")
MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 9, 3, JSEXN_NONE, "{0}.prototype.{1} called on incompatible {2}")
MSG_DEF(JSMSG_NO_CONSTRUCTOR, 10, 1, JSEXN_NONE, "{0} has no constructor")
MSG_DEF(JSMSG_CANT_ALIAS, 11, 3, JSEXN_NONE, "can't alias {0} to {1} in class {2}")
MSG_DEF(JSMSG_NO_PROTO, 12, 1, JSEXN_NONE, "sorry, Array.prototype.{0} is not yet implemented")
MSG_DEF(JSMSG_BAD_PROTO_SORT, 13, 0, JSEXN_NONE, "invalid Array.prototype.sort argument")
MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 14, 1, JSEXN_NONE, "internal error: no index for atom {0}")
MSG_DEF(JSMSG_TOO_MANY_LITERALS, 15, 0, JSEXN_NONE, "too many literals")
MSG_DEF(JSMSG_CANT_WATCH, 16, 1, JSEXN_NONE, "can't watch non-native objects of class {0}")
MSG_DEF(JSMSG_STACK_UNDERFLOW, 17, 2, JSEXN_NONE, "internal error compiling {0}: stack underflow at pc {1}")
MSG_DEF(JSMSG_NEED_DIET, 18, 1, JSEXN_NONE, "{0} too large")
MSG_DEF(JSMSG_BAD_CASE, 19, 2, JSEXN_NONE, "{0}, line {1}: invalid case expression")
MSG_DEF(JSMSG_READ_ONLY, 20, 1, JSEXN_NONE, "{0} is read-only")
MSG_DEF(JSMSG_NO_FORMAL, 21, 0, JSEXN_NONE, "missing formal parameter")
MSG_DEF(JSMSG_SAME_FORMAL, 22, 1, JSEXN_NONE, "duplicate formal argument {0}")
MSG_DEF(JSMSG_DENY, 23, 2, JSEXN_NONE, "{0} is not a {1}")
MSG_DEF(JSMSG_STACK_OVERFLOW, 24, 1, JSEXN_NONE, "stack overflow in {0}")
MSG_DEF(JSMSG_NOT_EXPORTED, 25, 1, JSEXN_NONE, "{0} is not exported")
MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_NONE, "too much recursion")
MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 0, JSEXN_NONE, "target of 'in' operator must be an object")
MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_NONE, "invalid new expression result {0}")
MSG_DEF(JSMSG_BAD_SHARP_DEF, 29, 1, JSEXN_NONE, "invalid sharp variable definition #{0}=")
MSG_DEF(JSMSG_BAD_SHARP_USE, 30, 1, JSEXN_NONE, "invalid sharp variable use #{0}#")
MSG_DEF(JSMSG_BAD_OPERANDS, 31, 2, JSEXN_NONE, "invalid {0} operand {1}")
MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_NONE, "unimplemented JavaScript bytecode {0}")
MSG_DEF(JSMSG_BAD_RADIX, 33, 1, JSEXN_NONE, "illegal radix {0}")
MSG_DEF(JSMSG_NAN, 34, 1, JSEXN_NONE, "{0} is not a number")
MSG_DEF(JSMSG_CANT_CONVERT, 35, 1, JSEXN_NONE, "can't convert {0} to an integer")
MSG_DEF(JSMSG_CYCLIC_VALUE, 36, 1, JSEXN_NONE, "cyclic {0} value")
MSG_DEF(JSMSG_PERMANENT, 37, 1, JSEXN_NONE, "{0} is permanent")
MSG_DEF(JSMSG_CANT_CONVERT_TO, 38, 2, JSEXN_NONE, "can't convert {0} to {1}")
MSG_DEF(JSMSG_NO_PROPERTIES, 39, 1, JSEXN_NONE, "{0} has no properties")
MSG_DEF(JSMSG_CANT_FIND_CLASS, 40, 1, JSEXN_NONE, "can't find class id {0}")
MSG_DEF(JSMSG_CANT_XDR_CLASS, 41, 1, JSEXN_NONE, "can't XDR class {0}")
MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 42, 2, JSEXN_NONE, "bytecode {0} too large (limit {1})")
MSG_DEF(JSMSG_UNKNOWN_FORMAT, 43, 1, JSEXN_NONE, "unknown bytecode format {0}")
MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 44, 0, JSEXN_NONE, "too many constructor arguments")
MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 45, 0, JSEXN_NONE, "too many function arguments")
MSG_DEF(JSMSG_BAD_QUANTIFIER, 46, 1, JSEXN_NONE, "invalid quantifier {0}")
MSG_DEF(JSMSG_MIN_TOO_BIG, 47, 1, JSEXN_NONE, "overlarge minimum {0}")
MSG_DEF(JSMSG_MAX_TOO_BIG, 48, 1, JSEXN_NONE, "overlarge maximum {0}")
MSG_DEF(JSMSG_OUT_OF_ORDER, 49, 1, JSEXN_NONE, "maximum {0} less than minimum")
MSG_DEF(JSMSG_ZERO_QUANTIFIER, 50, 1, JSEXN_NONE, "zero quantifier {0}")
MSG_DEF(JSMSG_UNTERM_QUANTIFIER, 51, 1, JSEXN_NONE, "unterminated quantifier {0}")
MSG_DEF(JSMSG_EMPTY_BEFORE_STAR, 52, 0, JSEXN_NONE, "regular expression before * could be empty")
MSG_DEF(JSMSG_EMPTY_BEFORE_PLUS, 53, 0, JSEXN_NONE, "regular expression before + could be empty")
MSG_DEF(JSMSG_MISSING_PAREN, 54, 1, JSEXN_NONE, "unterminated parenthetical {0}")
MSG_DEF(JSMSG_UNTERM_CLASS, 55, 1, JSEXN_NONE, "unterminated character class {0}")
MSG_DEF(JSMSG_TRAILING_SLASH, 56, 0, JSEXN_NONE, "trailing \\ in regular expression")
MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_NONE, "invalid range in character class")
MSG_DEF(JSMSG_BAD_FLAG, 58, 1, JSEXN_NONE, "invalid regular expression flag {0}")
MSG_DEF(JSMSG_NO_INPUT, 59, 3, JSEXN_NONE, "no input for /{0}/{1}{2}")
MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_NONE, "can't open {0}: {1}")
MSG_DEF(JSMSG_BAD_STRING_MASK, 61, 1, JSEXN_NONE, "invalid string escape mask {0}")
MSG_DEF(JSMSG_NO_STRING_PROTO, 62, 1, JSEXN_NONE, "sorry, String.prototype.{0} is not yet implemented")
MSG_DEF(JSMSG_END_OF_DATA, 63, 0, JSEXN_NONE, "unexpected end of data")
MSG_DEF(JSMSG_SEEK_BEYOND_START, 64, 0, JSEXN_NONE, "illegal seek beyond start")
MSG_DEF(JSMSG_SEEK_BEYOND_END, 65, 0, JSEXN_NONE, "illegal seek beyond end")
MSG_DEF(JSMSG_END_SEEK, 66, 0, JSEXN_NONE, "illegal end-based seek")
MSG_DEF(JSMSG_WHITHER_WHENCE, 67, 1, JSEXN_NONE, "unknown seek whence: {0}")
MSG_DEF(JSMSG_BAD_JVAL_TYPE, 68, 1, JSEXN_NONE, "unknown jsval type {0} for XDR")
MSG_DEF(JSMSG_TRAP_USAGE, 69, 0, JSEXN_NONE, "usage: trap [fun] [pc] expr")
MSG_DEF(JSMSG_LINE2PC_USAGE, 70, 0, JSEXN_NONE, "usage: line2pc [fun] line")
MSG_DEF(JSMSG_FILE_SCRIPTS_ONLY, 71, 0, JSEXN_NONE, "only works on JS scripts read from files")
MSG_DEF(JSMSG_UNEXPECTED_EOF, 72, 1, JSEXN_NONE, "unexpected EOF in {0}")
MSG_DEF(JSMSG_DOEXP_USAGE, 73, 0, JSEXN_NONE, "usage: doexp obj id")
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 74, 0, JSEXN_NONE, "missing ( before formal parameters")
MSG_DEF(JSMSG_MISSING_FORMAL, 75, 0, JSEXN_NONE, "missing formal parameter")
MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 76, 0, JSEXN_NONE, "missing ) after formal parameters")
MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 77, 0, JSEXN_NONE, "missing { before function body")
MSG_DEF(JSMSG_CURLY_AFTER_BODY, 78, 0, JSEXN_NONE, "missing } after function body")
MSG_DEF(JSMSG_PAREN_BEFORE_COND, 79, 0, JSEXN_NONE, "missing ( before condition")
MSG_DEF(JSMSG_PAREN_AFTER_COND, 80, 0, JSEXN_NONE, "missing ) after condition")
MSG_DEF(JSMSG_NO_IMPORT_NAME, 81, 0, JSEXN_NONE, "missing name in import statement")
MSG_DEF(JSMSG_NAME_AFTER_DOT, 82, 0, JSEXN_NONE, "missing name after . operator")
MSG_DEF(JSMSG_BRACKET_IN_INDEX, 83, 0, JSEXN_NONE, "missing ] in index expression")
MSG_DEF(JSMSG_NO_EXPORT_NAME, 84, 0, JSEXN_NONE, "missing name in export statement")
MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 85, 0, JSEXN_NONE, "missing ( before switch expression")
MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 86, 0, JSEXN_NONE, "missing ) after switch expression")
MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 87, 0, JSEXN_NONE, "missing { before switch body")
MSG_DEF(JSMSG_COLON_AFTER_CASE, 88, 0, JSEXN_NONE, "missing : after case label")
MSG_DEF(JSMSG_WHILE_AFTER_DO, 89, 0, JSEXN_NONE, "missing while after do-loop body")
MSG_DEF(JSMSG_PAREN_AFTER_FOR, 90, 0, JSEXN_NONE, "missing ( after for")
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 91, 0, JSEXN_NONE, "missing ; after for-loop initializer")
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 92, 0, JSEXN_NONE, "missing ; after for-loop condition")
MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 93, 0, JSEXN_NONE, "missing ) after for-loop control")
MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 94, 0, JSEXN_NONE, "missing { before try block")
MSG_DEF(JSMSG_CURLY_AFTER_TRY, 95, 0, JSEXN_NONE, "missing } after try block")
MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 96, 0, JSEXN_NONE, "missing ( before catch")
MSG_DEF(JSMSG_CATCH_IDENTIFIER, 97, 0, JSEXN_NONE, "missing identifier in catch")
MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 98, 0, JSEXN_NONE, "missing ) after catch")
MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 99, 0, JSEXN_NONE, "missing { before catch block")
MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 100, 0, JSEXN_NONE, "missing } after catch block")
MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 101, 0, JSEXN_NONE, "missing { before finally block")
MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 102, 0, JSEXN_NONE, "missing } after finally block")
MSG_DEF(JSMSG_CATCH_OR_FINALLY, 103, 0, JSEXN_NONE, "missing catch or finally after try")
MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 104, 0, JSEXN_NONE, "missing ( before with-statement object")
MSG_DEF(JSMSG_PAREN_AFTER_WITH, 105, 0, JSEXN_NONE, "missing ) after with-statement object")
MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 106, 0, JSEXN_NONE, "missing } in compound statement")
MSG_DEF(JSMSG_NO_VARIABLE_NAME, 107, 0, JSEXN_NONE, "missing variable name")
MSG_DEF(JSMSG_COLON_IN_COND, 108, 0, JSEXN_NONE, "missing : in conditional expression")
MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 109, 0, JSEXN_NONE, "missing ) after argument list")
MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 110, 0, JSEXN_NONE, "missing ] after element list")
MSG_DEF(JSMSG_COLON_AFTER_ID, 111, 0, JSEXN_NONE, "missing : after property id")
MSG_DEF(JSMSG_CURLY_AFTER_LIST, 112, 0, JSEXN_NONE, "missing } after property list")
MSG_DEF(JSMSG_PAREN_IN_PAREN, 113, 0, JSEXN_NONE, "missing ) in parenthetical")
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 114, 0, JSEXN_NONE, "missing ; before statement")
MSG_DEF(JSMSG_NO_RETURN_VALUE, 115, 0, JSEXN_NONE, "function does not always return a value")
MSG_DEF(JSMSG_DUPLICATE_FORMAL, 116, 1, JSEXN_NONE, "duplicate formal argument {0}")
MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 117, 1, JSEXN_NONE, "test for equality (==) mistyped as assignment (=)?{0}")
MSG_DEF(JSMSG_BAD_IMPORT, 118, 0, JSEXN_NONE, "invalid import expression")
MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 119, 0, JSEXN_NONE, "more than one switch default")
MSG_DEF(JSMSG_TOO_MANY_CASES, 120, 0, JSEXN_NONE, "too many switch cases")
MSG_DEF(JSMSG_BAD_SWITCH, 121, 0, JSEXN_NONE, "invalid switch statement")
MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 122, 0, JSEXN_NONE, "invalid for/in left-hand side")
MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 123, 0, JSEXN_NONE, "catch clause after general catch")
MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 124, 0, JSEXN_NONE, "catch without try")
MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 125, 0, JSEXN_NONE, "finally without try")
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 126, 0, JSEXN_NONE, "label not found")
MSG_DEF(JSMSG_TOUGH_BREAK, 127, 0, JSEXN_NONE, "invalid break")
MSG_DEF(JSMSG_BAD_CONTINUE, 128, 0, JSEXN_NONE, "invalid continue")
MSG_DEF(JSMSG_BAD_RETURN, 129, 0, JSEXN_NONE, "invalid return")
MSG_DEF(JSMSG_BAD_LABEL, 130, 0, JSEXN_NONE, "invalid label")
MSG_DEF(JSMSG_DUPLICATE_LABEL, 131, 0, JSEXN_NONE, "duplicate label")
MSG_DEF(JSMSG_VAR_HIDES_ARG, 132, 1, JSEXN_NONE, "variable {0} hides argument")
MSG_DEF(JSMSG_BAD_VAR_INIT, 133, 0, JSEXN_NONE, "invalid variable initialization")
MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 134, 0, JSEXN_NONE, "invalid assignment left-hand side")
MSG_DEF(JSMSG_BAD_OPERAND, 135, 1, JSEXN_NONE, "invalid {0} operand")
MSG_DEF(JSMSG_BAD_PROP_ID, 136, 0, JSEXN_NONE, "invalid property id")
MSG_DEF(JSMSG_RESERVED_ID, 137, 1, JSEXN_NONE, "{0} is a reserved identifier")
MSG_DEF(JSMSG_SYNTAX_ERROR, 138, 0, JSEXN_NONE, "syntax error")
MSG_DEF(JSMSG_BAD_SHARP_VAR_DEF, 139, 0, JSEXN_NONE, "invalid sharp variable definition")
MSG_DEF(JSMSG_BAD_PROTOTYPE, 140, 1, JSEXN_NONE, "'prototype' property of {0} is not an object")

Просмотреть файл

@ -212,7 +212,9 @@ num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (!js_ValueToECMAInt32(cx, argv[0], &base)) if (!js_ValueToECMAInt32(cx, argv[0], &base))
return JS_FALSE; return JS_FALSE;
if (base < 2 || base > 36) { if (base < 2 || base > 36) {
JS_ReportError(cx, "illegal radix %d", base); char numBuf[12];
sprintf(numBuf, "%d", base);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_RADIX, numBuf);
return JS_FALSE; return JS_FALSE;
} }
if (base != 10 && JSDOUBLE_IS_FINITE(d)) { if (base != 10 && JSDOUBLE_IS_FINITE(d)) {
@ -473,8 +475,9 @@ js_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
str = js_DecompileValueGenerator(cx, v, NULL); str = js_DecompileValueGenerator(cx, v, NULL);
badstr: badstr:
if (str) { if (str) {
JS_ReportError(cx, "%s is not a number", JS_ReportErrorNumber(cx, NULL, JSMSG_NAN,
JS_GetStringBytes(str)); JS_GetStringBytes(str));
} }
return JS_FALSE; return JS_FALSE;
#else #else
@ -557,8 +560,9 @@ js_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) { if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
str = js_DecompileValueGenerator(cx, v, NULL); str = js_DecompileValueGenerator(cx, v, NULL);
if (str) { if (str) {
JS_ReportError(cx, "can't convert %s to an integer", JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_CONVERT,
JS_GetStringBytes(str)); JS_GetStringBytes(str));
} }
return JS_FALSE; return JS_FALSE;
} }

Просмотреть файл

@ -138,7 +138,7 @@ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
slot = JSVAL_TO_INT(id); slot = JSVAL_TO_INT(id);
while (obj2) { while (obj2) {
if (obj2 == obj) { if (obj2 == obj) {
JS_ReportError(cx, "cyclic %s value", object_props[slot].name); JS_ReportErrorNumber(cx, NULL, JSMSG_CYCLIC_VALUE, object_props[slot].name);
return JS_FALSE; return JS_FALSE;
} }
obj2 = JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj2, slot)); obj2 = JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj2, slot));
@ -1806,7 +1806,7 @@ _readonly:
return JS_TRUE; return JS_TRUE;
str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL); str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL);
if (str) if (str)
JS_ReportError(cx, "%s is read-only", JS_GetStringBytes(str)); JS_ReportErrorNumber(cx, NULL, JSMSG_READ_ONLY, JS_GetStringBytes(str));
return JS_FALSE; return JS_FALSE;
} }
@ -1942,7 +1942,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
} }
str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL); str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL);
if (str) if (str)
JS_ReportError(cx, "%s is permanent", JS_GetStringBytes(str)); JS_ReportErrorNumber(cx, NULL, JSMSG_PERMANENT, JS_GetStringBytes(str));
return JS_FALSE; return JS_FALSE;
} }
@ -2056,7 +2056,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
*vp = OBJECT_TO_JSVAL(obj); *vp = OBJECT_TO_JSVAL(obj);
str = js_DecompileValueGenerator(cx, v, str); str = js_DecompileValueGenerator(cx, v, str);
if (str) { if (str) {
JS_ReportError(cx, "can't convert %s to %s", JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_CONVERT_TO,
JS_GetStringBytes(str), JS_GetStringBytes(str),
(hint == JSTYPE_VOID) (hint == JSTYPE_VOID)
? "primitive type" ? "primitive type"
@ -2388,7 +2388,7 @@ js_ValueToNonNullObject(JSContext *cx, jsval v)
if (!obj) { if (!obj) {
str = js_DecompileValueGenerator(cx, v, NULL); str = js_DecompileValueGenerator(cx, v, NULL);
if (str) { if (str) {
JS_ReportError(cx, "%s has no properties", JS_ReportErrorNumber(cx, NULL, JSMSG_NO_PROPERTIES,
JS_GetStringBytes(str)); JS_GetStringBytes(str));
} }
} }
@ -2474,7 +2474,9 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
} else { } else {
clasp = JS_FindClassById(xdr, classId); clasp = JS_FindClassById(xdr, classId);
if (!clasp) { if (!clasp) {
JS_ReportError(cx, "can't find class id %ld", (long)classId); char numBuf[12];
sprintf(numBuf, "%d", (long)classId);
JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_FIND_CLASS, numBuf);
ok = JS_FALSE; ok = JS_FALSE;
goto out; goto out;
} }
@ -2482,7 +2484,7 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
} }
if (!clasp->xdrObject) { if (!clasp->xdrObject) {
JS_ReportError(cx, "can't XDR class %s", clasp->name); JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_XDR_CLASS, clasp->name);
ok = JS_FALSE; ok = JS_FALSE;
} else { } else {
ok = clasp->xdrObject(xdr, objp); ok = clasp->xdrObject(xdr, objp);

Просмотреть файл

@ -111,7 +111,11 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
op = (JSOp)*pc; op = (JSOp)*pc;
if (op >= JSOP_LIMIT) { if (op >= JSOP_LIMIT) {
JS_ReportError(cx, "bytecode %d too large (limit %d)", op, JSOP_LIMIT); char numBuf1[12];
char numBuf2[12];
sprintf(numBuf1, "%d", op);
sprintf(numBuf2, "%d", JSOP_LIMIT);
JS_ReportErrorNumber(cx, NULL, JSMSG_BYTECODE_TOO_BIG, numBuf1, numBuf2);
return 0; return 0;
} }
cs = &js_CodeSpec[op]; cs = &js_CodeSpec[op];
@ -221,9 +225,12 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
fprintf(fp, " %u", GET_VARNO(pc)); fprintf(fp, " %u", GET_VARNO(pc));
break; break;
default: default: {
JS_ReportError(cx, "unknown bytecode format %x", cs->format); char numBuf[12];
sprintf(numBuf, "%x", cs->format);
JS_ReportErrorNumber(cx, NULL, JSMSG_UNKNOWN_FORMAT, numBuf);
return 0; return 0;
}
} }
fputs("\n", fp); fputs("\n", fp);
return len; return len;
@ -836,7 +843,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
len = js_GetSrcNoteOffset(sn, 0); len = js_GetSrcNoteOffset(sn, 0);
pc += 4; /* initprop, enterwith */ pc += 4; /* initprop, enterwith */
if (len) { if (len) {
js_printf(jp, " if "); js_printf(jp, " : ");
DECOMPILE_CODE(pc, len - 3); /* don't decompile ifeq */ DECOMPILE_CODE(pc, len - 3); /* don't decompile ifeq */
js_printf(jp, "%s", POP_STR()); js_printf(jp, "%s", POP_STR());
pc += len; pc += len;
@ -879,8 +886,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
todo = Sprint(&ss->sprinter, ""); todo = Sprint(&ss->sprinter, "");
break; break;
case JSOP_JSR: case JSOP_GOSUB:
case JSOP_RETSUB: case JSOP_RETSUB:
case JSOP_SETSP:
todo = -2; todo = -2;
break; break;

Просмотреть файл

@ -194,9 +194,10 @@ OPDEF(JSOP_INSTANCEOF,112,js_instanceof_str,js_instanceof_str,1,2,1,6,JOF_BYTE)
/* debugger op */ /* debugger op */
OPDEF(JSOP_DEBUGGER, 113,"debugger", NULL, 1, 0, 0, 0, JOF_BYTE) OPDEF(JSOP_DEBUGGER, 113,"debugger", NULL, 1, 0, 0, 0, JOF_BYTE)
/* jsr/return for finally handling */ /* gosub/retsub for finally handling */
OPDEF(JSOP_JSR, 114,"jsr", NULL, 3, 0, 1, 0, JOF_JUMP) OPDEF(JSOP_GOSUB, 114,"gosub", NULL, 3, 0, 1, 0, JOF_JUMP)
OPDEF(JSOP_RETSUB, 115,"retsub", NULL, 1, 1, 0, 0, JOF_BYTE) OPDEF(JSOP_RETSUB, 115,"retsub", NULL, 1, 1, 0, 0, JOF_BYTE)
/* more exception handling ops */ /* more exception handling ops */
OPDEF(JSOP_EXCEPTION, 116,"exception", NULL, 1, 0, 1, 0, JOF_BYTE) OPDEF(JSOP_EXCEPTION, 116,"exception", NULL, 1, 0, 1, 0, JOF_BYTE)
OPDEF(JSOP_SETSP, 117,"setsp", NULL, 3, 0, 0, 0, JOF_UINT16)

Просмотреть файл

@ -97,16 +97,18 @@ static JSParser PrimaryExpr;
* Insist that the next token be of type tt, or report err and throw or fail. * Insist that the next token be of type tt, or report err and throw or fail.
* NB: this macro uses cx and ts from its lexical environment. * NB: this macro uses cx and ts from its lexical environment.
*/ */
#define MUST_MATCH_TOKEN_THROW(tt, err, throw) \
#define MUST_MATCH_TOKEN_THROW(tt, errNo, throw) \
PR_BEGIN_MACRO \ PR_BEGIN_MACRO \
if (js_GetToken(cx, ts) != tt) { \ if (js_GetToken(cx, ts) != tt) { \
js_ReportCompileError(cx, ts, err); \ js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR, errNo); \
throw; \ throw; \
} \ } \
PR_END_MACRO PR_END_MACRO
#define MUST_MATCH_TOKEN(tt, err) \ #define MUST_MATCH_TOKEN(tt, errNo) \
MUST_MATCH_TOKEN_THROW(tt, err, return NULL) MUST_MATCH_TOKEN_THROW(tt, errNo, return NULL)
/* /*
* Allocate a JSParseNode from cx's temporary arena. * Allocate a JSParseNode from cx's temporary arena.
@ -160,10 +162,17 @@ WellTerminated(JSContext *cx, JSTokenStream *ts, JSTokenType lastExprType)
#if JS_HAS_LEXICAL_CLOSURE #if JS_HAS_LEXICAL_CLOSURE
if ((tt == TOK_FUNCTION || lastExprType == TOK_FUNCTION) && if ((tt == TOK_FUNCTION || lastExprType == TOK_FUNCTION) &&
cx->version < JSVERSION_1_2) { cx->version < JSVERSION_1_2) {
/*
* Checking against version < 1.2 and version >= 1.0
* in the above line breaks old javascript, so we keep it
* this way for now... XXX warning needed?
*/
return JS_TRUE; return JS_TRUE;
} }
#endif #endif
js_ReportCompileError(cx, ts, "missing ; before statement"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_SEMI_BEFORE_STMNT);
return JS_FALSE; return JS_FALSE;
} }
return JS_TRUE; return JS_TRUE;
@ -254,7 +263,7 @@ out:
static JSBool static JSBool
CheckFinalReturn(JSParseNode *pn) CheckFinalReturn(JSParseNode *pn)
{ {
JSBool ok; JSBool ok, hasDefault;
JSParseNode *pn2, *pn3; JSParseNode *pn2, *pn3;
switch (pn->pn_type) { switch (pn->pn_type) {
@ -266,16 +275,21 @@ CheckFinalReturn(JSParseNode *pn)
ok = CheckFinalReturn(pn->pn_kid2); ok = CheckFinalReturn(pn->pn_kid2);
ok &= pn->pn_kid3 && CheckFinalReturn(pn->pn_kid3); ok &= pn->pn_kid3 && CheckFinalReturn(pn->pn_kid3);
return ok; return ok;
#if JS_HAS_SWITCH_STATEMENT
case TOK_SWITCH: case TOK_SWITCH:
/* If a final switch has no default case, we judge it harshly. */ ok = JS_TRUE;
ok = pn->pn_kid3 && CheckFinalReturn(pn->pn_kid3);
for (pn2 = pn->pn_kid2->pn_head; ok && pn2; pn2 = pn2->pn_next) { for (pn2 = pn->pn_kid2->pn_head; ok && pn2; pn2 = pn2->pn_next) {
if (pn2->pn_type == TOK_DEFAULT)
hasDefault = JS_TRUE;
pn3 = pn2->pn_right; pn3 = pn2->pn_right;
PR_ASSERT(pn3->pn_type == TOK_LC); PR_ASSERT(pn3->pn_type == TOK_LC);
if (pn3->pn_head) if (pn3->pn_head)
ok &= CheckFinalReturn(PN_LAST(pn3)); ok &= CheckFinalReturn(PN_LAST(pn3));
} }
/* If a final switch has no default case, we judge it harshly. */
ok &= hasDefault;
return ok; return ok;
#endif /* JS_HAS_SWITCH_STATEMENT */
case TOK_WITH: case TOK_WITH:
return CheckFinalReturn(pn->pn_right); return CheckFinalReturn(pn->pn_right);
case TOK_RETURN: case TOK_RETURN:
@ -285,8 +299,6 @@ CheckFinalReturn(JSParseNode *pn)
} }
} }
static char badreturn_str[] = "function does not always return a value";
#endif /* CHECK_RETURN_EXPR */ #endif /* CHECK_RETURN_EXPR */
static JSParseNode * static JSParseNode *
@ -314,7 +326,8 @@ FunctionBody(JSContext *cx, JSTokenStream *ts, JSFunction *fun,
/* Check for falling off the end of a function that returns a value. */ /* Check for falling off the end of a function that returns a value. */
if (pn && (tc->flags & TCF_RETURN_EXPR)) { if (pn && (tc->flags & TCF_RETURN_EXPR)) {
if (!CheckFinalReturn(pn)) { if (!CheckFinalReturn(pn)) {
js_ReportCompileError(cx, ts, badreturn_str); js_ReportCompileErrorNumber(cx, ts,
JSREPORT_ERROR, JSMSG_NO_RETURN_VALUE);
pn = NULL; pn = NULL;
} }
} }
@ -417,12 +430,12 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
} }
/* Now parse formal argument list and compute fun->nargs. */ /* Now parse formal argument list and compute fun->nargs. */
MUST_MATCH_TOKEN_THROW(TOK_LP, "missing ( before formal parameters", MUST_MATCH_TOKEN_THROW(TOK_LP, JSMSG_PAREN_BEFORE_FORMAL,
ok = JS_FALSE; goto out); ok = JS_FALSE; goto out);
/* balance) */ /* balance) */
if (!js_MatchToken(cx, ts, TOK_RP)) { if (!js_MatchToken(cx, ts, TOK_RP)) {
do { do {
MUST_MATCH_TOKEN_THROW(TOK_NAME, "missing formal parameter", MUST_MATCH_TOKEN_THROW(TOK_NAME, JSMSG_MISSING_FORMAL,
ok = JS_FALSE; goto out); ok = JS_FALSE; goto out);
argAtom = ts->token.t_atom; argAtom = ts->token.t_atom;
pobj = NULL; pobj = NULL;
@ -434,8 +447,8 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
if (sprop->getter == js_GetArgument) { if (sprop->getter == js_GetArgument) {
#ifdef CHECK_ARGUMENT_HIDING #ifdef CHECK_ARGUMENT_HIDING
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop); OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
js_ReportCompileError(cx, ts, js_ReportCompileErrorNumber(cx, ts,JSREPORT_ERROR,
"duplicate formal argument %s", JSMSG_DUPLICATE_FORMAL,
ATOM_BYTES(argAtom)); ATOM_BYTES(argAtom));
ok = JS_FALSE; ok = JS_FALSE;
goto out; goto out;
@ -476,11 +489,11 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
} while (js_MatchToken(cx, ts, TOK_COMMA)); } while (js_MatchToken(cx, ts, TOK_COMMA));
/* (balance: */ /* (balance: */
MUST_MATCH_TOKEN_THROW(TOK_RP, "missing ) after formal parameters", MUST_MATCH_TOKEN_THROW(TOK_RP, JSMSG_PAREN_AFTER_FORMAL,
ok = JS_FALSE; goto out); ok = JS_FALSE; goto out);
} }
MUST_MATCH_TOKEN_THROW(TOK_LC, "missing { before function body", MUST_MATCH_TOKEN_THROW(TOK_LC, JSMSG_CURLY_BEFORE_BODY,
ok = JS_FALSE; goto out); ok = JS_FALSE; goto out);
pn->pn_pos.begin = ts->token.pos.begin; pn->pn_pos.begin = ts->token.pos.begin;
@ -491,7 +504,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
goto out; goto out;
} }
MUST_MATCH_TOKEN_THROW(TOK_RC, "missing } after function body", MUST_MATCH_TOKEN_THROW(TOK_RC, JSMSG_CURLY_AFTER_BODY,
ok = JS_FALSE; goto out); ok = JS_FALSE; goto out);
pn->pn_pos.end = ts->token.pos.end; pn->pn_pos.end = ts->token.pos.end;
@ -576,22 +589,23 @@ Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{ {
JSParseNode *pn, *pn2; JSParseNode *pn, *pn2;
MUST_MATCH_TOKEN(TOK_LP, "missing ( before condition"); MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);
pn = Expr(cx, ts, tc); pn = Expr(cx, ts, tc);
if (!pn) if (!pn)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_RP, "missing ) after condition"); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
/* /*
* Check for (a = b) and "correct" it to (a == b). * Check for (a = b) and "correct" it to (a == b).
* XXX not ECMA, but documented in several books -- need a compile option * XXX not ECMA, but documented in several books -- need a compile option
*/ */
if (pn->pn_type == TOK_ASSIGN && pn->pn_op == JSOP_NOP) { if (pn->pn_type == TOK_ASSIGN && pn->pn_op == JSOP_NOP) {
#ifdef CHECK_EQUALITY_ASSIGNMENT js_ReportCompileErrorNumber(cx, ts,JSREPORT_WARNING,
js_ReportCompileError(cx, ts, JSMSG_EQUAL_AS_ASSIGN,
"test for equality (==) mistyped as assignment (=)?\n" (JSVERSION_IS_ECMA(cx->version) ? "" :
"Assuming equality test"); "\nAssuming equality test"));
#endif if (JSVERSION_IS_ECMA(cx->version))
goto no_rewrite;
pn->pn_type = TOK_EQOP; pn->pn_type = TOK_EQOP;
pn->pn_op = cx->jsop_eq; pn->pn_op = cx->jsop_eq;
pn2 = pn->pn_left; pn2 = pn->pn_left;
@ -615,6 +629,7 @@ Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
PR_ASSERT(0); PR_ASSERT(0);
} }
} }
no_rewrite:
return pn; return pn;
} }
@ -650,7 +665,7 @@ ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
JSParseNode *pn, *pn2, *pn3; JSParseNode *pn, *pn2, *pn3;
JSTokenType tt; JSTokenType tt;
MUST_MATCH_TOKEN(TOK_NAME, "missing name in import statement"); MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME);
pn = NewParseNode(cx, &ts->token, PN_NULLARY); pn = NewParseNode(cx, &ts->token, PN_NULLARY);
if (!pn) if (!pn)
return NULL; return NULL;
@ -673,7 +688,7 @@ ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn2->pn_op = JSOP_IMPORTALL; pn2->pn_op = JSOP_IMPORTALL;
pn2->pn_atom = NULL; pn2->pn_atom = NULL;
} else { } else {
MUST_MATCH_TOKEN(TOK_NAME, "missing name after . operator"); MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NAME_AFTER_DOT);
pn2->pn_op = JSOP_GETPROP; pn2->pn_op = JSOP_GETPROP;
pn2->pn_atom = ts->token.t_atom; pn2->pn_atom = ts->token.t_atom;
pn2->pn_slot = -1; pn2->pn_slot = -1;
@ -690,7 +705,7 @@ ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL; return NULL;
/* [balance: */ /* [balance: */
MUST_MATCH_TOKEN(TOK_RB, "missing ] in index expression"); MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
pn2->pn_pos.begin = pn->pn_pos.begin; pn2->pn_pos.begin = pn->pn_pos.begin;
pn2->pn_pos.end = ts->token.pos.end; pn2->pn_pos.end = ts->token.pos.end;
@ -731,7 +746,8 @@ ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return pn; return pn;
bad_import: bad_import:
js_ReportCompileError(cx, ts, "invalid import expression"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_IMPORT);
return NULL; return NULL;
} }
#endif /* JS_HAS_EXPORT_IMPORT */ #endif /* JS_HAS_EXPORT_IMPORT */
@ -762,7 +778,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
PN_APPEND(pn, pn2); PN_APPEND(pn, pn2);
} else { } else {
do { do {
MUST_MATCH_TOKEN(TOK_NAME, "missing name in export statement"); MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_EXPORT_NAME);
pn2 = NewParseNode(cx, &ts->token, PN_NULLARY); pn2 = NewParseNode(cx, &ts->token, PN_NULLARY);
if (!pn2) if (!pn2)
return NULL; return NULL;
@ -831,30 +847,28 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{ {
uintN newlines; uintN newlines;
JSParseNode *pn5, *pn6; JSParseNode *pn5, *pn6;
JSBool seenDefault = JS_FALSE;
pn = NewParseNode(cx, &ts->token, PN_TERNARY); pn = NewParseNode(cx, &ts->token, PN_BINARY);
if (!pn) if (!pn)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_LP, "missing ( before switch expression"); MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH);
/* pn1 points to the switch's discriminant. */ /* pn1 points to the switch's discriminant. */
pn1 = Expr(cx, ts, tc); pn1 = Expr(cx, ts, tc);
if (!pn1) if (!pn1)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_RP, "missing ) after switch expression"); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_SWITCH);
MUST_MATCH_TOKEN(TOK_LC, "missing { before switch body"); MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_SWITCH);
/* balance} */ /* balance} */
/* pn2 is a list of case nodes, not including the default case. */ /* pn2 is a list of case nodes. The default case has pn_left == NULL */
pn2 = NewParseNode(cx, &ts->token, PN_LIST); pn2 = NewParseNode(cx, &ts->token, PN_LIST);
if (!pn2) if (!pn2)
return NULL; return NULL;
PN_INIT_LIST(pn2); PN_INIT_LIST(pn2);
/* If not null, pn3 points to the default case's node. */
pn3 = NULL;
js_PushStatement(tc, &stmtInfo, STMT_SWITCH, -1); js_PushStatement(tc, &stmtInfo, STMT_SWITCH, -1);
newlines = ts->flags & TSF_NEWLINES; newlines = ts->flags & TSF_NEWLINES;
if (newlines) if (newlines)
@ -862,37 +876,43 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
while ((tt = js_GetToken(cx, ts)) != TOK_RC) { while ((tt = js_GetToken(cx, ts)) != TOK_RC) {
switch (tt) { switch (tt) {
case TOK_DEFAULT:
if (seenDefault) {
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_TOO_MANY_DEFAULTS);
goto bad_switch;
}
seenDefault = JS_TRUE;
/* fall through */
case TOK_CASE: case TOK_CASE:
pn4 = NewParseNode(cx, &ts->token, PN_BINARY); pn4 = NewParseNode(cx, &ts->token, PN_BINARY);
if (!pn4) if (!pn4)
goto bad_switch; goto bad_switch;
pn4->pn_left = Expr(cx, ts, tc); if (tt == TOK_DEFAULT) {
if (!pn4->pn_left) pn4->pn_left = NULL;
} else {
pn4->pn_left = Expr(cx, ts, tc);
if (!pn4->pn_left)
goto bad_switch;
}
PN_APPEND(pn2, pn4);
if (pn2->pn_count == PR_BIT(16)) {
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_TOO_MANY_CASES);
goto bad_switch; goto bad_switch;
PN_APPEND(pn2, pn4); }
if (pn2->pn_count == PR_BIT(16)) { break;
js_ReportCompileError(cx, ts, "too many switch cases");
goto bad_switch;
}
break;
case TOK_DEFAULT:
if (pn3) {
js_ReportCompileError(cx, ts,
"more than one switch default");
goto bad_switch;
}
pn4 = NULL;
break;
case TOK_ERROR: case TOK_ERROR:
goto bad_switch; goto bad_switch;
default: default:
js_ReportCompileError(cx, ts, "invalid switch statement"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_SWITCH);
goto bad_switch; goto bad_switch;
} }
MUST_MATCH_TOKEN(TOK_COLON, "missing : after case label"); MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
pn5 = NewParseNode(cx, &ts->token, PN_LIST); pn5 = NewParseNode(cx, &ts->token, PN_LIST);
if (!pn5) if (!pn5)
@ -909,12 +929,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn5->pn_pos.end = pn6->pn_pos.end; pn5->pn_pos.end = pn6->pn_pos.end;
PN_APPEND(pn5, pn6); PN_APPEND(pn5, pn6);
} }
if (pn4) { pn4->pn_pos.end = pn5->pn_pos.end;
pn4->pn_pos.end = pn5->pn_pos.end; pn4->pn_right = pn5;
pn4->pn_right = pn5;
} else {
pn3 = pn5;
}
} }
if (newlines) if (newlines)
@ -924,7 +940,6 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn->pn_pos.end = pn2->pn_pos.end = ts->token.pos.end; pn->pn_pos.end = pn2->pn_pos.end = ts->token.pos.end;
pn->pn_kid1 = pn1; pn->pn_kid1 = pn1;
pn->pn_kid2 = pn2; pn->pn_kid2 = pn2;
pn->pn_kid3 = pn3;
return pn; return pn;
bad_switch: bad_switch:
@ -961,7 +976,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (!pn2) if (!pn2)
return NULL; return NULL;
pn->pn_left = pn2; pn->pn_left = pn2;
MUST_MATCH_TOKEN(TOK_WHILE, "missing while after do-loop body"); MUST_MATCH_TOKEN(TOK_WHILE, JSMSG_WHILE_AFTER_DO);
pn2 = Condition(cx, ts, tc); pn2 = Condition(cx, ts, tc);
if (!pn2) if (!pn2)
return NULL; return NULL;
@ -978,7 +993,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL; return NULL;
js_PushStatement(tc, &stmtInfo, STMT_FOR_LOOP, -1); js_PushStatement(tc, &stmtInfo, STMT_FOR_LOOP, -1);
MUST_MATCH_TOKEN(TOK_LP, "missing ( after for"); /* balance) */ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR); /* balance) */
tt = js_PeekToken(cx, ts); tt = js_PeekToken(cx, ts);
if (tt == TOK_SEMI) { if (tt == TOK_SEMI) {
/* No initializer -- set first kid of left sub-node to null. */ /* No initializer -- set first kid of left sub-node to null. */
@ -1024,7 +1039,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn1->pn_type != TOK_NAME && pn1->pn_type != TOK_NAME &&
pn1->pn_type != TOK_DOT && pn1->pn_type != TOK_DOT &&
pn1->pn_type != TOK_LB) { pn1->pn_type != TOK_LB) {
js_ReportCompileError(cx, ts, "invalid for/in left-hand side"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_FOR_LEFTSIDE);
return NULL; return NULL;
} }
@ -1035,7 +1051,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn->pn_left = pn2; pn->pn_left = pn2;
} else { } else {
/* Parse the loop condition or null into pn2. */ /* Parse the loop condition or null into pn2. */
MUST_MATCH_TOKEN(TOK_SEMI, "missing ; after for-loop initializer"); MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_INIT);
if (js_PeekToken(cx, ts) == TOK_SEMI) { if (js_PeekToken(cx, ts) == TOK_SEMI) {
pn2 = NULL; pn2 = NULL;
} else { } else {
@ -1045,7 +1061,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} }
/* Parse the update expression or null into pn3. */ /* Parse the update expression or null into pn3. */
MUST_MATCH_TOKEN(TOK_SEMI, "missing ; after for-loop condition"); MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_COND);
if (js_PeekToken(cx, ts) == TOK_RP) { if (js_PeekToken(cx, ts) == TOK_RP) {
pn3 = NULL; pn3 = NULL;
} else { } else {
@ -1066,7 +1082,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} }
/* (balance: */ /* (balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) after for-loop control"); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL);
/* Parse the loop body into pn->pn_right. */ /* Parse the loop body into pn->pn_right. */
pn2 = Statement(cx, ts, tc); pn2 = Statement(cx, ts, tc);
@ -1103,13 +1119,13 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn = NewParseNode(cx, &ts->token, PN_TERNARY); pn = NewParseNode(cx, &ts->token, PN_TERNARY);
pn->pn_op = JSOP_NOP; pn->pn_op = JSOP_NOP;
MUST_MATCH_TOKEN(TOK_LC, "missing { after before try block"); MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY);
/* } balance */ /* } balance */
pn->pn_kid1 = Statements(cx, ts, tc); pn->pn_kid1 = Statements(cx, ts, tc);
if (!pn->pn_kid1) if (!pn->pn_kid1)
return NULL; return NULL;
/* { balance */ /* { balance */
MUST_MATCH_TOKEN(TOK_RC, "missing } after try block"); MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_TRY);
pn->pn_kid2 = NULL; pn->pn_kid2 = NULL;
catchtail = pn; catchtail = pn;
@ -1121,8 +1137,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
*/ */
if (!catchtail->pn_kid1->pn_expr) { if (!catchtail->pn_kid1->pn_expr) {
js_ReportCompileError(cx, ts, js_ReportCompileErrorNumber(cx, ts, JSREPORT_WARNING,
"catch clause after general catch"); JSMSG_CATCH_AFTER_GENERAL);
return NULL; return NULL;
} }
@ -1139,8 +1155,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
(void)js_GetToken(cx, ts); /* eat `catch' */ (void)js_GetToken(cx, ts); /* eat `catch' */
MUST_MATCH_TOKEN(TOK_LP, "missing ( after catch"); /* balance) */ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_CATCH); /* balance) */
MUST_MATCH_TOKEN(TOK_NAME, "missing identifier in catch"); MUST_MATCH_TOKEN(TOK_NAME, JSMSG_CATCH_IDENTIFIER);
pn3->pn_atom = ts->token.t_atom; pn3->pn_atom = ts->token.t_atom;
if (js_PeekToken(cx, ts) == TOK_COLON) { if (js_PeekToken(cx, ts) == TOK_COLON) {
(void)js_GetToken(cx, ts); /* eat `:' */ (void)js_GetToken(cx, ts); /* eat `:' */
@ -1153,30 +1169,31 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn2->pn_kid1 = pn3; pn2->pn_kid1 = pn3;
/* ( balance: */ /* ( balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) after catch"); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_CATCH);
MUST_MATCH_TOKEN(TOK_LC, "missing { before catch block"); MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CATCH);
pn2->pn_kid3 = Statements(cx, ts, tc); pn2->pn_kid3 = Statements(cx, ts, tc);
if (!pn2->pn_kid3) if (!pn2->pn_kid3)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_RC, "missing } after catch block"); MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_CATCH);
catchtail = catchtail->pn_kid2 = pn2; catchtail = catchtail->pn_kid2 = pn2;
} }
catchtail->pn_kid2 = NULL; catchtail->pn_kid2 = NULL;
if (js_MatchToken(cx, ts, TOK_FINALLY)) { if (js_MatchToken(cx, ts, TOK_FINALLY)) {
MUST_MATCH_TOKEN(TOK_LC, "missing { before finally block"); tc->tryCount++;
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY);
pn->pn_kid3 = Statements(cx, ts, tc); pn->pn_kid3 = Statements(cx, ts, tc);
if (!pn->pn_kid3) if (!pn->pn_kid3)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_RC, "missing } after finally block"); MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_FINALLY);
} else { } else {
pn->pn_kid3 = NULL; pn->pn_kid3 = NULL;
} }
if (!pn->pn_kid2 && !pn->pn_kid3) { if (!pn->pn_kid2 && !pn->pn_kid3) {
js_ReportCompileError(cx, ts, js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
"missing catch or finally after try"); JSMSG_CATCH_OR_FINALLY);
return NULL; return NULL;
} }
tc->tryCount++; tc->tryCount++;
@ -1200,11 +1217,13 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
/* TOK_CATCH and TOK_FINALLY are both handled in the TOK_TRY case */ /* TOK_CATCH and TOK_FINALLY are both handled in the TOK_TRY case */
case TOK_CATCH: case TOK_CATCH:
js_ReportCompileError(cx, ts, "catch without try"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_CATCH_WITHOUT_TRY);
return NULL; return NULL;
case TOK_FINALLY: case TOK_FINALLY:
js_ReportCompileError(cx, ts, "finally without try"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_FINALLY_WITHOUT_TRY);
return NULL; return NULL;
#endif /* JS_HAS_EXCEPTIONS */ #endif /* JS_HAS_EXCEPTIONS */
@ -1220,7 +1239,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (label) { if (label) {
for (; ; stmt = stmt->down) { for (; ; stmt = stmt->down) {
if (!stmt) { if (!stmt) {
js_ReportCompileError(cx, ts, "label not found"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_LABEL_NOT_FOUND);
return NULL; return NULL;
} }
if (stmt->type == STMT_LABEL && stmt->label == label) if (stmt->type == STMT_LABEL && stmt->label == label)
@ -1229,7 +1249,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} else { } else {
for (; ; stmt = stmt->down) { for (; ; stmt = stmt->down) {
if (!stmt) { if (!stmt) {
js_ReportCompileError(cx, ts, "invalid break"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_TOUGH_BREAK);
return NULL; return NULL;
} }
if (STMT_IS_LOOP(stmt) || stmt->type == STMT_SWITCH) if (STMT_IS_LOOP(stmt) || stmt->type == STMT_SWITCH)
@ -1251,13 +1272,15 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (label) { if (label) {
for (stmt2 = NULL; ; stmt = stmt->down) { for (stmt2 = NULL; ; stmt = stmt->down) {
if (!stmt) { if (!stmt) {
js_ReportCompileError(cx, ts, "label not found"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_LABEL_NOT_FOUND);
return NULL; return NULL;
} }
if (stmt->type == STMT_LABEL) { if (stmt->type == STMT_LABEL) {
if (stmt->label == label) { if (stmt->label == label) {
if (!stmt2 || !STMT_IS_LOOP(stmt2)) { if (!stmt2 || !STMT_IS_LOOP(stmt2)) {
js_ReportCompileError(cx, ts, "invalid continue"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_CONTINUE);
return NULL; return NULL;
} }
break; break;
@ -1269,7 +1292,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} else { } else {
for (; ; stmt = stmt->down) { for (; ; stmt = stmt->down) {
if (!stmt) { if (!stmt) {
js_ReportCompileError(cx, ts, "invalid continue"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_CONTINUE);
return NULL; return NULL;
} }
if (STMT_IS_LOOP(stmt)) if (STMT_IS_LOOP(stmt))
@ -1284,13 +1308,13 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn = NewParseNode(cx, &ts->token, PN_BINARY); pn = NewParseNode(cx, &ts->token, PN_BINARY);
if (!pn) if (!pn)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_LP, "missing ( before with-statement object"); MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH);
/* balance) */ /* balance) */
pn2 = Expr(cx, ts, tc); pn2 = Expr(cx, ts, tc);
if (!pn2) if (!pn2)
return NULL; return NULL;
/* (balance: */ /* (balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) after with-statement object"); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH);
pn->pn_left = pn2; pn->pn_left = pn2;
js_PushStatement(tc, &stmtInfo, STMT_WITH, -1); js_PushStatement(tc, &stmtInfo, STMT_WITH, -1);
@ -1317,7 +1341,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
case TOK_RETURN: case TOK_RETURN:
if (!(tc->flags & TCF_IN_FUNCTION)) { if (!(tc->flags & TCF_IN_FUNCTION)) {
js_ReportCompileError(cx, ts, "invalid return"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_RETURN);
return NULL; return NULL;
} }
pn = NewParseNode(cx, &ts->token, PN_UNARY); pn = NewParseNode(cx, &ts->token, PN_UNARY);
@ -1350,7 +1375,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
#ifdef CHECK_RETURN_EXPR #ifdef CHECK_RETURN_EXPR
if ((tc->flags & (TCF_RETURN_EXPR | TCF_RETURN_VOID)) == if ((tc->flags & (TCF_RETURN_EXPR | TCF_RETURN_VOID)) ==
(TCF_RETURN_EXPR | TCF_RETURN_VOID)) { (TCF_RETURN_EXPR | TCF_RETURN_VOID)) {
js_ReportCompileError(cx, ts, badreturn_str); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_NO_RETURN_VALUE);
return NULL; return NULL;
} }
#endif #endif
@ -1363,7 +1389,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL; return NULL;
/* {balance: */ /* {balance: */
MUST_MATCH_TOKEN(TOK_RC, "missing } in compound statement"); MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_COMPOUND);
js_PopStatement(tc); js_PopStatement(tc);
return pn; return pn;
@ -1400,13 +1426,15 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
tt = ts->pushback.type; tt = ts->pushback.type;
if (tt == TOK_COLON) { if (tt == TOK_COLON) {
if (pn2->pn_type != TOK_NAME) { if (pn2->pn_type != TOK_NAME) {
js_ReportCompileError(cx, ts, "invalid label"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_LABEL);
return NULL; return NULL;
} }
label = pn2->pn_atom; label = pn2->pn_atom;
for (stmt = tc->topStmt; stmt; stmt = stmt->down) { for (stmt = tc->topStmt; stmt; stmt = stmt->down) {
if (stmt->type == STMT_LABEL && stmt->label == label) { if (stmt->type == STMT_LABEL && stmt->label == label) {
js_ReportCompileError(cx, ts, "duplicate label"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_DUPLICATE_LABEL);
return NULL; return NULL;
} }
} }
@ -1494,7 +1522,7 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} }
do { do {
MUST_MATCH_TOKEN(TOK_NAME, "missing variable name"); MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_VARIABLE_NAME);
atom = ts->token.t_atom; atom = ts->token.t_atom;
pn2 = NewParseNode(cx, &ts->token, PN_NAME); pn2 = NewParseNode(cx, &ts->token, PN_NAME);
@ -1514,8 +1542,9 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (sprop->getter == js_GetArgument) { if (sprop->getter == js_GetArgument) {
getter = sprop->getter; getter = sprop->getter;
#ifdef CHECK_ARGUMENT_HIDING #ifdef CHECK_ARGUMENT_HIDING
js_ReportCompileError(cx, ts, "variable %s hides argument", js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
ATOM_BYTES(atom)); JSMSG_VAR_HIDES_ARG,
ATOM_BYTES(atom));
ok = JS_FALSE; ok = JS_FALSE;
#else #else
ok = JS_TRUE; ok = JS_TRUE;
@ -1593,8 +1622,8 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (js_MatchToken(cx, ts, TOK_ASSIGN)) { if (js_MatchToken(cx, ts, TOK_ASSIGN)) {
if (ts->token.t_op != JSOP_NOP) { if (ts->token.t_op != JSOP_NOP) {
js_ReportCompileError(cx, ts, js_ReportCompileErrorNumber(cx, ts,JSREPORT_ERROR,
"invalid variable initialization"); JSMSG_BAD_VAR_INIT);
ok = JS_FALSE; ok = JS_FALSE;
} else { } else {
pn2->pn_expr = AssignExpr(cx, ts, tc); pn2->pn_expr = AssignExpr(cx, ts, tc);
@ -1729,7 +1758,8 @@ AssignExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn2->pn_op = JSOP_SETELEM; pn2->pn_op = JSOP_SETELEM;
break; break;
default: default:
js_ReportCompileError(cx, ts, "invalid assignment left-hand side"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_LEFTSIDE_OF_ASS);
return NULL; return NULL;
} }
pn = NewBinary(cx, TOK_ASSIGN, op, pn2, AssignExpr(cx, ts, tc)); pn = NewBinary(cx, TOK_ASSIGN, op, pn2, AssignExpr(cx, ts, tc));
@ -1767,7 +1797,7 @@ CondExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (!pn2) if (!pn2)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_COLON, "missing : in conditional expression"); MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND);
pn3 = AssignExpr(cx, ts, tc); pn3 = AssignExpr(cx, ts, tc);
if (!pn3) if (!pn3)
return NULL; return NULL;
@ -1951,7 +1981,8 @@ SetLvalKid(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, JSParseNode *kid,
if (kid->pn_type != TOK_NAME && if (kid->pn_type != TOK_NAME &&
kid->pn_type != TOK_DOT && kid->pn_type != TOK_DOT &&
kid->pn_type != TOK_LB) { kid->pn_type != TOK_LB) {
js_ReportCompileError(cx, ts, "invalid %s operand", name); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_OPERAND, name);
return NULL; return NULL;
} }
pn->pn_kid = kid; pn->pn_kid = kid;
@ -2108,7 +2139,7 @@ ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
} while (js_MatchToken(cx, ts, TOK_COMMA)); } while (js_MatchToken(cx, ts, TOK_COMMA));
/* (balance: */ /* (balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) after argument list"); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_ARGS);
} }
return listNode; return listNode;
} }
@ -2141,7 +2172,7 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
return NULL; return NULL;
} }
if (pn->pn_count - 1 >= ARGC_LIMIT) { if (pn->pn_count - 1 >= ARGC_LIMIT) {
JS_ReportError(cx, "too many constructor arguments"); JS_ReportErrorNumber(cx, NULL, JSMSG_TOO_MANY_CON_ARGS);
return NULL; return NULL;
} }
pn->pn_pos.end = PN_LAST(pn)->pn_pos.end; pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
@ -2156,7 +2187,7 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
pn2 = NewParseNode(cx, &ts->token, PN_NAME); pn2 = NewParseNode(cx, &ts->token, PN_NAME);
if (!pn2) if (!pn2)
return NULL; return NULL;
MUST_MATCH_TOKEN(TOK_NAME, "missing name after . operator"); MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NAME_AFTER_DOT);
pn2->pn_pos.begin = pn->pn_pos.begin; pn2->pn_pos.begin = pn->pn_pos.begin;
pn2->pn_pos.end = ts->token.pos.end; pn2->pn_pos.end = ts->token.pos.end;
pn2->pn_op = JSOP_GETPROP; pn2->pn_op = JSOP_GETPROP;
@ -2171,7 +2202,7 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
return NULL; return NULL;
/* [balance: */ /* [balance: */
MUST_MATCH_TOKEN(TOK_RB, "missing ] in index expression"); MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
pn2->pn_pos.begin = pn->pn_pos.begin; pn2->pn_pos.begin = pn->pn_pos.begin;
pn2->pn_pos.end = ts->token.pos.end; pn2->pn_pos.end = ts->token.pos.end;
@ -2198,7 +2229,7 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
if (!pn2) if (!pn2)
return NULL; return NULL;
if (pn2->pn_count - 1 >= ARGC_LIMIT) { if (pn2->pn_count - 1 >= ARGC_LIMIT) {
JS_ReportError(cx, "too many function arguments"); JS_ReportErrorNumber(cx, NULL, JSMSG_TOO_MANY_FUN_ARGS);
return NULL; return NULL;
} }
pn2->pn_pos.end = PN_LAST(pn2)->pn_pos.end; pn2->pn_pos.end = PN_LAST(pn2)->pn_pos.end;
@ -2293,7 +2324,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} }
/* [balance: */ /* [balance: */
MUST_MATCH_TOKEN(TOK_RB, "missing ] after element list"); MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST);
} }
pn->pn_pos.end = ts->token.pos.end; pn->pn_pos.end = ts->token.pos.end;
return pn; return pn;
@ -2331,11 +2362,12 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
case TOK_RC: case TOK_RC:
goto end_obj_init; goto end_obj_init;
default: default:
js_ReportCompileError(cx, ts, "invalid property id"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_PROP_ID);
return NULL; return NULL;
} }
MUST_MATCH_TOKEN(TOK_COLON, "missing : after property id"); MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_ID);
pn2 = NewBinary(cx, TOK_COLON, JSOP_INITPROP, pn3, pn2 = NewBinary(cx, TOK_COLON, JSOP_INITPROP, pn3,
AssignExpr(cx, ts, tc)); AssignExpr(cx, ts, tc));
if (!pn2) if (!pn2)
@ -2344,7 +2376,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} while (js_MatchToken(cx, ts, TOK_COMMA)); } while (js_MatchToken(cx, ts, TOK_COMMA));
/* {balance: */ /* {balance: */
MUST_MATCH_TOKEN(TOK_RC, "missing } after property list"); MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LIST);
} }
end_obj_init: end_obj_init:
pn->pn_pos.end = ts->token.pos.end; pn->pn_pos.end = ts->token.pos.end;
@ -2397,7 +2429,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL; return NULL;
/* (balance: */ /* (balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) in parenthetical"); MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
pn->pn_type = TOK_RP; pn->pn_type = TOK_RP;
pn->pn_pos.end = ts->token.pos.end; pn->pn_pos.end = ts->token.pos.end;
pn->pn_kid = pn2; pn->pn_kid = pn2;
@ -2450,7 +2482,8 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
case TOK_IMPORT: case TOK_IMPORT:
#endif #endif
case TOK_RESERVED: case TOK_RESERVED:
js_ReportCompileError(cx, ts, "%s is a reserved identifier", js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_RESERVED_ID,
js_DeflateString(cx, ts->token.ptr, js_DeflateString(cx, ts->token.ptr,
ts->token.pos.end.index - ts->token.pos.end.index -
ts->token.pos.begin.index)); ts->token.pos.begin.index));
@ -2461,7 +2494,8 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL; return NULL;
default: default:
js_ReportCompileError(cx, ts, "syntax error"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_SYNTAX_ERROR);
return NULL; return NULL;
} }
@ -2469,7 +2503,8 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (defsharp) { if (defsharp) {
if (notsharp) { if (notsharp) {
badsharp: badsharp:
js_ReportCompileError(cx, ts, "invalid sharp variable definition"); js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_SHARP_VAR_DEF);
return NULL; return NULL;
} }
defsharp->pn_kid = pn; defsharp->pn_kid = pn;
@ -2511,10 +2546,10 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn)
break; break;
case PN_BINARY: case PN_BINARY:
/* Neither kid may be null. */ /* First kid may be null (for default case in switch). */
pn1 = pn->pn_left; pn1 = pn->pn_left;
pn2 = pn->pn_right; pn2 = pn->pn_right;
if (!js_FoldConstants(cx, pn1)) if (pn1 && !js_FoldConstants(cx, pn1))
return JS_FALSE; return JS_FALSE;
if (!js_FoldConstants(cx, pn2)) if (!js_FoldConstants(cx, pn2))
return JS_FALSE; return JS_FALSE;

Просмотреть файл

@ -290,4 +290,12 @@ typedef void
(* CRT_CALL JSErrorReporter)(JSContext *cx, const char *message, (* CRT_CALL JSErrorReporter)(JSContext *cx, const char *message,
JSErrorReport *report); JSErrorReport *report);
typedef struct JSErrorFormatString {
const char *format;
const uintN argCount;
} JSErrorFormatString;
typedef const JSErrorFormatString *
(* CRT_CALL JSErrorCallBack)(const uintN errorNumber);
#endif /* jspubtd_h___ */ #endif /* jspubtd_h___ */

Просмотреть файл

@ -649,14 +649,14 @@ loop:
case '{': case '{':
c = *++cp; c = *++cp;
if (!JS7_ISDEC(c)) { if (!JS7_ISDEC(c)) {
JS_ReportError(state->context, "invalid quantifier %s", state->cp); JS_ReportErrorNumber(state->context, NULL, JSMSG_BAD_QUANTIFIER, state->cp);
return NULL; return NULL;
} }
min = (uint32)JS7_UNDEC(c); min = (uint32)JS7_UNDEC(c);
for (c = *++cp; JS7_ISDEC(c); c = *++cp) { for (c = *++cp; JS7_ISDEC(c); c = *++cp) {
min = 10 * min + (uint32)JS7_UNDEC(c); min = 10 * min + (uint32)JS7_UNDEC(c);
if (min >> 16) { if (min >> 16) {
JS_ReportError(state->context, "overlarge minimum %s", JS_ReportErrorNumber(state->context, NULL, JSMSG_MIN_TOO_BIG,
state->cp); state->cp);
return NULL; return NULL;
} }
@ -668,7 +668,7 @@ loop:
for (c = *++cp; JS7_ISDEC(c); c = *++cp) { for (c = *++cp; JS7_ISDEC(c); c = *++cp) {
max = 10 * max + (uint32)JS7_UNDEC(c); max = 10 * max + (uint32)JS7_UNDEC(c);
if (max >> 16) { if (max >> 16) {
JS_ReportError(state->context, "overlarge maximum %s", JS_ReportErrorNumber(state->context, NULL, JSMSG_MAX_TOO_BIG,
up); up);
return NULL; return NULL;
} }
@ -676,8 +676,8 @@ loop:
if (max == 0) if (max == 0)
goto zero_quant; goto zero_quant;
if (min > max) { if (min > max) {
JS_ReportError(state->context, JS_ReportErrorNumber(state->context, NULL,
"maximum %s less than minimum", up); JSMSG_OUT_OF_ORDER, up);
return NULL; return NULL;
} }
} else { } else {
@ -688,13 +688,14 @@ loop:
/* Exactly n times. */ /* Exactly n times. */
if (min == 0) { if (min == 0) {
zero_quant: zero_quant:
JS_ReportError(state->context, "zero quantifier %s", state->cp); JS_ReportErrorNumber(state->context, NULL, JSMSG_ZERO_QUANTIFIER,
state->cp);
return NULL; return NULL;
} }
max = min; max = min;
} }
if (*cp != '}') { if (*cp != '}') {
JS_ReportError(state->context, "unterminated quantifier %s", JS_ReportErrorNumber(state->context, NULL, JSMSG_UNTERM_QUANTIFIER,
state->cp); state->cp);
return NULL; return NULL;
} }
@ -712,8 +713,8 @@ loop:
case '*': case '*':
if (!(ren->flags & RENODE_NONEMPTY)) { if (!(ren->flags & RENODE_NONEMPTY)) {
JS_ReportError(state->context, JS_ReportErrorNumber(state->context, NULL,
"regular expression before * could be empty"); JSMSG_EMPTY_BEFORE_STAR);
return NULL; return NULL;
} }
cp++; cp++;
@ -722,8 +723,8 @@ loop:
case '+': case '+':
if (!(ren->flags & RENODE_NONEMPTY)) { if (!(ren->flags & RENODE_NONEMPTY)) {
JS_ReportError(state->context, JS_ReportErrorNumber(state->context, NULL,
"regular expression before + could be empty"); JSMSG_EMPTY_BEFORE_PLUS);
return NULL; return NULL;
} }
cp++; cp++;
@ -805,7 +806,7 @@ ParseAtom(CompilerState *state)
return NULL; return NULL;
cp = state->cp; cp = state->cp;
if (*cp != ')') { if (*cp != ')') {
JS_ReportError(state->context, "unterminated parenthetical %s", JS_ReportErrorNumber(state->context, NULL, JSMSG_MISSING_PAREN,
ocp); ocp);
return NULL; return NULL;
} }
@ -846,8 +847,8 @@ ParseAtom(CompilerState *state)
while ((c = *++cp) != ']') { while ((c = *++cp) != ']') {
if (c == 0) { if (c == 0) {
bad_cclass: bad_cclass:
JS_ReportError(state->context, JS_ReportErrorNumber(state->context, NULL,
"unterminated character class %s", ocp); JSMSG_UNTERM_CLASS, ocp);
return NULL; return NULL;
} }
if (c == '\\' && cp[1] != 0) if (c == '\\' && cp[1] != 0)
@ -863,7 +864,7 @@ ParseAtom(CompilerState *state)
c = *++cp; c = *++cp;
switch (c) { switch (c) {
case 0: case 0:
JS_ReportError(state->context, "trailing \\ in regular expression"); JS_ReportErrorNumber(state->context, NULL, JSMSG_TRAILING_SLASH);
return NULL; return NULL;
case 'f': case 'f':
@ -1834,8 +1835,8 @@ EmitRegExp(CompilerState *state, RENode *ren, JSRegExp *re)
if (inrange) { if (inrange) {
if (lastc > c) { if (lastc > c) {
JS_ReportError(state->context, JS_ReportErrorNumber(state->context, NULL,
"invalid range in character class"); JSMSG_BAD_CLASS_RANGE);
return JS_FALSE; return JS_FALSE;
} }
inrange = JS_FALSE; inrange = JS_FALSE;
@ -2032,10 +2033,12 @@ js_NewRegExpOpt(JSContext *cx, JSString *str, JSString *opt)
case 'i': case 'i':
flags |= JSREG_FOLD; flags |= JSREG_FOLD;
break; break;
default: default: {
JS_ReportError(cx, "invalid regular expression flag %c", char charBuf[2] = " ";
(char) *cp); charBuf[0] = (char)*cp;
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_FLAG, charBuf);
return NULL; return NULL;
}
} }
} }
} }
@ -3184,7 +3187,7 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
if (argc == 0) { if (argc == 0) {
str = cx->regExpStatics.input; str = cx->regExpStatics.input;
if (!str) { if (!str) {
JS_ReportError(cx, "no input for /%s/%s%s", JS_ReportErrorNumber(cx, NULL, JSMSG_NO_INPUT,
JS_GetStringBytes(re->source), JS_GetStringBytes(re->source),
(re->flags & JSREG_GLOB) ? "g" : "", (re->flags & JSREG_GLOB) ? "g" : "",
(re->flags & JSREG_FOLD) ? "i" : ""); (re->flags & JSREG_FOLD) ? "i" : "");

Просмотреть файл

@ -225,7 +225,7 @@ js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp)
} else { } else {
file = fopen(filename, "r"); file = fopen(filename, "r");
if (!file) { if (!file) {
JS_ReportError(cx, "can't open %s: %s", filename, strerror(errno)); JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_OPEN, filename, strerror(errno));
return NULL; return NULL;
} }
} }
@ -483,8 +483,8 @@ MatchChar(JSTokenStream *ts, int32 nextChar)
} }
void void
js_ReportCompileError(JSContext *cx, JSTokenStream *ts, const char *format, js_ReportCompileError(JSContext *cx, JSTokenStream *ts, uintN flags,
...) const char *format, ...)
{ {
va_list ap; va_list ap;
char *message; char *message;
@ -519,11 +519,13 @@ js_ReportCompileError(JSContext *cx, JSTokenStream *ts, const char *format,
: NULL; : NULL;
report.uclinebuf = ts->linebuf.base; report.uclinebuf = ts->linebuf.base;
report.uctokenptr = ts->token.ptr; report.uctokenptr = ts->token.ptr;
report.flags = flags;
(*onError)(cx, message, &report); (*onError)(cx, message, &report);
#if !defined XP_PC || !defined _MSC_VER || _MSC_VER > 800 #if !defined XP_PC || !defined _MSC_VER || _MSC_VER > 800
} else { } else {
if (!(ts->flags & TSF_INTERACTIVE)) if (!(ts->flags & TSF_INTERACTIVE))
fprintf(stderr, "JavaScript error: "); fprintf(stderr, "JavaScript %s: ",
JSREPORT_IS_WARNING(flags) ? "warning" : "error");
if (ts->filename) if (ts->filename)
fprintf(stderr, "%s, ", ts->filename); fprintf(stderr, "%s, ", ts->filename);
if (ts->lineno) if (ts->lineno)
@ -538,6 +540,68 @@ js_ReportCompileError(JSContext *cx, JSTokenStream *ts, const char *format,
free(message); free(message);
} }
void
js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, uintN flags,
const uintN errorNumber, ...)
{
va_list ap;
jschar *limit, lastc;
JSErrorReporter onError;
JSErrorReport report;
JSString *linestr;
char *message;
report.errorNumber = errorNumber;
report.messageArgs = NULL;
report.ucmessage = NULL;
message = NULL;
va_start(ap, errorNumber);
if (!js_ExpandErrorArguments(cx, NULL, errorNumber, &message, &report, ap))
return;
va_end(ap);
PR_ASSERT(ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT);
limit = ts->linebuf.limit;
lastc = limit[-1];
if (lastc == '\n')
limit[-1] = 0;
onError = cx->errorReporter;
if (onError) {
report.filename = ts->filename;
report.lineno = ts->lineno;
linestr = js_NewStringCopyZ(cx, ts->linebuf.base, 0);
report.linebuf = linestr
? JS_GetStringBytes(linestr)
: NULL;
report.tokenptr = linestr
? report.linebuf + (ts->token.ptr - ts->linebuf.base)
: NULL;
report.uclinebuf = ts->linebuf.base;
report.uctokenptr = ts->token.ptr;
report.flags = flags;
(*onError)(cx, message, &report);
#if !defined XP_PC || !defined _MSC_VER || _MSC_VER > 800
} else {
if (!(ts->flags & TSF_INTERACTIVE))
fprintf(stderr, "JavaScript %s: ",
JSREPORT_IS_WARNING(flags) ? "warning" : "error");
if (ts->filename)
fprintf(stderr, "%s, ", ts->filename);
if (ts->lineno)
fprintf(stderr, "line %u: ", ts->lineno);
fprintf(stderr, "%s:\n%s\n",message,
js_DeflateString(cx, ts->linebuf.base,
ts->linebuf.limit - ts->linebuf.base));
#endif
}
if (lastc == '\n')
limit[-1] = lastc;
if (message) free(message);
if (report.messageArgs) free(report.messageArgs);
}
JSTokenType JSTokenType
js_PeekToken(JSContext *cx, JSTokenStream *ts) js_PeekToken(JSContext *cx, JSTokenStream *ts)
{ {
@ -691,16 +755,20 @@ retry:
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
c = GetChar(ts); c = GetChar(ts);
radix = 16; radix = 16;
} else if (JS7_ISDEC(c) && c < '8') { } else if (JS7_ISDEC(c)) {
/* /*
* XXX Warning needed. Checking against c < '8' above is * We permit 08 and 09 as decimal numbers, which makes our
* non-ECMA, but is required to support legacy code; it's * behaviour superset of the ECMA numeric grammar. We might
* likely that "08" and "09" are in use in code having to do * not always be so permissive, so we warn about it.
* with dates. So we need to support it, which makes our */
* behavior a superset of ECMA in this area. We should be if (c > '7' && JSVERSION_IS_ECMA(cx->version)) {
* raising a warning if '8' or '9' is encountered. js_ReportCompileError(cx, ts, JSREPORT_WARNING,
*/ "0%c is not an ECMA-legal numeric constant",
radix = 8; c);
radix = 10;
} else {
radix = 8;
}
} }
} }
@ -730,7 +798,8 @@ retry:
c = GetChar(ts); c = GetChar(ts);
} }
if (!JS7_ISDEC(c)) { if (!JS7_ISDEC(c)) {
js_ReportCompileError(cx, ts, "missing exponent"); js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"missing exponent");
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
} }
do { do {
@ -746,12 +815,14 @@ retry:
if (radix == 10) { if (radix == 10) {
if (!js_strtod(cx, ts->tokenbuf.base, &endptr, &dval)) { if (!js_strtod(cx, ts->tokenbuf.base, &endptr, &dval)) {
js_ReportCompileError(cx, ts, "out of memory"); js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"out of memory");
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
} }
} else { } else {
if (!js_strtointeger(cx, ts->tokenbuf.base, &endptr, radix, &dval)) { if (!js_strtointeger(cx, ts->tokenbuf.base, &endptr, radix, &dval)) {
js_ReportCompileError(cx, ts, "out of memory"); js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"out of memory");
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
} }
} }
@ -766,7 +837,8 @@ retry:
while ((c = GetChar(ts)) != qc) { while ((c = GetChar(ts)) != qc) {
if (c == '\n' || c == EOF) { if (c == '\n' || c == EOF) {
UngetChar(ts, c); UngetChar(ts, c);
js_ReportCompileError(cx, ts, "unterminated string literal"); js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"unterminated string literal");
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
} }
if (c == '\\') { if (c == '\\') {
@ -955,11 +1027,13 @@ skipline:
if (c == '/' && MatchChar(ts, '*')) { if (c == '/' && MatchChar(ts, '*')) {
if (MatchChar(ts, '/')) if (MatchChar(ts, '/'))
goto retry; goto retry;
js_ReportCompileError(cx, ts, "nested comment"); js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"nested comment");
} }
} }
if (c == EOF) { if (c == EOF) {
js_ReportCompileError(cx, ts, "unterminated comment"); js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"unterminated comment");
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
} }
goto retry; goto retry;
@ -974,7 +1048,7 @@ skipline:
while ((c = GetChar(ts)) != '/') { while ((c = GetChar(ts)) != '/') {
if (c == '\n' || c == EOF) { if (c == '\n' || c == EOF) {
UngetChar(ts, c); UngetChar(ts, c);
js_ReportCompileError(cx, ts, js_ReportCompileError(cx, ts,JSREPORT_ERROR,
"unterminated regular expression literal"); "unterminated regular expression literal");
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
} }
@ -998,7 +1072,7 @@ skipline:
c = PeekChar(ts); c = PeekChar(ts);
if (JS7_ISLET(c)) { if (JS7_ISLET(c)) {
ts->token.ptr = ts->linebuf.ptr - 1; ts->token.ptr = ts->linebuf.ptr - 1;
js_ReportCompileError(cx, ts, js_ReportCompileError(cx, ts,JSREPORT_ERROR,
"invalid flag after regular expression"); "invalid flag after regular expression");
(void) GetChar(ts); (void) GetChar(ts);
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
@ -1065,7 +1139,7 @@ skipline:
break; break;
n = 10 * n + JS7_UNDEC(c); n = 10 * n + JS7_UNDEC(c);
if (n >= ATOM_INDEX_LIMIT) { if (n >= ATOM_INDEX_LIMIT) {
js_ReportCompileError(cx, ts, js_ReportCompileError(cx, ts,JSREPORT_ERROR,
"overlarge sharp variable number"); "overlarge sharp variable number");
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
} }
@ -1082,7 +1156,8 @@ skipline:
#endif /* JS_HAS_SHARP_VARS */ #endif /* JS_HAS_SHARP_VARS */
default: default:
js_ReportCompileError(cx, ts, "illegal character"); js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"illegal character");
RETURN(TOK_ERROR); RETURN(TOK_ERROR);
} }

Просмотреть файл

@ -226,9 +226,12 @@ js_MapKeywords(void (*mapfun)(const char *));
* associated with cx. * associated with cx.
*/ */
extern void extern void
js_ReportCompileError(JSContext *cx, JSTokenStream *ts, const char *format, js_ReportCompileError(JSContext *cx, JSTokenStream *ts, uintN flags,
...); const char *format, ...);
void
js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, uintN flags,
const uintN errorNumber, ...);
/* /*
* Look ahead one token and return its type. * Look ahead one token and return its type.
*/ */

Просмотреть файл

@ -109,7 +109,9 @@ str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
(mask = (jsint)d) != d || (mask = (jsint)d) != d ||
mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH)) mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))
{ {
JS_ReportError(cx, "invalid string escape mask %x", mask); char numBuf[12];
sprintf(numBuf, "%x", mask);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_STRING_MASK, numBuf);
return JS_FALSE; return JS_FALSE;
} }
} else { } else {
@ -744,8 +746,7 @@ str_lastIndexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
static JSBool static JSBool
str_nyi(JSContext *cx, const char *what) str_nyi(JSContext *cx, const char *what)
{ {
JS_ReportError(cx, "sorry, String.prototype.%s is not yet implemented", JS_ReportErrorNumber(cx, NULL, JSMSG_NO_STRING_PROTO, what);
what);
return JS_FALSE; return JS_FALSE;
} }
#endif #endif

Просмотреть файл

@ -21,6 +21,7 @@
#include "prtypes.h" #include "prtypes.h"
#include "prassert.h" #include "prassert.h"
#include "jsapi.h" #include "jsapi.h"
#include "jscntxt.h"
#include "jsobj.h" /* js_XDRObject */ #include "jsobj.h" /* js_XDRObject */
#include "jsstr.h" #include "jsstr.h"
#include "jsxdrapi.h" #include "jsxdrapi.h"
@ -43,13 +44,12 @@ typedef struct JSXDRMemState {
#define MEM_COUNT(xdr) (MEM_PRIV(xdr)->count) #define MEM_COUNT(xdr) (MEM_PRIV(xdr)->count)
#define MEM_LIMIT(xdr) (MEM_PRIV(xdr)->limit) #define MEM_LIMIT(xdr) (MEM_PRIV(xdr)->limit)
static char unexpected_end_of_data_str[] = "unexpected end of data";
#define MEM_LEFT(xdr, bytes) \ #define MEM_LEFT(xdr, bytes) \
PR_BEGIN_MACRO \ PR_BEGIN_MACRO \
if ((xdr)->mode == JSXDR_DECODE && \ if ((xdr)->mode == JSXDR_DECODE && \
MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \ MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
JS_ReportError((xdr)->cx, unexpected_end_of_data_str); \ JS_ReportErrorNumber((xdr)->cx, NULL, JSMSG_END_OF_DATA); \
return 0; \ return 0; \
} \ } \
PR_END_MACRO PR_END_MACRO
@ -70,7 +70,7 @@ static char unexpected_end_of_data_str[] = "unexpected end of data";
} \ } \
} else { \ } else { \
if (MEM_LIMIT(xdr) < MEM_COUNT(xdr) + bytes) { \ if (MEM_LIMIT(xdr) < MEM_COUNT(xdr) + bytes) { \
JS_ReportError((xdr)->cx, unexpected_end_of_data_str); \ JS_ReportErrorNumber((xdr)->cx, NULL, JSMSG_END_OF_DATA); \
return 0; \ return 0; \
} \ } \
} \ } \
@ -135,7 +135,7 @@ mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence)
switch (whence) { switch (whence) {
case JSXDR_SEEK_CUR: case JSXDR_SEEK_CUR:
if ((int32)MEM_COUNT(xdr) + offset < 0) { if ((int32)MEM_COUNT(xdr) + offset < 0) {
JS_ReportError(xdr->cx, "illegal seek beyond start"); JS_ReportErrorNumber(xdr->cx, NULL, JSMSG_SEEK_BEYOND_START);
return JS_FALSE; return JS_FALSE;
} }
if (offset > 0) if (offset > 0)
@ -144,7 +144,7 @@ mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence)
return JS_TRUE; return JS_TRUE;
case JSXDR_SEEK_SET: case JSXDR_SEEK_SET:
if (offset < 0) { if (offset < 0) {
JS_ReportError(xdr->cx, "illegal seek beyond start"); JS_ReportErrorNumber(xdr->cx, NULL, JSMSG_SEEK_BEYOND_START);
return JS_FALSE; return JS_FALSE;
} }
if (xdr->mode == JSXDR_ENCODE) { if (xdr->mode == JSXDR_ENCODE) {
@ -153,7 +153,7 @@ mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence)
MEM_COUNT(xdr) = offset; MEM_COUNT(xdr) = offset;
} else { } else {
if ((uint32)offset > MEM_LIMIT(xdr)) { if ((uint32)offset > MEM_LIMIT(xdr)) {
JS_ReportError(xdr->cx, "illegal seek beyond end"); JS_ReportErrorNumber(xdr->cx, NULL, JSMSG_SEEK_BEYOND_END);
return JS_FALSE; return JS_FALSE;
} }
MEM_COUNT(xdr) = offset; MEM_COUNT(xdr) = offset;
@ -163,13 +163,16 @@ mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence)
if (offset >= 0 || if (offset >= 0 ||
xdr->mode == JSXDR_ENCODE || xdr->mode == JSXDR_ENCODE ||
(int32)MEM_LIMIT(xdr) + offset < 0) { (int32)MEM_LIMIT(xdr) + offset < 0) {
JS_ReportError(xdr->cx, "illegal end-based seek"); JS_ReportErrorNumber(xdr->cx, NULL, JSMSG_END_SEEK);
return JS_FALSE; return JS_FALSE;
} }
MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset; MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset;
return JS_TRUE; return JS_TRUE;
default: default: {
JS_ReportError(xdr->cx, "unknown seek whence: %d", whence); char numBuf[12];
sprintf(numBuf, "%d", whence);
JS_ReportErrorNumber(xdr->cx, NULL, JSMSG_WHITHER_WHENCE, numBuf);
}
return JS_FALSE; return JS_FALSE;
} }
} }
@ -468,7 +471,8 @@ JS_XDRValue(JSXDRState *xdr, jsval *vp)
if (!JS_XDRUint32(xdr, (uint32 *)vp)) if (!JS_XDRUint32(xdr, (uint32 *)vp))
return JS_FALSE; return JS_FALSE;
break; break;
default: default: {
char numBuf[12];
if (type & JSVAL_INT) { if (type & JSVAL_INT) {
uint32 i; uint32 i;
if (xdr->mode == JSXDR_ENCODE) if (xdr->mode == JSXDR_ENCODE)
@ -479,7 +483,9 @@ JS_XDRValue(JSXDRState *xdr, jsval *vp)
*vp = INT_TO_JSVAL(i); *vp = INT_TO_JSVAL(i);
break; break;
} }
JS_ReportError(xdr->cx, "unknown jsval type %#lx for XDR", type); sprintf(numBuf, "%#lx", type);
JS_ReportErrorNumber(xdr->cx, NULL, JSMSG_BAD_JVAL_TYPE, type);
}
return JS_FALSE; return JS_FALSE;
} }
return JS_TRUE; return JS_TRUE;

Просмотреть файл

@ -46,6 +46,10 @@
#ifdef XP_UNIX #ifdef XP_UNIX
#ifdef SOLARIS
extern int gettimeofday(struct timeval *tv);
#endif
#include <sys/time.h> #include <sys/time.h>
#ifdef NEED_TIME_R #ifdef NEED_TIME_R
@ -294,7 +298,11 @@ PR_Now(void)
#endif #endif
#ifdef XP_UNIX #ifdef XP_UNIX
#if defined(SOLARIS)
gettimeofday(&tv);
#else
gettimeofday(&tv, 0); gettimeofday(&tv, 0);
#endif /* SOLARIS */
LL_UI2L(s2us, PR_USEC_PER_SEC); LL_UI2L(s2us, PR_USEC_PER_SEC);
LL_UI2L(s, tv.tv_sec); LL_UI2L(s, tv.tv_sec);
LL_UI2L(us, tv.tv_usec); LL_UI2L(us, tv.tv_usec);