/[jscoverage]/trunk/js/jsexn.cpp
ViewVC logotype

Diff of /trunk/js/jsexn.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 332 by siliconforks, Thu Oct 23 19:03:33 2008 UTC revision 585 by siliconforks, Sun Sep 12 15:13:23 2010 UTC
# Line 1  Line 1 
1  /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-  /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2   * vim: set ts=8 sw=4 et tw=78:   * vim: set ts=8 sw=4 et tw=78:
3   *   *
4   * ***** BEGIN LICENSE BLOCK *****   * ***** BEGIN LICENSE BLOCK *****
# Line 42  Line 42 
42   * JS standard exception implementation.   * JS standard exception implementation.
43   */   */
44    
 #include "jsstddef.h"  
45  #include <stdlib.h>  #include <stdlib.h>
46  #include <string.h>  #include <string.h>
47  #include "jstypes.h"  #include "jstypes.h"
48    #include "jsstdint.h"
49  #include "jsbit.h"  #include "jsbit.h"
50  #include "jsutil.h" /* Added by JSIFY */  #include "jsutil.h" /* Added by JSIFY */
51  #include "jsprf.h"  #include "jsprf.h"
# Line 68  Line 68 
68  Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);  Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
69    
70  static void  static void
 exn_finalize(JSContext *cx, JSObject *obj);  
   
 static void  
