📄 jsexn.c
字号:
/* -*- 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 JSBoolException(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static voidexn_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 voidexn_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 voidexn_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_CTORstatic 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 JSBoolInitExceptionObject(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 * so we can suppress any checkAccess failures. Such failures should stop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -