jsexn.c
来自「一个基于alice开发的机器人」· C语言 代码 · 共 1,082 行 · 第 1/3 页
C
1,082 行
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* JS standard exception implementation.
*/
#include "jsstddef.h"
#include <stdlib.h>
#include <string.h>
#include "jstypes.h"
#include "jsbit.h"
#include "jsutil.h" /* Added by JSIFY */
#include "jsprf.h"
#include "jsapi.h"
#include "jscntxt.h"
#include "jsconfig.h"
#include "jsexn.h"
#include "jsfun.h"
#include "jsinterp.h"
#include "jsopcode.h"
#include "jsnum.h"
#include "jsscript.h"
#if JS_HAS_ERROR_EXCEPTIONS
#if !JS_HAS_EXCEPTIONS
# error "JS_HAS_EXCEPTIONS must be defined to use JS_HAS_ERROR_EXCEPTIONS"
#endif
/* XXX consider adding rt->atomState.messageAtom */
static char js_message_str[] = "message";
static char js_filename_str[] = "fileName";
static char js_lineno_str[] = "lineNumber";
static char js_stack_str[] = "stack";
/* Forward declarations for ExceptionClass's initializer. */
static JSBool
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static void
exn_finalize(JSContext *cx, JSObject *obj);
static JSClass ExceptionClass = {
"Error",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, exn_finalize,
NULL, NULL, NULL, Exception,
NULL, NULL, NULL, 0
};
/*
* A copy of the JSErrorReport originally generated.
*/
typedef struct JSExnPrivate {
JSErrorReport *errorReport;
} JSExnPrivate;
/*
* Undo all the damage done by exn_newPrivate.
*/
static void
exn_destroyPrivate(JSContext *cx, JSExnPrivate *privateData)
{
JSErrorReport *report;
const jschar **args;
if (!privateData)
return;
report = privateData->errorReport;
if (report) {
if (report->uclinebuf)
JS_free(cx, (void *)report->uclinebuf);
if (report->filename)
JS_free(cx, (void *)report->filename);
if (report->ucmessage)
JS_free(cx, (void *)report->ucmessage);
if (report->messageArgs) {
args = report->messageArgs;
while (*args != NULL)
JS_free(cx, (void *)*args++);
JS_free(cx, (void *)report->messageArgs);
}
JS_free(cx, report);
}
JS_free(cx, privateData);
}
/*
* Copy everything interesting about an error into allocated memory.
*/
static JSExnPrivate *
exn_newPrivate(JSContext *cx, JSErrorReport *report)
{
intN i;
JSExnPrivate *newPrivate;
JSErrorReport *newReport;
size_t capacity;
newPrivate = (JSExnPrivate *)JS_malloc(cx, sizeof (JSExnPrivate));
if (!newPrivate)
return NULL;
memset(newPrivate, 0, sizeof (JSExnPrivate));
/* Copy the error report */
newReport = (JSErrorReport *)JS_malloc(cx, sizeof (JSErrorReport));
if (!newReport)
goto error;
memset(newReport, 0, sizeof (JSErrorReport));
newPrivate->errorReport = newReport;
if (report->filename != NULL) {
newReport->filename = JS_strdup(cx, report->filename);
if (!newReport->filename)
goto error;
} else {
newReport->filename = NULL;
}
newReport->lineno = report->lineno;
/*
* We don't need to copy linebuf and tokenptr, because they
* point into the deflated string cache. (currently?)
*/
newReport->linebuf = report->linebuf;
newReport->tokenptr = report->tokenptr;
/*
* But we do need to copy uclinebuf, uctokenptr, because they're
* pointers into internal tokenstream structs, and may go away.
*/
if (report->uclinebuf != NULL) {
capacity = js_strlen(report->uclinebuf) + 1;
newReport->uclinebuf =
(const jschar *)JS_malloc(cx, capacity * sizeof(jschar));
if (!newReport->uclinebuf)
goto error;
js_strncpy((jschar *)newReport->uclinebuf, report->uclinebuf, capacity);
newReport->uctokenptr = newReport->uclinebuf + (report->uctokenptr -
report->uclinebuf);
} else {
newReport->uclinebuf = newReport->uctokenptr = NULL;
}
if (report->ucmessage != NULL) {
capacity = js_strlen(report->ucmessage) + 1;
newReport->ucmessage = (const jschar *)
JS_malloc(cx, capacity * sizeof(jschar));
if (!newReport->ucmessage)
goto error;
js_strncpy((jschar *)newReport->ucmessage, report->ucmessage, capacity);
if (report->messageArgs) {
for (i = 0; report->messageArgs[i] != NULL; i++)
continue;
JS_ASSERT(i);
newReport->messageArgs =
(const jschar **)JS_malloc(cx, (i + 1) * sizeof(jschar *));
if (!newReport->messageArgs)
goto error;
for (i = 0; report->messageArgs[i] != NULL; i++) {
capacity = js_strlen(report->messageArgs[i]) + 1;
newReport->messageArgs[i] =
(const jschar *)JS_malloc(cx, capacity * sizeof(jschar));
if (!newReport->messageArgs[i])
goto error;
js_strncpy((jschar *)(newReport->messageArgs[i]),
report->messageArgs[i], capacity);
}
newReport->messageArgs[i] = NULL;
} else {
newReport->messageArgs = NULL;
}
} else {
newReport->ucmessage = NULL;
newReport->messageArgs = NULL;
}
newReport->errorNumber = report->errorNumber;
/* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
newReport->flags = report->flags;
return newPrivate;
error:
exn_destroyPrivate(cx, newPrivate);
return NULL;
}
static void
exn_finalize(JSContext *cx, JSObject *obj)
{
JSExnPrivate *privateData;
jsval privateValue;
privateValue = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
if (!JSVAL_IS_VOID(privateValue)) {
privateData = (JSExnPrivate*) JSVAL_TO_PRIVATE(privateValue);
if (privateData)
exn_destroyPrivate(cx, privateData);
}
}
JSErrorReport *
js_ErrorFromException(JSContext *cx, jsval exn)
{
JSObject *obj;
JSExnPrivate *privateData;
jsval privateValue;
if (JSVAL_IS_PRIMITIVE(exn))
return NULL;
obj = JSVAL_TO_OBJECT(exn);
if (OBJ_GET_CLASS(cx, obj) != &ExceptionClass)
return NULL;
privateValue = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
if (JSVAL_IS_VOID(privateValue))
return NULL;
privateData = (JSExnPrivate*) JSVAL_TO_PRIVATE(privateValue);
if (!privateData)
return NULL;
JS_ASSERT(privateData->errorReport);
return privateData->errorReport;
}
/*
* This must be kept in synch with the exceptions array below.
* XXX use a jsexn.tbl file a la jsopcode.tbl
*/
typedef enum JSExnType {
JSEXN_NONE = -1,
JSEXN_ERR,
JSEXN_INTERNALERR,
JSEXN_EVALERR,
JSEXN_RANGEERR,
JSEXN_REFERENCEERR,
JSEXN_SYNTAXERR,
JSEXN_TYPEERR,
JSEXN_URIERR,
JSEXN_LIMIT
} JSExnType;
struct JSExnSpec {
int protoIndex;
const char *name;
JSNative native;
};
/*
* All *Error constructors share the same JSClass, ExceptionClass. But each
* constructor function for an *Error class must have a distinct native 'call'
* function pointer, in order for instanceof to work properly across multiple
* standard class sets. See jsfun.c:fun_hasInstance.
*/
#define MAKE_EXCEPTION_CTOR(name) \
const char js_##name##_str[] = #name; \
static JSBool \
name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) \
{ \
return Exception(cx, obj, argc, argv, rval); \
}
MAKE_EXCEPTION_CTOR(Error)
MAKE_EXCEPTION_CTOR(InternalError)
MAKE_EXCEPTION_CTOR(EvalError)
MAKE_EXCEPTION_CTOR(RangeError)
MAKE_EXCEPTION_CTOR(ReferenceError)
MAKE_EXCEPTION_CTOR(SyntaxError)
MAKE_EXCEPTION_CTOR(TypeError)
MAKE_EXCEPTION_CTOR(URIError)
#undef MAKE_EXCEPTION_CTOR
static struct JSExnSpec exceptions[] = {
{ JSEXN_NONE, js_Error_str, Error },
{ JSEXN_ERR, js_InternalError_str, InternalError },
{ JSEXN_ERR, js_EvalError_str, EvalError },
{ JSEXN_ERR, js_RangeError_str, RangeError },
{ JSEXN_ERR, js_ReferenceError_str, ReferenceError },
{ JSEXN_ERR, js_SyntaxError_str, SyntaxError },
{ JSEXN_ERR, js_TypeError_str, TypeError },
{ JSEXN_ERR, js_URIError_str, URIError },
{0,NULL,NULL}
};
static JSBool
InitExceptionObject(JSContext *cx, JSObject *obj, JSString *message,
JSString *filename, uintN lineno)
{
JSCheckAccessOp checkAccess;
JSErrorReporter older;
JSExceptionState *state;
jschar *stackbuf;
size_t stacklen, stackmax;
JSStackFrame *fp;
jsval callerid, v;
JSBool ok;
JSString *argsrc, *stack;
uintN i, ulineno;
const char *cp;
char ulnbuf[11];
if (!JS_DefineProperty(cx, obj, js_message_str, STRING_TO_JSVAL(message),
NULL, NULL, JSPROP_ENUMERATE)) {
return JS_FALSE;
}
if (!JS_DefineProperty(cx, obj, js_filename_str,
STRING_TO_JSVAL(filename),
NULL, NULL, JSPROP_ENUMERATE)) {
return JS_FALSE;
}
if (!JS_DefineProperty(cx, obj, js_lineno_str,
INT_TO_JSVAL(lineno),
NULL, NULL, JSPROP_ENUMERATE)) {
return JS_FALSE;
}
/*
* Set the 'stack' property.
*
* First, set aside any error reporter for cx and save its exception state
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?