71  exn_trace(JSTracer *trc, JSObject *obj);  exn_trace(JSTracer *trc, JSObject *obj);
72    
73  static void  static void
# Line 167  Line 164 
164       */       */
165      mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize +      mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize +
166                   ucmessageSize + uclinebufSize + linebufSize + filenameSize;                   ucmessageSize + uclinebufSize + linebufSize + filenameSize;
167      cursor = (uint8 *)JS_malloc(cx, mallocSize);      cursor = (uint8 *)cx->malloc(mallocSize);
168      if (!cursor)      if (!cursor)
169          return NULL;          return NULL;
170    
# Line 280  Line 277 
277      callerid = ATOM_KEY(cx->runtime->atomState.callerAtom);      callerid = ATOM_KEY(cx->runtime->atomState.callerAtom);
278      stackDepth = 0;      stackDepth = 0;
279      valueCount = 0;      valueCount = 0;
280      for (fp = cx->fp; fp; fp = fp->down) {      for (fp = js_GetTopStackFrame(cx); fp; fp = fp->down) {
281          if (fp->fun && fp->argv) {          if (fp->fun && fp->argv) {
282              v = JSVAL_NULL;              v = JSVAL_NULL;
283              if (checkAccess &&              if (checkAccess &&
284                  !checkAccess(cx, fp->callee, callerid, JSACC_READ, &v)) {                  !checkAccess(cx, fp->callee(), callerid, JSACC_READ, &v)) {
285                  break;                  break;
286              }              }
287              valueCount += fp->argc;              valueCount += fp->argc;
# Line 304  Line 301 
301          js_ReportAllocationOverflow(cx);          js_ReportAllocationOverflow(cx);
302          return JS_FALSE;          return JS_FALSE;
303      }      }
304      priv = (JSExnPrivate *)JS_malloc(cx, size);      priv = (JSExnPrivate *)cx->malloc(size);
305      if (!priv)      if (!priv)
306          return JS_FALSE;          return JS_FALSE;
307    
# Line 321  Line 318 
318    
319      values = GetStackTraceValueBuffer(priv);      values = GetStackTraceValueBuffer(priv);
320      elem = priv->stackElems;      elem = priv->stackElems;
321      for (fp = cx->fp; fp != fpstop; fp = fp->down) {      for (fp = js_GetTopStackFrame(cx); fp != fpstop; fp = fp->down) {
322          if (!fp->fun) {          if (!fp->fun) {
323              elem->funName = NULL;              elem->funName = NULL;
324              elem->argc = 0;              elem->argc = 0;
# Line 338  Line 335 
335          if (fp->script) {          if (fp->script) {
336              elem->filename = fp->script->filename;              elem->filename = fp->script->filename;
337              if (fp->regs)              if (fp->regs)
338                  elem->ulineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);                  elem->ulineno = js_FramePCToLineNumber(cx, fp);
339          }          }
340          ++elem;          ++elem;
341      }      }
342      JS_ASSERT(priv->stackElems + stackDepth == elem);      JS_ASSERT(priv->stackElems + stackDepth == elem);
343      JS_ASSERT(GetStackTraceValueBuffer(priv) + valueCount == values);      JS_ASSERT(GetStackTraceValueBuffer(priv) + valueCount == values);
344    
345      STOBJ_SET_SLOT(exnObject, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(priv));      exnObject->setPrivate(priv);
346    
347      if (report) {      if (report) {
348          /*          /*
# Line 364  Line 361 
361      return JS_TRUE;      return JS_TRUE;
362  }  }
363    
364  static JSExnPrivate *  static inline JSExnPrivate *
365  GetExnPrivate(JSContext *cx, JSObject *obj)  GetExnPrivate(JSContext *cx, JSObject *obj)
366  {  {
367      jsval privateValue;      return (JSExnPrivate *) obj->getPrivate();
     JSExnPrivate *priv;  
   
     JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ErrorClass);  
     privateValue = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);  
     if (JSVAL_IS_VOID(privateValue))  
         return NULL;  
     priv = (JSExnPrivate *)JSVAL_TO_PRIVATE(privateValue);  
     JS_ASSERT(priv);  
     return priv;  
368  }  }
369    
370  static void  static void
# Line 420  Line 408 
408      priv = GetExnPrivate(cx, obj);      priv = GetExnPrivate(cx, obj);
409      if (priv) {      if (priv) {
410          if (priv->errorReport)          if (priv->errorReport)
411              JS_free(cx, priv->errorReport);              cx->free(priv->errorReport);
412          JS_free(cx, priv);          cx->free(priv);
413      }      }
414  }  }
415    
# Line 448  Line 436 
436          if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop))          if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop))
437              return JS_FALSE;              return JS_FALSE;
438          if (prop)          if (prop)
439              OBJ_DROP_PROPERTY(cx, pobj, prop);              pobj->dropProperty(cx, prop);
440      }      }
441      return JS_TRUE;      return JS_TRUE;
442  }  }
# Line 529  Line 517 
517      return priv->errorReport;      return priv->errorReport;
518  }  }
519    
 struct JSExnSpec {  
     int protoIndex;  
     const char *name;  
     JSProtoKey key;  
     JSNative native;  
 };  
   
 /*  
  * All *Error constructors share the same JSClass, js_ErrorClass.  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)                                             \  
 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,          JSProto_Error,          Error},  
     {JSEXN_ERR,  js_InternalError_str,  JSProto_InternalError,  InternalError},  
     {JSEXN_ERR,  js_EvalError_str,      JSProto_EvalError,      EvalError},  
     {JSEXN_ERR,  js_RangeError_str,     JSProto_RangeError,     RangeError},  
     {JSEXN_ERR,  js_ReferenceError_str, JSProto_ReferenceError, ReferenceError},  
     {JSEXN_ERR,  js_SyntaxError_str,    JSProto_SyntaxError,    SyntaxError},  
     {JSEXN_ERR,  js_TypeError_str,      JSProto_TypeError,      TypeError},  
     {JSEXN_ERR,  js_URIError_str,       JSProto_URIError,       URIError},  
     {0,          NULL,                  JSProto_Null,           NULL}  
 };  
   
520  static JSString *  static JSString *
521  ValueToShortSource(JSContext *cx, jsval v)  ValueToShortSource(JSContext *cx, jsval v)
522  {  {
# Line 632  Line 577 
577              if (stackmax >= STACK_LENGTH_LIMIT)                               \              if (stackmax >= STACK_LENGTH_LIMIT)                               \
578                  goto done;                                                    \                  goto done;                                                    \
579              stackmax = stackmax ? 2 * stackmax : 64;                          \              stackmax = stackmax ? 2 * stackmax : 64;                          \
580              ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar));   \              ptr_ = cx->realloc(stackbuf, (stackmax+1) * sizeof(jschar));      \
581              if (!ptr_)                                                        \              if (!ptr_)                                                        \
582                  goto bad;                                                     \                  goto bad;                                                     \
583              stackbuf = (jschar *) ptr_;                                       \              stackbuf = (jschar *) ptr_;                                       \
# Line 643  Line 588 
588  #define APPEND_STRING_TO_STACK(str)                                           \  #define APPEND_STRING_TO_STACK(str)                                           \
589      JS_BEGIN_MACRO                                                            \      JS_BEGIN_MACRO                                                            \
590          JSString *str_ = str;                                                 \          JSString *str_ = str;                                                 \
591          jschar *chars_;                                                       \          const jschar *chars_;                                                 \
592          size_t length_;                                                       \          size_t length_;                                                       \
593                                                                                \                                                                                \
594          JSSTRING_CHARS_AND_LENGTH(str_, chars_, length_);                     \          str_->getCharsAndLength(chars_, length_);                             \
595          if (length_ > stackmax - stacklen) {                                  \          if (length_ > stackmax - stacklen) {                                  \
596              void *ptr_;                                                       \              void *ptr_;                                                       \
597              if (stackmax >= STACK_LENGTH_LIMIT ||                             \              if (stackmax >= STACK_LENGTH_LIMIT ||                             \
# Line 654  Line 599 
599                  goto done;                                                    \                  goto done;                                                    \
600              }                                                                 \              }                                                                 \
601              stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_));            \              stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_));            \
602              ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar));   \              ptr_ = cx->realloc(stackbuf, (stackmax+1) * sizeof(jschar));      \
603              if (!ptr_)                                                        \              if (!ptr_)                                                        \
604                  goto bad;                                                     \                  goto bad;                                                     \
605              stackbuf = (jschar *) ptr_;                                       \              stackbuf = (jschar *) ptr_;                                       \
# Line 705  Line 650 
650           * don't use JS_realloc here; simply let the oversized allocation           * don't use JS_realloc here; simply let the oversized allocation
651           * be owned by the string in that rare case.           * be owned by the string in that rare case.
652           */           */
653          void *shrunk = JS_realloc(cx, stackbuf, (stacklen+1) * sizeof(jschar));          void *shrunk = cx->realloc(stackbuf, (stacklen+1) * sizeof(jschar));
654          if (shrunk)          if (shrunk)
655              stackbuf = (jschar *) shrunk;              stackbuf = (jschar *) shrunk;
656      }      }
# Line 717  Line 662 
662    
663    bad:    bad:
664      if (stackbuf)      if (stackbuf)
665          JS_free(cx, stackbuf);          cx->free(stackbuf);
666      return NULL;      return NULL;
667  }  }
668    
# Line 742  Line 687 
687      JSString *message, *filename;      JSString *message, *filename;
688      JSStackFrame *fp;      JSStackFrame *fp;
689    
690      if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {      if (!JS_IsConstructing(cx)) {
691          /*          /*
692           * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when           * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
693           * called as functions, without operator new.  But as we do not give           * called as functions, without operator new.  But as we do not give
# Line 750  Line 695 
695           * js_NewObject to find the class prototype, we must get the class           * js_NewObject to find the class prototype, we must get the class
696           * prototype ourselves.           * prototype ourselves.
697           */           */
698          if (!OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(argv[-2]),          if (!JSVAL_TO_OBJECT(argv[-2])->getProperty(cx,
699                                ATOM_TO_JSID(cx->runtime->atomState                                                      ATOM_TO_JSID(cx->runtime->atomState
700                                             .classPrototypeAtom),                                                                   .classPrototypeAtom),
701                                rval))                                                      rval)) {
702              return JS_FALSE;              return JS_FALSE;
703          obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL, 0);          }
704            obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL);
705          if (!obj)          if (!obj)
706              return JS_FALSE;              return JS_FALSE;
707          *rval = OBJECT_TO_JSVAL(obj);          *rval = OBJECT_TO_JSVAL(obj);
# Line 766  Line 712 
712       * data so that the finalizer doesn't attempt to free it.       * data so that the finalizer doesn't attempt to free it.
713       */       */
714      if (OBJ_GET_CLASS(cx, obj) == &js_ErrorClass)      if (OBJ_GET_CLASS(cx, obj) == &js_ErrorClass)
715          STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, JSVAL_VOID);          obj->setPrivate(NULL);
716    
717      /* Set the 'message' property. */      /* Set the 'message' property. */
718      if (argc != 0) {      if (argc != 0) {
# Line 786  Line 732 
732          argv[1] = STRING_TO_JSVAL(filename);          argv[1] = STRING_TO_JSVAL(filename);
733          fp = NULL;          fp = NULL;
734      } else {      } else {
735          fp = JS_GetScriptedCaller(cx, NULL);          fp = js_GetScriptedCaller(cx, NULL);
736          if (fp) {          if (fp) {
737              filename = FilenameToString(cx, fp->script->filename);              filename = FilenameToString(cx, fp->script->filename);
738              if (!filename)              if (!filename)
# Line 803  Line 749 
749              return JS_FALSE;              return JS_FALSE;
750      } else {      } else {
751          if (!fp)          if (!fp)
752              fp = JS_GetScriptedCaller(cx, NULL);              fp = js_GetScriptedCaller(cx, NULL);
753          lineno = (fp && fp->regs)          lineno = (fp && fp->regs) ? js_FramePCToLineNumber(cx, fp) : 0;
                  ? js_PCToLineNumber(cx, fp->script, fp->regs->pc)  
                  : 0;  
754      }      }
755    
756      return (OBJ_GET_CLASS(cx, obj) != &js_ErrorClass) ||      return (OBJ_GET_CLASS(cx, obj) != &js_ErrorClass) ||
# Line 830  Line 774 
774      size_t name_length, message_length, length;      size_t name_length, message_length, length;
775    
776      obj = JS_THIS_OBJECT(cx, vp);      obj = JS_THIS_OBJECT(cx, vp);
777      if (!obj ||      if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), &v))
         !OBJ_GET_PROPERTY(cx, obj,  
                           ATOM_TO_JSID(cx->runtime->atomState.nameAtom),  
                           &v)) {  
778          return JS_FALSE;          return JS_FALSE;
     }  
