Beispiel #1
0
void
FileReader::OnLoadEndArrayBuffer()
{
  AutoJSAPI jsapi;
  if (!jsapi.Init(GetParentObject())) {
    FreeDataAndDispatchError(NS_ERROR_FAILURE);
    return;
  }

  RootResultArrayBuffer();

  JSContext* cx = jsapi.cx();

  mResultArrayBuffer = JS_NewArrayBufferWithContents(cx, mDataLen, mFileData);
  if (mResultArrayBuffer) {
    mFileData = nullptr; // Transfer ownership
    FreeDataAndDispatchSuccess();
    return;
  }

  // Let's handle the error status.

  JS::Rooted<JS::Value> exceptionValue(cx);
  if (!JS_GetPendingException(cx, &exceptionValue) ||
      // This should not really happen, exception should always be an object.
      !exceptionValue.isObject()) {
    JS_ClearPendingException(jsapi.cx());
    FreeDataAndDispatchError(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  JS_ClearPendingException(jsapi.cx());

  JS::Rooted<JSObject*> exceptionObject(cx, &exceptionValue.toObject());
  JSErrorReport* er = JS_ErrorFromException(cx, exceptionObject);
  if (!er || er->message()) {
    FreeDataAndDispatchError(NS_ERROR_OUT_OF_MEMORY);
    return;
  }

  nsAutoString errorName;
  JSFlatString* name = js::GetErrorTypeName(cx, er->exnType);
  if (name) {
    AssignJSFlatString(errorName, name);
  }

  nsAutoCString errorMsg(er->message().c_str());
  nsAutoCString errorNameC = NS_LossyConvertUTF16toASCII(errorName);
  // XXX Code selected arbitrarily
  mError =
    new DOMException(NS_ERROR_DOM_INVALID_STATE_ERR, errorMsg,
                     errorNameC, DOMException_Binding::INVALID_STATE_ERR);

  FreeDataAndDispatchError();
}
Beispiel #2
0
JSErrorReport*
js::ErrorObject::getOrCreateErrorReport(JSContext* cx)
{
    if (JSErrorReport* r = getErrorReport())
        return r;

    // We build an error report on the stack and then use CopyErrorReport to do
    // the nitty-gritty malloc stuff.
    JSErrorReport report;

    // Type.
    JSExnType type_ = type();
    report.exnType = type_;

    // Filename.
    JSAutoByteString filenameStr;
    if (!filenameStr.encodeLatin1(cx, fileName(cx)))
        return nullptr;
    report.filename = filenameStr.ptr();

    // Coordinates.
    report.lineno = lineNumber();
    report.column = columnNumber();

    // Message. Note that |new Error()| will result in an undefined |message|
    // slot, so we need to explicitly substitute the empty string in that case.
    RootedString message(cx, getMessage());
    if (!message)
        message = cx->runtime()->emptyString;
    if (!message->ensureFlat(cx))
        return nullptr;

    UniquePtr<char[], JS::FreePolicy> utf8 = StringToNewUTF8CharsZ(cx, *message);
    if (!utf8)
        return nullptr;
    report.initOwnedMessage(utf8.release());

    // Cache and return.
    JSErrorReport* copy = CopyErrorReport(cx, &report);
    if (!copy)
        return nullptr;
    setReservedSlot(ERROR_REPORT_SLOT, PrivateValue(copy));
    return copy;
}
Beispiel #3
0
bool
js::ReportErrorVA(JSContext* cx, unsigned flags, const char* format,
                  ErrorArgumentsType argumentsType, va_list ap)
{
    JSErrorReport report;

    if (checkReportFlags(cx, &flags))
        return true;

    UniqueChars message(JS_vsmprintf(format, ap));
    if (!message) {
        ReportOutOfMemory(cx);
        return false;
    }

    MOZ_ASSERT_IF(argumentsType == ArgumentsAreASCII, JS::StringIsASCII(message.get()));

    report.flags = flags;
    report.errorNumber = JSMSG_USER_DEFINED_ERROR;
    if (argumentsType == ArgumentsAreASCII || argumentsType == ArgumentsAreUTF8) {
        report.initOwnedMessage(message.release());
    } else {
        MOZ_ASSERT(argumentsType == ArgumentsAreLatin1);
        Latin1Chars latin1(message.get(), strlen(message.get()));
        UTF8CharsZ utf8(JS::CharsToNewUTF8CharsZ(cx, latin1));
        if (!utf8)
            return false;
        report.initOwnedMessage(reinterpret_cast<const char*>(utf8.get()));
    }
    PopulateReportBlame(cx, &report);

    bool warning = JSREPORT_IS_WARNING(report.flags);

    ReportError(cx, &report, nullptr, nullptr);
    return warning;
}
Beispiel #4
0
JSErrorReport*
js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
{
    /*
     * We use a single malloc block to make a deep copy of JSErrorReport with
     * the following layout:
     *   JSErrorReport
     *   char array with characters for message_
     *   char16_t array with characters for linebuf
     *   char array with characters for filename
     * Such layout together with the properties enforced by the following
     * asserts does not need any extra alignment padding.
     */
    JS_STATIC_ASSERT(sizeof(JSErrorReport) % sizeof(const char*) == 0);
    JS_STATIC_ASSERT(sizeof(const char*) % sizeof(char16_t) == 0);

#define JS_CHARS_SIZE(chars) ((js_strlen(chars) + 1) * sizeof(char16_t))

    size_t filenameSize = report->filename ? strlen(report->filename) + 1 : 0;
    size_t linebufSize = 0;
    if (report->linebuf())
        linebufSize = (report->linebufLength() + 1) * sizeof(char16_t);
    size_t messageSize = 0;
    if (report->message())
        messageSize = strlen(report->message().c_str()) + 1;

    /*
     * The mallocSize can not overflow since it represents the sum of the
     * sizes of already allocated objects.
     */
    size_t mallocSize = sizeof(JSErrorReport) + messageSize + linebufSize + filenameSize;
    uint8_t* cursor = cx->pod_calloc<uint8_t>(mallocSize);
    if (!cursor)
        return nullptr;

    JSErrorReport* copy = (JSErrorReport*)cursor;
    cursor += sizeof(JSErrorReport);

    if (report->message()) {
        copy->initBorrowedMessage((const char*)cursor);
        js_memcpy(cursor, report->message().c_str(), messageSize);
        cursor += messageSize;
    }

    if (report->linebuf()) {
        const char16_t* linebufCopy = (const char16_t*)cursor;
        js_memcpy(cursor, report->linebuf(), linebufSize);
        cursor += linebufSize;
        copy->initBorrowedLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
    }

    if (report->filename) {
        copy->filename = (const char*)cursor;
        js_memcpy(cursor, report->filename, filenameSize);
    }
    MOZ_ASSERT(cursor + filenameSize == (uint8_t*)copy + mallocSize);

    /* Copy non-pointer members. */
    copy->isMuted = report->isMuted;
    copy->lineno = report->lineno;
    copy->column = report->column;
    copy->errorNumber = report->errorNumber;
    copy->exnType = report->exnType;

    /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
    copy->flags = report->flags;

#undef JS_CHARS_SIZE
    return copy;
}
Beispiel #5
0
JSErrorReport*
js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
{
    /*
     * We use a single malloc block to make a deep copy of JSErrorReport with
     * the following layout:
     *   JSErrorReport
     *   array of copies of report->messageArgs
     *   char16_t array with characters for all messageArgs
     *   char16_t array with characters for ucmessage
     *   char16_t array with characters for linebuf
     *   char array with characters for filename
     * Such layout together with the properties enforced by the following
     * asserts does not need any extra alignment padding.
     */
    JS_STATIC_ASSERT(sizeof(JSErrorReport) % sizeof(const char*) == 0);
    JS_STATIC_ASSERT(sizeof(const char*) % sizeof(char16_t) == 0);

#define JS_CHARS_SIZE(chars) ((js_strlen(chars) + 1) * sizeof(char16_t))

    size_t filenameSize = report->filename ? strlen(report->filename) + 1 : 0;
    size_t linebufSize = 0;
    if (report->linebuf())
        linebufSize = (report->linebufLength() + 1) * sizeof(char16_t);
    size_t ucmessageSize = 0;
    size_t argsArraySize = 0;
    size_t argsCopySize = 0;
    if (report->ucmessage) {
        ucmessageSize = JS_CHARS_SIZE(report->ucmessage);
        if (report->messageArgs) {
            size_t i = 0;
            for (; report->messageArgs[i]; ++i)
                argsCopySize += JS_CHARS_SIZE(report->messageArgs[i]);

            /* Non-null messageArgs should have at least one non-null arg. */
            MOZ_ASSERT(i != 0);
            argsArraySize = (i + 1) * sizeof(const char16_t*);
        }
    }

    /*
     * The mallocSize can not overflow since it represents the sum of the
     * sizes of already allocated objects.
     */
    size_t mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize +
                         ucmessageSize + linebufSize + filenameSize;
    uint8_t* cursor = cx->pod_calloc<uint8_t>(mallocSize);
    if (!cursor)
        return nullptr;

    JSErrorReport* copy = (JSErrorReport*)cursor;
    cursor += sizeof(JSErrorReport);

    if (argsArraySize != 0) {
        copy->messageArgs = (const char16_t**)cursor;
        cursor += argsArraySize;
        size_t i = 0;
        for (; report->messageArgs[i]; ++i) {
            copy->messageArgs[i] = (const char16_t*)cursor;
            size_t argSize = JS_CHARS_SIZE(report->messageArgs[i]);
            js_memcpy(cursor, report->messageArgs[i], argSize);
            cursor += argSize;
        }
        copy->messageArgs[i] = nullptr;
        MOZ_ASSERT(cursor == (uint8_t*)copy->messageArgs[0] + argsCopySize);
    }

    if (report->ucmessage) {
        copy->ucmessage = (const char16_t*)cursor;
        js_memcpy(cursor, report->ucmessage, ucmessageSize);
        cursor += ucmessageSize;
    }

    if (report->linebuf()) {
        const char16_t* linebufCopy = (const char16_t*)cursor;
        js_memcpy(cursor, report->linebuf(), linebufSize);
        cursor += linebufSize;
        copy->initLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
    }

    if (report->filename) {
        copy->filename = (const char*)cursor;
        js_memcpy(cursor, report->filename, filenameSize);
    }
    MOZ_ASSERT(cursor + filenameSize == (uint8_t*)copy + mallocSize);

    /* Copy non-pointer members. */
    copy->isMuted = report->isMuted;
    copy->lineno = report->lineno;
    copy->column = report->column;
    copy->errorNumber = report->errorNumber;
    copy->exnType = report->exnType;

    /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
    copy->flags = report->flags;

#undef JS_CHARS_SIZE
    return copy;
}