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)
OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH)
else
ifeq ($(OS_ARCH),AIX)
OS_RELEASE := $(shell uname -v).$(shell uname -r)
else
OS_RELEASE := $(shell uname -r)
endif
endif
# Virtually all Linux versions are identical.
# Any distinctions are handled in linux.h
@ -40,6 +44,8 @@ endif
ASFLAGS =
DEFINES =
#NS_USE_NATIVE = 1
include config/$(OS_CONFIG).mk
ifdef BUILD_OPT
@ -83,6 +89,20 @@ CFLAGS = $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \
-DJSFILE $(XCFLAGS)
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
PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \
$(INCLUDES) $(XCFLAGS)
@ -114,6 +134,7 @@ JS_HFILES = \
jscntxt.h \
jsdate.h \
jsemit.h \
jsexn.h \
jsfun.h \
jsgc.h \
jsinterp.h \
@ -160,6 +181,7 @@ JS_CFILES = \
jsdate.c \
jsdbgapi.c \
jsemit.c \
jsexn.c \
jsfun.c \
jsgc.c \
jsinterp.c \
@ -177,6 +199,10 @@ JS_CFILES = \
jsxdrapi.c \
$(NULL)
ifdef PERLCONNECT
JS_CFILES += jsperl.c
endif
LIB_CFILES = $(PR_CFILES) $(JS_CFILES)
LIB_ASFILES := $(wildcard *_$(OS_ARCH).s)
PROG_CFILES = js.c

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -13,15 +13,21 @@
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
#
# 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
#.c.o:

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

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

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

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

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

@ -104,6 +104,8 @@ static JSDJContext *_jsdjc;
#endif /* JSDEBUGGER_JAVA_UI */
#endif /* JSDEBUGGER */
static int reportWarnings;
static void
Process(JSContext *cx, JSObject *obj, char *filename)
{
@ -161,6 +163,31 @@ Process(JSContext *cx, JSObject *obj, char *filename)
if (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);
}
}
@ -180,7 +207,7 @@ static int
usage(void)
{
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;
}
@ -204,6 +231,9 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
JS_SetVersion(cx, atoi(argv[i+1]));
i++;
break;
case 'w':
reportWarnings++;
break;
case 'f':
if (i+1 == argc) {
@ -423,7 +453,7 @@ Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
int32 i;
if (argc == 0) {
JS_ReportError(cx, "usage: trap [fun] [pc] expr");
JS_ReportErrorNumber(cx, NULL, JSMSG_TRAP_USAGE);
return JS_FALSE;
}
argc--;
@ -457,7 +487,7 @@ LineToPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsbytecode *pc;
if (argc == 0) {
JS_ReportError(cx, "usage: line2pc [fun] line");
JS_ReportErrorNumber(cx, NULL, JSMSG_LINE2PC_USAGE);
return JS_FALSE;
}
script = cx->fp->down->script;
@ -619,13 +649,14 @@ DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
return JS_FALSE;
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;
}
file = fopen(fun->script->filename, "r");
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;
}
@ -652,7 +683,7 @@ DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
bupline = 0;
while (line1 < line2) {
if (!fgets(linebuf, LINE_BUF_LEN, file)) {
JS_ReportError(cx, "unexpected EOF in %s",
JS_ReportErrorNumber(cx, NULL, JSMSG_UNEXPECTED_EOF,
fun->script->filename);
goto bail;
}
@ -826,7 +857,7 @@ DoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
uintN attrs;
if (argc != 2) {
JS_ReportError(cx, "usage: doexp obj id");
JS_ReportErrorNumber(cx, NULL, JSMSG_DOEXP_USAGE);
return JS_FALSE;
}
if (!JS_ValueToObject(cx, argv[0], &obj))
@ -1120,24 +1151,52 @@ static void
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
int i, j, k, n;
char *prefix = NULL, *tmp;
fputs("js: ", stderr);
if (!report) {
fprintf(stderr, "%s\n", message);
return;
}
if (report->filename)
fprintf(stderr, "%s, ", report->filename);
if (report->lineno)
fprintf(stderr, "line %u: ", report->lineno);
fputs(message, stderr);
if (!report->linebuf) {
putc('\n', stderr);
/*
* Conditionally ignore reported warnings, and ignore error reports for
* which a JavaScript exception has been thrown.
*/
if ((JSREPORT_IS_WARNING(report->flags) && !reportWarnings) ||
JSREPORT_IS_EXCEPTION(report->flags)) {
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;
for (i = j = 0; i < n; i++) {
if (report->linebuf[i] == '\t') {
@ -1149,6 +1208,8 @@ my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
j++;
}
fputs("^\n", stderr);
out:
JS_free(cx, prefix);
}
#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
@ -1265,6 +1326,12 @@ main(int argc, char **argv)
JSContext *cx;
JSObject *glob, *it;
int result;
#ifdef LIVECONNECT
JavaVM *java_vm = NULL;
#endif
#ifdef JSDEBUGGER_JAVA_UI
JNIEnv *java_env;
#endif
#ifdef XP_OS2
/* these streams are normally line buffered on OS/2 and need a \n, *
@ -1278,10 +1345,10 @@ main(int argc, char **argv)
#endif
version = JSVERSION_DEFAULT;
#ifndef LIVECONNECT
argc--;
argv++;
#endif
rt = JS_NewRuntime(8L * 1024L * 1024L);
if (!rt)
return 1;
@ -1309,12 +1376,7 @@ main(int argc, char **argv)
return 1;
#ifdef PERLCONNECT
if (!js_InitPerlClass(cx, glob))
return 1;
#endif
#ifdef LIVECONNECT
if (!JSJ_SimpleInit(cx, glob, NULL, getenv("CLASSPATH")))
if (!JS_InitPerlClass(cx, glob))
return 1;
#endif
@ -1332,7 +1394,9 @@ main(int argc, char **argv)
if (! _jsdjc)
return 1;
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.
* 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 */
#ifdef LIVECONNECT
if (!JSJ_SimpleInit(cx, glob, java_vm, getenv("CLASSPATH")))
return 1;
#endif
result = ProcessArgs(cx, glob, argv, argc);
#ifdef JSDEBUGGER

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

@ -36,6 +36,7 @@
#include "jsconfig.h"
#include "jsdate.h"
#include "jsemit.h"
#include "jsexn.h"
#include "jsfun.h"
#include "jsgc.h"
#include "jsinterp.h"
@ -113,10 +114,12 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
if (required) {
fun = js_ValueToFunction(cx, &argv[-2], JS_FALSE);
if (fun) {
JS_ReportError(cx,
"%s requires more than %u argument%s",
char numBuf[12];
sprintf(numBuf, "%u", argc);
JS_ReportErrorNumber(cx, NULL, JSMSG_MORE_ARGS_NEEDED,
JS_GetFunctionName(fun),
argc, (argc == 1) ? "" : "s");
numBuf,
(argc == 1) ? "" : "s");
}
return JS_FALSE;
}
@ -184,10 +187,13 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
break;
case '*':
break;
default:
JS_ReportError(cx, "invalid format character %c", *cp);
default: {
char charBuf[2] = " ";
charBuf[0] = *cp;
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_CHAR, charBuf);
return JS_FALSE;
}
}
i++;
}
va_end(ap);
@ -239,9 +245,12 @@ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
if (ok)
*vp = BOOLEAN_TO_JSVAL(b);
break;
default:
JS_ReportError(cx, "unknown type %d", (int)type);
default: {
char numBuf[12];
sprintf(numBuf, "%d", (int)type);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_TYPE, numBuf);
ok = JS_FALSE;
}
break;
}
return ok;
@ -366,6 +375,22 @@ JS_NewRuntime(uint32 maxbytes)
{
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())
return NULL;
rt = malloc(sizeof(JSRuntime));
@ -663,6 +688,9 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
#endif
#if JS_HAS_SCRIPT_OBJECT
js_InitScriptClass(cx, obj) &&
#endif
#if JS_HAS_ERROR_EXCEPTIONS
js_InitExceptionClasses(cx, obj) &&
#endif
js_InitDateClass(cx, obj);
}
@ -679,7 +707,7 @@ JS_malloc(JSContext *cx, size_t nbytes)
{
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*/
nbytes = 1;
#endif
@ -797,7 +825,7 @@ JS_LockGCThing(JSContext *cx, void *thing)
CHECK_REQUEST(cx);
ok = js_LockGCThing(cx, thing);
if (!ok)
JS_ReportError(cx, "can't lock memory");
JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_LOCK);
return ok;
}
@ -809,7 +837,7 @@ JS_UnlockGCThing(JSContext *cx, void *thing)
CHECK_REQUEST(cx);
ok = js_UnlockGCThing(cx, thing);
if (!ok)
JS_ReportError(cx, "can't unlock memory");
JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_UNLOCK);
return ok;
}
@ -1015,7 +1043,7 @@ JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
if (argv) {
fun = js_ValueToFunction(cx, &argv[-2], JS_FALSE);
if (fun) {
JS_ReportError(cx, "%s.prototype.%s called on incompatible %s",
JS_ReportErrorNumber(cx, NULL, JSMSG_INCOMPATIBLE_PROTO,
clasp->name, JS_GetFunctionName(fun),
OBJ_GET_CLASS(cx, obj)->name);
}
@ -1108,7 +1136,7 @@ JS_GetConstructor(JSContext *cx, JSObject *proto)
if (!ok)
return NULL;
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);
return NULL;
}
@ -1323,7 +1351,7 @@ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
}
if (obj2 != obj || !OBJ_IS_NATIVE(obj2)) {
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);
return JS_FALSE;
}
@ -1361,17 +1389,14 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
return rval;
}
JS_PUBLIC_API(JSBool)
JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
static JSBool
GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
uintN *attrsp, JSBool *foundp)
{
JSAtom *atom;
JSObject *obj2;
JSProperty *prop;
JSBool ok;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, name, strlen(name), 0);
if (!atom)
return JS_FALSE;
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;
}
JS_PUBLIC_API(JSBool)
JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
static JSBool
SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
uintN attrs, JSBool *foundp)
{
JSAtom *atom;
JSObject *obj2;
JSProperty *prop;
JSBool ok;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, name, strlen(name), 0);
if (!atom)
return JS_FALSE;
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;
}
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_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
{
@ -1488,6 +1531,28 @@ JS_DefineUCProperty(JSContext *cx, JSObject *obj,
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_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
@ -1633,9 +1698,11 @@ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
return JS_FALSE;
}
if (obj2 != obj || !OBJ_IS_NATIVE(obj2)) {
char numBuf[12];
OBJ_DROP_PROPERTY(cx, obj2, prop);
JS_ReportError(cx, "can't alias %ld to %s in class %s",
(long)alias, name, OBJ_GET_CLASS(cx, obj2)->name);
sprintf(numBuf, "%ld", (long)alias);
JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_ALIAS,
numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
return JS_FALSE;
}
scope = (JSScope *) obj->map;
@ -2423,7 +2490,30 @@ JS_ReportError(JSContext *cx, const char *format, ...)
CHECK_REQUEST(cx);
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);
}
@ -2464,7 +2554,7 @@ JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
JS_free(cx, chars);
return obj;
#else
JS_ReportError(cx, "sorry, regular expression are not supported");
JS_ReportErrorNumber(cx, NULL, JSMSG_NO_REG_EXPS);
return NULL;
#endif
}
@ -2476,7 +2566,7 @@ JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
#if JS_HAS_REGEXPS
return js_NewRegExpObject(cx, chars, length, flags);
#else
JS_ReportError(cx, "sorry, regular expression are not supported");
JS_ReportErrorNumber(cx, NULL, JSMSG_NO_REG_EXPS);
return NULL;
#endif
}
@ -2528,7 +2618,7 @@ JS_IsExceptionPending(JSContext *cx)
{
CHECK_REQUEST(cx);
#if JS_HAS_EXCEPTIONS
return (JSBool) cx->fp->throwing;
return (JSBool) cx->throwing;
#else
return JS_FALSE;
#endif
@ -2539,9 +2629,9 @@ JS_GetPendingException(JSContext *cx, jsval *vp)
{
CHECK_REQUEST(cx);
#if JS_HAS_EXCEPTIONS
if (!cx->fp->throwing)
if (!cx->throwing)
return JS_FALSE;
*vp = cx->fp->exception;
*vp = cx->exception;
return JS_TRUE;
#else
return JS_FALSE;
@ -2553,8 +2643,8 @@ JS_SetPendingException(JSContext *cx, jsval v)
{
CHECK_REQUEST(cx);
#if JS_HAS_EXCEPTIONS
cx->fp->throwing = JS_TRUE;
cx->fp->exception = v;
cx->throwing = JS_TRUE;
cx->exception = v;
#endif
}
@ -2563,7 +2653,7 @@ JS_ClearPendingException(JSContext *cx)
{
CHECK_REQUEST(cx);
#if JS_HAS_EXCEPTIONS
cx->fp->throwing = JS_FALSE;
cx->throwing = JS_FALSE;
#endif
}

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

@ -605,6 +605,29 @@ JS_DefineUCProperty(JSContext *cx, JSObject *obj,
JSPropertyOp getter, JSPropertyOp setter,
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)
JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen,
@ -904,6 +927,19 @@ JS_CompareStrings(JSString *str1, JSString *str2);
extern JS_PUBLIC_API(void)
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.
*/
@ -917,8 +953,33 @@ struct JSErrorReport {
const char *tokenptr; /* pointer to error token in linebuf */
const jschar *uclinebuf; /* unicode (original) line buffer */
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)
JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);

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

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

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

@ -605,7 +605,9 @@ js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i)
PR_ASSERT(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;
}
atom = map->vector[i];
@ -629,7 +631,7 @@ js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
count = al->count;
if (count >= ATOM_INDEX_LIMIT) {
JS_ReportError(cx, "too many literals");
JS_ReportErrorNumber(cx, NULL, JSMSG_TOO_MANY_LITERALS);
return JS_FALSE;
}
vector = JS_malloc(cx, (size_t) count * sizeof *vector);

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