779      name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;      name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
780      *vp = STRING_TO_JSVAL(name);      *vp = STRING_TO_JSVAL(name);
781    
# Line 844  Line 784 
784      message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v)      message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v)
785                                   : cx->runtime->emptyString;                                   : cx->runtime->emptyString;
786    
787      if (JSSTRING_LENGTH(message) != 0) {      if (message->length() != 0) {
788          name_length = JSSTRING_LENGTH(name);          name_length = name->length();
789          message_length = JSSTRING_LENGTH(message);          message_length = message->length();
790          length = (name_length ? name_length + 2 : 0) + message_length;          length = (name_length ? name_length + 2 : 0) + message_length;
791          cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));          cp = chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar));
792          if (!chars)          if (!chars)
793              return JS_FALSE;              return JS_FALSE;
794    
795          if (name_length) {          if (name_length) {
796              js_strncpy(cp, JSSTRING_CHARS(name), name_length);              js_strncpy(cp, name->chars(), name_length);
797              cp += name_length;              cp += name_length;
798              *cp++ = ':'; *cp++ = ' ';              *cp++ = ':'; *cp++ = ' ';
799          }          }
800          js_strncpy(cp, JSSTRING_CHARS(message), message_length);          js_strncpy(cp, message->chars(), message_length);
801          cp += message_length;          cp += message_length;
802          *cp = 0;          *cp = 0;
803    
804          result = js_NewString(cx, chars, length);          result = js_NewString(cx, chars, length);
805          if (!result) {          if (!result) {
806              JS_free(cx, chars);              cx->free(chars);
807              return JS_FALSE;              return JS_FALSE;
808          }          }
809      } else {      } else {
# Line 891  Line 831 
831      jschar *chars, *cp;      jschar *chars, *cp;
832    
833      obj = JS_THIS_OBJECT(cx, vp);      obj = JS_THIS_OBJECT(cx, vp);
834      if (!obj ||      if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), vp))
         !OBJ_GET_PROPERTY(cx, obj,  
                           ATOM_TO_JSID(cx->runtime->atomState.nameAtom),  
                           vp)) {  
835          return JS_FALSE;          return JS_FALSE;
     }  
