js/src/vm/ErrorObject.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/vm/ErrorObject.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,151 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sw=4 et tw=78:
     1.6 + *
     1.7 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    1.10 +
    1.11 +#include "vm/ErrorObject-inl.h"
    1.12 +
    1.13 +#include "jsexn.h"
    1.14 +
    1.15 +#include "vm/GlobalObject.h"
    1.16 +
    1.17 +#include "jsobjinlines.h"
    1.18 +
    1.19 +#include "vm/Shape-inl.h"
    1.20 +
    1.21 +using namespace js;
    1.22 +using mozilla::PodZero;
    1.23 +
    1.24 +/* static */ Shape *
    1.25 +js::ErrorObject::assignInitialShape(ExclusiveContext *cx, Handle<ErrorObject*> obj)
    1.26 +{
    1.27 +    MOZ_ASSERT(obj->nativeEmpty());
    1.28 +
    1.29 +    if (!obj->addDataProperty(cx, cx->names().fileName, FILENAME_SLOT, 0))
    1.30 +        return nullptr;
    1.31 +    if (!obj->addDataProperty(cx, cx->names().lineNumber, LINENUMBER_SLOT, 0))
    1.32 +        return nullptr;
    1.33 +    if (!obj->addDataProperty(cx, cx->names().columnNumber, COLUMNNUMBER_SLOT, 0))
    1.34 +        return nullptr;
    1.35 +    return obj->addDataProperty(cx, cx->names().stack, STACK_SLOT, 0);
    1.36 +}
    1.37 +
    1.38 +/* static */ bool
    1.39 +js::ErrorObject::init(JSContext *cx, Handle<ErrorObject*> obj, JSExnType type,
    1.40 +                      ScopedJSFreePtr<JSErrorReport> *errorReport, HandleString fileName,
    1.41 +                      HandleString stack, uint32_t lineNumber, uint32_t columnNumber,
    1.42 +                      HandleString message)
    1.43 +{
    1.44 +    // Null out early in case of error, for exn_finalize's sake.
    1.45 +    obj->initReservedSlot(ERROR_REPORT_SLOT, PrivateValue(nullptr));
    1.46 +
    1.47 +    if (!EmptyShape::ensureInitialCustomShape<ErrorObject>(cx, obj))
    1.48 +        return false;
    1.49 +
    1.50 +    // The .message property isn't part of the initial shape because it's
    1.51 +    // present in some error objects -- |Error.prototype|, |new Error("f")|,
    1.52 +    // |new Error("")| -- but not in others -- |new Error(undefined)|,
    1.53 +    // |new Error()|.
    1.54 +    RootedShape messageShape(cx);
    1.55 +    if (message) {
    1.56 +        messageShape = obj->addDataProperty(cx, cx->names().message, MESSAGE_SLOT, 0);
    1.57 +        if (!messageShape)
    1.58 +            return false;
    1.59 +        MOZ_ASSERT(messageShape->slot() == MESSAGE_SLOT);
    1.60 +    }
    1.61 +
    1.62 +    MOZ_ASSERT(obj->nativeLookupPure(NameToId(cx->names().fileName))->slot() == FILENAME_SLOT);
    1.63 +    MOZ_ASSERT(obj->nativeLookupPure(NameToId(cx->names().lineNumber))->slot() == LINENUMBER_SLOT);
    1.64 +    MOZ_ASSERT(obj->nativeLookupPure(NameToId(cx->names().columnNumber))->slot() ==
    1.65 +               COLUMNNUMBER_SLOT);
    1.66 +    MOZ_ASSERT(obj->nativeLookupPure(NameToId(cx->names().stack))->slot() == STACK_SLOT);
    1.67 +    MOZ_ASSERT_IF(message,
    1.68 +                  obj->nativeLookupPure(NameToId(cx->names().message))->slot() == MESSAGE_SLOT);
    1.69 +
    1.70 +    MOZ_ASSERT(JSEXN_ERR <= type && type < JSEXN_LIMIT);
    1.71 +
    1.72 +    JSErrorReport *report = errorReport ? errorReport->forget() : nullptr;
    1.73 +    obj->initReservedSlot(EXNTYPE_SLOT, Int32Value(type));
    1.74 +    obj->setReservedSlot(ERROR_REPORT_SLOT, PrivateValue(report));
    1.75 +    obj->initReservedSlot(FILENAME_SLOT, StringValue(fileName));
    1.76 +    obj->initReservedSlot(LINENUMBER_SLOT, Int32Value(lineNumber));
    1.77 +    obj->initReservedSlot(COLUMNNUMBER_SLOT, Int32Value(columnNumber));
    1.78 +    obj->initReservedSlot(STACK_SLOT, StringValue(stack));
    1.79 +    if (message)
    1.80 +        obj->nativeSetSlotWithType(cx, messageShape, StringValue(message));
    1.81 +
    1.82 +    if (report && report->originPrincipals)
    1.83 +        JS_HoldPrincipals(report->originPrincipals);
    1.84 +
    1.85 +    return true;
    1.86 +}
    1.87 +
    1.88 +/* static */ ErrorObject *
    1.89 +js::ErrorObject::create(JSContext *cx, JSExnType errorType, HandleString stack,
    1.90 +                        HandleString fileName, uint32_t lineNumber, uint32_t columnNumber,
    1.91 +                        ScopedJSFreePtr<JSErrorReport> *report, HandleString message)
    1.92 +{
    1.93 +    Rooted<JSObject*> proto(cx, GlobalObject::getOrCreateCustomErrorPrototype(cx, cx->global(), errorType));
    1.94 +    if (!proto)
    1.95 +        return nullptr;
    1.96 +
    1.97 +    Rooted<ErrorObject*> errObject(cx);
    1.98 +    {
    1.99 +        JSObject* obj = NewObjectWithGivenProto(cx, &ErrorObject::class_, proto, nullptr);
   1.100 +        if (!obj)
   1.101 +            return nullptr;
   1.102 +        errObject = &obj->as<ErrorObject>();
   1.103 +    }
   1.104 +
   1.105 +    if (!ErrorObject::init(cx, errObject, errorType, report, fileName, stack,
   1.106 +                           lineNumber, columnNumber, message))
   1.107 +    {
   1.108 +        return nullptr;
   1.109 +    }
   1.110 +
   1.111 +    return errObject;
   1.112 +}
   1.113 +
   1.114 +JSErrorReport *
   1.115 +js::ErrorObject::getOrCreateErrorReport(JSContext *cx)
   1.116 +{
   1.117 +    if (JSErrorReport *r = getErrorReport())
   1.118 +        return r;
   1.119 +
   1.120 +    // We build an error report on the stack and then use CopyErrorReport to do
   1.121 +    // the nitty-gritty malloc stuff.
   1.122 +    JSErrorReport report;
   1.123 +    PodZero(&report);
   1.124 +
   1.125 +    // Type.
   1.126 +    JSExnType type_ = type();
   1.127 +    report.exnType = type_;
   1.128 +
   1.129 +    // Filename.
   1.130 +    JSAutoByteString filenameStr;
   1.131 +    if (!filenameStr.encodeLatin1(cx, fileName(cx)))
   1.132 +        return nullptr;
   1.133 +    report.filename = filenameStr.ptr();
   1.134 +
   1.135 +    // Coordinates.
   1.136 +    report.lineno = lineNumber();
   1.137 +    report.column = columnNumber();
   1.138 +
   1.139 +    // Message. Note that |new Error()| will result in an undefined |message|
   1.140 +    // slot, so we need to explicitly substitute the empty string in that case.
   1.141 +    RootedString message(cx, getMessage());
   1.142 +    if (!message)
   1.143 +        message = cx->runtime()->emptyString;
   1.144 +    if (!message->ensureFlat(cx))
   1.145 +        return nullptr;
   1.146 +    report.ucmessage = message->asFlat().chars();
   1.147 +
   1.148 +    // Cache and return.
   1.149 +    JSErrorReport *copy = CopyErrorReport(cx, &report);
   1.150 +    if (!copy)
   1.151 +        return nullptr;
   1.152 +    setReservedSlot(ERROR_REPORT_SLOT, PrivateValue(copy));
   1.153 +    return copy;
   1.154 +}

mercurial