@ -32,6 +32,7 @@
#include "jscntxt.h"
#include "jsconfig.h"
#include "jsdbgapi.h"
#include "jsexn.h"
#include "jsgc.h"
#include "jslock.h"
#include "jsobj.h"
@ -168,7 +169,7 @@ js_ContextIterator(JSRuntime *rt, JSContext **iterp)
}
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;
JSErrorReport report, *reportp;
@ -181,8 +182,10 @@ js_ReportErrorVA(JSContext *cx, const char *format, va_list ap)
/* XXX should fetch line somehow */
report.linebuf = NULL;
report.tokenptr = NULL;
report.flags = flags;
reportp = &report;
} else {
/* XXXshaver still fill out report here for flags? */
reportp = NULL;
}
last = PR_vsmprintf(format, ap);
@ -193,6 +196,161 @@ js_ReportErrorVA(JSContext *cx, const char *format, va_list ap)
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_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
{
@ -213,7 +371,7 @@ js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
void
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
@ -221,3 +379,14 @@ js_ReportIsNotDefined(JSContext *cx, const char *name)
void js_traceon(JSContext *cx) { cx->tracefp = stderr; }
void js_traceoff(JSContext *cx) { cx->tracefp = NULL; }
#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;
#endif
JSStackFrame *dormantFrameChain; /* dormant frame chains */
JSPackedBool throwing; /* is there a pending exception? */
jsval exception; /* most-recently-thrown exceptin */
};
typedef struct JSInterpreterHooks {
@ -188,7 +190,14 @@ js_ContextIterator(JSRuntime *rt, JSContext **iterp);
*/
#ifdef va_start
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
/*
@ -200,6 +209,17 @@ js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
extern void
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
#endif /* jscntxt_h___ */

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

@ -68,6 +68,7 @@
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof 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_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
#elif JS_VERSION == 110
@ -114,6 +115,7 @@
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof 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_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
#elif JS_VERSION == 120
@ -160,6 +162,7 @@
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof 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_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
#elif JS_VERSION == 130
@ -206,6 +209,7 @@
#define JS_HAS_INSTANCEOF 0 /* has {p:1} instanceof 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_ERROR_EXCEPTIONS 0 /* has error object hierarchy */
#elif JS_VERSION == 140
@ -252,6 +256,9 @@
#define JS_HAS_INSTANCEOF 1 /* has {p:1} instanceof 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_ERROR_EXCEPTIONS 1 /* rt errors reflected as exceptions */
#define JS_HAS_DFLT_MSG_STRINGS 1 /* provides English error messages */
#else

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

@ -345,7 +345,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
JSWatchPoint *wp;
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);
return JS_FALSE;
}
@ -580,12 +580,36 @@ JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
return fp->fun && fp->fun->call;
}
/* this is deprecated, use JS_GetFrameScopeChain instead */
JS_PUBLIC_API(JSObject *)
JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
{
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_GetFrameThis(JSContext *cx, JSStackFrame *fp)
{
@ -680,12 +704,22 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
sym = sprop->symbols;
pd->id = sym ? js_IdToValue(sym_id(sym)) : JSVAL_VOID;
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)
| ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 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_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->slot = (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE))
? JSVAL_TO_INT(sprop->id)
@ -706,11 +740,16 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
uint32 i, n;
JSPropertyDesc *pd;
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;
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->array = NULL;
return JS_TRUE;

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