836      name = js_ValueToString(cx, *vp);      name = js_ValueToString(cx, *vp);
837      if (!name)      if (!name)
838          return JS_FALSE;          return JS_FALSE;
# Line 934  Line 870 
870              ok = JS_FALSE;              ok = JS_FALSE;
871              goto out;              goto out;
872          }          }
873          lineno_length = JSSTRING_LENGTH(lineno_as_str);          lineno_length = lineno_as_str->length();
874      } else {      } else {
875          lineno_as_str = NULL;          lineno_as_str = NULL;
876          lineno_length = 0;          lineno_length = 0;
877      }      }
878    
879      /* Magic 8, for the characters in ``(new ())''. */      /* Magic 8, for the characters in ``(new ())''. */
880      name_length = JSSTRING_LENGTH(name);      name_length = name->length();
881      message_length = JSSTRING_LENGTH(message);      message_length = message->length();
882      length = 8 + name_length + message_length;      length = 8 + name_length + message_length;
883    
884      filename_length = JSSTRING_LENGTH(filename);      filename_length = filename->length();
885      if (filename_length != 0) {      if (filename_length != 0) {
886          /* append filename as ``, {filename}'' */          /* append filename as ``, {filename}'' */
887          length += 2 + filename_length;          length += 2 + filename_length;
# Line 963  Line 899 
899          }          }
900      }      }
901    
902      cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));      cp = chars = (jschar *) cx->malloc((length + 1) * sizeof(jschar));
903      if (!chars) {      if (!chars) {
904          ok = JS_FALSE;          ok = JS_FALSE;
905          goto out;          goto out;
906      }      }
907    
908      *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';      *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
909      js_strncpy(cp, JSSTRING_CHARS(name), name_length);      js_strncpy(cp, name->chars(), name_length);
910      cp += name_length;      cp += name_length;
911      *cp++ = '(';      *cp++ = '(';
912      if (message_length != 0) {      if (message_length != 0) {
913          js_strncpy(cp, JSSTRING_CHARS(message), message_length);          js_strncpy(cp, message->chars(), message_length);
914          cp += message_length;          cp += message_length;
915      }      }
916    
917      if (filename_length != 0) {      if (filename_length != 0) {
918          /* append filename as ``, {filename}'' */          /* append filename as ``, {filename}'' */
919          *cp++ = ','; *cp++ = ' ';          *cp++ = ','; *cp++ = ' ';
920          js_strncpy(cp, JSSTRING_CHARS(filename), filename_length);          js_strncpy(cp, filename->chars(), filename_length);
921          cp += filename_length;          cp += filename_length;
922      } else {      } else {
923          if (lineno_as_str) {          if (lineno_as_str) {
# Line 995  Line 931 
931      if (lineno_as_str) {      if (lineno_as_str) {
932          /* append lineno as ``, {lineno_as_str}'' */          /* append lineno as ``, {lineno_as_str}'' */
933          *cp++ = ','; *cp++ = ' ';          *cp++ = ','; *cp++ = ' ';
934          js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length);          js_strncpy(cp, lineno_as_str->chars(), lineno_length);
935          cp += lineno_length;          cp += lineno_length;
936      }      }
937    
# Line 1003  Line 939 
939    
940      result = js_NewString(cx, chars, length);      result = js_NewString(cx, chars, length);
941      if (!result) {      if (!result) {
942          JS_free(cx, chars);          cx->free(chars);
943          ok = JS_FALSE;          ok = JS_FALSE;
944          goto out;          goto out;
945      }      }
# Line 1024  Line 960 
960      JS_FS_END      JS_FS_END
961  };  };
962    
963    /* JSProto_ ordering for exceptions shall match JSEXN_ constants. */
964    JS_STATIC_ASSERT(JSEXN_ERR == 0);
965    JS_STATIC_ASSERT(JSProto_Error + JSEXN_INTERNALERR  == JSProto_InternalError);
966    JS_STATIC_ASSERT(JSProto_Error + JSEXN_EVALERR      == JSProto_EvalError);
967    JS_STATIC_ASSERT(JSProto_Error + JSEXN_RANGEERR     == JSProto_RangeError);
968    JS_STATIC_ASSERT(JSProto_Error + JSEXN_REFERENCEERR == JSProto_ReferenceError);
969    JS_STATIC_ASSERT(JSProto_Error + JSEXN_SYNTAXERR    == JSProto_SyntaxError);
970    JS_STATIC_ASSERT(JSProto_Error + JSEXN_TYPEERR      == JSProto_TypeError);
971    JS_STATIC_ASSERT(JSProto_Error + JSEXN_URIERR       == JSProto_URIError);
972    
973    static JS_INLINE JSProtoKey
974    GetExceptionProtoKey(intN exn)
975    {
976        JS_ASSERT(JSEXN_ERR <= exn);
977        JS_ASSERT(exn < JSEXN_LIMIT);
978        return (JSProtoKey) (JSProto_Error + exn);
979    }
980    
981  JSObject *  JSObject *
982  js_InitExceptionClasses(JSContext *cx, JSObject *obj)  js_InitExceptionClasses(JSContext *cx, JSObject *obj)
983  {  {
984      JSObject *obj_proto, *protos[JSEXN_LIMIT];      jsval roots[3];
985      int i;      JSObject *obj_proto, *error_proto;
986        jsval empty;
987    
988      /*      /*
989       * If lazy class initialization occurs for any Error subclass, then all       * If lazy class initialization occurs for any Error subclass, then all
# Line 1045  Line 1000 
1000          return NULL;          return NULL;
1001      }      }
1002    
1003      if (!js_EnterLocalRootScope(cx))      memset(roots, 0, sizeof(roots));
1004          return NULL;      JSAutoTempValueRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots);
1005    
1006    #ifdef __GNUC__
1007        error_proto = NULL;   /* quell GCC overwarning */
1008    #endif
1009    
1010      /* Initialize the prototypes first. */      /* Initialize the prototypes first. */
1011      for (i = 0; exceptions[i].name != 0; i++) {      for (intN i = JSEXN_ERR; i != JSEXN_LIMIT; i++) {
1012            JSObject *proto;
1013            JSProtoKey protoKey;
1014          JSAtom *atom;          JSAtom *atom;
1015          JSFunction *fun;          JSFunction *fun;
         JSString *nameString;  
         int protoIndex = exceptions[i].protoIndex;  
1016    
1017          /* Make the prototype for the current constructor name. */          /* Make the prototype for the current constructor name. */
1018          protos[i] = js_NewObject(cx, &js_ErrorClass,          proto = js_NewObject(cx, &js_ErrorClass,
1019                                   (protoIndex != JSEXN_NONE)                               (i != JSEXN_ERR) ? error_proto : obj_proto,
1020                                   ? protos[protoIndex]                               obj);
1021                                   : obj_proto,          if (!proto)
1022                                   obj, 0);              return NULL;
1023          if (!protos[i])          if (i == JSEXN_ERR) {
1024              break;              error_proto = proto;
1025                roots[0] = OBJECT_TO_JSVAL(proto);
1026            } else {
1027                // We cannot share the root for error_proto and other prototypes
1028                // as error_proto must be rooted until the function returns.
1029                roots[1] = OBJECT_TO_JSVAL(proto);
1030            }
1031    
1032          /* So exn_finalize knows whether to destroy private data. */          /* So exn_finalize knows whether to destroy private data. */
1033          STOBJ_SET_SLOT(protos[i], JSSLOT_PRIVATE, JSVAL_VOID);          proto->setPrivate(NULL);
1034    
1035          /* Make a constructor function for the current name. */          /* Make a constructor function for the current name. */
1036          atom = cx->runtime->atomState.classAtoms[exceptions[i].key];          protoKey = GetExceptionProtoKey(i);
1037          fun = js_DefineFunction(cx, obj, atom, exceptions[i].native, 3, 0);          atom = cx->runtime->atomState.classAtoms[protoKey];
1038            fun = js_DefineFunction(cx, obj, atom, Exception, 3, 0);
1039          if (!fun)          if (!fun)
1040              break;              return NULL;
1041            roots[2] = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
1042    
1043          /* Make this constructor make objects of class Exception. */          /* Make this constructor make objects of class Exception. */
1044          fun->u.n.clasp = &js_ErrorClass;          FUN_CLASP(fun) = &js_ErrorClass;
1045    
1046          /* Make the prototype and constructor links. */          /* Make the prototype and constructor links. */
1047          if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), protos[i],          if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), proto,
1048                                    JSPROP_READONLY | JSPROP_PERMANENT)) {                                    JSPROP_READONLY | JSPROP_PERMANENT)) {
1049              break;              return NULL;
1050          }          }
1051    
         /* proto bootstrap bit from JS_InitClass omitted. */  
         nameString = JS_NewStringCopyZ(cx, exceptions[i].name);  
         if (!nameString)  
             break;  
   
1052          /* Add the name property to the prototype. */          /* Add the name property to the prototype. */
1053          if (!JS_DefineProperty(cx, protos[i], js_name_str,          if (!JS_DefineProperty(cx, proto, js_name_str, ATOM_KEY(atom),
1054                                 STRING_TO_JSVAL(nameString),                                 NULL, NULL, JSPROP_ENUMERATE)) {
1055                                 NULL, NULL,              return NULL;
                                JSPROP_ENUMERATE)) {  
             break;  
1056          }          }
1057    
1058          /* Finally, stash the constructor for later uses. */          /* Finally, stash the constructor for later uses. */
1059          if (!js_SetClassObject(cx, obj, exceptions[i].key, FUN_OBJECT(fun)))          if (!js_SetClassObject(cx, obj, protoKey, FUN_OBJECT(fun)))
1060              break;              return NULL;
1061      }      }
1062    
     js_LeaveLocalRootScope(cx);  
     if (exceptions[i].name)  
         return NULL;  
   
1063      /*      /*
1064       * Add an empty message property.  (To Exception.prototype only,       * Set default values and add methods. We do it only for Error.prototype
1065       * because this property will be the same for all the exception       * as the rest of exceptions delegate to it.
      * protos.)  
1066       */       */
1067      if (!JS_DefineProperty(cx, protos[0], js_message_str,      empty = STRING_TO_JSVAL(cx->runtime->emptyString);
1068                             STRING_TO_JSVAL(cx->runtime->emptyString),      if (!JS_DefineProperty(cx, error_proto, js_message_str, empty,
1069                             NULL, NULL, JSPROP_ENUMERATE)) {                             NULL, NULL, JSPROP_ENUMERATE) ||
1070            !JS_DefineProperty(cx, error_proto, js_fileName_str, empty,
1071                               NULL, NULL, JSPROP_ENUMERATE) ||
1072            !JS_DefineProperty(cx, error_proto, js_lineNumber_str, JSVAL_ZERO,
1073                               NULL, NULL, JSPROP_ENUMERATE) ||
1074            !JS_DefineFunctions(cx, error_proto, exception_methods)) {
1075          return NULL;          return NULL;
1076      }      }
     if (!JS_DefineProperty(cx, protos[0], js_fileName_str,  
                            STRING_TO_JSVAL(cx->runtime->emptyString),  
                            NULL, NULL, JSPROP_ENUMERATE)) {  
         return NULL;  
     }  
     if (!JS_DefineProperty(cx, protos[0], js_lineNumber_str,  
                            INT_TO_JSVAL(0),  
                            NULL, NULL, JSPROP_ENUMERATE)) {  
         return NULL;  
     }  
   
     /*  
      * Add methods only to Exception.prototype, because ostensibly all  
      * exception types delegate to that.  
      */  
     if (!JS_DefineFunctions(cx, protos[0], exception_methods))  
         return NULL;  