@ -130,9 +130,16 @@ JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
extern JS_PUBLIC_API(void *)
JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp);
/* this is deprecated, use JS_GetFrameScopeChain instead */
extern JS_PUBLIC_API(JSObject *)
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 *)
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp);

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

@ -107,9 +107,11 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
nuses = 2 + GET_ARGC(pc); /* stack: fun, this, [argc arguments] */
cg->stackDepth -= nuses;
if (cg->stackDepth < 0) {
JS_ReportError(cx,
"internal error compiling %s: stack underflow at pc %d",
cg->filename ? cg->filename : "stdin", target);
char numBuf[12];
sprintf(numBuf, "%d", target);
JS_ReportErrorNumber(cx, NULL,
JSMSG_STACK_UNDERFLOW,
cg->filename ? cg->filename : "stdin", numBuf);
}
cg->stackDepth += cs->ndefs;
if ((uintN)cg->stackDepth > cg->maxStackDepth)
@ -199,7 +201,7 @@ StatementName(JSCodeGenerator *cg)
static void
ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg)
{
JS_ReportError(cx, "%s too large", StatementName(cg));
JS_ReportErrorNumber(cx, NULL, JSMSG_NEED_DIET, StatementName(cg));
}
JSBool
@ -238,7 +240,7 @@ EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
switch (stmt->type) {
case STMT_FINALLY:
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
js_Emit3(cx, cg, JSOP_JSR, JUMP_OFFSET_HI(finallyIndex),
js_Emit3(cx, cg, JSOP_GOSUB, JUMP_OFFSET_HI(finallyIndex),
JUMP_OFFSET_LO(finallyIndex)) < 0)
return -1;
finallyIndex--;
@ -462,7 +464,7 @@ FixupFinallyJumps(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t tryStart,
jsbytecode *pc;
pc = cg->base + tryStart;
BYTECODE_ITER(pc, cg->next, \
if (*pc == JSOP_JSR) { \
if (*pc == JSOP_GOSUB) { \
ptrdiff_t index = GET_JUMP_OFFSET(pc); \
if (index <= 0) { \
if (index == 0) { \
@ -664,6 +666,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
void *mark;
JSParseNode **table;
jsbytecode *pc;
JSBool hasDefault = JS_FALSE;
/* Emit code for the discriminant first. */
if (!js_EmitTree(cx, cg, pn->pn_kid1))
@ -686,6 +689,11 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
high = JSVAL_INT_MIN;
cg2.base = NULL;
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
if (pn3->pn_type == TOK_DEFAULT) {
hasDefault = JS_TRUE;
ncases--; /* one of the "cases" was the default */
continue;
}
PR_ASSERT(pn3->pn_type == TOK_CASE);
if (!cg2.base) {
if (!js_InitCodeGenerator(cx, &cg2, cg->filename,
@ -722,10 +730,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (!JSVAL_IS_NUMBER(pn3->pn_val) &&
!JSVAL_IS_STRING(pn3->pn_val) &&
!JSVAL_IS_BOOLEAN(pn3->pn_val)) {
JS_ReportError(cx,
"%s, line %u: invalid case expression",
char numBuf[12];
sprintf(numBuf, "%u", pn4->pn_pos.begin.lineno);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_CASE,
cg2.filename ? cg2.filename : "stdin",
pn4->pn_pos.begin.lineno);
numBuf);
return JS_FALSE;
}
@ -782,15 +792,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (!js_EmitTree(cx, cg, pn4))
return JS_FALSE;
pn3->pn_offset = pn4->pn_offset;
if (pn3->pn_type == TOK_DEFAULT)
off = pn3->pn_offset - top;
}
/* Emit the default case (if any) and compute default offset. */
pn3 = pn->pn_kid3;
if (pn3) {
if (!js_EmitTree(cx, cg, pn3))
return JS_FALSE;
off = pn3->pn_offset - top;
} else {
if (!hasDefault) {
/* If no default case, offset for default is to end of switch */
off = CG_OFFSET(cg) - top;
}
@ -824,6 +831,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
memset(table, 0, tablesize);
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
if (pn3->pn_type == TOK_DEFAULT)
continue;
i = JSVAL_TO_INT(pn3->pn_val);
i -= low;
PR_ASSERT((uint32)i < tablen);
@ -843,6 +852,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
pc += 2;
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
if (pn3->pn_type == TOK_DEFAULT)
continue;
atom = js_AtomizeValue(cx, pn3->pn_val, 0);
if (!atom)
return JS_FALSE;
@ -1130,24 +1141,25 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
case TOK_TRY: {
ptrdiff_t start, end, catchStart, finallyCatch, catchjmp = -1;
JSParseNode *iter = pn;
uint16 depth;
/* XXX use -(CG_OFFSET + 1) */
#define EMIT_FINALLY_JSR(cx, cg) \
#define EMIT_FINALLY_GOSUB(cx, cg) \
PR_BEGIN_MACRO \
if (!js_Emit3(cx, cg, JSOP_JSR, 0, 0)) \
if (!js_Emit3(cx, cg, JSOP_GOSUB, 0, 0)) \
return JS_FALSE; \
PR_END_MACRO
;
/*
* When a finally block is `active' (STMT_FINALLY on the treeContext),
* non-local jumps result in a JSR being written into the bytecode
* stream for later fixup. The jsr is written with offset 0 for the
* non-local jumps result in a GOSUB being written into the bytecode
* stream for later fixup. The GOSUB is written with offset 0 for the
* innermost finally, -1 for the next, etc. As the finally fixup code
* runs for each finished try/finally, it will fix the JSRs with
* runs for each finished try/finally, it will fix the GOSUBs with
* offset 0 to match the appropriate finally code for its block
* and decrement all others by one.
*
* NOTE: This will cause problems if we use JSRs for something other
* NOTE: This will cause problems if we use GOSUBs for something other
* than finally handling in the future. Caveat hacker!
*/
if (pn->pn_kid3) {
@ -1155,6 +1167,20 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
CG_OFFSET(cg));
}
/*
* About SETSP:
* An exception can be thrown while the stack is in an
* unbalanced state, and this causes problems with things like
* function invocation later on.
*
* To fix this, we compute the `balanced' stack depth upon try entry,
* and then restore the stack to this depth when we hit the first catch
* or finally block. We can't just zero the stack, because things like
* for/in and with that are active upon entry to the block keep things
* on the stack.
*/
depth = cg->stackDepth;
/* mark try location for decompilation, then emit try block */
if (js_NewSrcNote2(cx, cg, SRC_TRYFIN, 0) < 0 ||
js_Emit1(cx, cg, JSOP_NOP) < 0)
@ -1167,7 +1193,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
return JS_FALSE;
if (pn->pn_kid3)
EMIT_FINALLY_JSR(cx, cg);
EMIT_FINALLY_GOSUB(cx, cg);
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
return JS_FALSE;
jmp = js_Emit3(cx, cg, JSOP_GOTO, 0, 0);
@ -1196,7 +1222,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
*
* If there's no catch block without a catchguard, the last
* <offset to next catch block> points to rethrow code. This
* code will jsr to the finally code if appropriate, and is
* code will GOSUB to the finally code if appropriate, and is
* also used for the catch-all trynote for capturing exceptions
* thrown from catch{} blocks.
*/
@ -1216,6 +1242,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)
return JS_FALSE;
} else {
/* set stack to orig depth (see SETSP comment above) */
EMIT_ATOM_INDEX_OP(JSOP_SETSP, (jsatomid)depth);
}
/* non-zero guardnote is length of catchguard */
@ -1277,9 +1306,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)
return JS_FALSE;
/* jsr <finally>, if required */
/* gosub <finally>, if required */
if (pn->pn_kid3)
EMIT_FINALLY_JSR(cx, cg);
EMIT_FINALLY_GOSUB(cx, cg);
/* this will get fixed up to jump to after catch/finally */
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
@ -1292,13 +1321,21 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
/*
* we use a [leavewith],[jsr],rethrow block for rethrowing
* we use a [leavewith],[gosub],rethrow block for rethrowing
* when there's no unguarded catch, and also for
* running finally code while letting an uncaught exception
* pass through
*/
if (pn->pn_kid3 ||
(catchjmp != -1 && iter->pn_kid1->pn_expr)) {
/*
* Emit another stack fix, because the catch could itself
* throw an exception in an unbalanced state, and the finally
* may need to call functions etc.
*/
EMIT_ATOM_INDEX_OP(JSOP_SETSP, (jsatomid)depth);
if (catchjmp != -1) {
CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, catchjmp);
}
@ -1312,7 +1349,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (pn->pn_kid3) {
finallyCatch = CG_OFFSET(cg);
EMIT_FINALLY_JSR(cx, cg);
EMIT_FINALLY_GOSUB(cx, cg);
}
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
js_Emit1(cx, cg, JSOP_EXCEPTION) < 0 ||
@ -1322,7 +1359,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
/* if we've got a finally, it goes here, and we have to fix up
the jsrs that might have been emitted before non-local jumps */
the gosubs that might have been emitted before non-local jumps */
if (pn->pn_kid3) {
ptrdiff_t finallyIndex;
@ -1335,7 +1372,6 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
!js_EmitTree(cx, cg, pn->pn_kid3) ||
js_Emit1(cx, cg, JSOP_RETSUB) < 0)
return JS_FALSE;
}
if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 ||
@ -2293,13 +2329,32 @@ JSBool
js_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg)
{
size_t size;
if (!cg->treeContext.tryCount)
return JS_TRUE;
if (!cg->tryBase) {
size = (cg->treeContext.tryCount + 1) * sizeof(JSTryNote);
PR_ARENA_ALLOCATE(cg->tryBase, &cx->tempPool, size);
if (!cg->tryBase)
return JS_FALSE;
cg->tryNext = cg->tryBase;
} else {
/* already have some TryNotes here, so extend them. */
ptrdiff_t nextOffset = cg->tryNext - cg->tryBase;
size_t oldsize = (char *)cg->tryLimit - (char *)cg->tryBase;
size = oldsize + cg->treeContext.tryCount * sizeof(JSTryNote);
PR_ARENA_GROW(cg->tryBase, &cx->tempPool, oldsize, size);
if (!cg->tryBase)
return JS_FALSE;
/* need to reset tryNext because GROW may relocate the block */
cg->tryNext = (JSTryNote *)((char *)cg->tryBase + nextOffset);
}
cg->tryLimit = (JSTryNote *)((char *)cg->tryBase + size);
/* reset tryCount */
cg->treeContext.tryCount = 0;
return JS_TRUE;
}

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:
if (JSVERSION_IS_ECMA(cx->version))
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;
}
@ -1130,21 +1130,36 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
#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
fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
{
jsval pval;
JSString *str;
if (!OBJ_GET_PROPERTY(cx, obj,
(jsid)cx->runtime->atomState.classPrototypeAtom,
&pval)) {
return JS_FALSE;
}
if (JSVAL_IS_PRIMITIVE(pval)) {
*bp = JS_FALSE;
return JS_TRUE;
}
if (!JSVAL_IS_PRIMITIVE(pval))
return js_IsDelegate(cx, JSVAL_TO_OBJECT(pval), v, bp);
/*
* 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_FALSE;
}
#else /* !JS_HAS_INSTANCEOF */
@ -1446,7 +1461,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
* TOK_ERROR.
*/
if (tt != TOK_NAME) {
JS_ReportError(cx, "missing formal parameter");
JS_ReportErrorNumber(cx, NULL, JSMSG_NO_FORMAL);
goto badargs;
}
/* Get the atom corresponding to the name from the tokenstream;
@ -1461,7 +1476,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
#ifdef CHECK_ARGUMENT_HIDING
PR_ASSERT(sprop->getter == js_GetArgument);
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
JS_ReportError(cx, "duplicate formal argument %s",
JS_ReportErrorNumber(cx, NULL, JSMSG_SAME_FORMAL,
ATOM_BYTES(atom));
goto badargs;
#else
@ -1714,7 +1729,7 @@ js_ReportIsNotFunction(JSContext *cx, jsval *vp, JSBool constructing)
if (fp)
fp->sp = sp;
if (str) {
JS_ReportError(cx, "%s is not a %s",
JS_ReportErrorNumber(cx, NULL, JSMSG_DENY,
JS_GetStringBytes(str),
constructing ? "constructor" : "function");
}

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

@ -42,7 +42,8 @@ struct JSFunction {
extern JSClass js_ArgumentsClass;
extern JSClass js_CallClass;
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.

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

@ -583,8 +583,18 @@ gc_root_marker(PRHashEntry *he, intN i, void *arg)
{
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);
}
return HT_ENUMERATE_NEXT;
}

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

@ -285,7 +285,7 @@ js_AllocStack(JSContext *cx, uintN nslots, void **markp)
*markp = PR_ARENA_MARK(&cx->stackPool);
PR_ARENA_ALLOCATE(sp, &cx->stackPool, nslots * sizeof(jsval));
if (!sp) {
JS_ReportError(cx, "stack overflow in %s",
JS_ReportErrorNumber(cx, NULL, JSMSG_STACK_OVERFLOW,
(cx->fp && cx->fp->fun)
? JS_GetFunctionName(cx->fp->fun)
: "script");
@ -506,11 +506,17 @@ have_fun:
frame.constructing = constructing;
frame.overrides = 0;
frame.debugging = JS_FALSE;
frame.throwing = JS_FALSE;
frame.dormantNext = NULL;
/* Compute the 'this' parameter and store it in frame. */
if (thisp && OBJ_GET_CLASS(cx, thisp) != &js_CallClass) {
/*
* Compute the 'this' parameter and store it in frame.
* Activation objects ("Call" objects not created with "new Call", i.e.,
* "Call" objects with private data) may not be referred to by 'this'
* as dictated by ECMA.
*/
if (thisp && !(OBJ_GET_CLASS(cx, thisp) == &js_CallClass &&
JS_GetPrivate(cx, thisp) != NULL))
{
/* Some objects (e.g., With) delegate 'this' to another object. */
thisp = OBJ_THIS_OBJECT(cx, thisp);
if (!thisp) {
@ -650,14 +656,6 @@ have_fun:
ok = JS_TRUE;
}
#if JS_HAS_EXCEPTIONS
/* Native or script returns JS_FALSE on error or uncaught exception */
if (!ok && frame.throwing) {
fp->throwing = JS_TRUE;
fp->exception = frame.exception;
}
#endif
out:
/*
* Checking frame.annotation limits the use of this hook for uses other
@ -736,6 +734,7 @@ out:
fp->sp = oldsp;
if (oldfp != fp)
cx->fp = oldfp;
return ok;
}
@ -775,7 +774,6 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script, JSFunction *fun,
frame.constructing = JS_FALSE;
frame.overrides = 0;
frame.debugging = debugging;
frame.throwing = JS_FALSE;
frame.dormantNext = NULL;
/*
@ -790,6 +788,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script, JSFunction *fun,
* chains and marks objects in the same way that it marks object in the
* primary cx->fp chain.
*/
if (oldfp && oldfp != down) {
PR_ASSERT(!oldfp->dormantNext);
oldfp->dormantNext = cx->dormantFrameChain;
@ -850,7 +849,7 @@ ImportProperty(JSContext *cx, JSObject *obj, jsid id)
if (!(attrs & JSPROP_EXPORTED)) {
str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL);
if (str) {
JS_ReportError(cx, "%s is not exported",
JS_ReportErrorNumber(cx, NULL, JSMSG_NOT_EXPORTED,
JS_GetStringBytes(str));
}
return JS_FALSE;
@ -963,6 +962,7 @@ js_Interpret(JSContext *cx, jsval *result)
jschar *chars;
jsint i, j;
jsdouble d, d2;
JSClass *clasp;
JSFunction *fun;
JSType type;
#ifdef DEBUG
@ -986,7 +986,7 @@ js_Interpret(JSContext *cx, jsval *result)
#endif
if (cx->interpLevel == MAX_INTERP_LEVEL) {
JS_ReportError(cx, "too much recursion");
JS_ReportErrorNumber(cx, NULL, JSMSG_OVER_RECURSED);
return JS_FALSE;
}
cx->interpLevel++;
@ -1193,7 +1193,7 @@ js_Interpret(JSContext *cx, jsval *result)
case JSOP_IN:
rval = POP();
if (!JSVAL_IS_OBJECT(rval) || rval == JSVAL_NULL) {
JS_ReportError(cx, "target of 'in' operator must be an object");
JS_ReportErrorNumber(cx, NULL, JSMSG_IN_NOT_OBJECT);
ok = JS_FALSE;
goto out;
}
@ -1855,9 +1855,14 @@ js_Interpret(JSContext *cx, jsval *result)
vp = sp - (2 + argc);
PR_ASSERT(vp >= newsp);
fun = NULL;
obj2 = NULL;
lval = *vp;
if (!JSVAL_IS_OBJECT(lval) ||
(obj2 = JSVAL_TO_OBJECT(lval)) == NULL ||
/* XXX clean up to avoid special cases above ObjectOps layer */
(clasp = OBJ_GET_CLASS(cx, obj2),
clasp == &js_FunctionClass || clasp == &js_ClosureClass) ||
!obj2->map->ops->construct) {
fun = js_ValueToFunction(cx, vp, JS_TRUE);
if (!fun) {
@ -1899,8 +1904,7 @@ js_Interpret(JSContext *cx, jsval *result)
if (!ok) {
cx->newborn[GCX_OBJECT] = NULL;
#if JS_HAS_EXCEPTIONS
if (fp->throwing) {
sp[-1] = fp->exception;
if (cx->throwing) {
goto do_throw;
}
#endif
@ -1911,13 +1915,13 @@ js_Interpret(JSContext *cx, jsval *result)
rval = *vp;
if (JSVAL_IS_PRIMITIVE(rval)) {
if (fun || !JSVERSION_IS_ECMA(cx->version)) {
/* Pre-ECMA code would coerce result to obj. */
*vp = OBJECT_TO_JSVAL(obj);
break;
}
/* native [[Construct]] returning primitive is error */
str = js_ValueToString(cx, rval);
if (str) {
JS_ReportError(cx, "invalid new expression result %s",
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_NEW_RESULT,
JS_GetStringBytes(str));
}
ok = JS_FALSE;
@ -2119,11 +2123,8 @@ js_Interpret(JSContext *cx, jsval *result)
RESTORE_SP(fp);
if (!ok) {
#if JS_HAS_EXCEPTIONS
if (fp->throwing) {
/* do_throw expects to have the exception on the stack */
sp[-1] = fp->exception;
if (cx->throwing)
goto do_throw;
}
#endif
goto out;
}
@ -2224,15 +2225,24 @@ js_Interpret(JSContext *cx, jsval *result)
#if JS_HAS_SWITCH_STATEMENT
case JSOP_TABLESWITCH:
pc2 = pc;
len = GET_JUMP_OFFSET(pc2);
/*
* ECMAv2 forbids conversion of discriminant, so we will skip to
* the default case if the discriminant isn't an int jsval.
* (This opcode is only emitted for all-integer switches.)
*/
if (JSVERSION_IS_ECMAv2(cx->version) &&
!JSVAL_IS_INT(*sp))
break;
SAVE_SP(fp);
ok = PopInt(cx, &i);
RESTORE_SP(fp);
if (!ok)
goto out;
pc2 = pc;
len = GET_JUMP_OFFSET(pc2);
pc2 += 2;
low = GET_JUMP_OFFSET(pc2);
pc2 += 2;
@ -2546,8 +2556,9 @@ js_Interpret(JSContext *cx, jsval *result)
id = (jsid) INT_TO_JSVAL(i);
rval = sp[-1];
if (JSVAL_IS_PRIMITIVE(rval)) {
JS_ReportError(cx, "invalid sharp variable definition #%u=",
(unsigned) i);
char numBuf[12];
sprintf(numBuf, "%u", (unsigned) i);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_SHARP_DEF, numBuf);
ok = JS_FALSE;
goto out;
}
@ -2568,8 +2579,9 @@ js_Interpret(JSContext *cx, jsval *result)
goto out;
}
if (!JSVAL_IS_OBJECT(rval)) {
JS_ReportError(cx, "invalid sharp variable use #%u#",
(unsigned) i);
char numBuf[12];
sprintf(numBuf, "%u", (unsigned) i);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_SHARP_USE, numBuf);
ok = JS_FALSE;
goto out;
}
@ -2579,7 +2591,14 @@ js_Interpret(JSContext *cx, jsval *result)
#endif /* JS_HAS_INITIALIZERS */
#if JS_HAS_EXCEPTIONS
case JSOP_JSR:
/* reset the stack to the given depth */
case JSOP_SETSP:
i = (jsint) GET_ATOM_INDEX(pc);
PR_ASSERT(i >= 0);
sp = newsp + i;
break;
case JSOP_GOSUB:
len = GET_JUMP_OFFSET(pc);
PUSH(INT_TO_JSVAL(pc - script->code));
CHECK_BRANCH(len);
@ -2594,12 +2613,13 @@ js_Interpret(JSContext *cx, jsval *result)
break;
case JSOP_EXCEPTION:
PUSH(fp->exception);
PUSH(cx->exception);
break;
case JSOP_THROW:
cx->throwing = JS_TRUE;
cx->exception = POP();
do_throw:
fp->exception = POP();
tn = script->trynotes;
offset = PTRDIFF(pc, script->code, jsbytecode);
if (tn) {
@ -2608,12 +2628,12 @@ js_Interpret(JSContext *cx, jsval *result)
if (tn->catchStart) {
pc = script->code + tn->catchStart;
len = 0;
cx->throwing = JS_FALSE; /* caught */
goto advance_pc;
}
}
/* Not in a catch block, so propagate the exception. */
fp->throwing = JS_TRUE;
ok = JS_FALSE;
goto out;
#endif /* JS_HAS_EXCEPTIONS */
@ -2624,8 +2644,9 @@ js_Interpret(JSContext *cx, jsval *result)
if (JSVAL_IS_PRIMITIVE(rval)) {
str = js_DecompileValueGenerator(cx, rval, NULL);
if (str) {
JS_ReportError(cx, "invalid %s operand %s",
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_OPERANDS,
js_instanceof_str, JS_GetStringBytes(str));
}
ok = JS_FALSE;
goto out;
@ -2666,11 +2687,14 @@ js_Interpret(JSContext *cx, jsval *result)
break;
#endif /* JS_HAS_DEBUGGER_KEYWORD */
default:
JS_ReportError(cx, "unimplemented JavaScript bytecode %d", op);
default: {
char numBuf[12];
sprintf(numBuf, "%d", op);
JS_ReportErrorNumber(cx, NULL, JSMSG_BAD_BYTECODE, numBuf);
ok = JS_FALSE;
goto out;
}
}
advance_pc:
pc += len;

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

@ -48,8 +48,6 @@ struct JSStackFrame {
JSPackedBool constructing; /* true if called via new operator */
uint8 overrides; /* bit-set of overridden Call properties */
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 */
};

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))
return JS_FALSE;
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;
}
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);
badstr:
if (str) {
JS_ReportError(cx, "%s is not a number",
JS_ReportErrorNumber(cx, NULL, JSMSG_NAN,
JS_GetStringBytes(str));
}
return JS_FALSE;
#else
@ -557,8 +560,9 @@ js_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
str = js_DecompileValueGenerator(cx, v, NULL);
if (str) {
JS_ReportError(cx, "can't convert %s to an integer",
JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_CONVERT,
JS_GetStringBytes(str));
}
return JS_FALSE;
}

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

@ -138,7 +138,7 @@ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
slot = JSVAL_TO_INT(id);
while (obj2) {
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;
}
obj2 = JSVAL_TO_OBJECT(OBJ_GET_SLOT(cx, obj2, slot));
@ -1806,7 +1806,7 @@ _readonly:
return JS_TRUE;
str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL);
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;
}
@ -1942,7 +1942,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
}
str = js_DecompileValueGenerator(cx, js_IdToValue(id), NULL);
if (str)
JS_ReportError(cx, "%s is permanent", JS_GetStringBytes(str));
JS_ReportErrorNumber(cx, NULL, JSMSG_PERMANENT, JS_GetStringBytes(str));
return JS_FALSE;
}
@ -2056,7 +2056,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
*vp = OBJECT_TO_JSVAL(obj);
str = js_DecompileValueGenerator(cx, v, str);
if (str) {
JS_ReportError(cx, "can't convert %s to %s",
JS_ReportErrorNumber(cx, NULL, JSMSG_CANT_CONVERT_TO,
JS_GetStringBytes(str),
(hint == JSTYPE_VOID)
? "primitive type"
@ -2388,7 +2388,7 @@ js_ValueToNonNullObject(JSContext *cx, jsval v)
if (!obj) {
str = js_DecompileValueGenerator(cx, v, NULL);
if (str) {
JS_ReportError(cx, "%s has no properties",
JS_ReportErrorNumber(cx, NULL, JSMSG_NO_PROPERTIES,
JS_GetStringBytes(str));
}
}
@ -2474,7 +2474,9 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
} else {
clasp = JS_FindClassById(xdr, classId);
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;
goto out;
}
@ -2482,7 +2484,7 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
}
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;
} else {
ok = clasp->xdrObject(xdr, objp);

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

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

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

@ -194,9 +194,10 @@ OPDEF(JSOP_INSTANCEOF,112,js_instanceof_str,js_instanceof_str,1,2,1,6,JOF_BYTE)
/* debugger op */
OPDEF(JSOP_DEBUGGER, 113,"debugger", NULL, 1, 0, 0, 0, JOF_BYTE)
/* jsr/return for finally handling */
OPDEF(JSOP_JSR, 114,"jsr", NULL, 3, 0, 1, 0, JOF_JUMP)
/* gosub/retsub for finally handling */
OPDEF(JSOP_GOSUB, 114,"gosub", NULL, 3, 0, 1, 0, JOF_JUMP)
OPDEF(JSOP_RETSUB, 115,"retsub", NULL, 1, 1, 0, 0, JOF_BYTE)
/* more exception handling ops */
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.
* 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 \
if (js_GetToken(cx, ts) != tt) { \
js_ReportCompileError(cx, ts, err); \
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR, errNo); \
throw; \
} \
PR_END_MACRO
#define MUST_MATCH_TOKEN(tt, err) \
MUST_MATCH_TOKEN_THROW(tt, err, return NULL)
#define MUST_MATCH_TOKEN(tt, errNo) \
MUST_MATCH_TOKEN_THROW(tt, errNo, return NULL)
/*
* 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 ((tt == TOK_FUNCTION || lastExprType == TOK_FUNCTION) &&
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;
}
#endif
js_ReportCompileError(cx, ts, "missing ; before statement");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_SEMI_BEFORE_STMNT);
return JS_FALSE;
}
return JS_TRUE;
@ -254,7 +263,7 @@ out:
static JSBool
CheckFinalReturn(JSParseNode *pn)
{
JSBool ok;
JSBool ok, hasDefault;
JSParseNode *pn2, *pn3;
switch (pn->pn_type) {
@ -266,16 +275,21 @@ CheckFinalReturn(JSParseNode *pn)
ok = CheckFinalReturn(pn->pn_kid2);
ok &= pn->pn_kid3 && CheckFinalReturn(pn->pn_kid3);
return ok;
#if JS_HAS_SWITCH_STATEMENT
case TOK_SWITCH:
/* If a final switch has no default case, we judge it harshly. */
ok = pn->pn_kid3 && CheckFinalReturn(pn->pn_kid3);
ok = JS_TRUE;
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;
PR_ASSERT(pn3->pn_type == TOK_LC);
if (pn3->pn_head)
ok &= CheckFinalReturn(PN_LAST(pn3));
}
/* If a final switch has no default case, we judge it harshly. */
ok &= hasDefault;
return ok;
#endif /* JS_HAS_SWITCH_STATEMENT */
case TOK_WITH:
return CheckFinalReturn(pn->pn_right);
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 */
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. */
if (pn && (tc->flags & TCF_RETURN_EXPR)) {
if (!CheckFinalReturn(pn)) {
js_ReportCompileError(cx, ts, badreturn_str);
js_ReportCompileErrorNumber(cx, ts,
JSREPORT_ERROR, JSMSG_NO_RETURN_VALUE);
pn = NULL;
}
}
@ -417,12 +430,12 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
}
/* 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);
/* balance) */
if (!js_MatchToken(cx, ts, TOK_RP)) {
do {
MUST_MATCH_TOKEN_THROW(TOK_NAME, "missing formal parameter",
MUST_MATCH_TOKEN_THROW(TOK_NAME, JSMSG_MISSING_FORMAL,
ok = JS_FALSE; goto out);
argAtom = ts->token.t_atom;
pobj = NULL;
@ -434,8 +447,8 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
if (sprop->getter == js_GetArgument) {
#ifdef CHECK_ARGUMENT_HIDING
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
js_ReportCompileError(cx, ts,
"duplicate formal argument %s",
js_ReportCompileErrorNumber(cx, ts,JSREPORT_ERROR,
JSMSG_DUPLICATE_FORMAL,
ATOM_BYTES(argAtom));
ok = JS_FALSE;
goto out;
@ -476,11 +489,11 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
} while (js_MatchToken(cx, ts, TOK_COMMA));
/* (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);
}
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);
pn->pn_pos.begin = ts->token.pos.begin;
@ -491,7 +504,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
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);
pn->pn_pos.end = ts->token.pos.end;
@ -576,22 +589,23 @@ Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
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);
if (!pn)
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).
* XXX not ECMA, but documented in several books -- need a compile option
*/
if (pn->pn_type == TOK_ASSIGN && pn->pn_op == JSOP_NOP) {
#ifdef CHECK_EQUALITY_ASSIGNMENT
js_ReportCompileError(cx, ts,
"test for equality (==) mistyped as assignment (=)?\n"
"Assuming equality test");
#endif
js_ReportCompileErrorNumber(cx, ts,JSREPORT_WARNING,
JSMSG_EQUAL_AS_ASSIGN,
(JSVERSION_IS_ECMA(cx->version) ? "" :
"\nAssuming equality test"));
if (JSVERSION_IS_ECMA(cx->version))
goto no_rewrite;
pn->pn_type = TOK_EQOP;
pn->pn_op = cx->jsop_eq;
pn2 = pn->pn_left;
@ -615,6 +629,7 @@ Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
PR_ASSERT(0);
}
}
no_rewrite:
return pn;
}
@ -650,7 +665,7 @@ ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
JSParseNode *pn, *pn2, *pn3;
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);
if (!pn)
return NULL;
@ -673,7 +688,7 @@ ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn2->pn_op = JSOP_IMPORTALL;
pn2->pn_atom = NULL;
} 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_atom = ts->token.t_atom;
pn2->pn_slot = -1;
@ -690,7 +705,7 @@ ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL;
/* [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.end = ts->token.pos.end;
@ -731,7 +746,8 @@ ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return pn;
bad_import:
js_ReportCompileError(cx, ts, "invalid import expression");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_IMPORT);
return NULL;
}
#endif /* JS_HAS_EXPORT_IMPORT */
@ -762,7 +778,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
PN_APPEND(pn, pn2);
} else {
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);
if (!pn2)
return NULL;
@ -831,30 +847,28 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
uintN newlines;
JSParseNode *pn5, *pn6;
JSBool seenDefault = JS_FALSE;
pn = NewParseNode(cx, &ts->token, PN_TERNARY);
pn = NewParseNode(cx, &ts->token, PN_BINARY);
if (!pn)
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 = Expr(cx, ts, tc);
if (!pn1)
return NULL;
MUST_MATCH_TOKEN(TOK_RP, "missing ) after switch expression");
MUST_MATCH_TOKEN(TOK_LC, "missing { before switch body");
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_SWITCH);
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_SWITCH);
/* 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);
if (!pn2)
return NULL;
PN_INIT_LIST(pn2);
/* If not null, pn3 points to the default case's node. */
pn3 = NULL;
js_PushStatement(tc, &stmtInfo, STMT_SWITCH, -1);
newlines = ts->flags & TSF_NEWLINES;
if (newlines)
@ -862,37 +876,43 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
while ((tt = js_GetToken(cx, ts)) != TOK_RC) {
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:
pn4 = NewParseNode(cx, &ts->token, PN_BINARY);
if (!pn4)
goto bad_switch;
if (tt == TOK_DEFAULT) {
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_ReportCompileError(cx, ts, "too many switch cases");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_TOO_MANY_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:
goto bad_switch;
default:
js_ReportCompileError(cx, ts, "invalid switch statement");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_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);
if (!pn5)
@ -909,12 +929,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn5->pn_pos.end = pn6->pn_pos.end;
PN_APPEND(pn5, pn6);
}
if (pn4) {
pn4->pn_pos.end = pn5->pn_pos.end;
pn4->pn_right = pn5;
} else {
pn3 = pn5;
}
}
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_kid1 = pn1;
pn->pn_kid2 = pn2;
pn->pn_kid3 = pn3;
return pn;
bad_switch:
@ -961,7 +976,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (!pn2)
return NULL;
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);
if (!pn2)
return NULL;
@ -978,7 +993,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL;
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);
if (tt == TOK_SEMI) {
/* 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_DOT &&
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;
}
@ -1035,7 +1051,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn->pn_left = pn2;
} else {
/* 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) {
pn2 = NULL;
} else {
@ -1045,7 +1061,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
}
/* 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) {
pn3 = NULL;
} else {
@ -1066,7 +1082,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
}
/* (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. */
pn2 = Statement(cx, ts, tc);
@ -1103,13 +1119,13 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn = NewParseNode(cx, &ts->token, PN_TERNARY);
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 */
pn->pn_kid1 = Statements(cx, ts, tc);
if (!pn->pn_kid1)
return NULL;
/* { balance */
MUST_MATCH_TOKEN(TOK_RC, "missing } after try block");
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_TRY);
pn->pn_kid2 = NULL;
catchtail = pn;
@ -1121,8 +1137,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
*/
if (!catchtail->pn_kid1->pn_expr) {
js_ReportCompileError(cx, ts,
"catch clause after general catch");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_WARNING,
JSMSG_CATCH_AFTER_GENERAL);
return NULL;
}
@ -1139,8 +1155,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
(void)js_GetToken(cx, ts); /* eat `catch' */
MUST_MATCH_TOKEN(TOK_LP, "missing ( after catch"); /* balance) */
MUST_MATCH_TOKEN(TOK_NAME, "missing identifier in catch");
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_CATCH); /* balance) */
MUST_MATCH_TOKEN(TOK_NAME, JSMSG_CATCH_IDENTIFIER);
pn3->pn_atom = ts->token.t_atom;
if (js_PeekToken(cx, ts) == TOK_COLON) {
(void)js_GetToken(cx, ts); /* eat `:' */
@ -1153,30 +1169,31 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn2->pn_kid1 = pn3;
/* ( 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);
if (!pn2->pn_kid3)
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->pn_kid2 = NULL;
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);
if (!pn->pn_kid3)
return NULL;
MUST_MATCH_TOKEN(TOK_RC, "missing } after finally block");
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_FINALLY);
} else {
pn->pn_kid3 = NULL;
}
if (!pn->pn_kid2 && !pn->pn_kid3) {
js_ReportCompileError(cx, ts,
"missing catch or finally after try");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_CATCH_OR_FINALLY);
return NULL;
}
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 */
case TOK_CATCH:
js_ReportCompileError(cx, ts, "catch without try");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_CATCH_WITHOUT_TRY);
return NULL;
case TOK_FINALLY:
js_ReportCompileError(cx, ts, "finally without try");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_FINALLY_WITHOUT_TRY);
return NULL;
#endif /* JS_HAS_EXCEPTIONS */
@ -1220,7 +1239,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (label) {
for (; ; stmt = stmt->down) {
if (!stmt) {
js_ReportCompileError(cx, ts, "label not found");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_LABEL_NOT_FOUND);
return NULL;
}
if (stmt->type == STMT_LABEL && stmt->label == label)
@ -1229,7 +1249,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} else {
for (; ; stmt = stmt->down) {
if (!stmt) {
js_ReportCompileError(cx, ts, "invalid break");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_TOUGH_BREAK);
return NULL;
}
if (STMT_IS_LOOP(stmt) || stmt->type == STMT_SWITCH)
@ -1251,13 +1272,15 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (label) {
for (stmt2 = NULL; ; stmt = stmt->down) {
if (!stmt) {
js_ReportCompileError(cx, ts, "label not found");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_LABEL_NOT_FOUND);
return NULL;
}
if (stmt->type == STMT_LABEL) {
if (stmt->label == label) {
if (!stmt2 || !STMT_IS_LOOP(stmt2)) {
js_ReportCompileError(cx, ts, "invalid continue");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_CONTINUE);
return NULL;
}
break;
@ -1269,7 +1292,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} else {
for (; ; stmt = stmt->down) {
if (!stmt) {
js_ReportCompileError(cx, ts, "invalid continue");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_CONTINUE);
return NULL;
}
if (STMT_IS_LOOP(stmt))
@ -1284,13 +1308,13 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn = NewParseNode(cx, &ts->token, PN_BINARY);
if (!pn)
return NULL;
MUST_MATCH_TOKEN(TOK_LP, "missing ( before with-statement object");
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH);
/* balance) */
pn2 = Expr(cx, ts, tc);
if (!pn2)
return NULL;
/* (balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) after with-statement object");
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH);
pn->pn_left = pn2;
js_PushStatement(tc, &stmtInfo, STMT_WITH, -1);
@ -1317,7 +1341,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
case TOK_RETURN:
if (!(tc->flags & TCF_IN_FUNCTION)) {
js_ReportCompileError(cx, ts, "invalid return");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_RETURN);
return NULL;
}
pn = NewParseNode(cx, &ts->token, PN_UNARY);
@ -1350,7 +1375,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
#ifdef CHECK_RETURN_EXPR
if ((tc->flags & (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;
}
#endif
@ -1363,7 +1389,7 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL;
/* {balance: */
MUST_MATCH_TOKEN(TOK_RC, "missing } in compound statement");
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_COMPOUND);
js_PopStatement(tc);
return pn;
@ -1400,13 +1426,15 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
tt = ts->pushback.type;
if (tt == TOK_COLON) {
if (pn2->pn_type != TOK_NAME) {
js_ReportCompileError(cx, ts, "invalid label");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_LABEL);
return NULL;
}
label = pn2->pn_atom;
for (stmt = tc->topStmt; stmt; stmt = stmt->down) {
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;
}
}
@ -1494,7 +1522,7 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
}
do {
MUST_MATCH_TOKEN(TOK_NAME, "missing variable name");
MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_VARIABLE_NAME);
atom = ts->token.t_atom;
pn2 = NewParseNode(cx, &ts->token, PN_NAME);
@ -1514,7 +1542,8 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (sprop->getter == js_GetArgument) {
getter = sprop->getter;
#ifdef CHECK_ARGUMENT_HIDING
js_ReportCompileError(cx, ts, "variable %s hides argument",
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_VAR_HIDES_ARG,
ATOM_BYTES(atom));
ok = JS_FALSE;
#else
@ -1593,8 +1622,8 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (js_MatchToken(cx, ts, TOK_ASSIGN)) {
if (ts->token.t_op != JSOP_NOP) {
js_ReportCompileError(cx, ts,
"invalid variable initialization");
js_ReportCompileErrorNumber(cx, ts,JSREPORT_ERROR,
JSMSG_BAD_VAR_INIT);
ok = JS_FALSE;
} else {
pn2->pn_expr = AssignExpr(cx, ts, tc);
@ -1729,7 +1758,8 @@ AssignExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
pn2->pn_op = JSOP_SETELEM;
break;
default:
js_ReportCompileError(cx, ts, "invalid assignment left-hand side");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_LEFTSIDE_OF_ASS);
return NULL;
}
pn = NewBinary(cx, TOK_ASSIGN, op, pn2, AssignExpr(cx, ts, tc));
@ -1767,7 +1797,7 @@ CondExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (!pn2)
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);
if (!pn3)
return NULL;
@ -1951,7 +1981,8 @@ SetLvalKid(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, JSParseNode *kid,
if (kid->pn_type != TOK_NAME &&
kid->pn_type != TOK_DOT &&
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;
}
pn->pn_kid = kid;
@ -2108,7 +2139,7 @@ ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
} while (js_MatchToken(cx, ts, TOK_COMMA));
/* (balance: */
MUST_MATCH_TOKEN(TOK_RP, "missing ) after argument list");
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_ARGS);
}
return listNode;
}
@ -2141,7 +2172,7 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
return NULL;
}
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;
}
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);
if (!pn2)
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.end = ts->token.pos.end;
pn2->pn_op = JSOP_GETPROP;
@ -2171,7 +2202,7 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
return NULL;
/* [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.end = ts->token.pos.end;
@ -2198,7 +2229,7 @@ MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
if (!pn2)
return NULL;
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;
}
pn2->pn_pos.end = PN_LAST(pn2)->pn_pos.end;
@ -2293,7 +2324,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
}
/* [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;
return pn;
@ -2331,11 +2362,12 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
case TOK_RC:
goto end_obj_init;
default:
js_ReportCompileError(cx, ts, "invalid property id");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_PROP_ID);
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,
AssignExpr(cx, ts, tc));
if (!pn2)
@ -2344,7 +2376,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
} while (js_MatchToken(cx, ts, TOK_COMMA));
/* {balance: */
MUST_MATCH_TOKEN(TOK_RC, "missing } after property list");
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LIST);
}
end_obj_init:
pn->pn_pos.end = ts->token.pos.end;
@ -2397,7 +2429,7 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL;
/* (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_pos.end = ts->token.pos.end;
pn->pn_kid = pn2;
@ -2450,7 +2482,8 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
case TOK_IMPORT:
#endif
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,
ts->token.pos.end.index -
ts->token.pos.begin.index));
@ -2461,7 +2494,8 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
return NULL;
default:
js_ReportCompileError(cx, ts, "syntax error");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_SYNTAX_ERROR);
return NULL;
}
@ -2469,7 +2503,8 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (defsharp) {
if (notsharp) {
badsharp:
js_ReportCompileError(cx, ts, "invalid sharp variable definition");
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR,
JSMSG_BAD_SHARP_VAR_DEF);
return NULL;
}
defsharp->pn_kid = pn;
@ -2511,10 +2546,10 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn)
break;
case PN_BINARY:
/* Neither kid may be null. */
/* First kid may be null (for default case in switch). */
pn1 = pn->pn_left;
pn2 = pn->pn_right;
if (!js_FoldConstants(cx, pn1))
if (pn1 && !js_FoldConstants(cx, pn1))
return JS_FALSE;
if (!js_FoldConstants(cx, pn2))
return JS_FALSE;

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

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

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

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

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