1077    
1078      return protos[0];      return error_proto;
1079  }  }
1080    
1081  const JSErrorFormatString*  const JSErrorFormatString*
# Line 1220  Line 1163 
1163       * exception constructor name in the scope chain of the current context's       * exception constructor name in the scope chain of the current context's
1164       * top stack frame, or in the global object if no frame is active.       * top stack frame, or in the global object if no frame is active.
1165       */       */
1166      ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(exceptions[exn].key),      ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(GetExceptionProtoKey(exn)),
1167                                &errProto);                                &errProto);
1168      if (!ok)      if (!ok)
1169          goto out;          goto out;
1170      tv[0] = OBJECT_TO_JSVAL(errProto);      tv[0] = OBJECT_TO_JSVAL(errProto);
1171    
1172      errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL, 0);      errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL);
1173      if (!errObject) {      if (!errObject) {
1174          ok = JS_FALSE;          ok = JS_FALSE;
1175          goto out;          goto out;
# Line 1357  Line 1300 
1300          memset(&report, 0, sizeof report);          memset(&report, 0, sizeof report);
1301          report.filename = filename;          report.filename = filename;
1302          report.lineno = (uintN) lineno;          report.lineno = (uintN) lineno;
1303            if (JSVAL_IS_STRING(roots[2])) {
1304                report.ucmessage = js_GetStringChars(cx, JSVAL_TO_STRING(roots[2]));
1305                if (!report.ucmessage)
1306                    return false;
1307            }
1308      }      }
1309    
1310      if (!reportp) {      if (!reportp) {

Legend:
Removed from v.332  
changed lines
  Added in v.585

  ViewVC Help
Powered by ViewVC 1.1.24