@ -225,7 +225,7 @@ js_NewFileTokenStream(JSContext *cx, const char *filename, FILE *defaultfp)
} else {
file = fopen(filename, "r");
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;
}
}
@ -483,8 +483,8 @@ MatchChar(JSTokenStream *ts, int32 nextChar)
}
void
js_ReportCompileError(JSContext *cx, JSTokenStream *ts, const char *format,
...)
js_ReportCompileError(JSContext *cx, JSTokenStream *ts, uintN flags,
const char *format, ...)
{
va_list ap;
char *message;
@ -519,11 +519,13 @@ js_ReportCompileError(JSContext *cx, JSTokenStream *ts, const char *format,
: 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 error: ");
fprintf(stderr, "JavaScript %s: ",
JSREPORT_IS_WARNING(flags) ? "warning" : "error");
if (ts->filename)
fprintf(stderr, "%s, ", ts->filename);
if (ts->lineno)
@ -538,6 +540,68 @@ js_ReportCompileError(JSContext *cx, JSTokenStream *ts, const char *format,
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
js_PeekToken(JSContext *cx, JSTokenStream *ts)
{
@ -691,18 +755,22 @@ retry:
RETURN(TOK_ERROR);
c = GetChar(ts);
radix = 16;
} else if (JS7_ISDEC(c) && c < '8') {
} else if (JS7_ISDEC(c)) {
/*
* XXX Warning needed. Checking against c < '8' above is
* non-ECMA, but is required to support legacy code; it's
* likely that "08" and "09" are in use in code having to do
* with dates. So we need to support it, which makes our
* behavior a superset of ECMA in this area. We should be
* raising a warning if '8' or '9' is encountered.
* We permit 08 and 09 as decimal numbers, which makes our
* behaviour superset of the ECMA numeric grammar. We might
* not always be so permissive, so we warn about it.
*/
if (c > '7' && JSVERSION_IS_ECMA(cx->version)) {
js_ReportCompileError(cx, ts, JSREPORT_WARNING,
"0%c is not an ECMA-legal numeric constant",
c);
radix = 10;
} else {
radix = 8;
}
}
}
while (JS7_ISHEX(c)) {
if (radix < 16 && (JS7_ISLET(c) || (radix == 8 && c >= '8')))
@ -730,7 +798,8 @@ retry:
c = GetChar(ts);
}
if (!JS7_ISDEC(c)) {
js_ReportCompileError(cx, ts, "missing exponent");
js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"missing exponent");
RETURN(TOK_ERROR);
}
do {
@ -746,12 +815,14 @@ retry:
if (radix == 10) {
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);
}
} else {
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);
}
}
@ -766,7 +837,8 @@ retry:
while ((c = GetChar(ts)) != qc) {
if (c == '\n' || c == EOF) {
UngetChar(ts, c);
js_ReportCompileError(cx, ts, "unterminated string literal");
js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"unterminated string literal");
RETURN(TOK_ERROR);
}
if (c == '\\') {
@ -955,11 +1027,13 @@ skipline:
if (c == '/' && MatchChar(ts, '*')) {
if (MatchChar(ts, '/'))
goto retry;
js_ReportCompileError(cx, ts, "nested comment");
js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"nested comment");
}
}
if (c == EOF) {
js_ReportCompileError(cx, ts, "unterminated comment");
js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"unterminated comment");
RETURN(TOK_ERROR);
}
goto retry;
@ -974,7 +1048,7 @@ skipline:
while ((c = GetChar(ts)) != '/') {
if (c == '\n' || c == EOF) {
UngetChar(ts, c);
js_ReportCompileError(cx, ts,
js_ReportCompileError(cx, ts,JSREPORT_ERROR,
"unterminated regular expression literal");
RETURN(TOK_ERROR);
}
@ -998,7 +1072,7 @@ skipline:
c = PeekChar(ts);
if (JS7_ISLET(c)) {
ts->token.ptr = ts->linebuf.ptr - 1;
js_ReportCompileError(cx, ts,
js_ReportCompileError(cx, ts,JSREPORT_ERROR,
"invalid flag after regular expression");
(void) GetChar(ts);
RETURN(TOK_ERROR);
@ -1065,7 +1139,7 @@ skipline:
break;
n = 10 * n + JS7_UNDEC(c);
if (n >= ATOM_INDEX_LIMIT) {
js_ReportCompileError(cx, ts,
js_ReportCompileError(cx, ts,JSREPORT_ERROR,
"overlarge sharp variable number");
RETURN(TOK_ERROR);
}
@ -1082,7 +1156,8 @@ skipline:
#endif /* JS_HAS_SHARP_VARS */
default:
js_ReportCompileError(cx, ts, "illegal character");
js_ReportCompileError(cx, ts, JSREPORT_ERROR,
"illegal character");
RETURN(TOK_ERROR);
}

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

@ -226,9 +226,12 @@ js_MapKeywords(void (*mapfun)(const char *));
* associated with cx.
*/
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.
*/

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

@ -109,7 +109,9 @@ str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
(mask = (jsint)d) != d ||
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;
}
} else {
@ -744,8 +746,7 @@ str_lastIndexOf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
static JSBool
str_nyi(JSContext *cx, const char *what)
{
JS_ReportError(cx, "sorry, String.prototype.%s is not yet implemented",
what);
JS_ReportErrorNumber(cx, NULL, JSMSG_NO_STRING_PROTO, what);
return JS_FALSE;
}
#endif

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

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

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

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